Уязвимости веб-приложений
XSS, CSRF, SQL/NoSQL-инъекции, SSRF, SSTI, обход каталога, инъекция команд, небезопасная десериализация и угрозы загрузки файлов.
17 вопросов
JuniorТеорияОчень частоЧто такое SQL-инъекция и как от неё защититься?
Что такое SQL-инъекция и как от неё защититься?
SQL-инъекция возникает, когда недоверенный ввод склеивается в запрос, позволяя изменить его структуру — обойти аутентификацию, выгрузить данные, выполнить команды. Защита — параметризованные запросы: данные идут отдельно от SQL, и ввод не меняет запрос. Минимальные права снижают ущерб.
Типичные ошибки
- ✗Считать ручное экранирование кавычек надёжной заменой параметризации
- ✗Думать, что хранимые процедуры с конкатенацией ввода защищены
- ✗Полагать, что инъекция затрагивает только чтение, не запись/RCE
Уточняющие вопросы
- →Почему параметризованный запрос делает структуру запроса неизменяемой вводом?
- →Как принцип наименьших привилегий учётки БД снижает ущерб от инъекции?
JuniorТеорияОчень частоЧто такое XSS и чем от него защищаться?
Что такое XSS и чем от него защищаться?
XSS внедряет на страницу JavaScript атакующего, исполняемый в браузере жертвы: кража сессий или действия от её имени. Основная защита — контекстное экранирование вывода недоверенных данных, усиленное Content Security Policy. Флаги httpOnly/secure снижают кражу cookie, но не XSS.
Типичные ошибки
- ✗Путать XSS с CSRF — это разные классы атак
- ✗Считать флаги httpOnly/secure достаточной защитой от самого XSS
- ✗Экранировать ввод вместо контекстного экранирования вывода
Уточняющие вопросы
- →Чем отличаются stored, reflected и DOM-based XSS?
- →Как Content Security Policy ограничивает выполнение внедрённого скрипта?
JuniorДебаггингЧастоНайдите RCE в обёртке nslookup на Flask
Найдите RCE в обёртке nslookup на Flask
OS command injection — domain подставляется в shell-строку при shell=True, и спецсимволы shell выполняют произвольные команды (RCE). Фикс: shell=False со списком аргументов (ввод — один аргумент) и проверка имени хоста.
Типичные ошибки
- ✗Считать проблемой DoS или SSRF вместо инъекции команд
- ✗Думать, что blacklist опасных символов надёжнее списка аргументов и shell=False
- ✗Полагать, что shell=True обязателен для запуска внешней команды
Уточняющие вопросы
- →Почему shell=False со списком аргументов устраняет инъекцию у корня?
- →Почему чёрный список спецсимволов — ненадёжная защита здесь?
JuniorТеорияЧастоЧто такое CSRF и при каких условиях денежный эндпоинт уязвим?
Что такое CSRF и при каких условиях денежный эндпоинт уязвим?
CSRF заставляет браузер вошедшей жертвы отправить подделанный изменяющий запрос. POST /pay уязвим, только если сессия в cookie, отправляемой кросс-сайтово автоматически, нет анти-CSRF токена и у cookie нет SameSite. Токены и SameSite=Lax закрывают это.
Типичные ошибки
- ✗Путать CSRF с XSS (CSRF не исполняет скрипт у жертвы)
- ✗Считать, что POST или TLS сами по себе защищают от CSRF
- ✗Не учитывать роль атрибута SameSite у cookie
Уточняющие вопросы
- →Почему запрос с Content-Type application/json труднее подделать через CSRF?
- →Как анти-CSRF токен подтверждает, что запрос пришёл с вашей страницы?
JuniorДебаггингЧастоНайдите уязвимость чтения файла по имени из запроса
Найдите уязвимость чтения файла по имени из запроса
Path traversal (обход каталога) — fileName склеивается в путь без проверки, поэтому ../ выходит за пределы open-media/ и читает произвольные файлы. Фикс: нормализовать итоговый путь и проверить, что он внутри базовой директории, либо белый список имён.
Типичные ошибки
- ✗Считать, что фильтрация только расширения файла останавливает обход каталога
- ✗Полагаться на удаление подстроки '../' без нормализации итогового пути
- ✗Путать path traversal с XSS из-за наличия пользовательского ввода
Уточняющие вопросы
- →Почему проверять нужно нормализованный путь, а не исходную строку?
- →Чем подход с белым списком имён надёжнее фильтрации '../'?
MiddleТеорияЧастоЧто такое серверная подделка запроса (SSRF) и как обходят фильтр локальных адресов?
Что такое серверная подделка запроса (SSRF) и как обходят фильтр локальных адресов?
SSRF заставляет сервер запросить выбранный атакующим URL, дотягиваясь до внутренних сервисов или метаданных облака, недоступных клиенту. Чёрные списки localhost обходят альтернативными записями IP, открытым редиректом, TOCTOU и DNS rebinding. Защита — сверять итоговый резолвленный IP с белым списком.
Типичные ошибки
- ✗Путать SSRF с CSRF (направление запроса противоположное)
- ✗Считать чёрный список строк localhost/127.0.0.1 достаточной защитой
- ✗Игнорировать слепой SSRF, считая его безвредным
Уточняющие вопросы
- →Как DNS rebinding обходит проверку, выполненную до запроса?
- →Почему проверять надёжнее итоговый резолвленный IP, а не строку URL?
MiddleДебаггингИногдаНайдите слепую SQL-инъекцию через text() в SQLAlchemy
Найдите слепую SQL-инъекцию через text() в SQLAlchemy
SQL-инъекция — text() выполняет склеенную f-строку как есть, не параметризуя её, поэтому table_name внедряет произвольный SQL. Слепая: ответа с данными нет, выполнение подтверждают лишь по времени. Фикс: связанные параметры и белый список.
Типичные ошибки
- ✗Думать, что
text()параметризует подставленную f-строку - ✗Считать слепую инъекцию невозможной без видимого вывода
- ✗Принимать инъекцию за состояние гонки или раскрытие информации
Уточняющие вопросы
- →Как атакующий извлекает данные через слепую инъекцию по времени побитово?
- →Почему связанные параметры устраняют инъекцию, а чёрный список — нет?
MiddleДебаггингИногдаНайдите небезопасную десериализацию недоверенных данных
Найдите небезопасную десериализацию недоверенных данных
Небезопасная десериализация — readObject создаёт произвольные выбранные атакующим классы из недоверенных байтов, поэтому цепочка гаджетов выполняет код при десериализации (RCE). Фикс: не десериализовать недоверенный ввод; JSON со схемой или белый список.
Типичные ошибки
- ✗Считать десериализацию Java типобезопасной и неспособной к RCE
- ✗Думать, что try/catch вокруг readObject устраняет угрозу
- ✗Путать это с XXE или с утечкой через логирование
Уточняющие вопросы
- →Что такое цепочка гаджетов и почему её хватает для RCE без своего класса?
- →Чем безопасный формат данных (JSON) надёжнее нативной сериализации объектов?
MiddleДебаггингИногдаНайдите DOM XSS в обработчике postMessage
Найдите DOM XSS в обработчике postMessage
DOM XSS: любое окно может прислать {type:'go_to_link', url:'javascript:alert(1)'}, и обработчик выполнит это через location.assign, запустив скрипт. Два изъяна: нет белого списка event.origin и нет проверки схемы URL. Фикс: проверять e.origin по доверенному списку, затем принимать только http/https URL (отклонять javascript:/data:) перед переходом.
Типичные ошибки
- ✗Принимать DOM XSS за DoS, CSRF или отсутствие экранирования вывода
- ✗Думать, что
location.assignне исполняет схемуjavascript: - ✗Чинить только одну из двух проблем (origin ИЛИ схему URL)
Уточняющие вопросы
- →Почему проверки
event.originнедостаточно без валидации схемы URL? - →Чем DOM XSS отличается от отражённого XSS по месту исполнения?
MiddleДебаггингИногдаНайдите чтение локальных файлов в обход проверки картинки на PHP
Найдите чтение локальных файлов в обход проверки картинки на PHP
Local File Read — readfile($url) отдаёт любой путь, поэтому обёртка php://filter читает произвольные файлы. Проверка mime обходится, так как цепочка фильтров перекодирует начальные байты, пока getimagesize() не примет их за картинку, либо через TOCTOU. Фикс: белый список источников, запрет php://, одно скачивание, переэнкод.
Типичные ошибки
- ✗Считать проверку getimagesize() достаточной защитой от чтения файлов
- ✗Видеть только SSRF и упускать Local File Read через php://filter
- ✗Не учитывать TOCTOU между проверкой и readfile
Уточняющие вопросы
- →Как цепочка php://filter превращает байты файла в подобие картинки?
- →Почему TOCTOU обходит проверку mime даже без обёртки php://?
MiddleДебаггингИногдаНайдите NoSQL-инъекцию в логине на Mongoose
Найдите NoSQL-инъекцию в логине на Mongoose
NoSQL-инъекция из-за неверной обработки типа — username не приводится к строке, поэтому атакующий шлёт объект из операторов MongoDB, меняющий семантику запроса и обходящий поиск. Фикс: привести к строке и искать по явному полю вместо передачи сырого объекта запроса.
Типичные ошибки
- ✗Считать NoSQL неуязвимым к инъекции из-за отсутствия SQL-синтаксиса
- ✗Передавать сырой объект запроса в драйвер БД без приведения типов
- ✗Путать это с классической SQL-инъекцией или с гонкой
Уточняющие вопросы
- →Как оператор $regex в поле пароля позволяет посимвольно его перебрать?
- →Почему приведение к строке у источника надёжнее фильтрации операторов?
MiddleДебаггингИногдаВозможна ли SQL-инъекция через literal() в ORM-запросе?
Возможна ли SQL-инъекция через literal() в ORM-запросе?
Да — literal() это лазейка для сырого SQL; ORM НЕ параметризует текст внутри него. Подстановка :firstName — это лишь строковая замена, и на устаревшей версии особый firstName (и lastName, равный :firstName) выходит из literal и внедряет SQL. Фикс: никогда не помещать пользовательский ввод рядом с literal(); полагаться на параметризованные операторы where ORM и обновить библиотеку.
Типичные ошибки
- ✗Думать, что ORM параметризует сырой SQL внутри
literal() - ✗Считать, что наличие
replacementsделает весь запрос безопасным - ✗Принимать инъекцию через literal за баг производительности
Уточняющие вопросы
- →Почему
replacementsне защищает текст, переданный вliteral()? - →Когда вообще оправдано использовать
literal()в ORM-запросе?
MiddleДебаггингИногдаНайдите серверную инъекцию в шаблон (SSTI) в lodash на пользовательском вводе
Найдите серверную инъекцию в шаблон (SSTI) в lodash на пользовательском вводе
Серверная инъекция в шаблон (SSTI) — name становится частью исходника шаблона, а escapeHTML нейтрализует только HTML, не синтаксис шаблона. Выражение ${...} компилируется и исполняется на сервере, давая RCE. Фикс: передавать name как данные в фиксированный шаблон, а не в текст.
Типичные ошибки
- ✗Считать escapeHTML защитой от инъекции синтаксиса шаблона
- ✗Путать SSTI с отражённым XSS (выполнение на сервере, не в браузере)
- ✗Собирать строку шаблона из пользовательского ввода
Уточняющие вопросы
- →Почему экранирование HTML не мешает выполнению выражения ${...}?
- →В чём разница между передачей ввода как данных и как текста шаблона?
JuniorДебаггингРедкоНайдите обход каталога в конфиге nginx с alias
Найдите обход каталога в конфиге nginx с alias
Обход каталога через alias из-за отсутствия завершающего слэша у location. Раз у /assets нет завершающего слэша, nginx дописывает к alias часть URI после /assets как есть, поэтому /assets../app/db.php превращается в /var/www/webapp/app/db.php — на уровень выше static/. Фикс: добавить завершающий слэш и к location, и к alias.
Типичные ошибки
- ✗Считать отсутствие завершающего слэша стилевым, а не security-изъяном
- ✗Думать, что nginx сам нормализует
..до сопоставления с alias - ✗Принимать обход каталога за раскрытие информации или DoS
Уточняющие вопросы
- →Почему завершающий слэш на
locationустраняет дописывание остатка URI? - →Чем поведение
aliasотличается отrootпри сопоставлении пути?
JuniorТеорияРедкоОт чего защищают атрибуты ссылки rel=noopener и rel=noreferrer?
От чего защищают атрибуты ссылки rel=noopener и rel=noreferrer?
Ссылка с target="_blank" даёт открытой странице ссылку window.opener на вашу, и та может перенаправить её на фишинговую копию (reverse tabnabbing). rel="noopener" обрывает эту ссылку. rel="noreferrer" дополнительно убирает заголовок Referer, скрывая URL источника.
Типичные ошибки
- ✗Считать, что noopener защищает страницу назначения, а не вашу
- ✗Путать reverse tabnabbing с CSRF или XSS
- ✗Думать, что noreferrer влияет только на аналитику, не на безопасность
Уточняющие вопросы
- →Как именно открытая вкладка через window.opener подменяет исходную страницу?
- →Почему современные браузеры по умолчанию применяют noopener для target=_blank?
MiddleДебаггингРедкоНайдите состояние гонки в эндпоинте перевода денег
Найдите состояние гонки в эндпоинте перевода денег
Гонка TOCTOU: чтение-проверка-запись не атомарны, поэтому тысячи параллельных запросов читают один баланс, все проходят проверку >= и каждый списывает — атакующий тратит куда больше, чем есть. Фикс: сделать атомарным — транзакция с построчной (пессимистичной) блокировкой или один условный апдейт (UPDATE ... SET balance = balance - :amt WHERE balance >= :amt).
Типичные ошибки
- ✗Принимать гонку за проблему CSRF или rate limiting
- ✗Считать, что проверка >= перед записью защищает при конкурентности
- ✗Лечить симптом лимитом запросов вместо атомарности операции
Уточняющие вопросы
- →Почему условный UPDATE одним запросом устраняет гонку у корня?
- →Чем пессимистичная блокировка строки отличается от лимита запросов здесь?
MiddleТеорияРедкоКакие атаки возможны на сервис, который рендерит офисные документы (xlsx, docx, csv) как картинки?
Какие атаки возможны на сервис, который рендерит офисные документы (xlsx, docx, csv) как картинки?
xlsx/docx — ZIP-архивы из XML, поверхность атаки большая. Атаки: Zip Slip — путь в архиве выходит за каталог распаковки; XXE — внешние сущности в XML дают доступ к файлам/SSRF; CSV-инъекция — ячейка =cmd|... исполняется при открытии; макросы; CVE библиотеки. Защита — валидация путей, отключение внешних сущностей и макросов, песочница.
Типичные ошибки
- ✗Считать рендеринг в картинку безопасным и игнорировать содержимое документа
- ✗Не знать, что xlsx/docx — это ZIP с XML (Zip Slip, XXE)
- ✗Думать, что CSV — инертные данные, и упускать инъекцию формул
Уточняющие вопросы
- →Почему формат xlsx как ZIP-архив открывает векторы Zip Slip и XXE?
- →Как снять отпечаток движка рендеринга через SSRF и метаданные?