加入收藏 | 设为首页 | 会员中心 | 我要投稿 安卓应用网 (https://www.0791zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > PHP > 正文

CI框架安全类Security.php源码分析

发布时间:2020-05-28 09:43:11 所属栏目:PHP 来源:互联网
导读:之前我们分析了CI框架的session类session.php,本文我们继续分析CI框架的安全类security.php文件,方便我们更详细的了解CI框架,从而更熟练的应用CI框架

CI安全类提供了全局防御CSRF攻击和XSS攻击策略,只需要在配置文件开启即可:

代码如下:

并提供了实用方法:

代码如下:security->xss_clean($data);//第二个参数为TRUE,验证图片安全 $this->security->sanitize_filename()//过滤文件名

CI也提供了安全函数:

xss_clean()//xss过滤 sanitize_filename()//净化文件名 do_hash()//md5或sha加密 strip_image_tags() //删除图片标签的不必要字符 encode_php_tags()//把PHP脚本标签强制转成实体对象

代码如下:

'[removed]', 'document.write'=> '[removed]', '.parentNode'=> '[removed]', '.innerHTML'=> '[removed]', 'window.location'=> '[removed]', '-moz-binding'=> '[removed]', ''=> '-->', ' ''=> '' ); //不允许出现的正则表达式数组 protected $_never_allowed_regex = array( 'javascripts*:', 'expressions*((|()',// CSS and IE 'vbscripts*:',// IE,surprise! 'Redirects+302', "(["'])?datas*:[^1]*?base64[^1]*?,[^1]*?1?" ); //构造函数 public function __construct() { // CSRF保护是否开启 if (config_item('csrf_protection') === TRUE) { // CSRF配置 foreach (array('csrf_expire','csrf_token_name','csrf_cookie_name') as $key) { if (FALSE !== ($val = config_item($key))) { $this->{'_'.$key} = $val; } } // _csrf_cookie_name加上cookie前缀 if (config_item('cookie_prefix')) { $this->_csrf_cookie_name = config_item('cookie_prefix').$this->_csrf_cookie_name; } // 设置csrf的hash值 $this->_csrf_set_hash(); } log_message('debug',"Security Class Initialized"); } // -------------------------------------------------------------------- /** * Verify Cross Site Request Forgery Protection * * @returnobject */ public function csrf_verify() { // 如果不是post请求,则设置csrf的cookie值 if (strtoupper($_SERVER['REQUEST_METHOD']) !== 'POST') { return $this->csrf_set_cookie(); } // Do the tokens exist in both the _POST and _COOKIE arrays? if ( ! isset($_POST[$this->_csrf_token_name],$_COOKIE[$this->_csrf_cookie_name])) { $this->csrf_show_error(); } // token匹配吗 if ($_POST[$this->_csrf_token_name] != $_COOKIE[$this->_csrf_cookie_name]) { $this->csrf_show_error(); } // We kill this since we're done and we don't want to // polute the _POST array unset($_POST[$this->_csrf_token_name]); // Nothing should last forever unset($_COOKIE[$this->_csrf_cookie_name]); $this->_csrf_set_hash(); $this->csrf_set_cookie(); log_message('debug','CSRF token verified'); return $this; } // -------------------------------------------------------------------- /** * 设置csrf的cookie值 */ public function csrf_set_cookie() { $expire = time() + $this->_csrf_expire; $secure_cookie = (config_item('cookie_secure') === TRUE) ? 1 : 0; if ($secure_cookie && (empty($_SERVER['HTTPS']) OR strtolower($_SERVER['HTTPS']) === 'off')) { return FALSE; } setcookie($this->_csrf_cookie_name,$this->_csrf_hash,$expire,config_item('cookie_path'),config_item('cookie_domain'),$secure_cookie); log_message('debug',"CRSF cookie Set"); return $this; } //csrf保存 public function csrf_show_error() { show_error('The action you have requested is not allowed.'); } //获取csrf的hash值 public function get_csrf_hash() { return $this->_csrf_hash; } //获取csrf的token值 public function get_csrf_token_name() { return $this->_csrf_token_name; } /** * XSS 过滤 */ public function xss_clean($str,$is_image = FALSE) { //是否是数组 if (is_array($str)) { while (list($key) = each($str)) { $str[$key] = $this->xss_clean($str[$key]); } return $str; } //去掉可见字符串 $str = remove_invisible_characters($str); // 验证实体url $str = $this->_validate_entities($str); /* * URL 解码 * * Just in case stuff like this is submitted: * * Google|<|$)/si",'_decode_entity'),$str); /* * Remove Invisible Characters Again! */ $str = remove_invisible_characters($str); /* * Convert all tabs to spaces * * This prevents strings like this: javascript * NOTE: we deal with spaces between characters later. * NOTE: preg_replace was found to be amazingly slow here on * large blocks of data,so we use str_replace. */ if (strpos($str,"t") !== FALSE) { $str = str_replace("t",' ',$str); } /* * Capture converted string for later comparison */ $converted_string = $str; // Remove Strings that are never allowed $str = $this->_do_never_allowed($str); /* * Makes PHP tags safe * * Note: XML tags are inadvertently replaced too: * * '),array(''),$str); } /* * Compact any exploded words * * This corrects words like: j a v a s c r i p t * These words are compacted back to their correct state. */ $words = array( 'javascript','expression','vbscript','script','base64', 'applet','alert','document','write','cookie','window' ); foreach ($words as $word) { $temp = ''; for ($i = 0,$wordlen = strlen($word); $i < $wordlen; $i++) { $temp .= substr($word,$i,1)."s*"; } // We only want to do this when it is followed by a non-word character // That way valid stuff like "dealer to" does not become "dealerto" $str = preg_replace_callback('#('.substr($temp,-3).')(W)#is','_compact_exploded_words'),$str); } /* * Remove disallowed Javascript in links or img tags * We used to do some version comparisons and use of stripos for PHP5, * but it is dog slow compared to these simplified non-capturing * preg_match(),especially if the pattern exists in the string */ do { $original = $str; if (preg_match("/]*?)(>|$)#si",'_js_link_removal'),$str); } if (preg_match("/CI框架安全类Security.php源码分析]*?)(s?/?>|$)#si",'_js_img_removal'),$str); } if (preg_match("/script/i",$str) OR preg_match("/xss/i",$str)) { $str = preg_replace("#<(/*)(script|xss)(.*?)>#si",'[removed]',$str); } } while($original != $str); unset($original); // Remove evil attributes such as style,onclick and xmlns $str = $this->_remove_evil_attributes($str,$is_image); /* * Sanitize naughty HTML elements * * If a tag containing any of the words in the list * below is found,the tag gets converted to entities. * * So this: * Becomes: */ $naughty = 'alert|applet|audio|basefont|base|behavior|bgsound|blink|body|embed|expression|form|frameset|frame|head|html|ilayer|iframe|input|isindex|layer|link|meta|object|plaintext|style|script|textarea|title|video|xml|xss'; $str = preg_replace_callback('#<(/*s*)('.$naughty.')([^><]*)([><]*)#is','_sanitize_naughty_html'),$str); /* * Sanitize naughty scripting elements * * Similar to above,only instead of looking for * tags it looks for PHP and JavaScript commands * that are disallowed. Rather than removing the * code,it simply converts the parenthesis to entities * rendering the code un-executable. * * For example:eval('some code') * Becomes:eval('some code') */ $str = preg_replace('#(alert|cmd|passthru|eval|exec|expression|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(s*)((.*?))#si',")",$str); // Final clean up // This adds a bit of extra precaution in case // something got through the above filters $str = $this->_do_never_allowed($str); /* * Images are Handled in a Special Way * - Essentially,we want to know that after all of the character * conversion is done whether any unwanted,likely XSS,code was found. * If not,we return TRUE,as the image is clean. * However,if the string post-conversion does not matched the * string post-removal of XSS,then it fails,as there was unwanted XSS * code found and removed/changed during processing. */ if ($is_image === TRUE) { return ($str == $converted_string) ? TRUE: FALSE; } log_message('debug',"XSS Filtering completed"); return $str; } // -------------------------------------------------------------------- //保护url的随机hash值 public function xss_hash() { if ($this->_xss_hash == '') { mt_srand(); $this->_xss_hash = md5(time() + mt_rand(0,1999999999)); } return $this->_xss_hash; } // -------------------------------------------------------------------- /** * html实体转码 */ public function entity_decode($str,$charset='UTF-8') { if (stristr($str,'&') === FALSE) { return $str; } $str = html_entity_decode($str,ENT_COMPAT,$charset); $str = preg_replace('~&#x(0*[0-9a-f]{2,5})~ei','chr(hexdec(",$str); return preg_replace('~&#([0-9]{2,4})~e','chr(,$str); } // -------------------------------------------------------------------- //过滤文件名,保证文件名安全 public function sanitize_filename($str,$relative_path = FALSE) { $bad = array( "../", "", "<", ">", "'", '"', '&', '$', '#', '{', '}', '[', ']', '=', ';', '?', "%20", "%22", "%3c",// < "%253c",// < "%3e",// > "%0e",// > "%28",// ( "%29",// ) "%2528",// ( "%26",// & "%24",// $ "%3f",// ? "%3b",// ; "%3d"// = ); if ( ! $relative_path) { $bad[] = './'; $bad[] = '/'; } $str = remove_invisible_characters($str,FALSE); return stripslashes(str_replace($bad,'',$str)); } //压缩单词如j a v a s c r i p t成javascript protected function _compact_exploded_words($matches) { return preg_replace('/s+/s',$matches[1]).$matches[2]; } // -------------------------------------------------------------------- /* * 去掉一些危害的html属性 */ protected function _remove_evil_attributes($str,$is_image) { // All javascript event handlers (e.g. onload,onclick,onmouSEOver),style,and xmlns $evil_attributes = array('onw*','style','xmlns','formaction'); if ($is_image === TRUE) { /* * Adobe Photoshop puts XML metadata into JFIF images, * including namespacing,so we have to allow this for images. */ unset($evil_attributes[array_search('xmlns',$evil_attributes)]); } do { $count = 0; $attribs = array(); // find occurrences of illegal attribute strings with quotes (042 and 047 are octal quotes) preg_match_all('/('.implode('|',$evil_attributes).')s*=s*(42|47)([^2]*?)(,$str,$matches,PREG_SET_ORDER); foreach ($matches as $attr) { $attribs[] = preg_quote($attr[0],'/'); } // find occurrences of illegal attribute strings without quotes preg_match_all('/('.implode('|',$evil_attributes).')s*=s*([^s>]*)/is','/'); } // replace illegal attribute strings that are inside an html tag if (count($attribs) > 0) { $str = preg_replace('/(<]+?)([^A-Za-z<>-])(.*?)('.implode('|',$attribs).')(.*?)([s><]?)([><]*)/i','$1$2 $4$6$7$8',-1,$count); } } while ($count); return $str; } // -------------------------------------------------------------------- /** * 净化html,补齐未关闭的标签 */ protected function _sanitize_naughty_html($matches) { // encode opening brace $str = '<'.$matches[1].$matches[2].$matches[3]; // encode captured opening or closing brace to prevent recursive vectors $str .= str_replace(array('>','<'),array('>', $matches[4]); return $str; } // -------------------------------------------------------------------- /** * 过滤超链接中js */ protected function _js_link_removal($match) { return str_replace( $match[1], preg_replace( '#href=.*?(alert(|alert(|javascript:|livescript:|mocha:|charset=|window.|document.|.cookie|_filter_attributes(str_replace(array('<','>'),$match[1])) ), $match[0] ); } // -------------------------------------------------------------------- /** * 过滤图片链接中的js */ protected function _js_img_removal($match) { return str_replace( $match[1], preg_replace( '#src=.*?(alert(|alert(|javascript:|livescript:|mocha:|charset=|window.|document.|.cookie|','<',''),'\'),$match[0]); } // -------------------------------------------------------------------- //过滤html标签属性 protected function _filter_attributes($str) { $out = ''; if (preg_match_all('#s*[a-z-]+s*=s*(42|47)([^1]*?)1#is',$matches)) { foreach ($matches[0] as $match) { $out .= preg_replace("#/*.*?*/#s",$match); } } return $out; } // -------------------------------------------------------------------- //html实体转码 protected function _decode_entity($match) { return $this->entity_decode($match[0],strtoupper(config_item('charset'))); } // -------------------------------------------------------------------- /** * 验证url实体 */ protected function _validate_entities($str) { /* * Protect GET variables in URLs */ // 901119URL5918AMP18930PROTECT8198 $str = preg_replace('|&([a-z_0-9-]+)=([a-z_0-9-]+)|i',$this->xss_hash()."",$str); /* * Validate standard character entities * * Add a semicolon if missing. We do this to enable * the conversion of entities to ASCII later. * */ $str = preg_replace('#(&#?[0-9a-z]{2,})([x00-x20])*;?#i',"",$str); /* * Validate UTF16 two byte encoding (x00) * * Just as above,adds a semicolon if missing. * */ $str = preg_replace('#(&#x?)([0-9A-F]+);?#i',"); /* * Un-Protect GET variables in URLs */ $str = str_replace($this->xss_hash(),'&',$str); return $str; } // ---------------------------------------------------------------------- //过滤不允许出现的字符串 protected function _do_never_allowed($str) { $str = str_replace(array_keys($this->_never_allowed_str),$this->_never_allowed_str,$str); foreach ($this->_never_allowed_regex as $regex) { $str = preg_replace('#'.$regex.'#is',$str); } return $str; } // -------------------------------------------------------------------- //设置csrf的hash值 protected function _csrf_set_hash() { if ($this->_csrf_hash == '') { // 如果_csrf_cookie_name存在,直接作为csrf hash值 if (isset($_COOKIE[$this->_csrf_cookie_name]) && preg_match('#^[0-9a-f]{32}$#iS',$_COOKIE[$this->_csrf_cookie_name]) === 1) { return $this->_csrf_hash = $_COOKIE[$this->_csrf_cookie_name]; } //否则随机一个md5字符串 return $this->_csrf_hash = md5(uniqid(rand(),TRUE)); } return $this->_csrf_hash; } }

(编辑:安卓应用网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读