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 相关文章推荐
模拟OICQ的实现思路和核心程序(二)
Oct 09 PHP
模仿OSO的论坛(三)
Oct 09 PHP
模板引擎Smarty深入浅出介绍
Dec 06 PHP
用PHP提取中英文词语以及数字的首字母的方法介绍
Apr 23 PHP
laravel 5 实现模板主题功能
Mar 02 PHP
php根据日期或时间戳获取星座信息和生肖等信息
Oct 20 PHP
Thinkphp结合AJAX长轮询实现PC与APP推送详解
Jul 31 PHP
PHP中使用mpdf 导出PDF文件的实现方法
Oct 22 PHP
PHP生成二维码与识别二维码的方法详解【附源码下载】
Mar 07 PHP
PHP DB 数据库连接类定义与用法示例
Mar 11 PHP
php用户名的密码加密更安全的方法
Jun 21 PHP
如何在PHP环境中使用ProtoBuf数据格式
Jun 19 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中数组合并的两种方法及区别介绍
2012/09/14 PHP
解析如何修改phpmyadmin中的默认登陆超时时间
2013/06/25 PHP
php使用正则表达式获取图片url的方法
2015/01/16 PHP
PHP生成静态HTML文档实现代码
2016/06/23 PHP
PHP支付系统设计与典型案例分享
2016/08/02 PHP
如何修改Laravel中url()函数生成URL的根地址
2017/08/11 PHP
PHP fprintf()函数用法讲解
2019/02/16 PHP
PHP中的Iterator迭代对象属性详解
2019/04/12 PHP
Yii框架的redis命令使用方法简单示例
2019/10/15 PHP
分页栏的web标准实现
2011/11/01 Javascript
js控制网页前进和后退的方法
2015/06/08 Javascript
jQuery超酷平面式时钟效果代码分享
2020/03/30 Javascript
浅析AngularJS Filter用法
2015/12/28 Javascript
JavaScript实现简单Tip提示框效果
2016/04/20 Javascript
jQuery动态增减行的实例代码解析(推荐)
2016/12/05 Javascript
概述如何实现一个简单的浏览器端js模块加载器
2016/12/07 Javascript
浅谈js中的变量名和函数名重名
2017/02/13 Javascript
详解webpack自动生成html页面
2017/06/29 Javascript
vue.js 微信支付前端代码分享
2018/02/10 Javascript
Vue 组件注册实例详解
2019/02/23 Javascript
mock.js模拟前后台交互
2019/07/25 Javascript
Vue Element校验validate的实例
2020/09/21 Javascript
浅析Python中的join()方法的使用
2015/05/19 Python
详解Python中映射类型的内建函数和工厂函数
2015/08/19 Python
Python(TensorFlow框架)实现手写数字识别系统的方法
2018/05/29 Python
Python 获取中文字拼音首个字母的方法
2018/11/28 Python
基于python计算并显示日间、星期客流高峰
2020/05/07 Python
CSS3毛玻璃效果(blur)有白边问题的解决方法
2016/11/15 HTML / CSS
美国隐形眼镜销售网站:ContactsDirect
2017/10/28 全球购物
敏捷开发的主要原则都有哪些
2015/04/26 面试题
大学生职业生涯规划书前言
2014/01/09 职场文书
给校长的建议书600字
2014/05/15 职场文书
销售员工作检讨书(推荐篇)
2014/10/18 职场文书
2015入党自传书范文
2015/06/26 职场文书
Python爬虫之爬取最新更新的小说网站
2021/05/06 Python
SQLServer常见数学函数梳理总结
2022/08/05 MySQL