web-dev-qa-db-fra.com

Quand et pourquoi contourner les désinfectants XSS avec double codage fonctionne-t-il?

J'ai lu sur différents sites différentes façons de contourner les désinfectants XSS, comme le double codage de caractères spéciaux tels que /<>:"', ou en utilisant différents schémas de codage.

Cependant, la plupart de ces sites n'expliquent pas pourquoi ces attaques peuvent fonctionner et dans quels cas. Par exemple, je sais que les navigateurs modernes encodent les caractères spéciaux par URL, alors que cURL ne le fait pas; vous ne pouvez donc pas créer un PoC en utilisant cURL (ou Burp Proxy).

Quelqu'un peut-il donner une explication très détaillée sur la façon dont les navigateurs codent et gèrent les données d'entrée (les deux POST et GET) et comment une application Web (PHP) typique les gère? D'après ma petite expérience en PHP (alors que j'étais à l'université), j'accédais simplement à des paramètres comme $_POST["query"] sans même penser au codage, aux pratiques de sécurité, etc.

25
XII

Regardons cet exemple de charge utile (A), codé une fois (B) et deux fois (C):

A. <script> alert(1) </script>
B. %3Cscript%3E alert(1) %3C%2Fscript%3E
C. %253Cscript%253E alert(1) %253C%252Fscript%253E

Le double codage peut être utilisé pour contourner les filtres XSS lorsque différentes parties de l'application font des hypothèses différentes quant au codage ou non d'une variable. Par exemple, considérez le code vulnérable suivant:

$input = htmlentities($_GET["query"]);
echo urldecode($input);

Ce code bloquerait la charge utile s'il était codé simplement (comme dans B). PHP URL décode vos variables GET pour vous par défaut (en transformant B en A), donc < Et > Seraient passés à htmlentities qui les neutralise. Cependant, si vous envoyez C à la place, ce serait l'URL décodée en B qui passerait par htmlentities inchangé. Puisqu'il est à nouveau décodé avant d'être répété, il se transforme en la charge utile dangereuse A .

Donc, le bogue ici est qu'il existe une autre couche de décodage d'URL après le filtre XSS. Lorsque les deux lignes sont côte à côte comme ceci, le problème est assez évident. Mais ces deux choses peuvent être dans des modules séparés, ce qui rend la détection difficile. Comme il est difficile de garder une trace des chaînes qui sont encodées par URL, il est tentant de simplement ajouter un décodage supplémentaire pour être sûr - après tout, cela n'affecte généralement pas les données non encodées.

Le manuel PHP met en garde à ce sujet:

Attention: Les superglobaux $_GET Et $_REQUEST Sont déjà décodés. L'utilisation de urldecode() sur un élément dans $_GET Ou $_REQUEST Pourrait avoir des résultats inattendus et dangereux.

À mon avis, le manuel n'est pas assez prudent ici - décoder toutes les données non fiables après le filtrage pour XSS est dangereux, peu importe d'où il vient. Soyez extrêmement prudent lorsque vous modifiez vos données après les avoir filtrées!

Pour plus de lecture, voir OWASP .

33
Anders