Parameter Pollution | JSON Injection

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

HTTP Parameter Pollution (HPP) - Resumen

HTTP Parameter Pollution (HPP) es una técnica donde los atacantes manipulan parámetros HTTP para cambiar el comportamiento de una aplicación web de maneras no previstas. Esta manipulación se realiza añadiendo, modificando o duplicando parámetros HTTP. El efecto de estas manipulaciones no es directamente visible para el usuario pero puede alterar significativamente la funcionalidad de la aplicación en el lado del servidor, con impactos observables en el lado del cliente.

Ejemplo de HTTP Parameter Pollution (HPP)

Una URL de transacción de una aplicación bancaria:

  • Original URL: https://www.victim.com/send/?from=accountA&to=accountB&amount=10000

Al insertar un parámetro from adicional:

  • Manipulated URL: https://www.victim.com/send/?from=accountA&to=accountB&amount=10000&from=accountC

La transacción podría cobrarse incorrectamente a accountC en lugar de a accountA, mostrando el potencial de HPP para manipular transacciones u otras funcionalidades como restablecimientos de contraseña, ajustes de 2FA o solicitudes de API key.

Parseo de parámetros específico por tecnología

  • La forma en que se analizan y priorizan los parámetros depende de la tecnología web subyacente, lo que afecta cómo se puede explotar HPP.
  • Herramientas como Wappalyzer ayudan a identificar estas tecnologías y sus comportamientos de parseo.

PHP y explotación de HPP

Caso de manipulación de OTP:

  • Contexto: Se explotó un mecanismo de login que requería un One-Time Password (OTP).
  • Método: Interceptando la solicitud de OTP usando herramientas como Burp Suite, los atacantes duplicaron el parámetro email en la petición HTTP.
  • Resultado: El OTP, destinado al email inicial, se envió en su lugar a la segunda dirección de email especificada en la petición manipulada. Esta falla permitió acceso no autorizado al eludir la medida de seguridad prevista.

Este escenario destaca una negligencia crítica en el backend de la aplicación, que procesó el primer parámetro email para la generación del OTP pero usó el último para la entrega.

Caso de manipulación de API Key:

  • Escenario: Una aplicación permite a los usuarios actualizar su API key a través de una página de configuración de perfil.
  • Vector de ataque: Un atacante descubre que agregando un parámetro api_key adicional al POST puede manipular el resultado de la función de actualización de API key.
  • Técnica: Utilizando una herramienta como Burp Suite, el atacante crea una petición que incluye dos parámetros api_key: uno legítimo y otro malicioso. El servidor, al procesar solo la última aparición, actualiza la API key con el valor proporcionado por el atacante.
  • Resultado: El atacante obtiene control sobre la funcionalidad de API del víctima, pudiendo acceder o modificar datos privados sin autorización.

Este ejemplo subraya la necesidad de un manejo seguro de parámetros, especialmente en funcionalidades tan críticas como la gestión de API keys.

Parseo de parámetros: Flask vs. PHP

La forma en que las tecnologías web manejan parámetros HTTP duplicados varía, afectando su susceptibilidad a ataques HPP:

  • Flask: Adopta el primer valor del parámetro encontrado, por ejemplo a=1 en una query string a=1&a=2, priorizando la instancia inicial sobre las duplicadas.
  • PHP (en Apache HTTP Server): Contrariamente, prioriza el último valor del parámetro, optando por a=2 en el ejemplo dado. Este comportamiento puede facilitar inadvertidamente explotaciones HPP al respetar el parámetro manipulado por el atacante sobre el original.

Notas de prueba de HPP (OWASP WSTG)

  • Los estándares HTTP no definen cómo interpretar múltiples parámetros con el mismo nombre, por lo que el comportamiento varía entre stacks y componentes.
  • Al probar HPP del lado servidor, duplica cada parámetro en query strings o cuerpos y observa si la aplicación concatena valores, usa el primero/último, o produce errores.
  • Para HPP del lado cliente, inyecta un & codificado en URL dentro de un valor de parámetro reflejado (por ejemplo, %26HPP_TEST) y busca ocurrencias decodificadas como &HPP_TEST o &HPP_TEST dentro de enlaces generados o acciones de formularios.

Server-Side Parameter Pollution (SSPP) en APIs internas

Algunas aplicaciones insertan input del usuario en peticiones del lado servidor a APIs internas. Si ese input no está correctamente codificado, puedes inyectar o sobrescribir parámetros en la petición interna. Prueba cualquier input de usuario, incluidos query parameters, campos de formulario, headers y parámetros de ruta en la URL.

Pruebas comunes:

  • Agregar un nuevo parámetro con %26 (ampersand codificado en URL).
  • Truncar la query downstream con %23 (hash codificado en URL).
  • Sobrescribir un parámetro existente duplicándolo.

