Функция фильтрации XSS в PHP - PullRequest
39 голосов
/ 26 августа 2009

Кто-нибудь знает о хорошей функции для фильтрации общих входных данных из форм? Zend_Filter_input требует предварительных знаний о содержимом входных данных, и я обеспокоен тем, что использование чего-то вроде HTML Purifier сильно повлияет на производительность.

Как насчет чего-то вроде: http://snipplr.com/view/1848/php--sacar-xss/

Большое спасибо за любой вклад.

Ответы [ 10 ]

78 голосов
/ 26 августа 2009

Простой способ? Используйте strip_tags():

$str = strip_tags($input);

Вы также можете использовать filter_var() для этого:

$str = filter_var($input, FILTER_SANITIZE_STRING);

Преимущество filter_var() состоит в том, что вы можете управлять поведением, например, удаляя или кодируя младшие и старшие символы.

Вот список дезинфицирующих фильтров .

26 голосов
/ 16 ноября 2009

Существует несколько способов использования хакерами для атак XSS, встроенные функции PHP не отвечают на все виды атак XSS. Следовательно, такие функции, как strip_tags, filter_var, mysql_real_escape_string, htmlentities, htmlspecialchars и т.д., не защищают нас на 100% Вам нужен лучший механизм, вот что является решением:

function xss_clean($data)
{
// Fix &entity\n;
$data = str_replace(array('&','<','>'), array('&','<','>'), $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('#([a-z]*)[\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('#([a-z]*)[\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('#([a-z]*)[\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;
}
7 голосов
/ 11 декабря 2009

лучший и безопасный способ - использовать HTML Purifier. Перейдите по этой ссылке, чтобы получить некоторые советы по ее использованию с Zend Framework.

Очиститель HTML с Zend Framework

3 голосов
/ 11 октября 2012

У меня похожая проблема. Мне нужно, чтобы пользователи отправляли html-контент на страницу профиля с помощью отличного редактора WYSIWYG (Redactorjs!), Я написал следующую функцию для очистки представленного 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 содержит все разрешенные атрибуты и правила проверки. Может быть, это полезно для некоторых из вас. Я еще не проверял, так что советы приветствуются

2 голосов
/ 09 мая 2011
function clean($data){
    $data = rawurldecode($data);
    return filter_var($data, FILTER_SANITIZE_SPEC_CHARS);
}
1 голос
/ 08 января 2015

htmlspecialchars() идеально подходит для фильтрации пользовательского ввода, отображаемого в HTML-формах.

0 голосов
/ 24 июня 2017

Я нашел решение моей проблемы с постами с немецким умлаутом. Чтобы полностью очистить (убить) посты, я кодирую входящие данные:

    *$data = utf8_encode($data);
    ... function ...*

И, наконец, я декодирую вывод, чтобы получить правильные знаки:

    *$data = utf8_decode($data);*

Теперь пост проходит через функцию фильтра, и я получаю правильный результат ...

0 голосов
/ 01 августа 2015

Все вышеперечисленные методы не позволяют сохранить некоторые теги, такие как <a>, <table> и т. Д. Существует окончательное решение http://sourceforge.net/projects/kses/ Drupal использует его

0 голосов
/ 28 апреля 2014

Попробуйте использовать для Clean XSS

xss_clean($data): "><script>alert(String.fromCharCode(74,111,104,116,111,32,82,111,98,98,105,101))</script>
0 голосов
/ 03 июля 2012

Согласно www.mcafeesecure.com Общее решение для функции фильтрации уязвимых к межсайтовому скриптингу (XSS) может быть:

function xss_cleaner($input_str) {
    $return_str = str_replace( array('<','>',"'",'"',')','('), array('&lt;','&gt;','&apos;','&#x22;','&#x29;','&#x28;'), $input_str );
    $return_str = str_ireplace( '%3Cscript', '', $return_str );
    return $return_str;
}
...