L'échec du filtrage HTML

(c) News0ft

Ok, alors j’en croise encore qui tentent de filtrer des XSS à coup d’expressions régulières… donc de parser du HTML avec des expressions régulières… non content de tuer des chatons et de rendre fou les gens sur stackoverflow et on croise souvent des WAF et autres dispositifs qui possèdent de superbes regexps épiques qui matchent pas mal de vecteurs de XSS et le bon vieux alert().

C’est clairement une approche qui est vouée à l’échec, d’une si l’on se réfère à ce fameux post de StackOverflow la réponse qui suit le texte fleuve apporte une vrai réponse scientifique au problème :

« HTML is a Chomsky Type 2 grammar (context free grammar) and RegEx is a Chomsky Type 3 grammar (regular expression) »

Alors allez tous réviser vos cours de théorie du langage et n’uttilisez plus de regexp pour parser du HTML… programmez plutôt votre propre parseur, ou utilisez des librairies déjà faites pour ça.

Pour ceux qui n’ont pas eu la chance d’avoir ce type d’enseignement, je vais essayer de vous expliquer pourquoi c’est pourri avec un exemple simple (sous réserve que j’arrive à inclure du code dans la nouvelle interface fancy classe de blogger >.< ).

Prenons le cas récent des data URI accepté dans les navigateurs modernes :

<object data= »data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg== »></object>

Si on vous demande d’écrire une expression régulière pour détecter une attaque par xss basée sur ça… vous allez probablement tenter de matcher sur data:text/html ? ou de matcher sur le tag object ? ou sur le blob base64 ? mais hélas ces foutus URI acceptent par exemple des échappement de type htmlentity genre &colon à la place du : , il est aussi possible de placer du bourrage à différents endroits de la data URI histoire de bien pourrir votre pattern matching… bourrage qui dépend du navigateur (plus particulièrement du parser chargé d’interpréter les data URI). Un bourrage similaire pourra être placé autour ou dans le nom du tag, pour là encore vous compliquer un peu plus la tâche.

Là ou les choses deviennent carrément atroces, c’est si jamais votre application fait usage des balises object (genre pour du flash ? oui la pratique limite toujours la théorie…) et/ou contient parfois des blobs base64 parce-que c’est bien pratique aussi. Il vous faudra donc analyser les paramètres des balises <OBJECT> en fonction de leur contexte d’utilisation. Sans compter qu’il vous faudra écrire une expression régulière similaire pour tous ces foutus vecteurs de XSS.

On imagine assez vite la complexité (et la maintenabilité) de l’expression en question croître à mesure que de nouvelles fonctionnalités et de nouveaux bugs de parsing sont ajoutés/découverts dans nos chers navigateurs. Et je ne vous parle même pas des problèmes de performances qui vous forcerons à monter des clusters de cartes graphiques pour traiter les flux de vos sites de prod. C’est d’ailleurs ce constat qui est à l’origine de l’approche de NAXSI

Ceux qui font de la validation de pages web pour du test fonctionnel ont vite compris qu’il ne servait à rien de vouloir valider la structure des documents html avec une telle approche, et se sont rapidement tourné vers l’utilisation de moteurs HTML pour analyser les pages web. Et des gens très compétents ont vite compris qu’il fallait écrire des parseurs dédiés pour pouvoir effectuer de la détection d’intrusion (entre autre) sur HTTP, et non se reposer sur des expressions régulières.

D’autres ont compris qu’il était plus rentable d’investir dans la qualité du code de leurs applications et qui intègrent directement les fonctions WAF dans leur librairies de contrôle… mais bon ça veut dire investir sur l’humain dont on connait les limites et dont on à du mal à maitriser le budget, et non acheter une boite magique pleine de promesses à coût fixe.

Sinon pour ceux qui cherchent un bon bouquin sur l’évasion de filtres en général dans le monde du web je vous conseille l’excellent web application obfuscation qui traite de façon très détaillée les différentes techniques permettant d’échapper à ces foutus regexps.

Prochain billet j’vous parle de JavaScript…