Веб-безопасность
Python-приложение редко ломают через сам Python. Ломают границу между вашим кодом и браузером — там, где строка от пользователя превращается в HTML, где кука решает, кем считать запрос, и где токен подменяет собой обращение к базе. Все уязвимости этой темы имеют одну общую форму: данные, пришедшие снаружи, где-то были приняты за код или за доказательство личности. XSS — это данные, принятые за разметку. CSRF — чужой запрос, принятый за ваш, потому что браузер сам приложил куку. Подделанный JWT — payload, принятый за истину без проверки подписи. Разобрав эту форму один раз, вы узнаёте её и в SQL-инъекции, и в десериализации pickle, и в подстановке шаблона.
Python-специфика здесь неожиданная — фреймворки закрывают большинство дыр по умолчанию, а разработчик отключает защиту руками. Django экранирует {{ value }} в каждом шаблоне, пока кто-то не напишет mark_safe, чтобы «прошла вёрстка». CsrfViewMiddleware стоит в стандартном MIDDLEWARE, пока кто-то не повесит @csrf_exempt, чтобы «починить» падающий AJAX. PyJWT требует явный список algorithms, пока кто-то не подставит туда значение из заголовка самого токена. Поэтому вопрос звучит как «что такое XSS», а проверяют другое — понимаете ли вы, почему экранировать надо на выводе и почему у каждого контекста вывода своё экранирование. Слои ниже разбирают эти механизмы по одному.
Карта темы
- Аутентификация и авторизация — кто вы против того, что вам можно; жёсткий порядок шагов, разница
401и403и проверка владения объектом. - Куки и состояние поверх HTTP —
Set-Cookie, область видимости по домену и пути, сессия Django и почему браузер прикладывает куку сам. - XSS — данные, принятые за разметку — хранимый, отражённый и DOM-based; автоэкранирование шаблонов и выбор инструмента под контекст вывода.
- Флаги и подпись куки — что реально делают
HttpOnly,SecureиSameSite, зачем поверх них нужен CSRF-токен и почему подпись не является шифрованием. - JWT — подписан, но не зашифрован — три сегмента
base64url, атакиalg:noneи путаницаHMAC/RSA, цена отзыва токена и выбор хранилища в браузере.
Частые ошибки и ловушки
| Ошибка | Последствие |
|---|---|
Считать HttpOnly шифрованием значения куки | Флаг лишь убирает куку из document.cookie; значение как было читаемым, так и осталось — в трафике, в отладчике, в профиле браузера |
Читать Secure как «кука не уходит на сервер» | Secure только запрещает отправку по чистому HTTP; сервер получает куку в каждом запросе — на этом построена вся схема сессий |
| Путать подпись и шифрование | HMAC даёт целостность — сервер заметит подмену; конфиденциальности он не даёт, содержимое подписанной куки и payload JWT читает любой, кто их держит |
| Экранировать на входе, а не на выводе | Одна и та же строка безопасна в теле HTML и опасна внутри <script> или в href; нужный контекст известен только в точке вывода |
Помечать пользовательские данные mark_safe или фильтром safe | Автоэкранирование выключается ровно для тех данных, ради которых работало — самый частый способ вернуть XSS в защищённый по умолчанию проект |
Проверить is_authenticated и взять объект по pk из URL | Запрос аутентифицирован, но не авторизован — любой залогиненный пользователь читает чужой объект, подставив другой pk |
Доверять полю alg из заголовка входящего токена | Алгоритм проверки выбирает атакующий — отсюда alg:none и подпись HS256 публичным ключом RSA |
Считать JWT мгновенно отзываемым | Токен валиден до exp у любого, кто его получил; отзыв требует состояния на сервере — денилиста jti, версии токена или коротких access-токенов |
Значение для собеседований
Тема почти всегда идёт лесенкой из трёх ступеней, и на каждой проверяют не термин, а механизм. Джуниора спрашивают про разницу аутентификации и авторизации и про то, что такое кука и XSS — здесь ждут не определения, а правильного порядка («сначала кто, потом что можно») и понимания, что кука лежит в браузере, а не на сервере, и что XSS исполняется у каждого зрителя страницы. Мидла спрашивают, как защитить куку и что такое JWT. Тут провал даёт не незнание флагов, а неверная модель — очень многие уверены, что HttpOnly шифрует значение, а подпись делает payload секретным. Одна фраза «подпись даёт целостность, но не конфиденциальность» закрывает сразу два вопроса.
Сеньорские вопросы — про защиту от XSS и про ловушки JWT, и оба про эшелонирование. По XSS засчитывают ответ, где экранирование привязано к контексту вывода, санитизация делается проверенной библиотекой, а CSP и HttpOnly названы вторым рубежом, а не решением. Ответы «ограничу длину поля» и «у нас HTTPS» проваливают вопрос сразу. По JWT ждут три пункта — секретам не место в payload, ожидаемый alg фиксирует сервер, отзыв стоит состояния. Самая частая ошибка на этом уровне — говорить о JWT как о строгом улучшении сессий, не назвав, чем за stateless заплатили. Хороший ответ звучит как размен, а не как реклама.