WAF à travers les yeux des pirates

Aujourd'hui, nous allons parler de l'un des mécanismes de sécurité modernes pour les applications Web, à savoir le Web Application Firewall (WAF). Nous discuterons des WAF modernes et sur quoi ils sont basés, ainsi que des techniques de contournement, comment les utiliser et pourquoi vous ne devriez jamais vous fier entièrement aux WAF. Nous parlons du point de vue des pentesters; nous n'avons jamais développé de WAF et collecté uniquement des données à partir de sources ouvertes. Ainsi, nous ne pouvons que nous référer à notre propre expérience et ne pas être au courant de certaines particularités des WAF.




Avertissement: il s'agit d'une traduction de l'article du russe vers l'anglais, l'article a été publié fin 2017, respectivement, certaines informations pourraient devenir obsolètes.

Table des matières


  1. Présentation
  2. Le WAF moderne
  3. Identification du WAF
  4. Cheatsheet de contournement WAF
  5. Contournement WAF en pratique
  6. Conclusion

Si vous savez pourquoi les WAF sont utilisés et comment ils fonctionnent, vous pouvez passer directement à la section de contournement.

Présentation


Les WAF sont devenus très populaires récemment. Les fournisseurs proposent diverses solutions dans différentes gammes de prix, kits de distribution et options, ciblant différents clients, des petites aux grandes entreprises. Les WAF sont populaires car ils constituent une solution complexe pour la protection des applications Web, qui couvre un large éventail de tâches. C'est pourquoi les développeurs d'applications Web peuvent s'appuyer sur WAF pour certains aspects de sécurité. Cependant, les WAF ne peuvent pas garantir une sécurité totale.



Alors, de quoi un WAF devrait-il être capable de justifier sa mise en œuvre dans un projet? Sa fonction principale est de détecter et de bloquer toute demande qui, selon l'analyse du WAF, présente des anomalies ou un vecteur d'attaque. L'analyse ne doit pas entraver l'interaction entre les utilisateurs légitimes et l'application Web tout en détectant avec précision et en temps opportun toute tentative d'attaque. Afin de mettre en œuvre une telle fonctionnalité, les développeurs WAF utilisent des expressions régulières, des tokenizers, une analyse de comportement, une analyse de réputation et bien sûr un apprentissage automatique. Souvent, toutes ces technologies sont utilisées ensemble. WAF peut également implémenter d'autres fonctions: protection DDoS, interdiction des adresses IP des attaquants, surveillance des adresses IP suspectes, ajout d'en-têtes de sécurité (X-XSS-Protection, X-Frame-Options, etc.), ajout d'indicateurs http uniquement au cookie, mise en œuvre de le mécanisme HSTS et les jetons CSRF. En outre, certains WAF ont des modules côté client JavaScript pour les sites Web.

Bien sûr, les WAF créent des obstacles pour les pirates et les pentesters. WAF rend la recherche et l'exploitation de vulnérabilités plus gourmandes en ressources (sauf si l'attaquant connaît des méthodes de contournement 0day efficaces pour un WAF spécifique). Les scanners automatiques sont pratiquement inutiles lors de l'analyse des applications Web protégées par WAF. WAF est une protection fiable contre les «scriptkiddies». Cependant, un pirate expérimenté ou un chercheur sans motivation suffisante ne voudrait probablement pas perdre de temps à essayer de trouver des moyens de le contourner. Il convient de noter que plus l'application Web est complexe, plus sa surface d'attaque est grande et plus il est facile de trouver une méthode de contournement.

Lors de nos récents audits, nous trouvions assez souvent des WAF différents. Nous en reparlerons plus tard. Nous avons déjà testé deux WAF propriétaires dans deux scénarios principaux:

  • Nous savons qu'il existe une certaine vulnérabilité dans une application Web et nous essayons de contourner le WAF pour l'exploiter;
  • Nous ne connaissons aucune vulnérabilité, nous devons donc en trouver une malgré le WAF, puis l'exploiter en contournant le WAF.

Mais d'abord, regardons de plus près les mécanismes de base derrière WAF et voyons quels problèmes ils ont.

Le WAF moderne


Pour pouvoir trouver efficacement divers moyens de contourner le WAF, nous devons d'abord trouver des mécanismes modernes de classification des demandes. Chaque WAF est spécifique et unique, mais il existe des méthodes générales d'analyse. Jetons un coup d'oeil à ceux-ci.



Règles basées sur des expressions régulières


La majorité des WAF existants utilisent des règles basées sur des expressions régulières. Le développeur recherche un certain ensemble d'attaques connues pour identifier les structures syntaxiques clés qui pourraient pointer vers une attaque. Sur la base de ces données, le développeur crée des expressions régulières qui trouvent de telles structures syntaxiques. Cela semble simple, mais cette méthode présente certains inconvénients. Premièrement, une expression régulière peut être appliquée à une seule demande, voire à un seul paramètre de demande, ce qui réduit évidemment l'efficacité de ces règles et laisse des angles morts. Deuxièmement, la syntaxe des expressions régulières et la logique complexe des protocoles de texte, qui permet le remplacement de structures équivalentes et l'utilisation de différentes représentations de symboles, entraînent des erreurs lors de la création de ces règles.

Création de partitions


