Уязвимости веб-приложений
Почти каждая веб-уязвимость сводится к одной идее — недоверенные данные пересекают границу и становятся кодом или командой. Ввод пользователя попадает в SQL-запрос, в HTML-страницу, в строку shell, в путь файла или в тело сериализованного объекта — и там, где парсер не отличает ваши данные от ваших инструкций, атакующий берёт управление. Задача защиты всегда одна и та же — держать данные данными на каждом переходе.
Этот раздел разбирает главные классы веб-атак не как коллекцию пейлоадов, а как набор границ доверия и способов их удержать. По каждому классу — механизм (как ввод превращается в исполнение), конкретный пример и защита у корня, а не косметика. Именно смешение классов (принять SQL-инъекцию за гонку, XSS за CSRF, path traversal за XSS) — самая частая ловушка на собеседовании. Полная карта — в слоях ниже.
Карта темы
- XSS — межсайтовый скриптинг — как чужой JavaScript попадает на страницу и почему главная защита — контекстное экранирование вывода и CSP.
- DOM-based XSS — XSS целиком в браузере, поток «источник → опасный sink» и безопасные приёмники вместо
innerHTML. - CSRF — подделка межсайтового запроса — как чужой сайт заставляет браузер жертвы отправить изменяющий запрос и чем это закрывают
SameSiteи токены. - Clickjacking и tabnabbing — обман через невидимый iframe и захват вкладки через
window.opener, защита заголовками иrel=noopener. - SQL-инъекция — как ввод меняет структуру запроса и почему параметризация закрывает это у корня.
- Слепая SQL-инъекция — извлечение данных без видимого вывода через булев и временной оракул, и та же защита параметризацией.
- NoSQL-инъекция — операторы вроде
$ne/$regexв JSON-теле и защита приведением типа и схемой. - SQL-инъекция через ORM — сырые лазейки (
literal,raw,text), которые ORM не параметризует. - Инъекция OS-команд — спецсимволы shell и защита через вектор аргументов без интерпретатора.
- SSTI — инъекция в шаблон — ввод как исходник шаблона против ввода как данных, путь к RCE на сервере.
- Небезопасная десериализация — цепочки гаджетов из недоверенных байтов и защита безопасным форматом и allowlist классов.
- Обход каталога (path traversal) —
../в имени файла и защита канонизацией пути и проверкой префикса. - Чтение локальных файлов (LFR) — обёртки
php://и обход mime-проверки, защита allowlist источников и переэнкодом. - Обход каталога через nginx alias — рассинхрон завершающих слэшей у
location/aliasкак security-баг. - SSRF — подделка серверного запроса — сервер запрашивает внутренние адреса, обходы чёрного списка и защита проверкой резолвленного IP.
- Гонки в бизнес-логике — TOCTOU на read-modify-write и защита атомарностью операции.
- Атаки через офисные документы — xlsx/docx как ZIP+XML (Zip Slip, XXE, CSV-инъекция) и защита разбором в песочнице.
Частые ошибки и ловушки
| Ошибка | Последствие |
|---|---|
| Экранировать ввод вместо контекстного экранирования вывода | XSS проходит — опасен именно контекст рендера, а не момент приёма |
Считать httpOnly/TLS/POST достаточной защитой от CSRF или XSS | Ложное чувство безопасности; сам класс атаки не закрыт |
Фильтровать чёрным списком (символы, ../, localhost) | Всегда находится обход через кодирование или альтернативную запись |
| Ручное экранирование кавычек вместо параметризации SQL | Забытый край или экзотическая кодировка — и инъекция возвращается |
Доверять «безопасности» ORM и класть ввод рядом с literal/raw | Сырые лазейки ORM не параметризуются — прямая SQL-инъекция |
| Проверять исходную строку URL/пути, а не резолвленный результат | Нормализация после проверки (TOCTOU, DNS rebinding) обходит фильтр |
| Считать рендер в картинку или «не-SQL» БД неуязвимыми | Zip Slip, XXE, CSV-инъекция, $ne/$regex — атака просто в другом синтаксисе |
| Путать классы атак между собой | Неверный диагноз ведёт к фиксу, который не закрывает уязвимость |
Значение для собеседований
Веб-уязвимости спрашивают, чтобы проверить, видите ли вы границу доверия и умеете ли назвать защиту, которая закрывает класс атаки у корня, а не лечит симптом. Сильный кандидат по коду быстро называет класс («это OS command injection, потому что ввод идёт в shell-строку»), объясняет механизм в одном предложении и даёт фикс, устраняющий саму возможность («вектор аргументов без shell»), а не чёрный список.
Что обычно проверяют:
- Правильную классификацию: инъекция против гонки, XSS против CSRF, SSRF против CSRF, path traversal против XSS.
- Защиту у корня: параметризация, контекстное экранирование + CSP, вектор аргументов, allowlist, атомарность, канонизация пути.
- Почему популярные «полумеры» не работают — чёрные списки,
httpOnly,try/catch, проверка до нормализации. - Понимание, что «данные становятся кодом» — общий корень большинства этих багов.
Типичный неверный ответ: назвать симптоматический фикс за корневой — «добавим rate limiting против гонки», «экранируем вывод против SQL-инъекции», «включим HTTPS против CSRF». Каждый из них оставляет исходный класс атаки открытым.