Gestion du XSS

Eléphant du PHP | 209 Messages

22 juin 2011, 16:41

Bonjour,

Je tente de régler une bonne fois pour toute ces histoires de XSS (il serait temps :-) ).

Dans les tutoriels, on voit souvent qu'il faut filtrer les entrées. Ok, mais c'est une méthode, qui est un peu pénible est contraignante.
Si un utilisateur veut s'appeller <script>alert('hello')</script>, c'est son problème et pas le mien.

Mon idée est de récupérer les données de l'utilisateur sans les filtrer. La sauvegarde dans la base de données se faisant avec des requêtes préparés pour éviter l'injection SQL, mais là n'est pas le débat.

Le problème va venir des affichages des pages HTML. Afin d'avoir quelque chose qui fonctionne dans tous les cas, je vois trois endroit où d'afficher le contenu d'une variable :
- dans une page HTML (dans le contenu d'une balise, dans la valeur d'un attribut)
- dans un paramètre d'URL pour affichage en HTML
- dans un paramètre d'URL pour une redirection via un header("Location: ...")

J'ai donc développé les trois fonctions suivantes :
<?php
//echo for HTML output
function hecho($texte){
	echo htmlentities($texte,ENT_QUOTES,"UTF-8");
}

//echo for displaying URL
function uecho(array $param,$script = false){
	if (! $script){
		$script = $_SERVER['PHP_SELF'];
	}
	echo $script."?".http_build_query($param,'','&');
}

//redirecting
function redirect(array $param,$script){
	header("Location: $script?".http_build_query($param));
	exit;
}

Ainsi qu'un petit script pour tester tous ca :
<?php
$xss = "";
if (isset($_GET['xss'])){
	$xss = $_GET['xss'];
}

if (isset($_GET['redirect'])){
	unset($_GET['redirect']);
	redirect($_GET,$_SERVER['PHP_SELF']);
}

$redirect_args = $_GET;
$redirect_args['redirect'] = true;

header("Content-type: text/html; charset=UTF-8");
?>

Contenu de xss : <?php  hecho($xss); ?>
URL <a href='<?php uecho($_GET) ?>'>

<br/>
<?php uecho($_GET) ?></a>
<br/>
<img src='' alt='<?php  hecho($xss); ?>' title='<?php  hecho($xss); ?>'></img>
<br/>
<img src="" alt="<?php  hecho($xss); ?>" title="<?php  hecho($xss); ?>"></img>

<form>
	<input name='xss' value='<?php hecho($xss)?>' />
	<input type='submit'/>
</form>

<a href='<?php uecho($redirect_args) ?>'>redirect</a>

Si :
- j'enlève complètement tous les opérateurs echo, print, printf de mon site
- je les remplace par une l'appel à une des trois fonctions
- je valide tous de même les adresse emails ainsi que les URL
Alors :
- je suis définitivement protégé contre les attaques XSS
- je n'ai pas oublié de cas tordus

Merci de vos réponses éclairées.
--
Eric

ViPHP
ViPHP | 2577 Messages

23 juin 2011, 13:38

Bonjour,

Je me contente de traiter

- l'affichage de textes en remplacant les < et > par leur équivalent "& l t ;" et "& g t;". Ca supprime de problème des <script> </script>.

- l'affichage des attributs en remplacant les " par des \".

- je fait l'impasse sur les url qui ne me semble par trop dangereuse (à tord ?) mais uniquement source de bugs. L'url est un aussi attribut.

devlop78
Invité n'ayant pas de compte PHPfrance

24 juin 2011, 03:45

L'idée est pas mal, mais ne pas se reposer uniquement là dessus. Même si on sait que ça va être échappé, il est important d'identifier les sources dangereuses. L'exemple typique est celui du caractère nul dans une inclusion de fichier, ça peut provoquer de beaux dégats, et là, on peut toujours filtrer en entrée $_POST, $_GET, etc, mais il y aura toujours moyen de trouver une faille ;)

Eléphant du PHP | 209 Messages

24 juin 2011, 07:43

@Mazarini

A mon avis, les URL, c'est aussi dangereux que le reste, si tu fais un
$attribut = $_GET['attribut'];
?>
<a href='test.php?attribut=<?php echo $attribut?>'>test</a>
[php] 

tu va au devant de très mauvaise surprise ! ( '><script>alert('toto')</script> ) 

On dirais par contre qu'en mettant htmlspecialchars pour encoder l'URL ca fonctionne aussi, mais je ne pense pas que cela respecte les RFC ...

@develop78
[quote="devlop78"]L'exemple typique est celui du caractère nul dans une inclusion de fichier, ça peut provoquer de beaux dégats,[/quote]
C'est quoi cette faille ?
--
Eric

ViPHP
ViPHP | 2577 Messages

27 juin 2011, 15:07

Bonjour,

Dans un lien, l'url est un attribut, donc je remplace les " par des \". Si je mettais des simples quotes, je les remplacerai par des \'.