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 相关文章推荐
生成ubuntu自动切换壁纸xml文件的php代码
Jul 17 PHP
谨慎使用PHP的引用原因分析
Sep 06 PHP
新手菜鸟必读:session与cookie的区别
Aug 22 PHP
实现获取http内容的php函数分享
Feb 16 PHP
php+mysqli数据库连接的两种方式
Jan 28 PHP
WordPress自定义时间显示格式
Mar 27 PHP
使用PHPCMS搭建wap手机网站
Sep 20 PHP
PHP中SSO Cookie登录分析和实现
Nov 06 PHP
PHP Cookie学习笔记
Aug 23 PHP
浅谈PHP安全防护之Web攻击
Jan 03 PHP
PHP构造二叉树算法示例
Jun 21 PHP
VSCode+PHPstudy配置PHP开发环境的步骤详解
Aug 20 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调用mysql存储过程
2007/02/14 PHP
PHP的explode和implode的使用说明
2011/07/17 PHP
php判断用户是否手机访问代码
2015/06/08 PHP
PHP编写RESTful接口
2016/02/23 PHP
jquery制作搜狐快站页面效果示例分享
2014/02/21 Javascript
JavaScript中创建字典对象(dictionary)实例
2015/03/31 Javascript
JavaScript使用replace函数替换字符串的方法
2015/04/06 Javascript
jQuery实现动态添加和删除一个div
2015/08/12 Javascript
浅谈Javascript中的12种DOM节点类型
2016/08/19 Javascript
ExtJS 4.2 Grid组件单元格合并的方法
2016/10/12 Javascript
浅谈React Native Flexbox布局(小结)
2018/01/08 Javascript
详解Vue项目编译后部署在非网站根目录的解决方案
2018/04/26 Javascript
ios设备中angularjs无法改变页面title的解决方法
2018/09/13 Javascript
详解在vue-cli项目下简单使用mockjs模拟数据
2018/10/19 Javascript
一个因@click.stop引发的bug的解决
2019/01/08 Javascript
python实现多线程抓取知乎用户
2016/12/12 Python
Django 导出 Excel 代码的实例详解
2017/08/11 Python
python正则表达式面试题解答
2020/04/28 Python
Python使用Flask-SQLAlchemy连接数据库操作示例
2018/08/31 Python
python读取文件名并改名字的实例
2019/01/07 Python
python+opencv像素的加减和加权操作的实现
2019/07/14 Python
使用python实现离散时间傅里叶变换的方法
2019/09/02 Python
基于python全局设置id 自动化测试元素定位过程解析
2019/09/04 Python
Python中输入和输出(打印)数据实例方法
2019/10/13 Python
Python中的X[:,0]、X[:,1]、X[:,:,0]、X[:,:,1]、X[:,m:n]和X[:,:,m:n]
2020/02/13 Python
Python实现邮件发送的详细设置方法(遇到问题)
2021/01/18 Python
联想台湾官网:Lenovo TW
2018/05/09 全球购物
Discard Protocol抛弃协议的作用是什么
2015/10/10 面试题
酒店个人培训自我鉴定
2013/12/11 职场文书
建筑工程管理专业自荐信范文
2013/12/28 职场文书
公务员政审个人鉴定
2014/02/25 职场文书
魂断蓝桥观后感
2015/06/10 职场文书
导游词之清晏园
2019/11/22 职场文书
php远程请求CURL案例(爬虫、保存登录状态)
2021/04/01 PHP
php访问对象中的成员的实例方法
2021/11/17 PHP
win10系统xps文件怎么打开?win10打开xps文件的两种操作方法
2022/07/23 数码科技