Инъекционные атаки
Инъекции в серверные интерпретаторы — варианты SQLi, NoSQL, OS-команды, LDAP, XXE, SSTI, ошибки ORM, CRLF/заголовки и mass-assignment, и общая защита от всех них.
15 вопросов
JuniorТеорияОчень частоКакая одна идея объединяет все классы инъекций и какая защита из неё следует?
Какая одна идея объединяет все классы инъекций и какая защита из неё следует?
Любая инъекция — одна и та же поломка: недоверенные данные попадают в интерпретатор и разбираются как код. Отсюда защита: держать данные вне грамматики через параметризацию или структурные аргументы, а за ними — валидация по списку и минимум прав.
Типичные ошибки
- ✗Считать каждый класс инъекций отдельной проблемой своего синтаксиса
- ✗Ставить очистку ввода выше параметризации в иерархии защиты
- ✗Выдавать WAF за устранение причины вместо слоя эшелонированной защиты
Уточняющие вопросы
- →Как в эту же модель укладываются классы инъекций LDAP и XPath?
- →Почему учётная запись БД с минимумом прав — слой сдерживания, а не фикс?
JuniorТеорияОчень частоПочему параметризованные запросы останавливают SQL-инъекцию, а экранирование — нет?
Почему параметризованные запросы останавливают SQL-инъекцию, а экранирование — нет?
Параметризация передаёт SQL и значения по разным каналам: движок сперва разбирает запрос, затем подставляет значения как данные, поэтому ввод не возвращается в парсер как код. Экранирование строит одну строку, и один промах снова делает данные синтаксисом.
Типичные ошибки
- ✗Считать, что экранирование и параметризация отличаются лишь удобством
- ✗Думать, что драйвер проверяет значения на опасные ключевые слова SQL
- ✗Полагать, что хранимые процедуры параметризованы по определению
Уточняющие вопросы
- →Почему хранимая процедура, склеивающая свои аргументы, всё ещё уязвима?
- →Какие части запроса, например имена таблиц, нельзя передать параметром?
JuniorТеорияОчень частоЧто такое XXE и почему лечится настройкой парсера, а не фильтрацией ввода?
Что такое XXE и почему лечится настройкой парсера, а не фильтрацией ввода?
XXE возникает, когда XML-парсер разрешает объявленную в документе внешнюю сущность, и документ подтягивает локальный файл или внутренний URL. Лечится настройкой парсера, а не фильтрацией ввода: отключите DTD и внешние сущности.
Типичные ошибки
- ✗Пытаться блокировать XXE поиском объявления сущности в теле документа
- ✗Считать, что современные парсеры везде отключают внешние сущности по умолчанию
- ✗Видеть в XXE только чтение файлов, забывая про запросы во внутреннюю сеть
Уточняющие вопросы
- →Как XXE переходит в класс подделки запросов
SSRFпротив внутренних сервисов? - →Какие форматы кроме чистого XML, например SVG или DOCX, доходят до того же парсера?
MiddleТеорияЧастоЧем обнаружение булевой слепой SQLi отличается от обнаружения слепой SQLi по времени?
Чем обнаружение булевой слепой SQLi отличается от обнаружения слепой SQLi по времени?
Оба варианта скрывают результат запроса. Булевому обнаружению нужен ответ, который всё же различается — длина, статус или содержимое при истинном и ложном условии. Если ответ неизменен, остаётся задержка: намеренная пауза подтверждает выполнение.
Типичные ошибки
- ✗Считать, что слепой инъекции нужна видимая ошибка или возвращённая строка
- ✗Принимать задержку за шум, а не за единственный оставшийся сигнал
- ✗Думать, что подавление вывода устраняет саму уязвимость
Уточняющие вопросы
- →Почему обнаружение по времени ненадёжно на нагруженной точке или за прокси?
- →Почему параметризация запроса закрывает оба варианта разом?
MiddleТеорияЧастоКак сырые помощники ORM возвращают SQL-инъекцию в казалось бы безопасный слой?
Как сырые помощники ORM возвращают SQL-инъекцию в казалось бы безопасный слой?
ORM параметризует лишь запросы, которые строит сам. Помощники с сырым фрагментом — raw(), text(), рукописная строка where — отдают текст драйверу напрямую, поэтому подставленное значение снова разбирается как SQL.
Типичные ошибки
- ✗Считать, что ORM делает безопасным любой запрос независимо от способа сборки
- ✗Подставлять идентификатор в сырой фрагмент, считая его не пользовательским
- ✗Думать, что сырой помощник всё равно связывает подставленные значения
Уточняющие вопросы
- →Как проверить кодовую базу на сырые фрагменты, не читая каждый запрос?
- →Почему имена таблиц и колонок требуют белого списка, а не связанного параметра?
MiddleТеорияЧастоЧто такое инъекция OS-команд и почему корень проблемы — вызов оболочки?
Что такое инъекция OS-команд и почему корень проблемы — вызов оболочки?
Приложение собирает командную строку из ввода и отдаёт оболочке. Оболочка — полноценный интерпретатор, поэтому метасимволы разбивают команду на несколько, и ввод становится кодом. Фикс — не звать оболочку, а запускать бинарь с массивом аргументов.
Типичные ошибки
- ✗Заковычивать подставленное значение вместо полного отказа от оболочки
- ✗Считать, что чёрный список метасимволов покрывает все разделители оболочки
- ✗Думать, что непривилегированная учётка предотвращает инъекцию, а не ограничивает её
Уточняющие вопросы
- →Почему массив аргументов полностью убирает интерпретатор из цепочки?
- →Как учётная запись с минимумом прав ограничивает ущерб при отказе контроля?
MiddleДебаггингЧастоОпределите причину по журналу API с синтаксической ошибкой SQL из параметра запроса
Определите причину по журналу API с синтаксической ошибкой SQL из параметра запроса
Кавычка из параметра дошла до парсера SQL и досрочно закрыла литерал — значит, запрос склеен, и перед нами SQL-инъекция, а не плохой ввод. Чинить надо оба дефекта: связать ref параметром и убрать ошибку драйвера из ответа.
Типичные ошибки
- ✗Читать синтаксическую ошибку как плохой ввод, а не как доказательство склейки
- ✗Чинить только утёкшую трассировку, оставляя запрос склеенным
- ✗Считать фильтрацию параметра на периметре устранением первопричины
Уточняющие вопросы
- →Почему подавление ошибки усложняет поиск дыры, но не делает её безопаснее?
- →Что искать в кодовой базе, чтобы найти соседние запросы, собранные так же?
SeniorТеорияЧастоПочему SQL-инъекцию второго порядка так трудно поймать на ревью и тестами?
Почему SQL-инъекцию второго порядка так трудно поймать на ревью и тестами?
Значение сохраняется безопасно параметризованной вставкой и лишь позже читается обратно и склеивается в другой запрос — часто отчётом или фоновой задачей. Источник и приёмник в разных запросах, сканеры их не связывают, а выполнение слепое.
Типичные ошибки
- ✗Считать данные, уже лежащие в базе, доверенными в момент повторного использования
- ✗Ждать, что сканер одного запроса свяжет поздний приёмник с ранней записью
- ✗Винить параметризованную вставку вместо склеивающего потребителя
Уточняющие вопросы
- →Как анализ потока данных через хранилище меняет ваш подход к ревью?
- →Почему экранирование при записи делает сохранённое значение опасным для потребителей?
JuniorТеорияИногдаЧто такое операторная NoSQL-инъекция в MongoDB и как её предотвратить?
Что такое операторная NoSQL-инъекция в MongoDB и как её предотвратить?
Фильтры Mongo — это документы, поэтому сырое значение JSON может прийти объектом-оператором вместо скаляра: поле, ждущее строку, получает объект с $ne, и сравнение совпадает всегда. Лечится приведением каждого поля к ожидаемому типу.
Типичные ошибки
- ✗Считать документные базы неуязвимыми, раз в них нет SQL
- ✗Передавать разобранное тело запроса в фильтр без приведения типов
- ✗Полагаться на чёрный список с
$вместо проверки типов значений
Уточняющие вопросы
- →Почему слой схемы или DTO убирает этот класс уязвимостей целиком?
- →Как оператор запроса
$whereрасширяет последствия за пределы сравнения?
MiddleТеорияИногдаЧто ломает CRLF-инъекция в HTTP-ответах и в журналах приложения?
Что ломает CRLF-инъекция в HTTP-ответах и в журналах приложения?
Оба формата используют перевод строки разделителем структуры. Неотфильтрованный перевод в заголовке завершает его досрочно и даёт дописать заголовки или тело, расщепив ответ; в журнале — подделать запись. Фикс — отвергать управляющие символы.
Типичные ошибки
- ✗Считать подделку журнала косметикой, а не искажением доказательств
- ✗Полагать, что фреймворк убирает переводы строк из любого заголовка
- ✗Фильтровать только возврат каретки, пропуская одиночный перевод строки
Уточняющие вопросы
- →Почему подделка журнала подрывает восстановление таймлайна при расследовании?
- →Какие заголовки чаще всего собираются из пользовательского ввода на практике?
MiddleТеорияИногдаЧто такое mass assignment и почему правильное лекарство — белый список на запись?
Что такое mass assignment и почему правильное лекарство — белый список на запись?
Автопривязка копирует все поля тела запроса в модель, поэтому клиент дописывает атрибут, которого не было в форме, — роль или владельца, — и он сохраняется. Белый список переворачивает умолчание: связываются лишь поля, разрешённые точке.
Типичные ошибки
- ✗Вести чёрный список чувствительных полей вместо явного белого списка
- ✗Считать, что фреймворк отбрасывает атрибуты, не задуманные для точки
- ✗Полагаться на скрытое или отключённое поле формы для защиты записи
Уточняющие вопросы
- →Почему объект передачи под каждую точку лучше одной общей модели для записи?
- →Чем это отличается от класса нарушений авторизации
IDORна той же записи?
MiddleКодИногдаИсправьте инъекцию команд в этом помощнике миниатюр, вызывающем оболочку
Исправьте инъекцию команд в этом помощнике миниатюр, вызывающем оболочку
При shell=True оболочка разбирает всю собранную строку, поэтому filename может дописать команды. Уберите оболочку и передайте список аргументов, затем ограничьте значение: сведите к чистому имени по строгому шаблону.
Типичные ошибки
- ✗Заковычивать подставленный путь вместо отказа от
shell=True - ✗Делать основной защитой фильтрацию чёрного списка метасимволов
- ✗Передавать сырое имя в список аргументов без всякой проверки
Уточняющие вопросы
- →Почему список аргументов останавливает инъекцию даже без валидации?
- →Почему путь надо пересобрать из имени файла, а не доверять присланному?
MiddleТеорияИногдаПочему пользовательский ввод должен быть данными шаблона, а не самим шаблоном?
Почему пользовательский ввод должен быть данными шаблона, а не самим шаблоном?
Шаблонизатор — это интерпретатор. Ввод, переданный значением, лишь подставляется, а ввод, скомпилированный как исходник шаблона, исполняется в серверном процессе. Фикс структурный: шаблоны из кода, данные пользователя — только связанная переменная.
Типичные ошибки
- ✗Путать экранирование вывода с недопуском ввода в исходник шаблона
- ✗Собирать строку шаблона из ввода ради настраиваемых писем или отчётов
- ✗Считать, что последствия ограничены разметкой, а не исполнением на сервере
Уточняющие вопросы
- →Как поддержать настраиваемые письма, не компилируя шаблоны пользователя?
- →Почему песочница движка снижает ущерб, но не убирает ошибку проектирования?
SeniorТеорияИногдаПочему инъекция аргументов срабатывает даже там, где оболочки нет вовсе?
Почему инъекция аргументов срабатывает даже там, где оболочки нет вовсе?
Массив аргументов убирает оболочку, но не собственный разбор опций у бинаря. Значение с ведущим дефисом читается как флаг, поэтому ввод меняет поведение утилиты, а не её объект. Фикс — разделитель -- и отказ от значений в форме опции.
Типичные ошибки
- ✗Считать массив аргументов исчерпывающей защитой самой по себе
- ✗Забывать разделитель конца опций перед подконтрольными операндами
- ✗Думать, что расположение значения в конце выводит его из разбора опций
Уточняющие вопросы
- →Как проверить обёртку над утилитами, чьи флаги пишут файлы или грузят конфиги?
- →Почему белый список ожидаемых форм значения сильнее срезания ведущих дефисов?
SeniorТеорияИногдаКак защищаться от внеполосного XXE, когда парсер ничего не возвращает?
Как защищаться от внеполосного XXE, когда парсер ничего не возвращает?
Параметрические сущности заставляют парсер открыть исходящее соединение, поэтому данные уходят побочным каналом и вывод не нужен. Основной контроль тот же — отключить DTD и внешние сущности, за ними — ограничение исходящего трафика.
Типичные ошибки
- ✗Считать, что парсер без вывода ничего не может утечь
- ✗Заменять настройку парсера сетевыми контролями вместо их добавления
- ✗Алертить на ошибки разбора, оставляя обработку DTD включённой
Уточняющие вопросы
- →Почему исходящий DNS часто остаётся последним каналом после блокировки HTTP?
- →Как обнаружить этот класс в трафике, когда журналы приложения остаются чистыми?