Валидация и санитизация ввода
Большинство уязвимостей сводится к одному: программа поверила вводу, который не должна была.
Валидация — проверка, что ввод соответствует ожиданиям (тип, формат, диапазон). Санитизация — приведение ввода к безопасному виду перед использованием.
Два разных действия
Их часто путают, но это разные шаги:
- Валидация отвечает на вопрос «ожидали ли мы такие данные?». Возраст — это число от 0 до 120? Email похож на email? Если нет — отклоняем.
- Санитизация отвечает на вопрос «как безопасно это использовать?». Например, экранировать данные перед вставкой в HTML.
Часто нужны оба: сначала проверить, потом безопасно использовать в нужном контексте.
Allowlist надёжнее blocklist
Есть два подхода к проверке. Blocklist (чёрный список) пытается перечислить всё плохое и запретить — но злоумышленник придумает то, чего в списке нет. Allowlist (белый список) описывает, что разрешено, и отвергает всё остальное. Allowlist почти всегда надёжнее, потому что список допустимого конечен и его проще задать точно.
import re
# Allowlist: имя пользователя — только латиница, цифры, _ , длина 3-16
pattern = re.compile(r"^[a-zA-Z0-9_]{3,16}$")
def valid_username(name):
return bool(pattern.fullmatch(name))
for name in ["alice_42", "hi", "drop table users", "плохой", "ok_name"]:
print(f"{name!r:20} ->", valid_username(name))
Вывод:
'alice_42' -> True 'hi' -> False 'drop table users' -> False 'плохой' -> False 'ok_name' -> True
Мы разрешили строго определённый набор символов и длину — всё подозрительное отсеялось само, без перечисления «плохого».
Проверять нужно на сервере
Проверки на клиенте (в браузере) — это удобство для пользователя, а не безопасность. Их легко обойти: запрос можно отправить напрямую, минуя интерфейс. Решающая валидация всегда на сервере, где её нельзя обойти. Клиентская проверка — приятный бонус, серверная — обязательна.
Нормализация перед проверкой
Иногда один и тот же ввод можно записать по-разному (разный регистр, лишние пробелы, разные кодировки). Перед проверкой данные стоит привести к единой форме (нормализовать), иначе обходной вариант проскочит мимо валидации. Простой пример — обрезать пробелы и привести email к нижнему регистру перед сравнением.
Связь с предыдущими уязвимостями
| Уязвимость | Что её закрывает |
| SQL-инъекция | параметризация + валидация типа |
| XSS | экранирование вывода (санитизация под контекст) |
| Переполнения, сбои | проверка длины и диапазона |
Видно, что валидация и санитизация — сквозная защита: они стоят на пути почти каждой уязвимости из этого курса.
Итог
- Валидация проверяет, что ввод ожидаемый; санитизация — что его безопасно использовать.
- Allowlist (что разрешено) надёжнее blocklist (что запрещено).
- Решающая проверка всегда на сервере — клиентскую легко обойти.
- Нормализуйте ввод перед проверкой, чтобы не пропустить обходные варианты.