Ceux qui savent comment fonctionnent les pare-feu réseau et les antivirus doivent être familiarisés avec ce mécanisme. Il ne détecte pas les attaques mais complète d'autres mécanismes en les rendant plus précis et flexibles. Le fait est qu'une structure «suspecte» dans une demande n'est pas une condition suffisante pour détecter une attaque et peut conduire à de nombreux faux positifs. Ce problème est résolu en implémentant un système de classement. Chaque règle basée sur des expressions régulières est complétée par des informations sur sa criticité; une fois toutes les règles déclenchées identifiées, leur criticité est résumée. Si la criticité totale atteint la valeur seuil, l'attaque est détectée et la demande est bloquée. Malgré sa simplicité, ce mécanisme s'est avéré efficace et est largement utilisé pour de telles tâches.

Tokenizers


Cette méthode de détection a été présentée au Black Hat 2012 comme une libinjection de bibliothèque C / C +, qui permet d'identifier les injections SQL rapidement et avec précision. En ce moment, il existe de nombreux ports de libinjection pour différents langages de programmation, comme PHP, Lua, Python, etc. Ce mécanisme recherche les signatures présentées comme un ensemble de jetons. Un certain nombre de signatures sont sur liste noire, et elles sont jugées indésirables et malveillantes. En d'autres termes, avant qu'une requête ne soit analysée, elle est traduite en un ensemble de jetons. Les jetons sont divisés en certains types, comme variable, chaîne, opérateur régulier, inconnu, nombre, commentaire, opérateur de type union, fonction, virgule, etc. L'un des principaux inconvénients de la méthode est qu'il est possible de construire une structure qui conduirait à la formation incorrecte de jetons, donc la signature de la demande sera différente de celle attendue. Ces structures sont généralement appelées brise-jetons, et nous en discuterons plus tard

Analyse comportementale


La détection et le blocage des tentatives d'exploitation dans les requêtes ne sont pas la seule tâche des WAF. Il est également important d'identifier le processus de recherche de vulnérabilité et le WAF doit réagir en conséquence. Il peut se manifester sous forme de tentatives d'analyse, de force brute de répertoire, de fuzzing des paramètres et d'autres méthodes automatiques. Les WAF avancés peuvent créer des chaînes de requêtes typiques d'un comportement normal normal et bloquer les tentatives d'envoi de requêtes inhabituelles. Cette méthode ne détecte pas tant les attaques, car elle entrave le processus de recherche de vulnérabilité. Limiter le nombre de requêtes par minute n'affecterait pas un utilisateur habituel mais serait un sérieux obstacle pour les scanners, qui fonctionnent sur plusieurs threads.

Analyse de réputation


Il s'agit d'un autre mécanisme directement hérité des pare-feu et des antivirus. Aujourd'hui, presque tous les WAF incluent des listes d'adresses de VPN, d'anonymiseurs, de nœuds Tor et de botnets pour bloquer les demandes de ceux-ci. Les WAF avancés peuvent mettre à jour automatiquement leurs bases et les compléter avec des entrées supplémentaires en fonction du trafic analysé.

Apprentissage automatique


C'est l'un des aspects les plus discutables du WAF. Notons que le terme «machine learning» est assez large et comprend de nombreuses technologies et méthodes. De plus, ce n'est qu'une des classes de l'IA. «Mise en œuvre» de l'apprentissage automatique ou «utilisation de l'IA» sont des expressions marketing très populaires. Il n'est pas toujours clair quels algorithmes sont utilisés exactement, et parfois cela ressemble à du charabia. Les fournisseurs qui utilisent vraiment l'apprentissage automatique et le font efficacement ne sont pas disposés à partager leur expérience. Cela rend difficile pour un étranger d'essayer de comprendre la situation. Essayons néanmoins de faire quelques remarques sur la base des informations disponibles.

Premièrement, l'apprentissage automatique dépend entièrement des données sur lesquelles il a été formé, ce qui pose un certain problème. Un développeur doit disposer d'une base d'attaques complète et à jour, ce qui est difficile à réaliser. C'est pourquoi de nombreux développeurs enregistrent de manière approfondie les résultats de leurs WAF et coopèrent avec les fournisseurs fournissant des systèmes IDS et SIEM pour obtenir des exemples d'attaques réelles. Deuxièmement, un modèle formé sur une application Web abstraite peut s'avérer totalement inefficace sur une application Web réelle. Pour une meilleure qualité, il est recommandé de former en plus un modèle au stade de la mise en œuvre, qui nécessite beaucoup de ressources et de temps et n'accorde toujours pas les meilleurs résultats.

Identification du WAF


Les développeurs WAF utilisent différentes méthodes pour informer l'utilisateur que la demande a été bloquée. Ainsi, nous pouvons identifier le WAF en analysant la réponse à notre demande d'attaque. Ceci est généralement appelé WAF Fingerprint. Les empreintes digitales peuvent aider si un WAF n'est pas mis à jour pour une raison quelconque (s'applique principalement aux projets open source). Les développeurs de WAF propriétaires prennent soin de leurs clients et implémentent des mises à jour automatiques. De plus, une fois que nous avons identifié le WAF, qui s'est avéré être mis à jour, nous pouvons toujours utiliser les informations le concernant pour en savoir plus sur sa logique.

Voici une liste des empreintes digitales WAF possibles:

  • Cookies supplémentaires
  • En-têtes supplémentaires à toute réponse ou demande
  • Contenu de la réponse (en cas de demande bloquée)
  • Code de réponse (en cas de demande bloquée)
  • Adresse IP (Cloud WAF)
  • Module côté client JS (WAF côté client)

