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更新mysql后获取影响的行数发生异常解决方法
Mar 28 PHP
浅析php fwrite写入txt文件的时候用 \r\n不能换行的问题
Aug 06 PHP
ThinkPHP空模块和空操作详解
Jun 30 PHP
PHP中使用SimpleXML检查XML文件结构实例
Jan 07 PHP
php使用标签替换的方式生成静态页面
May 21 PHP
非常重要的php正则表达式详解
Jan 04 PHP
PHP打印输出函数汇总
Aug 28 PHP
关于Laravel Route重定向的一个注意点
Jan 16 PHP
Laravel 集成微信用户登录和绑定的实现
Dec 27 PHP
Yii框架小部件(Widgets)用法实例详解
May 15 PHP
PHP利用curl发送HTTP请求的实例代码
Jul 09 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
php 各种应用乱码问题的解决方法
2010/05/09 PHP
php中用数组的方法设置cookies
2011/04/21 PHP
在PHP中运行Linux命令并启动SSH服务的例子
2014/06/12 PHP
php常用文件操作函数汇总
2014/11/22 PHP
PHP5.2中PDO的简单使用方法
2016/03/25 PHP
PHP简单预防sql注入的方法
2016/09/27 PHP
php自定义排序uasort函数示例【二维数组按指定键值排序】
2019/06/19 PHP
Nigma vs Liquid BO3 第二场2.13
2021/03/10 DOTA
js去字符串前后空格5种实现方法及比较
2013/04/03 Javascript
JS实现CheckBox复选框全选全不选功能
2015/05/06 Javascript
初步使用Node连接Mysql数据库
2016/03/03 Javascript
JS实现利用两个队列表示一个栈的方法
2017/12/13 Javascript
10个在JavaScript开发中常遇到的BUG
2017/12/18 Javascript
Vue iview-admin框架二级菜单改为三级菜单的方法
2018/07/03 Javascript
vue 本地服务不能被外部IP访问的完美解决方法
2018/10/29 Javascript
JQuery实现ajax请求的示例和注意事项
2018/12/10 jQuery
Vue2(三)实现子菜单展开收缩,带动画效果实现方法
2019/04/28 Javascript
jQuery操作动画完整实例分析
2020/01/10 jQuery
[49:40]2018DOTA2亚洲邀请赛小组赛 A组加赛 TNC vs Newbee
2018/04/03 DOTA
Python实现统计英文单词个数及字符串分割代码
2015/05/28 Python
使用 Python 实现微信公众号粉丝迁移流程
2018/01/03 Python
Python try except finally资源回收的实现
2021/01/25 Python
html5移动端自适应布局的实现
2020/04/15 HTML / CSS
英国Flybe航空官网:欧洲最大的独立支线廉价航空公司
2019/07/15 全球购物
我们没有写servlet的构造方法,那么容器是怎么创建servlet的实例呢
2013/04/24 面试题
审计工作个人的自我评价
2013/12/25 职场文书
中学生学雷锋活动心得体会
2014/03/10 职场文书
安全保卫工作竞聘材料
2014/08/25 职场文书
2014年班务工作总结
2014/12/02 职场文书
2015年乡镇扶贫工作总结
2015/04/08 职场文书
学校2015年纠风工作总结
2015/05/15 职场文书
唐山大地震观后感
2015/06/05 职场文书
2016教师校本培训心得体会
2016/01/08 职场文书
农村房屋租赁合同(范本)
2019/07/23 职场文书
导游词之桂林
2019/08/20 职场文书
MySQL 外键约束和表关系相关总结
2021/06/20 MySQL