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 18 PHP
解决163/sohu/sina不能够收到PHP MAIL函数发出邮件的问题
Mar 13 PHP
PHP中使用gettext来支持多语言的方法
May 02 PHP
PHP网站备份程序代码分享
Jun 10 PHP
PHP生成指定长度随机数最简洁的方法
Jul 14 PHP
php实现window平台的checkdnsrr函数
May 27 PHP
php线性表的入栈与出栈实例分析
Jun 12 PHP
PHP中static关键字以及与self关键字的区别
Jul 01 PHP
crontab无法执行php的解决方法
Jan 25 PHP
PHP实现文件下载【实例分享】
Apr 28 PHP
利用php操作memcache缓存的基础方法示例
Aug 02 PHP
PHP实现的简单对称加密与解密方法实例小结
Aug 28 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文件上传的简单实例
2013/10/19 PHP
Parse正式发布开源PHP SDK
2014/08/11 PHP
PHP获取MySQL执行sql语句的查询时间方法
2018/08/21 PHP
ASP中进行HTML数据及JS数据编码函数
2009/11/11 Javascript
JavaScript与Div对层定位和移动获得坐标的实现代码
2010/09/08 Javascript
jQuery中:text选择器用法实例
2015/01/03 Javascript
jquery插件unobtrusive实现片段式加载
2015/06/15 Javascript
jQuery简单操作cookie的插件实例
2016/01/13 Javascript
[原创]JQuery 在表单提交之前修改 提交的值
2016/04/14 Javascript
nodejs 终端打印进度条实例代码
2017/04/22 NodeJs
基于Require.js使用方法(总结)
2017/10/26 Javascript
AngularJs 终极购物车(实例讲解)
2017/11/08 Javascript
Vue项目中如何使用Axios封装http请求详解
2019/10/23 Javascript
Javascript作用域和作用域链原理解析
2020/03/03 Javascript
Vue自定义组件双向绑定实现原理及方法详解
2020/09/03 Javascript
JavaScript实现点击出现子菜单效果
2021/02/08 Javascript
Python中optionParser模块的使用方法实例教程
2014/08/29 Python
Python Requests安装与简单运用
2016/04/07 Python
Python中列表list以及list与数组array的相互转换实现方法
2017/09/22 Python
Python实现购物车程序
2018/04/16 Python
Python 数据处理库 pandas进阶教程
2018/04/21 Python
Python多线程threading join和守护线程setDeamon原理详解
2020/03/18 Python
Python3 + Appium + 安卓模拟器实现APP自动化测试并生成测试报告
2021/01/27 Python
Python爬虫UA伪装爬取的实例讲解
2021/02/19 Python
Application Cache未缓存文件无法访问无法加载问题
2014/05/31 HTML / CSS
加拿大女鞋品牌:ALDO
2016/11/13 全球购物
彪马日本官网:PUMA日本
2019/01/31 全球购物
预备党员政审材料
2014/02/04 职场文书
外国人聘用意向书
2014/04/01 职场文书
农村文化活动总结
2014/08/28 职场文书
上课迟到检讨书300字
2014/10/15 职场文书
个人年底工作总结
2015/03/10 职场文书
全陪导游词开场白
2015/05/29 职场文书
建国大业观后感800字
2015/06/01 职场文书
RPM包方式安装Oracle21c的方法详解
2021/08/23 Oracle
Java异常处理try catch的基本用法
2021/12/06 Java/Android