Illustrons-le avec quelques exemples

PT AF
Code de réponse pour la demande bloquée: 403
Peut insérer le module client waf.js dans la page de réponse
Corps de la réponse:

<h1>Forbidden</h1> <pre>Request ID: 2017-07-31-13-59-56-72BCA33A11EC3784</pre> 

Un en-tête supplémentaire qui ajoute par waf.js:

 X-RequestId: cbb8ff9a-4e91-48b4-8ce6-1beddc197a30 

Nemesida waf
Code de réponse pour la demande bloquée: 403
Corps de la réponse:

 <p style="font-size: 16px; align: center;"> Suspicious activity detected. Access to the site is blocked. If you think that is's an erroneous blocking, please email us at <a href="mailto:nwaf@pentestit.ru">nwaf@pentestit.ru</a> and specify your IP-address. </p> 

Wallarm
Code de réponse pour la demande bloquée: 403
En-tête supplémentaire: nginx-wallarm

Citrix NetScaler AppFirewall
Cookie supplémentaire:

 ns_af=31+LrS3EeEOBbxBV7AWDFIEhrn8A000; ns_af_.target.br_%2F_wat=QVNQU0VTU0lP TklEQVFRU0RDU0Nf?6IgJizHRbTRNuNoOpbBOiKRET2gA 

Mod_Security ver. 2.9
Code de réponse pour la demande bloquée: 403
Organe de réponse:

 <head> <title>403 Forbidden</title> </head><body> <h1>Forbidden</h1> <p>You don't have permission to access /form.php on this server.<br /></p> 

Mod_Security ver. <2,9
Code de réponse pour demande bloquée: 406 ou 501
Dans le corps de la réponse, vous pouvez trouver mod_security, Mod_Security ou NOYB

Pare-feu en vernis
Ajoute les en-têtes suivants à la réponse:

 X-Varnish: 127936309 131303037. X-Varnish: 435491096 Via: 1.1 varnish-v4 

Les développeurs WAF décident eux-mêmes du code de réponse à retourner en cas de demande bloquée; il existe également des codes spécifiques. Par exemple, Web_Knight WAF renvoie le code 999 et dotDefender renvoie le code 200 avec un corps de réponse vide ou avec un message d'erreur. En plus de cela, les développeurs peuvent créer une page de réponse personnalisée avec un autre contenu.

Le WAF, comme toute autre application, évolue et change. C'est pourquoi il est important de vérifier en permanence la pertinence des empreintes digitales que vous possédez.

Aide-mémoire de contournement WAF


L'idée générale derrière la recherche de moyens de contourner le WAF est de transformer la demande dont nous avons besoin afin qu'elle soit toujours valide pour l'application Web mais pas pour le WAF ou semble inoffensive. Il est important qu'un type de WAF puisse servir de nombreux types de serveurs différents, y compris les serveurs «exotiques», comme Unicorn, Tornado, Weblogic, Lighttpd, etc. Chaque serveur peut percevoir des cas exclusifs d'analyse de requête HTTP d'une manière différente, qui doit également être prise en compte par WAF. Ainsi, un attaquant peut utiliser les spécificités des serveurs de l'analyse des requêtes HTTP pour trouver un moyen de contourner le WAF.



Il est difficile de classer toutes les manières possibles de contourner WAF, soit par les mécanismes de sécurité WAF, soit par domaine d'utilisation. Les mêmes voies de contournement peuvent interagir et affecter simultanément différents composants d'un WAF. Les techniques décrites ci-dessous ont été collectées à partir de sources ouvertes ou découvertes lors de nos propres recherches et se sont avérées parmi les plus efficaces.

Ajout de symboles spéciaux


Divers symboles spéciaux peuvent violer la logique d'analyse d'un WAF et en même temps être valablement interprétés par le serveur. Les variations de ces symboles peuvent être différentes: ils peuvent être transformés en urlencode (bien que la plupart des WAF puissent gérer cela) ou d'autres encodages. Il est également possible d'insérer des symboles spéciaux dans une requête sans aucun encodage, au format brut, ce qui peut surprendre un WAF. Par exemple, \ r \ n \ r \ n dans cette présentation peut être perçu comme la fin d'un corps de requête HTTP, et l'octet nul peut violer la logique d'analyse des expressions régulières et des analyseurs de données. De plus, d'autres symboles spéciaux des vingt premiers symboles de la table ASCII peuvent être utiles.
Exemples:

  • 0x00 - octet nul;
  • 0x0D - Retour chariot;
  • 0x0A - Saut de ligne;
  • 0x0B - Onglet vertical;
  • 0x09 - Onglet horizontal;
  • 0x0C - Nouvelle page

Lors de la recherche d'un contournement, il est utile d'insérer des symboles spéciaux à différents endroits du corps de la demande et pas seulement dans les valeurs des paramètres. Par exemple, si une demande est au format JSON, nous pouvons insérer des octets NULL à la fois dans un paramètre et entre les paramètres, à la fois au début et à la fin de JSON. Il en va de même pour les autres formats du corps d'une requête POST. En général, nous vous recommandons de faire des recherches et de vous amuser, de rechercher des endroits qui peuvent être surveillés et analysés par WAF, et d'essayer d'utiliser différents symboles spéciaux là-bas.