Example:

GET /userSearch?name=peter%26name=carlos&back=/home

Potencialmente resulta en una solicitud del lado del servidor como:

GET /users/search?name=peter&name=carlos&publicProfile=true

Parameter pollution por tecnología

Los resultados se tomaron de https://medium.com/@0xAwali/http-parameter-pollution-in-2024-32ec1b810f89

PHP 8.3.11 AND Apache 2.4.62

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*l_Pf2JNCYhmfAvfk7UTEbQ.jpeg

  1. Ignorar cualquier cosa después de %00 en el nombre del parámetro.
  2. Maneja name[] como array.
  3. _GET no significa el método GET.
  4. Prefiere el último parámetro.

Ruby 3.3.5 and WEBrick 1.8.2

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*kKxtZ8qEmgTIMS81py5hhg.jpeg

  1. Usa los delimitadores & y ; para separar parámetros.
  2. No reconoce name[].
  3. Prefiere el primer parámetro.

Spring MVC 6.0.23 AND Apache Tomcat 10.1.30

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*llG22MF1gPTYZYFVCmCiVw.jpeg

  1. POST RequestMapping == PostMapping & GET RequestMapping == GetMapping.
  2. POST RequestMapping & PostMapping reconoce name[].
  3. Prefiere name si name AND name[] existen.
  4. Concatena parámetros p. ej. first,last.
  5. POST RequestMapping & PostMapping reconoce parámetros de query con Content-Type.

NodeJS 20.17.0 AND Express 4.21.0

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*JzNkLOSW7orcHXswtMHGMA.jpeg

  1. Reconoce name[].
  2. Concatena parámetros p. ej. first,last.

GO 1.22.7

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*NVvN1N8sL4g_Gi796FzlZA.jpeg

  1. No reconoce name[].
  2. Prefiere el primer parámetro.

Python 3.12.6 AND Werkzeug 3.0.4 AND Flask 3.0.3

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*Se5467PFFjIlmT3O7KNlWQ.jpeg

  1. No reconoce name[].
  2. Prefiere el primer parámetro.

Python 3.12.6 AND Django 4.2.15

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*rf38VXut5YhAx0ZhUzgT8Q.jpeg

  1. No reconoce name[].
  2. Prefiere el último parámetro.

Python 3.12.6 AND Tornado 6.4.1

https://miro.medium.com/v2/resize:fit:1100/format:webp/1*obCn7xahDc296JZccXM2qQ.jpeg

  1. No reconoce name[].
  2. Prefiere el último parámetro.

JSON Injection

JSON, XML and YAML Hacking

Claves duplicadas

obj = {"test": "user", "test": "admin"}

El front-end podría considerar la primera ocurrencia mientras que el backend usa la segunda ocurrencia de la clave.

Key Collision: Character Truncation and Comments

Ciertos caracteres no serán interpretados correctamente por el frontend, pero el backend los interpretará y usará esas claves; esto podría ser útil para bypass certain restrictions:

{"test": 1, "test\[raw \x0d byte]": 2}
{"test": 1, "test\ud800": 2}
{"test": 1, "test"": 2}
{"test": 1, "te\st": 2}

Observa cómo en estos casos el front end podría pensar que test == 1 y el backend pensará que test == 2.

Esto también puede usarse para eludir restricciones de valor como:

{"role": "administrator\[raw \x0d byte]"}
{"role":"administrator\ud800"}
{"role": "administrator""}
{"role": "admini\strator"}

Usando Comment Truncation

obj = {"description": "Duplicate with comments", "test": 2, "extra": /*, "test": 1, "extra2": */}

Aquí usaremos el serializer de cada parser para ver su salida respectiva.

Serializer 1 (e.g., GoLang’s GoJay library) producirá:

  • description = "Duplicate with comments"
  • test = 2
  • extra = ""

Serializer 2 (e.g., Java’s JSON-iterator library) producirá:

  • description = "Duplicate with comments"
  • extra = "/*"
  • extra2 = "*/"
  • test = 1

Alternativamente, el uso directo de comentarios también puede ser efectivo:

obj = {"description": "Comment support", "test": 1, "extra": "a"/*, "test": 2, "extra2": "b"*/}

La biblioteca GSON de Java:

{ "description": "Comment support", "test": 1, "extra": "a" }

La biblioteca simdjson de Ruby:

{ "description": "Comment support", "test": 2, "extra": "a", "extra2": "b" }

Precedencia inconsistente: Deserialization vs. Serialization

obj = {"test": 1, "test": 2}

obj["test"] // 1
obj.toString() // {"test": 2}

Float and Integer

El número

999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999

puede decodificarse en múltiples representaciones, incluyendo:

999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
9.999999999999999e95
1E+96
0
9223372036854775807

Lo cual podría crear inconsistencias

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