搜索
首页php教程php手册CI框架安全类Security.php源码分析

之前我们分析了CI框架的session类session.php,本文我们继续分析CI框架的安全类security.php文件,方便我们更详细的了解CI框架,从而更熟练的应用CI框架

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

复制代码 代码如下:


$config['csrf_protection'] = TRUE;
$config['global_xss_filtering'] = TRUE;

并提供了实用方法:

复制代码 代码如下:


$this->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脚本标签强制转成实体对象

复制代码 代码如下:


/**
 * 安全类
 */
class CI_Security {
 //url的随机hash值
 protected $_xss_hash   = '';
 //防csrf攻击的cookie标记的哈希值 
 protected $_csrf_hash   = '';
 //防csrf cookie过期时间
 protected $_csrf_expire   = 7200;
 //防csrf的cookie名称
 protected $_csrf_token_name  = 'ci_csrf_token';
 //防csrf的token名称
 protected $_csrf_cookie_name = 'ci_csrf_token';
 //不允许出现的字符串数组
 protected $_never_allowed_str = array(
  'document.cookie' => '[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");
 }
 // --------------------------------------------------------------------
 /**
  * 验证跨站请求伪造保护
  *
  * @return 对象
 */
 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'))
  {
   返回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 设置");
  返回 $this;
 }
 //csrf保存
 公共函数 csrf_show_error()
 {
  show_error('不允许您请求的操作。');
 }
 //获取csrf的hash值
 公共函数 get_csrf_hash()
 {
  返回 $this->_csrf_hash;
 }
 //获取csrf的token值
 公共函数 get_csrf_token_name()
 {
  返回 $this->_csrf_token_name;
 }
 /**
  * XSS 过滤
 */
 公共函数 xss_clean($str, $is_image = FALSE)
 {
  // 是否是备份
  if (is_array($str))
  {
   while (list($key) = every($str))
   {
    $str[$key] = $this->xss_clean($str[$key]);
   }
   返回 $str;
  }
  //去掉可见字符串
  $str = remove_invisible_characters($str);
  // 验证实体url
  $str = $this->_validate_entities($str);
  /*
   * URL 解码
   *
   * 以防万一提交这样的东西:
   *
   * Google
   *
   * 注意:使用 rawurldecode() 所以它不会删除加号
   *
   */
  $str = rawurldecode($str);
  /*
   * 将字符实体转换为 ASCII
   *
   * 这使得我们下面的测试能够可靠地工作。
   * 我们只转换标签内的实体
   * 这些是会带来安全问题的。
   *
   */
  $str = preg_replace_callback("/[a-z] =(['"]).*?\1/si", array($this, '_convert_attribute'), $str);
  $str = preg_replace_callback("/|   /*
   * 再次删除隐形字符!
   */
  $str = remove_invisible_characters($str);
  /*
   * 将所有制表符转换为空格
   *
   * 这可以防止这样的字符串:ja vascript
   * 注意:我们稍后会处理字符之间的空格。
   * 注意:发现 preg_replace 在
上速度慢得惊人    * 大块数据,所以我们使用str_replace。
   */
  if (strpos($str, "t") !== FALSE)
  {
   $str = str_replace("t", ' ', $str);
  }
  /*
   * 捕获转换后的字符串以便稍后比较
   */
  $converted_string = $str;
  // 删除不允许的字符串
  $str = $this->_do_never_allowed($str);
  /*
   * 使 PHP 标签安全
   *
   * 注意:XML 标签也会被无意中替换:
   *
   *    *
   * 不过好像没啥问题。
   */
  if ($is_image === TRUE)
  {
   // 图像有 PHP 短开头的倾向和
   // 经常关闭标签,所以我们跳过这些并且仅
   // 做长的开始标签。
   $str = preg_replace('/(php)/i', "\1", $str);
  }
  其他
  {
   $str = str_replace(array('', '?'.'>'), array('', '?>'), $str);
  }
  /*
   * 压缩任何分解的单词
   *
   * 这更正了以下单词: j a v a s c r i p t
   * 这些单词被压缩回到正确的状态。
   */
  $words = 数组(
   'javascript', '表达式', 'vbscript', '脚本', 'base64',
   '小程序'、'警报'、'文档'、'写入'、'cookie'、'窗口'
  );
  foreach($words 作为 $word)
  {
   $temp = '';
   for ($i = 0, $wordlen = strlen($word); $i    {
    $temp .= substr($word, $i, 1)."s*";
   }
   // 我们只想在后面跟着非单词字符
时执行此操作    // 这样,像“dealer to”这样的有效内容就不会变成“dealerto”
   $str = preg_replace_callback('#('.substr($temp, 0, -3).')(W)#is', array($this, '_compact_exploded_words'), $str);
  }
  /*
   * 删除链接或 img 标签中不允许的 Javascript
   * 我们曾经为PHP5做过一些版本比较和stripos的使用,
   * 但与这些简化的非捕获相比,它太慢了
   * preg_match(),特别是如果字符串中存在模式
   */
  做
  {
   $original = $str;
   if (preg_match("/    {
    $str = preg_replace_callback("#]*?)(>|$)#si", array($this, '_js_link_removal'), $str);
   }
   if (preg_match("/CI框架安全类Security.php源码分析    {
    $str = preg_replace_callback("#CI框架安全类Security.php源码分析]*?)(s?/?>|$)#si", array($this, '_js_img_removal'), $str);
   }
   if (preg_match("/script/i", $str) OR preg_match("/xss/i", $str))
   {
    $str = preg_replace("##si", '[已删除]', $str);
   }
  }
  while($original!=$str);
  未设置($original);
  // 移除 style、onclick 和 xmlns
等邪恶属性   $str = $this->_remove_evil_attributes($str, $is_image);
  /*
   * 清理顽皮的 HTML 元素
   *
   * 如果标签包含列表中的任何单词
   * 找到下面,标签被转换为实体。
   *
   * 所以这样:
   * 变成:
   */
  $naughty = 'alert|applet|audio|basefont|base|behavior|bgsound|blink|body|embed|表达式|form|frameset|frame|head|html|ilayer|iframe|input|isindex|layer|link|meta|对象|纯文本|样式|脚本|文本区域|标题|视频|xml|xss';
  $str = preg_replace_callback('#   /*
   * 清理顽皮的脚本元素
   *
   * 与上面类似,只是不寻找
   * 标记它寻找 PHP 和 JavaScript 命令
   * 是不允许的。  而不是删除
   * 代码,它只是将括号转换为实体
   * 使代码不可执行。
   *
   * 例如:eval('一些代码')
   * 变成:  eval('一些代码')
   */
  $str = preg_replace('#(alert|cmd|passthru|eval|exec|表达式|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(s*)((.*?))#si', " \1\2(\3)", $str);
  // 最终清理
  // 这增加了一些额外的预防措施,以防万一
  // 通过上述过滤器的东西
  $str = $this->_do_never_allowed($str);
  /*
   * 图像以特殊方式处理
   * - 本质上,我们想知道在所有角色之后
   * 无论是否发现任何不需要的(可能是 XSS)代码,都会完成转换。
   * 如果不是,我们返回 TRUE,因为图像是干净的。
   * 但是,如果转换后的字符串与
不匹配    * 删除 XSS 后的字符串,然后失败,因为存在不需要的 XSS
   * 在处理过程中发现并删除/更改了代码。
   */
  if ($is_image === TRUE)
  {
   返回($str == $converted_string)?正确:错误;
  }
  log_message('debug', "XSS 过滤完成");
  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('~(0*[0-9a-f]{2,5})~ei', 'chr(hexdec("\1"))', $str);
  return preg_replace('~([0-9]{2,4})~e', 'chr(\1)', $str);
 }
 // --------------------------------------------------------------------
 //过滤文件名,保证文件名安全
 public function sanitize_filename($str, $relative_path = FALSE)
 {
  $bad = array(
   "../",
   "",
   "    ">",
   "'",
   '"',
   '&',
   '$',
   '#',
   '{',
   '}',
   '[',
   ']',
   '=',
   ';',
   '?',
   " ",
   """,
   "    "%3c", //    ">",  // >
   "",  // >
   "(",  // (
   ")",  // )
   "%28", // (
   "&",  // &
   "$",  // $
   "?",  // ?
   ";",  // ;
   "="  // =
  );
  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*(

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)