Par exemple:

 {"id":1337,"string0x00":"test' or sleep(9)#"} {"id":1337,"string":"test'/*0x00*/ or sleep(9)#"} {"id":1337,"string"0x0A0x0D:"test' or sleep(9)#"} 

 <a href="ja0x09vas0x0A0x0Dcript:alert(1)">clickme</a> <a 0x00 href="javascript:alert(1)">clickme</a> <svg/0x00/onload="alert(1)"> 

 id=1337/*0x0C*/1 UNION SELECT version(), user() -- 

Pour plus de clarté, nous avons remplacé les symboles spéciaux par leur présentation hexadécimale.

Remplacement des symboles d'espace


Dans la plupart des syntaxes, les mots clés et les opérateurs doivent être séparés, mais les symboles d'espace préférables ne sont pas spécifiés. Ainsi, au lieu du 0x20 commun (espace), vous pouvez utiliser 0x0B (onglet vertical) ou 0x09 (onglet horizontal). Remplacer les espaces par des structures de division sans leur propre sens tombe dans la même catégorie. En SQL, il s'agit de / ** / (commentaires SQL sur plusieurs lignes), # \ r \ n (commentaire SQL sur une ligne, se terminant par un saut de ligne), - \ r \ n (commentaire SQL alternatif sur une ligne, se terminant avec saut de ligne). Voici quelques exemples:

 http://test.com/test?id=1%09union/**/select/**/1,2,3 http://test.com/test?id=1%09union%23%0A%0Dselect%2D%2D%0A%0D1,2,3 

De plus, nous pouvons transformer une expression pour se débarrasser des espaces en utilisant la syntaxe du langage. Par exemple, en SQL, nous pouvons utiliser des parenthèses:

 UNION(SELECT(1),2,3,4,5,(6)FROM(Users)WHERE(login='admin')) 

Et dans JS, utilisez / :

 <svg/onload=confirm(1)> 

Changer l'encodage


Cette méthode est basée sur l'utilisation de différents encodages pour empêcher WAF de décoder les données à certains endroits. Par exemple, si un symbole est remplacé par son code URL, WAF ne pourra pas comprendre qu'il doit décoder les données et transmettra la demande. Dans le même temps, le même paramètre sera accepté et décodé avec succès par l'application Web.

La forme décimale d'un symbole HTML est & # 106 ou & # 0000106 .WAF peut connaître la version courte et ne pas connaître la version avec des zéros supplémentaires (il ne doit pas y avoir plus de 7 symboles au total). De la même manière, la forme hexadécimale d'un symbole HTML est & # x6A ou & # x000006A .

Il y a aussi une astuce avec les caractères d'échappement avec une barre oblique inverse \ , par exemple:

 <svg/on\load=a\lert(1)> 

Cependant, cela dépend de la façon dont une application Web traite ces données d'entrée. Ainsi, la séquence \ l sera traitée comme un l et transformée en un seul symbole; WAF peut traiter chaque symbole séparément et il peut rompre les expressions régulières ou une autre logique WAF. Ainsi, WAF manquera les mots-clés. En utilisant cette technique, nous ne pouvons pas échapper les caractères \ n , \ r , \ t , car ils seront transformés en différents caractères: nouvelle ligne, retour chariot et tabulation.

Le codage HTML peut être utilisé à l'intérieur des attributs de balise, par exemple:

 <a href="javascript&colon;alert(1)">clickme</a> <input/onmouseover="javascript&colon;confirm&lpar;1rpar;"> 

Ces caractères peuvent être facilement remplacés par une autre représentation HTML des caractères cibles. Vous pouvez rechercher différentes transformations de personnages ici .

Outre le codage HTML, nous pouvons insérer des caractères avec \ u :

 <a href="javascript:\u0061lert(1)">Clickme</a> <svg onload=confir\u006d(1)> 

Examinons également le vecteur lié à l'insertion de caractères spéciaux. Brisons la charge utile avec le codage HTML:

 <a href="ja&Tab;vas&#x0000A;cript:alert(1)">clickme</a> 

Dans ce cas, nous pouvons également placer d'autres caractères de séparation.

Ainsi, nous vous recommandons de combiner différents encodages avec d'autres méthodes, par exemple, pour encoder des caractères spéciaux.

Recherche de structures syntaxiques équivalentes atypiques


Cette méthode vise à trouver un mode d'exploitation non pris en compte par les développeurs de WAF, ou un vecteur qui n'était pas présent dans l'échantillon d'apprentissage du machine learning. Des exemples simples seraient les fonctions JavaScript: this, top self, parent, frames; attributs de balise: liaison de données, ontoggle, onfilterchange, onbeforescriptexecute, onpointerover, srcdoc; et opérateurs SQL: lpad, field, bit_count .

Voici quelques exemples:

 <script>window['alert'](0)</script> <script>parent['alert'](1)</script> <script>self['alert'](2)</script> 

 SELECT if(LPAD(' ',4,version())='5.7',sleep(5),null); 

Vous pouvez également utiliser la représentation non symbolique des expressions JavaScript:


Un problème évident avec cela est de longues charges utiles.

