47 votes

Fonction de filtrage XSS en PHP

Est-ce que quelqu'un connaît une fonction utile 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 quelque chose comme: http://snipplr.com/view/1848/php--sacar-xss/

Merci beaucoup pour toute contribution.

87voto

cletus Points 276888

De façon Simple? Utiliser strip_tags():

$str = strip_tags($input);

Vous pouvez également utiliser filter_var() pour que:

$str = filter_var($input, FILTER_SANITIZE_STRING);

L'avantage de l' filter_var() , c'est que vous pouvez contrôler le comportement, par exemple, de décapage ou de codage de basse et de haute caractères.

Voici une liste de désinfection des filtres.

33voto

Sarfraz Points 168484

Il existe un certain nombre de façons dont les pirates informatiques ont été utilisés 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 quelle est 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;
}
 

7voto

ArneRie Points 9722

le meilleur et le plus sûr consiste à utiliser HTML Purifier. Suivez ce lien pour des astuces sur son utilisation avec Zend Framework.

Purificateur HTML avec Zend Framework

3voto

3eighty Points 51

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. C'est peut-être utile pour certains d'entre vous. Je n'ai pas encore testé, les pourboires sont les bienvenus

2voto

ingnorant Points 31
function clean($data){
    $data = rawurldecode($data);
    return filter_var($data, FILTER_SANITIZE_SPEC_CHARS);
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X