Меры Безопасности
Веб-приложения обычно сталкиваются со множеством проблем безопасности, и очень сложно сделать всё правильно. Flask пытается решить некоторые из этих проблем за вас, но есть и несколько других, о которых вам нужно позаботиться самостоятельно.
Переполнение сайтом (XSS)
Переполнение сайтом — это концепция внедрения произвольного HTML (и вместе с ним JavaScript) в контекст веб-сайта. Для решения этой проблемы разработчики должны правильно экранировать текст, чтобы он не содержал произвольных HTML-тегов. Дополнительную информацию можно найти в статье Википедии о Переполнении сайтом.
Flask настраивает Jinja2 для автоматической экранизации всех значений, если явно не указано обратное. Это должно исключить все проблемы с XSS, вызванные в шаблонах, но всё ещё есть другие места, где нужно быть осторожным:
- генерация HTML без помощи Jinja2
- вызов
Markupна данных, отправленных пользователем - отправка HTML из загруженных файлов, никогда этого не делайте, используйте заголовок
Content-Disposition: attachmentдля предотвращения этой проблемы. - отправка текстовых файлов из загруженных файлов. Некоторые браузеры используют угадывание типа контента, основанное на первых нескольких байтах, поэтому пользователи могут обмануть браузер, чтобы он выполнил HTML.
Ещё одна важная вещь — это атрибуты без кавычек. Хотя Jinja2 может защитить вас от проблем с XSS, экранируя HTML, есть одна вещь, от которой он не может вас защитить: XSS через инъекцию атрибутов. Чтобы противостоять этому потенциальному вектору атаки, обязательно заключайте ваши атрибуты в двойные или одинарные кавычки при использовании выражений Jinja в них:
<a href="{{ href }}">the text</a>
Зачем это нужно? Потому что если вы этого не сделаете, злоумышленник может легко внедрить пользовательские обработчики JavaScript. Например, злоумышленник может внедрить такой фрагмент HTML+JavaScript:
onmouseover=alert(document.cookie)
Когда пользователь затем наведёт курсор мыши на ссылку, cookie будет представлен пользователю в окне всплывающего сообщения. Но вместо того, чтобы показывать cookie пользователю, хороший злоумышленник может также выполнить любой другой JavaScript-код. В сочетании с инъекциями CSS злоумышленник может даже заставить элемент заполнить всю страницу, так что пользователю нужно будет просто навести курсор мыши на любую часть страницы, чтобы вызвать атаку.
Подделка межсайтовых запросов (CSRF)
Ещё одна большая проблема — CSRF. Это очень сложная тема, и я не буду подробно её описывать здесь, а просто упомяну, что это такое и как теоретически её предотвратить.
Если ваша информация об авторизации хранится в cookie, у вас есть неявное управление состоянием. Состояние «быть авторизованным» контролируется cookie, и это cookie отправляется с каждым запросом на страницу. К сожалению, это включает в себя запросы, инициированные сторонними сайтами. Если вы этого не учтёте, некоторые люди могут обмануть пользователей вашего приложения с помощью социальной инженерии, чтобы те выполняли глупые действия, не зная об этом.
Предположим, у вас есть определённый URL, который, при отправке POST запросов, удалит профиль пользователя (скажем http://example.com/user/delete). Если теперь злоумышленник создаёт страницу, которая отправляет POST-запрос на эту страницу с помощью JavaScript, то ему нужно просто обмануть некоторых пользователей, чтобы они загрузили эту страницу, и их профили будут удалены.
Представьте, что вы управляете Facebook с миллионами одновременных пользователей, и кто-то отправляет ссылки на изображения милых котят. Когда пользователи перейдут на эту страницу, их профили будут удалены, пока они смотрят на изображения пушистых котов.
Как можно предотвратить это? В основном для каждого запроса, который изменяет контент на сервере, вам нужно либо использовать одноразовый токен и сохранить его в cookie и также передать его с данными формы. После получения данных на сервере снова, вам нужно будет сравнить два токена и убедиться, что они равны.
Почему Flask не делает это за вас? Идеальное место для этого — в рамках проверки форм, которая не существует в Flask.
Безопасность JSON
В Flask 0.10 и ниже jsonify() не сериализовал массивы верхнего уровня в JSON. Это произошло из-за уязвимости в ECMAScript 4.
ECMAScript 5 закрыл эту уязвимость, поэтому уязвимыми остаются только очень старые браузеры. У всех этих браузеров есть другие более серьёзные уязвимости, поэтому это поведение было изменено, и jsonify() теперь поддерживает сериализацию массивов.
© 2007–2020 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/0.12.x/security/