Le contournement WAF avec cette technique dépend de l'attaque et de la pile de technologies exploitée. Le célèbre exploit ImageTragick en est un bon exemple. La plupart des WAF qui protègent contre cette attaque avaient des mots-clés sur liste noire comme URL , capacité et étiquette, car ces mots étaient mentionnés dans la majorité des articles et des PoC décrivant cette vulnérabilité. Bien qu'il ait été bientôt révélé que d'autres mots clés peuvent également être utilisés, par exemple, éphémère et pango . Par conséquent, les WAF pourraient être contournés avec l'utilisation de ces mots clés.

Pollution des paramètres HTTP (HPP) et fragmentation des paramètres HTTP (HPF)


L'attaque HPP est basée sur la façon dont un serveur interprète les paramètres avec les mêmes noms. Voici quelques contournements possibles:

  • Le serveur utilise le dernier paramètre reçu et WAF ne vérifie que le premier;
  • Le serveur unit la valeur des paramètres similaires et WAF les vérifie séparément.

Vous pouvez comparer la façon dont différents serveurs traitent les mêmes paramètres dans le tableau ci-dessous:



À son tour, l'attaque HPF est basée sur un principe différent. Si la logique d'une application Web réunit deux paramètres ou plus dans une demande, l'adversaire peut diviser la demande pour contourner certaines vérifications WAF.
L'injection SQL suivante est un exemple d'une telle attaque:

 http://test.com/url?a=1+select&b=1+from&c=base 

HPF et HPP sont très similaires, mais le premier cible une application Web et le second l'environnement dans lequel elle fonctionne. La combinaison de ces techniques augmente les chances de contourner un WAF.

Normalisation Unicode


La normalisation Unicode est une fonctionnalité d'Unicode destinée à comparer les symboles Unicode qui se ressemblent. Par exemple, les symboles «ª» et «ᵃ» ont des codes différents mais sont très similaires dans le cas contraire, donc après normalisation, ils ressembleront tous les deux à un simple «a» et seront considérés comme identiques. La normalisation permet de transformer certains symboles Unicode complexes en leurs alternatives plus simples. Il existe une table de normalisation Unicode avec tous les symboles Unicode et leurs normalisations possibles. En l'utilisant, vous pouvez créer différentes charges utiles et les combiner avec d'autres méthodes. Cependant, cela ne fonctionne pas pour toutes les applications Web et est très dépendant de l'environnement.

Par exemple, dans le tableau ci-dessus, nous pouvons voir que les symboles et transforment en simple < . Si une application utilise le codage HTML après la normalisation, il est fort probable que le symbole normalisé < sera codé dans &lt; . Mais, dans d'autres cas, les développeurs peuvent avoir ignoré cette fonctionnalité et non codé les symboles Unicode. Ainsi, nous obtenons des symboles non codés HTML < et > , qui peuvent être transformés en attaque XSS. WAF peut avoir du mal à comprendre les symboles Unicode - il peut tout simplement ne pas avoir de règles pour de telles astuces, et l'apprentissage automatique peut également être inutile. Tout en trouvant un contournement dans les applications Web avec la normalisation Unicode, nous pouvons remplacer non seulement <> mais aussi d'autres symboles de la charge utile.

Par exemple:

 <img src﹦x onerror=alert︵1)> 

Récemment, ce problème a été trouvé dans le programme Rockstar BugBounty de HackerOne. Il n'y avait pas de WAF, seulement un filtrage strict des entrées utilisateur:

hackerone.com/reports/231444
hackerone.com/reports/231389

Brise-jetons


Les attaques contre les tokenizers tentent de briser la logique de la division d'une requête en tokens à l'aide des soi-disant disjoncteurs de token. Les disjoncteurs de jetons sont des symboles qui permettent d'affecter la correspondance entre un élément d'une chaîne et un certain jeton, et ainsi de contourner la recherche par signature. Mais lors de l'utilisation du disjoncteur de jeton, la demande doit rester valide. La demande suivante est un exemple d'attaque utilisant un disjoncteur de jeton

 SELECT-@1,version() 

- @ est le disjoncteur de jeton.

Il y a une feuille de déchiffrage qui a été acquise par fuzzing mysql et en vérifiant les résultats dans libinjection.

En savoir plus sur la recherche de problèmes dans la libinjection:

Un autre flou
Fuzz à contourner
Comment contourner la libinjection

Utilisation des fonctionnalités de RFC


Dans les spécifications du protocole HTTP / 1.1 et de divers types de requêtes (par exemple multipart / form-data), nous pouvons trouver des choses curieuses liées aux cas limites et aux astuces de traitement des en-têtes et des paramètres. Les développeurs WAF ne prennent souvent pas en compte de tels problèmes, par conséquent, un WAF peut analyser une demande de manière incorrecte et manquer la partie des données, où un vecteur d'attaque est masqué. La plupart des problèmes dans les WAF sont liés au traitement des données en plusieurs parties / formulaires et aux valeurs spécifiques du paramètre de limite, qui spécifie les limites de paramètre dans de telles demandes. En plus de cela, les développeurs de serveurs peuvent également se tromper et ne pas prendre entièrement en charge les spécifications, il peut donc y avoir des fonctionnalités non documentées dans l'analyseur HTTP d'un serveur.

Dans une requête HTTP avec multipart / form-data, la limite des paramètres est en charge de la ségrégation des différents paramètres dans le corps d'une requête. Selon la RFC, une frontière précédemment spécifiée avec un préfixe contenant "-" doit être placée avant chaque nouveau paramètre POST, afin que le serveur soit capable de discriminer les différents paramètres d'une demande.

 POST /vuln.php HTTP/1.1 Host: test.com Connection: close Content-Type: multipart/form-data; boundary=1049989664 Content-Length: 192 --1049989664 Content-Disposition: form-data; name="id" 287356 --1049989664-- 

