Безопасность сайтов — тема, о которой редко говорят с новичками. При этом от нее зависит судьба любого бизнеса. Проблемы с безопасностью могут привести к утечке данных пользователей и даже к полному уничтожению сайта.
Исследования показывают, что у подавляющего большинства сайтов есть проблемы с безопасностью, и они подвержены атакам. И иногда случаются громкие взломы и утечки данных сотен тысяч и миллионов пользователей.
В этом уроке поговорим о том, как стоит поступать, чтобы злоумышленники не получили данные пользователей, и как обезопасить свой сайт от атак. Об этой теме нужно говорить как можно раньше, что позволит избежать фатальных ошибок.
Защищаем сайт от атак
Чтобы сайты были защищены, нужно соблюдать первое главное правило безопасности — никогда не доверяйте пользователям. В первую очередь это правило касается данных, которые они вводят.
Представим, что нам нужно вывести имя пользователя, взятое из адреса: /users/nick. Код, который реализует эту функциональность, рассчитывает на то, что в адресе используются только допустимые имена. Но что произойдет, если попытаться открыть такой адрес:
# Вот, что может произойти, если доверять данным,
# которые ввел пользователь, и не обрабатывать их:
http://localhost:8000/users/%3Cscript%3Ealert('attack!')%3B%3C%2Fscript%3E
В этом адресе закодирован код на JavaScript, который в оригинале выглядит так:
<script>
alert('attack!');
</script>
Проблема в том, что этот код не отобразился, а был вставлен в HTML как его часть и выполнился. Для браузера такой JS выглядит как часть страницы. Если попробовать открыть получившийся HTML, то он будет выглядеть так:
<h1><script>alert('attack!');</script></h1>
Совсем не то, что мы ожидали. Такая атака называется XSS или «межсайтовый скриптинг». Она работает так:
- На страницу внедряется вредоносный код, который выполняется в браузере пользователя
- Этот код отправляет информацию о пользователе на сервер злоумышленника
Специфика подобных атак заключается в том, что вредоносный код может использовать авторизацию пользователя в веб-системе. Так он получает к ней расширенный доступ или авторизационные данные пользователя. XSS относится к одному из самых распространенных типов атак из-за большого количества уязвимостей даже на сайтах больших и серьезных компаний, например, Facebook.
Уязвимость возникает из-за доверия к пользовательским данным. В нашем коде вывод слага делается без предварительной обработки. Но это неправильно.
Дело в том, что браузер пытается интерпретировать как HTML всё, что похоже на него. Если в исходном коде встречается конструкция <текст>
, то браузер автоматически считает ее тегом. Чтобы вывести данные, которые не рассматриваются как HTML, нужно использовать специализированные функции для превращения теги в html entities:
import html
text = "A 'quote' is <b>bold</b>"
print(html.escape(text))
# => A 'quote' is <b>bold</b>
Получившаяся строка содержит безопасное описание тегов в виде html entities. Например, <
отобразится как <
, а >
как >
. Используемый нами шаблонизатор Jinja2 внутри Flask уже настроен на автоматическое экранирование всех значений. Поэтому, если применить простой вывод переменной:
<h1>{{ name}}</h1>
Мы получим следующий результат:
Автоматическое экранирование помогает исключить проблемы с XSS атаками, но есть и другие места, где нужно быть осторожным:
- Генерация HTML без помощи Jinja2
- Обработка разметки, предоставляемой пользователем
- Обработка HTML кода из загруженных пользователем файлов
Хоть Jinja2 и защищает от XSS, экранируя HTML, есть два вида уязвимостей, от которых Jinja2 не может защитить:
- XSS путем внедрения в атрибуты. Чтобы защититься от таких атак, нужно заключать значения атрибутов в двойные или одинарные кавычки:
<input value="{{ value }}">
Если этого не сделать, то злоумышленник может с легкостью внедрить JS-код на страницу, например:
onclick = alert('attack!')
- Атрибут
href
тегаa
может содержатьjavascript:URI
, который браузер выполнит при нажатии:
<a href="{{ value }}">Нажми тут</a>
<a href="javascript:alert('attack!');">Нажми тут</a>
Чтобы защитить от такого вида атак, необходимо использовать заголовок ответа Content Security Policy (CSP).
Кроме XSS часто встречаются и другие виды атак, например, SQL Injection. Но чтобы их понимать, важно разобраться в принципе работы базы данных.
Дополнительные материалы
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.