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部分常见问题总结
Mar 27 PHP
第4章 数据处理-php正则表达式-郑阿奇(续)
Jul 04 PHP
Javascript与PHP验证用户输入URL地址是否正确
Oct 09 PHP
php实现的简单日志写入函数
Mar 31 PHP
Yii数据读取与跳转参数传递用法实例分析
Jul 12 PHP
PHP中利用sleep函数实现定时执行功能实现代码
Aug 25 PHP
手把手编写PHP框架 深入了解MVC运行流程
Sep 19 PHP
PHP实现文件上传下载实例
Oct 18 PHP
php base64 编码与解码实例代码
Mar 21 PHP
php获得刚插入数据的id 的几种方法总结
May 31 PHP
PHP自动载入类文件函数__autoload的使用方法
Mar 25 PHP
PHP实现页面静态化深入讲解
Mar 04 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中类型转换 ,常量,系统常量,魔术常量的详解
2017/10/26 PHP
laravel按天、按小时,查询数据的实例
2019/10/09 PHP
laravel model模型处理之修改查询或修改字段时的类型格式案例
2019/10/17 PHP
使用jQuery实现返回顶部
2015/01/26 Javascript
DEDECMS如何为文章添加HOT NEW标志图片
2015/08/14 Javascript
Javascript removeChild()删除节点及删除子节点的方法
2015/12/27 Javascript
AngularJS 入门教程之HTML DOM实例详解
2016/07/28 Javascript
Bootstrap框架结合jQuery仿百度换肤功能实例解析
2016/09/17 Javascript
js 打开新页面在屏幕中间的实现方法
2016/11/02 Javascript
jQuery Easyui datagrid editor为combobox时指定数据源实例
2016/12/19 Javascript
JavaScript实现替换字符串中最后一个字符的方法
2017/03/07 Javascript
JavaScript实现获取远程的html到当前页面中
2017/03/26 Javascript
微信小程序页面传值实例分析
2017/04/19 Javascript
jquery鼠标悬停导航下划线滑出效果
2017/09/29 jQuery
利用vue组件自定义v-model实现一个Tab组件方法示例
2017/12/06 Javascript
解决Jquery下拉框数据动态获取的问题
2018/01/25 jQuery
Vue-router的使用和出现空白页,路由对象属性详解
2018/09/03 Javascript
微信小程序自定义tabBar在uni-app的适配详解
2019/09/30 Javascript
vue proxy 的优势与使用场景实现
2020/06/15 Javascript
[41:52]2018DOTA2亚洲邀请赛3月29日小组赛B组Effect VS Secret
2018/03/30 DOTA
python查找指定具有相同内容文件的方法
2015/06/28 Python
在Python的Django框架中创建语言文件
2015/07/27 Python
Python自动化部署工具Fabric的简单上手指南
2016/04/19 Python
Python编写简单的HTML页面合并脚本
2016/07/11 Python
python实现数据图表
2017/07/29 Python
python实现发送邮件功能代码
2017/12/14 Python
Python中单线程、多线程和多进程的效率对比实验实例
2019/05/14 Python
python2使用bs4爬取腾讯社招过程解析
2019/08/14 Python
HTML5 canvas实现移动端上传头像拖拽裁剪效果
2016/03/14 HTML / CSS
台湾百利市购物中心:e-Payless
2017/08/16 全球购物
法国二手手袋、手表和奢侈珠宝购物网站:Collector Square
2018/07/05 全球购物
jurlique茱莉蔻英国官网:澳洲天然护肤品
2018/08/03 全球购物
澳大利亚婴儿喂养品牌:Cherub Baby
2018/11/01 全球购物
德国网上超市:myTime.de
2019/08/26 全球购物
导游词之重庆钓鱼城
2019/09/19 职场文书
Python3中PyQt5简单实现文件打开及保存
2021/06/10 Python