L'attaque peut également être basée sur le fait qu'un serveur et un WAF gèrent différemment une situation où la frontière est laissée vide. Selon la RFC, dans ce cas, «-» est la frontière entre les paramètres. Néanmoins, un WAF peut utiliser un analyseur qui ne tient pas compte de cela, et, par conséquent, le WAF passera la demande parce que les données des paramètres d'une demande POST n'apparaîtraient pas dans l'analyseur. Le serveur Web peut analyser une telle demande sans problème et remettre les données pour un traitement ultérieur.
Voici quelques exemples plus intéressants.

 POST /vuln.php HTTP/1.1 Host: test.com Connection: close Content-Type: multipart/form-data; boundary= Content-Length: 192 -- Content-Disposition: form-data; name="id" 123' or sleep(20)# ---- 

Nous donnerons quelques exemples plus intéressants des diapositives de Bo0oM à ZeroNights 2016 et l'expliquerons:

 POST /vuln.php HTTP/1.1 Host: test.com Content-Type: multipart/form-data; boundary=FIRST; Content-Type: multipart/form-data; boundary=SECOND; Content-Type: multipart/form-data; boundary=THIRD; --THIRD Content-Disposition: form-data; name=param UNION SELECT version() --THIRD-- 

Dans cette attaque, nous essayons de définir lequel des paramètres de limite sera accepté par le WAF et lequel par le serveur Web. Ainsi, s'ils acceptent différents paramètres, il est possible d'effectuer une attaque en spécifiant une limite que le WAF ne verra pas. Cette attaque est un peu comme HPP.

 POST /vuln.php HTTP/1.1 Host: test.com Content-Type: multipart/form-data; xxxboundaryxxx=FIRST; boundary=SECOND; --FIRST Content-Disposition: form-data; name=param UNION SELECT version() --FIRST-- 

Cette attaque est basée sur l'hypothèse qu'il existe une différence dans l'analyse d'une demande HTTP par le WAF et par le serveur Web. À savoir, l'analyseur du serveur Web recherche la première entrée «limite», puis le symbole «=», et seulement après cela définit la valeur de limite. L'analyseur WAF, à son tour, ne recherche que l'entrée «limite =», puis définit la limite. Si ces conditions sont remplies, le WAF ne trouvera pas la limite dans la demande et ne pourra donc pas trouver et analyser le paramètre. Au contraire, le serveur Web recevra la demande et traitera le paramètre. Cette attaque fonctionnera également dans l'autre sens: l'analyseur du serveur Web recherche «limite =» et l'analyseur WAF ne recherche que «limite». Dans ce cas, nous n'aurons qu'à changer la frontière réelle de FIRST à SECOND.

 POST /somepage.php HTTP/1.1 Host: test.com Content-Type: multipart/form-data; boundary=Test0x00othertext; --Test Content-Disposition: form-data; name=param Attack --Test-- 

Cette attaque utilise également des caractères spéciaux. Dans le paramètre de limite, nous avons ajouté NULL-byte afin que le serveur Web le coupe, mais le WAF l'accepte dans son intégralité. Dans ce cas, WAF ne peut pas analyser le paramètre car il ne peut pas trouver ses limites.

Contourner l'apprentissage automatique


La logique est simple: nous devons composer une attaque qui satisferait les paramètres du modèle statistique entraîné. Mais cela dépend fortement de la façon dont le WAF a été formé et du modèle de formation utilisé. Parfois, il est possible de trouver une échappatoire, et parfois ce n'est pas le cas. Habituellement, au stade de la mise en œuvre, un WAF avec apprentissage automatique nécessite une formation supplémentaire basée sur la demande adressée à l'application Web du client. Cela pose un problème pour les pentesters: les paramètres qui se ressemblent et ne changent pas beaucoup d'une demande à l'autre ne peuvent pas être testés, car toute digression à partir de la forme de paramètre habituelle serait considérée comme une anomalie. Disons que nous devons demander à api.test.com/getuser?id=123 . L'ID de paramètre est toujours numérique et il était numérique dans l'exemple d'apprentissage. Si le module d'apprentissage automatique trouve autre chose que des nombres dans ce paramètre, il décidera très probablement qu'il s'agit d'une anomalie. Un autre exemple: supposons que WAF ait été formé pour classer la demande POST sur api.test.com/setMarkDown avec des paramètres POST contenant du texte de démarque. De toute évidence, il peut y avoir des guillemets, des symboles spéciaux et essentiellement n'importe quoi dans le démarque. Dans ce cas, il est beaucoup plus facile de contourner le module d'apprentissage automatique car le WAF tolère les guillemets et les symboles spéciaux.

De plus, sur les exemples de notre pratique, nous montrerons qu'il ne va pas toujours aussi loin que le module d'apprentissage automatique en raison des problèmes d'analyse des paramètres causés par les méthodes de contournement décrites ci-dessus.

En général, nous devons considérer les spécificités d'une demande testée et ses paramètres, présumer toutes les options possibles des valeurs des paramètres, auxquelles WAF peut être tolérant, et s'appuyer sur celles-ci.

Quand WAF est inutile?


