web-dev-qa-db-fra.com

Fonction de filtrage XSS dans PHP

Quelqu'un connaît-il une bonne fonction pour filtrer les entrées génériques des formulaires? Zend_Filter_input semble nécessiter une connaissance préalable du contenu de l'entrée et je crains que l'utilisation de quelque chose comme HTML Purifier ait un impact important sur les performances.

Qu'en est-il de quelque chose comme: http://snipplr.com/view/1848/php--sacar-xss/

Merci beaucoup pour toute contribution.

39
codecowboy

Un moyen simple? Utilisez strip_tags() :

$str = strip_tags($input);

Vous pouvez également utiliser filter_var() pour cela:

$str = filter_var($input, FILTER_SANITIZE_STRING);

L'avantage de filter_var() est que vous pouvez contrôler le comportement, par exemple, en supprimant ou en codant les caractères bas et hauts.

Voici une liste de filtres de désinfection .

80
cletus

Il existe un certain nombre de façons dont les pirates informatiques peuvent utiliser pour les attaques XSS, les fonctions intégrées de PHP ne répondent pas à toutes sortes d'attaques XSS. Par conséquent, des fonctions telles que strip_tags, filter_var, mysql_real_escape_string, htmlentities, htmlspecialchars, etc. ne nous protègent pas à 100%. Vous avez besoin d'un meilleur mécanisme, voici la solution:

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;
}
26
Sarfraz

le meilleur et le plus sûr est d'utiliser HTML Purifier. Suivez ce lien pour obtenir des conseils sur son utilisation avec Zend Framework.

Purificateur HTML avec Zend Framework

7
opHASnoNAME

J'ai le même problème. J'ai besoin que les utilisateurs soumettent du contenu html à une page de profil avec un excellent éditeur WYSIWYG (Redactorjs!), J'ai écrit la fonction suivante pour nettoyer le html soumis:

    <?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()); } ?>

Le tableau $ check contient tous les attributs et règles de validation autorisés. Peut-être que cela est utile pour certains d'entre vous. Je n'ai pas encore testé, donc les conseils sont les bienvenus

3
3eighty
function clean($data){
    $data = rawurldecode($data);
    return filter_var($data, FILTER_SANITIZE_SPEC_CHARS);
}
2
ingnorant

htmlspecialchars() est parfaitement adapté pour filtrer les entrées utilisateur affichées sous forme html.

1
Doug Amos

Selon www.mcafeesecure.com, la solution générale pour les vulnérabilités à la fonction de filtre de script intersite (XSS) peut être:

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;
}
0
Taras

Toutes les méthodes ci-dessus ne permettent pas de conserver certaines balises comme <a>, <table> etc. Il existe une solution ultime http://sourceforge.net/projects/kses/ Drupal l'utilise

0
ymakux