Цель модуля
Научить разработчика проверять входные данные по назначению и контексту, применять параметризованные запросы и безопасное кодирование вывода, а также понимать, почему проверка только на стороне браузера не защищает продукт.
Откуда приходят недоверенные данные
Недоверенные данные — это всё, что формируется вне доверенной части продукта и может быть изменено третьим лицом. К ним относятся: поля форм, параметры адресной строки, заголовки запросов и значения печенья, содержимое загружаемых файлов, данные из внешних служб, сообщения из очередей и даже значения, которые предыдущий модуль системы записал в хранилище без проверки.
Подмена источника — типичная причина, по которой проверка оказывается неполной: разработчик считает данные пришедшими от своего модуля, а на самом деле они проходят через внешний интерфейс, к которому есть доступ у постороннего.
Типовые атаки на входные данные
| Атака | Суть | Что закрывает |
|---|---|---|
| Внедрение команд языка запросов | Недоверенный фрагмент попадает в текст запроса к базе данных и меняет его смысл | Параметризованные запросы и подготовленные выражения, отказ от сборки запроса склейкой строк |
| Внедрение команд оболочки | Данные пользователя попадают в строку запуска системной команды | Отказ от запуска оболочки, передача аргументов списком, разрешающий список допустимых значений |
| Межсайтовое выполнение сценариев | Сохранённый текст выводится в страницу как разметка и исполняется в браузере другого пользователя | Экранирование вывода по контексту, безопасная работа с разметкой |
| Обход пути к файлу | В имени файла передаются последовательности перехода по каталогам | Приведение имени к известному виду, проверка итогового пути по разрешённому каталогу |
| Подделка запроса | Браузер пользователя выполняет действие без его намерения | Проверка источника запроса, одноразовые метки форм |
Как выстроить проверку входных данных
- Определите для каждого поля тип, допустимый диапазон, длину и формат — и запишите это правило явно.
- Проверяйте данные на стороне сервера, независимо от того, что уже проверил браузер.
- Применяйте разрешающий список допустимых значений вместо запрещающего списка запрещённых.
- Не собирайте запросы и команды склейкой строк: разделяйте код запроса и данные.
- Экранируйте данные при выводе в тот контекст, куда они попадают: разметка, атрибут, сценарий, файл, журнал.
- При отказе проверки возвращайте понятное общее сообщение и записывайте подробность в журнал, но не раскрывайте внутреннее устройство системы.
Типовые ошибки разработчика
- «В браузере уже проверено» — ограничение длины поля обходится одним запросом и не является защитой.
- Сборка текста запроса из частей со значениями пользователя — прямой путь к внедрению команд языка запросов.
- Доверие к скрытым полям формы: их значение меняется вручную за секунды.
- Одна общая проверка «на всё» вместо проверки по назначению каждого поля.
- Вывод недоверенных данных в журнал без обезвреживания: через переносы строк можно подделать записи журнала.
- Раскрытие подробностей ошибки пользователю: текст исключения подсказывает злоумышленнику устройство системы.
Проверка при разборе кода
При проверке кода коллега обязан спросить: откуда пришли эти данные, что произойдёт при самом худшем их значении, где именно они проверяются и где выводятся. Если ответ «проверка не нужна, источник доверенный», требуется явное обоснование и ссылка на модуль, который формирует эти данные под контролем.
Проверочный список перед выходом на работу
- Для каждого нового поля описано правило допустимых значений, длины и формата.
- Проверка выполняется на стороне сервера, а не только в браузере.
- Запросы к базе данных параметризованы, склейка строк со значениями отсутствует.
- Системные команды запускаются без участия оболочки, аргументы передаются по отдельности.
- Вывод экранируется по контексту, в который он попадает.
- Сообщения об ошибке пользователю не раскрывают внутреннее устройство системы.
Вопросы для самопроверки
- Почему проверка в браузере не считается защитой? Её можно обойти, отправив запрос напрямую в обход страницы; сервер обязан проверять данные сам.
- Что делать, если поле раньше приходило от внутренней службы? Уточнить, попадает ли оно туда из внешнего интерфейса, и всё равно проверять на границе системы.
- Как одним правилом закрыть внедрение команд языка запросов? Использовать параметризованные запросы: код запроса и данные передаются раздельно.
Основание и что делать при сомнении
Модуль опирается на: ГОСТ Р 56939-2016 «Защита информации. Разработка безопасного программного обеспечения», приказ ФСТЭК России от 11.02.2013 № 17.
Если ситуация не описана в модуле и вы не уверены в правильном действии, не принимайте решение самостоятельно: обратитесь к руководителю и в службу информационной безопасности до того, как выполнить операцию с данными или доступами.