WAF analyse les requêtes et recherche les comportements anormaux, mais il existe certaines classes de vulnérabilités qu'il ne peut pas découvrir. Par exemple, les vulnérabilités logiques, qui n'ont pas d'anomalies mais ont des actions qui perturbent la logique d'une application Web. Très probablement, WAF serait également inutile en cas de condition de concurrence, d'IDOR et d'authentification utilisateur non sécurisée.

Utilitaires existants


Il existe des outils automatiques pour trouver les contournements WAF, écrits par les passionnés de ce domaine. Voici les plus célèbres et les plus dignes:

lightbulb-framework - un framework complet pour tester des applications web protégées avec WAF. Il est écrit sur Python et est également porté en tant que plugin pour Burp Suite. Ses principales caractéristiques sont ces deux algorithmes:

  • GOFA - un algorithme d'apprentissage automatique actif qui permet d'analyser la filtration et la désinfection des paramètres dans une application Web.
  • SFADiff - algorithme de test de boîte noire déférent, basé sur la formation avec des automates finis symboliques (SFA). Il permet de trouver des différences dans le comportement des applications Web, ce qui aide à identifier le WAF et à trouver un contournement.

Bypass WAF - un plugin pour Burp Suite, qui permet de configurer la modification automatique des éléments dans le corps d'une demande selon différentes règles et modifications de codage. Il peut également automatiser une attaque HPP.

WAFW00F - un outil d'identification WAF, écrit sur Python. Il a une base WAF décente et est toujours en cours de mise à jour. Cependant, les résultats peuvent être imprécis car de nombreux WAF sont mis à jour plus fréquemment que le projet lui-même.

Contournement du waf en pratique




Nous avons effectué un test de pénétration d'une boutique en ligne, qui était protégée par PT AF (Positive Technologies Application Firewall). Il était difficile de trouver un point faible, qui pourrait être une base pour une dérivation. Mais bientôt, nous avons découvert un comportement inhabituel du côté de l'application Web, qui n'a pas été filtré par le WAF. L'anomalie a été trouvée dans la recherche dans l'histoire des biens achetés. La demande a été envoyée au format JSON et ressemblait à ça:

 {"request":{"Count":10,"Offset":0,"ItemName":"Phone"}} 

Nous avons placé les valeurs Phone ' et Phone' + ' dans le paramètre ItemName et constaté que le serveur renvoyait des réponses différentes pour ces deux demandes. Dans le premier cas, la réponse était vide; dans le second cas, il contenait des données sur d'autres marchandises avec le mot Phone dans leur nom, comme si le paramètre ItemName avait Phone comme valeur. Ce type de comportement est bien connu des pirates et des pentesters et indique que l'application a un problème avec la filtration des entrées utilisateur, ce qui entraîne entre autres l'injection SQL.

Voyons pourquoi cela se produit avec un exemple d'injection SQL. Si un tel comportement se trouve dans une application Web, il est fort probable que les données d'une demande SQL soient en concaténation avec la demande elle-même. Dans le premier cas, avec le paramètre Phone , nous aurons la requête SQL suivante:

 SELECT item FROM items WHERE item_name='Phone'' 

De toute évidence, il ne sera pas exécuté en raison d'une syntaxe incorrecte et ne retournera aucun résultat. La deuxième demande, avec le paramètre Phone '+' , ressemblera à ceci:

 SELECT item FROM items WHERE item_name='Phone'+'' 

Sa syntaxe est correcte, il sélectionnera donc les marchandises sous le nom de Téléphone . Cette méthode de détection des vulnérabilités présente un énorme avantage lors du test d'une application web protégée par WAF. Le symbole de guillemet simple n'est pas considéré comme une anomalie suffisante dans un paramètre par la plupart des WAF modernes, ils transmettent donc une demande avec.

Nous avons décrit la détection de vulnérabilité, mais qu'en est-il de contourner WAF et d'exploiter la vulnérabilité? Après avoir traversé quelques contournements, nous avons trouvé un problème dans le WAF. Il s'est avéré que ce WAF est vulnérable aux caractères spéciaux ajoutés aux paramètres JSON. En fait, si nous ajoutions les symboles JSON 0x0A, 0x0D (\ r \ n ou carrige reutrn et nouvelle ligne) au format brut, sans aucun codage, dans un champ de texte, le WAF le transmettrait et l'application Web le considérerait comme être correct et le traiter. Très probablement, le problème était dans l'analyseur JSON, qui n'était pas fait pour les symboles spéciaux et analysait JSON jusqu'à un endroit où ces symboles apparaîtraient. Ainsi, l'analyseur WAF n'obtiendrait pas la demande complète, nous pourrions donc insérer n'importe quel vecteur d'attaque après des caractères spéciaux. Outre le saut de ligne, d'autres caractères (par exemple NULL-byte) fonctionneraient également. En conséquence, nous pourrions écrire la demande suivante, qui désactiverait le WAF alors qu'il tentait de vérifier cette demande (le saut de ligne et le retour chariot ont été remplacés par leur représentation textuelle):

 {"request":{"kill-waf":"die0x0A0x0D", "Count":10,"Offset":0,"ItemName":["'+(SELECT 'Phone'+CHAR(ASCII(substring(@@version,1,1))-24))+'"]}} 

0x0A et 0x0D est un octet brut.

