PHP和XSS跨站攻击的防范


Posted in PHP onApril 17, 2007

其实这个话题很早就想说说了,发现国内不少PHP站点都有XSS漏洞。今天偶然看到PHP5的一个XSS漏洞,在此小结一下。顺便提醒,使用PHP5的朋友最好打下补丁,或者升级一下。

如果你不懂什么是XSS,可以看这里,或者这里(中文的也许会好懂一些)。

国内不少论坛都存在跨站脚本漏洞,例如这里  有一个Google Hack+XSS的攻击例子,针对的是Discuz 4.0.0RC3。国外也很多这样的例子,甚至Google也出现过,不过在12月初时修正了。跨站攻击很容易就可以构造,而且非常隐蔽,不易被查觉(通常盗取信息后马上跳转回原页面)。
如何攻击,在此不作说明(也不要问我),主要谈谈如何防范。首先,跨站脚本攻击都是由于对用户的输入没有进行严格的过滤造成的,所以我们必须在所有数据进入我们的网站和数据库之前把可能的危险拦截。针对非法的HTML代码包括单双引号等,可以使用htmlentities() 。

<?php
$str = "A 'quote' is <b>bold</b>";

// Outputs: A 'quote' is <b>bold</b>
echo htmlentities($str);

// Outputs: A 'quote' is <b>bold</b>
echo htmlentities($str, ENT_QUOTES);
?>

这样可以使非法的脚本失效。

但是要注意一点,htmlentities()默认编码为 ISO-8859-1,如果你的非法脚本编码为其它,那么可能无法过滤掉,同时浏览器却可以识别和执行。这个问题我先找几个站点测试后再说。

这里提供一个过滤非法脚本的函数:

function RemoveXSS($val) { 
   // remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed 
   // this prevents some character re-spacing such as <java\0script> 
   // note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some inputs 
   $val = preg_replace('/([\x00-\x08][\x0b-\x0c][\x0e-\x20])/', '', $val); 

   // straight replacements, the user should never need these since they're normal characters 
   // this prevents like <IMG SRC=@avascript:alert('XSS')> 
   $search = 'abcdefghijklmnopqrstuvwxyz'; 
   $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; 
   $search .= '1234567890!@#$%^&*()'; 
   $search .= '~`";:?+/={}[]-_|\'\\'; 
   for ($i = 0; $i < strlen($search); $i++) { 
      // ;? matches the ;, which is optional 
      // 0{0,7} matches any padded zeros, which are optional and go up to 8 chars 

      // @ @ search for the hex values 
      $val = preg_replace('/(&#[x|X]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val); // with a ; 
      // @ @ 0{0,7} matches '0' zero to seven times 
      $val = preg_replace('/(�{0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ; 
   } 

   // now the only remaining whitespace attacks are \t, \n, and \r 
   $ra1 = Array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'style', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base'); 
   $ra2 = Array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload'); 
   $ra = array_merge($ra1, $ra2); 

   $found = true; // keep replacing as long as the previous round replaced something 
   while ($found == true) { 
      $val_before = $val; 
      for ($i = 0; $i < sizeof($ra); $i++) { 
         $pattern = '/'; 
         for ($j = 0; $j < strlen($ra[$i]); $j++) { 
            if ($j > 0) { 
               $pattern .= '('; 
               $pattern .= '(&#[x|X]0{0,8}([9][a][b]);?)?'; 
               $pattern .= '|(�{0,8}([9][10][13]);?)?'; 
               $pattern .= ')?'; 
            } 
            $pattern .= $ra[$i][$j]; 
         } 
         $pattern .= '/i'; 
         $replacement = substr($ra[$i], 0, 2).'<x>'.substr($ra[$i], 2); // add in <> to nerf the tag 
         $val = preg_replace($pattern, $replacement, $val); // filter out the hex tags 
         if ($val_before == $val) { 
            // no replacements were made, so exit the loop 
            $found = false; 
         } 
      } 
   } 
}

PHP 相关文章推荐
一个阿拉伯数字转中文数字的函数
Oct 09 PHP
浅析PHP递归函数返回值使用方法
Feb 18 PHP
PHP调用MsSQL Server 2012存储过程获取多结果集(包含output参数)的详解
Jul 03 PHP
PHP 线程安全与非线程安全版本的区别深入解析
Aug 06 PHP
js和php邮箱地址验证的实现方法
Jan 09 PHP
又一个PHP实现的冒泡排序算法分享
Aug 21 PHP
PHP创建文件,并向文件中写入数据,覆盖,追加的实现代码
Mar 25 PHP
yii2带搜索功能的下拉框实例详解
May 12 PHP
基于PHP实现数据分页显示功能
May 26 PHP
总结PHP删除字符串最后一个字符的三种方法
Aug 30 PHP
PHP基于imagick扩展实现合成图片的两种方法【附imagick扩展下载】
Nov 14 PHP
Yii框架 session 数据库存储操作方法示例
Nov 18 PHP
PHP与SQL注入攻击[三]
Apr 17 #PHP
PHP与SQL注入攻击[二]
Apr 17 #PHP
PHP与SQL注入攻击[一]
Apr 17 #PHP
使用Xdebug调试和优化PHP程序之[1]
Apr 17 #PHP
php下用GD生成生成缩略图的两个选择和区别
Apr 17 #PHP
15种PHP Encoder的比较
Apr 17 #PHP
dede全站URL静态化改造[070414更正]
Apr 17 #PHP
You might like
重置版宣传动画
2020/04/09 魔兽争霸
Apache, PHP在Windows 9x/NT下的安装与配置 (二)
2006/10/09 PHP
PHP array_push 数组函数
2009/12/26 PHP
PHP+MYSQL实现用户的增删改查
2015/03/24 PHP
详解HTTP Cookie状态管理机制
2016/01/14 PHP
phpinfo() 中 Local Value(局部变量)Master Value(主变量) 的区别
2016/02/03 PHP
laravel框架邮箱认证实现方法详解
2019/11/22 PHP
js函数使用技巧之 setTimeout(function(){},0)
2009/02/09 Javascript
基于jQuery的自动完成插件
2011/02/03 Javascript
腾讯UED 漂亮的提示信息效果代码
2011/09/12 Javascript
使用jQuery清空file文件域的解决方案
2013/04/12 Javascript
JavaScript strike方法入门实例(给字符串加上删除线)
2014/10/17 Javascript
JS动态修改iframe高度和宽度的方法
2015/04/01 Javascript
jquery实现点击弹出带标题栏的弹出层(从右上角飞入)效果
2015/09/19 Javascript
Bootstrap每天必学之警告框插件
2016/04/26 Javascript
浅谈JS验证表单文本域输入空格的问题
2017/02/14 Javascript
Vue自定义过滤器格式化数字三位加一逗号实现代码
2018/03/23 Javascript
js实现继承的方法及优缺点总结
2019/05/08 Javascript
基于Vue SEO的四种方案(小结)
2019/07/01 Javascript
Javascript执行流程细节原理解析
2020/05/14 Javascript
Jquery cookie插件实现原理代码解析
2020/08/04 jQuery
vue中可编辑树状表格的实现代码
2020/10/31 Javascript
python定时检查某个进程是否已经关闭的方法
2015/05/20 Python
Django框架中方法的访问和查找
2015/07/15 Python
python定时利用QQ邮件发送天气预报的实例
2017/11/17 Python
Python3导入自定义模块的三种方法详解
2018/04/13 Python
Django将默认的SQLite更换为MySQL的实现
2019/11/18 Python
call在Python中改进数列的实例讲解
2020/12/09 Python
python绘制高斯曲线
2021/02/19 Python
卡西欧B级产品官方网站:Casio Outlet
2018/05/22 全球购物
size?爱尔兰官方网站:英国伦敦的球鞋精品店
2019/03/31 全球购物
学前教育求职自荐信范文
2013/12/25 职场文书
培训讲师岗位职责
2014/04/13 职场文书
多媒体教室标语
2014/06/26 职场文书
武侯祠导游词
2015/02/04 职场文书
动视暴雪取消疫苗禁令 让所有员工返回线下工作
2022/04/03 其他游戏