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 相关文章推荐
编写PHP的安全策略
Oct 09 PHP
图象函数中的中文显示
Oct 09 PHP
php header示例代码(推荐)
Sep 08 PHP
在php和MySql中计算时间差的方法
Apr 22 PHP
php 搜索框提示(自动完成)实例代码
Feb 05 PHP
支持中文字母数字、自定义字体php验证码代码
Feb 27 PHP
PHP中nowdoc和heredoc使用需要注意的一点
Mar 21 PHP
php实现按指定大小等比缩放生成上传图片缩略图的方法
Dec 15 PHP
Java和PHP在Web开发方面对比分析
Mar 01 PHP
yii2.0使用Plupload实现带缩放功能的多图上传
Dec 22 PHP
PHP数组生成XML格式数据的封装类实例
Nov 10 PHP
php unicode编码和字符串互转的方法
Aug 12 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中call_user_func函数使用注意事项
2014/11/21 PHP
什么是PEAR?什么是PECL?PHP中两个容易混淆的概念解释
2015/07/01 PHP
YII框架学习笔记之命名空间、操作响应与视图操作示例
2019/04/30 PHP
网页图片延时加载的js代码
2010/04/22 Javascript
探讨jQuery的ajax使用场景(c#)
2013/12/03 Javascript
javascript根据时间生成m位随机数最大13位
2014/10/30 Javascript
简单谈谈javascript代码复用模式
2015/01/28 Javascript
JS封装cookie操作函数实例(设置、读取、删除)
2015/11/17 Javascript
JavaScript操作HTML DOM节点的基础教程
2016/03/11 Javascript
bootstrap网页框架的使用方法
2016/05/10 Javascript
jQuery动态生成Bootstrap表格
2016/11/01 Javascript
JS实现倒计时(天数、时、分、秒)
2016/11/16 Javascript
jquery实现放大镜简洁代码(推荐)
2017/06/08 jQuery
微信小程序画布圆形进度条显示效果
2020/11/17 Javascript
js实现继承的方法及优缺点总结
2019/05/08 Javascript
JS数组方法push()、pop()用法实例分析
2020/01/18 Javascript
JS数组方法shift()、unshift()用法实例分析
2020/01/18 Javascript
[01:25]DOTA2自定义游戏灵园鬼域等你踏足
2015/10/30 DOTA
[01:39:04]DOTA2-DPC中国联赛 正赛 SAG vs CDEC BO3 第二场 2月1日
2021/03/11 DOTA
Matplotlib 生成不同大小的subplots实例
2018/05/25 Python
详解Django-restframework 之频率源码分析
2019/02/27 Python
python监控进程状态,记录重启时间及进程号的实例
2019/07/15 Python
python画微信表情符的实例代码
2019/10/09 Python
Python 复平面绘图实例
2019/11/21 Python
Python任务调度利器之APScheduler详解
2020/04/02 Python
pandas将list数据拆分成行或列的实现
2020/12/13 Python
详解Python中@staticmethod和@classmethod区别及使用示例代码
2020/12/14 Python
通用的Django注册功能模块实现方法
2021/02/05 Python
html5之Canvas路径绘图、坐标变换应用实例
2012/12/26 HTML / CSS
马来西亚网上美容店:Hermo.my
2017/11/25 全球购物
新西兰优惠网站:Treat Me
2019/07/04 全球购物
写给妈妈的道歉信
2014/01/11 职场文书
主管会计岗位职责
2014/03/13 职场文书
大学新生军训自我鉴定范文
2014/09/13 职场文书
2015年世界环境日活动方案
2015/05/05 职场文书
python爬取某网站原图作为壁纸
2021/06/02 Python