PHP中的XSS过滤function
有没有人知道有一个很好的function,从表单过滤通用input? Zend_Filter_input似乎需要事先了解input内容,我担心使用诸如HTML Purifier之类的东西会对性能产生很大的影响。
怎么样的东西: http : //snipplr.com/view/1848/php–sacar-xss/
非常感谢您的任何意见。
简单的方法? 使用strip_tags()
:
$str = strip_tags($input);
你也可以使用filter_var()
来做到这一点:
$str = filter_var($input, FILTER_SANITIZE_STRING);
filter_var()
的优点是可以通过例如剥离或编码低位和高位字符来控制行为。
这是一个消毒filter列表。
黑客利用XSS攻击的方式有很多种,PHP的内置函数不会对各种XSS攻击做出反应。 因此,strip_tags,filter_var,mysql_real_escape_string,htmlentities,htmlspecialchars等函数不能保护我们100%。 你需要一个更好的机制,这里是解决scheme:
function xss_clean($data) { // Fix &entity\n; $data = str_replace(array('&','<','>'), array('&amp;','&lt;','&gt;'), $data); $data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data); $data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data); $data = html_entity_decode($data, ENT_COMPAT, 'UTF-8'); // Remove any attribute starting with "on" or xmlns $data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $data); // Remove javascript: and vbscript: protocols $data = preg_replace('#([az]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data); $data = preg_replace('#([az]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data); $data = preg_replace('#([az]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data); // Only works in IE: <span style="width: expression(alert('Ping!'));"></span> $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data); $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data); $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data); // Remove namespaced elements (we do not need them) $data = preg_replace('#</*\w+:\w[^>]*+>#i', '', $data); do { // Remove really unwanted tags $old_data = $data; $data = preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $data); } while ($old_data !== $data); // we are done... return $data; }
最好的和安全的方式是使用HTML净化器。 按照这个链接了解如何在Zend Framework中使用它。
使用Zend框架的HTML净化器
我有一个类似的问题。 我需要用户用一个伟大的所见即所得编辑器(Redactorjs!)提交html内容到一个configuration文件页面,我写了下面的函数来清理提交的html:
<?php function filterxss($str) { //Initialize DOM: $dom = new DOMDocument(); //Load content and add UTF8 hint: $dom->loadHTML('<meta http-equiv="content-type" content="text/html; charset=utf-8">'.$str); //Array holds allowed attributes and validation rules: $check = array('src'=>'#(http://[^\s]+(?=\.(jpe?g|png|gif)))#i','href'=>'|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i'); //Loop all elements: foreach($dom->getElementsByTagName('*') as $node){ for($i = $node->attributes->length -1; $i >= 0; $i--){ //Get the attribute: $attribute = $node->attributes->item($i); //Check if attribute is allowed: if( in_array($attribute->name,array_keys($check))) { //Validate by regex: if(!preg_match($check[$attribute->name],$attribute->value)) { //No match? Remove the attribute $node->removeAttributeNode($attribute); } }else{ //Not allowed? Remove the attribute: $node->removeAttributeNode($attribute); } } } var_dump($dom->saveHTML()); } ?>
$ check数组包含所有允许的属性和validation规则。 也许这对你们中的一些人有用。 我还没有testing,所以提示是值得欢迎的
function clean($data){ $data = rawurldecode($data); return filter_var($data, FILTER_SANITIZE_SPEC_CHARS); }
htmlspecialchars()
完全适用于过滤HTML表单中显示的用户input。
根据www.mcafeesecure.com通用解决scheme易受跨站脚本(XSS)过滤function可以:
function xss_cleaner($input_str) { $return_str = str_replace( array('<','>',"'",'"',')','('), array('<','>',''','"',')','('), $input_str ); $return_str = str_ireplace( '%3Cscript', '', $return_str ); return $return_str; }
尝试使用Clean XSS
xss_clean($data): "><script>alert(String.fromCharCode(74,111,104,116,111,32,82,111,98,98,105,101))</script>
以上所有方法都不允许保留一些标签,如<a>
, <table>
等。有一个最终的解决schemehttp://sourceforge.net/projects/kses/ Drupal使用它
我发现一个解决scheme,我的问题与德语元音变音的post。 要提供从完全清理(杀死)职位,我编码传入的数据:
*$data = utf8_encode($data); ... function ...*
最后我解码输出得到正确的标志:
*$data = utf8_decode($data);*
现在的post通过过滤function,我得到一个正确的结果…