Ainsi, nous avons pu tester facilement et rapidement tous les paramètres pour toutes les vulnérabilités (deux d'entre eux ont été trouvés dans d'autres paramètres). Le contournement de WAF et l'exploitation de cette injection nous ont permis de compromettre totalement tous les utilisateurs de l'application Web.

Les mêmes problèmes ont également été constatés dans Nemesida WAF . La seule différence est que la demande n'était pas en codage JSON, mais c'était une demande POST habituelle avec des paramètres, et un paramètre a été concédé à la requête SQL sous forme de nombre. Si certains symboles ont été placés dans une demande en code URL, par exemple, % 03% 04, alors WAF bloque une demande, mais si les symboles ont été placés sous forme brute sans encodage URL, WAF ignore cette demande. Il convient de noter que l'expression SQL normale a été placée pour demander ainsi que dans le WAF précédent. L'expression SQL était un simple «UNION SELECT» sans aucune obfuscation supplémentaire, ce qui signifie que WAF ne pouvait tout simplement pas analyser correctement la demande et continuer l'analyse. Mais il y a un problème - comment rendre la syntaxe de requête SQL correcte? Parce que l'utilisation de caractères spéciaux comme % 03% 04 dans la requête SQL n'est pas correcte. La réponse est simple - nous avons juste besoin d'utiliser les commentaires / ** /. Ainsi, la demande de résultat ressemblait à:

 /*0x03 0x04*/1 UNION SELECT version(), user() -- 

0x03 et 0x04 est un octet brut.

En outre, un autre problème a été détecté dans Nemesida WAF. Il était lié à un traitement incorrect des demandes POST avec des données en plusieurs parties / formulaires. Comme nous l'avons décrit ci-dessous, dans une requête HTTP avec multipart / form-data, la frontière des paramètres est en charge de la ségrégation des différents paramètres dans le corps d'une requête. Selon la RFC, une frontière précédemment spécifiée avec un préfixe contenant "-" doit être placée avant chaque nouveau paramètre POST, afin que le serveur soit capable de discriminer les différents paramètres d'une demande.
Le problème était donc que le serveur et le WAF géraient la situation différemment lorsque le paramètre de limite était vide. Sur la base de la RFC, dans une telle situation, la frontière entre les paramètres sera une séquence de caractères «-» . Cependant, WAF a utilisé un analyseur qui ne prend pas en compte cette fonctionnalité, c'est pourquoi WAF transmet à nouveau la demande, car les données des paramètres de demande POST ne sont tout simplement pas entrées dans le module d'analyseur et le serveur a analysé cette situation sans aucun problème. et transféré les données à la suite du traitement. Voici un exemple de demande pour cette attaque:

 POST /wp-content/plugins/answer-my-question/modal.php HTTP/1.1 Host: example.com Content-Type: multipart/form-data; boundary= Content-Length: 209 -- Content-Disposition: form-data; name="id" 1 UNION SELECT 1,2,3,CONVERT(version() USING utf8) AS name,CONVERT(user() USING utf8) AS name,6,7,8,9,10,11,12 FROM wp_users WHERE id=1 ---- 

Les deux problèmes ont été signalés à Pentestit, les gars ont payé une récompense pour leur programme de primes de bogues pour Nemesida WAF, et ont corrigé les problèmes dès que possible. Merci pour cela.

Comme nous pouvons le voir, les WAF peuvent être modernes et intelligents, mais il est parfois possible de les contourner simplement en ajoutant un seul caractère spécial. Aujourd'hui, nous ne pouvons pas prévoir tous les types de données d'entrée possibles pour tous les serveurs au stade du développement, et l'apprentissage automatique, mis en œuvre pour faire exactement cela, tombe sur des analyseurs qui se retrouvent coincés avec des caractères spéciaux.

Conclusion


Alors, devons-nous nous reposer entièrement sur WAF? La réponse est NON.

Dans l'un de nos audits, nous avons découvert un contournement WAF qui nous a permis d'exploiter certaines vulnérabilités. Il s'est avéré que les développeurs avaient déjà effectué un audit de l'application Web, avant qu'elle ne soit protégée par WAF, et qu'elle révélait les mêmes vulnérabilités. Au lieu de les réparer, ils ont décidé d'acheter un WAF moderne équipé de machine learning. Il est dommage que le fournisseur du WAF n'ait pas insisté pour corriger d'abord les vulnérabilités; ou peut-être que les développeurs eux-mêmes pensaient que le WAF serait une meilleure option. Nous ne savons cependant pas avec certitude. Quoi qu'il en soit, c'est un exemple d'une très mauvaise pratique, de la part des développeurs et du fournisseur. Il convient également de noter que l'apprentissage automatique est toujours une boîte noire et ressemble plus à un dispositif de marketing qu'à une véritable défense.

En général, WAF est une solution de sécurité moderne, et cela ne fera pas de mal de l'avoir avec vos applications Web. Bien qu'aujourd'hui, il ne peut qu'entraver le processus de recherche et d'exploitation des vulnérabilités, mais il ne peut pas les protéger complètement. Dans l'état actuel des choses, c'est l'état de l'art depuis un bon moment. Les vulnérabilités dans les applications Web ne peuvent être corrigées qu'en corrigeant le code qui leur est associé, et c'est la seule solution infaillible.

Contributeurs

Ilia Bulatov barracud4
Denis Rybin thefaeriedragon
Alexander Romanov web_rock

Source: https://habr.com/ru/post/fr454592/


All Articles