Зарегистрируйтесь, чтобы продолжить обучение

Безопасность Python: Веб-разработка (Flask)

Безопасность сайтов — тема, о которой редко говорят с новичками. При этом от нее зависит судьба любого бизнеса. Проблемы с безопасностью могут привести к утечке данных пользователей и даже к полному уничтожению сайта.

Исследования показывают, что у подавляющего большинства сайтов есть проблемы с безопасностью, и они подвержены атакам. И иногда случаются громкие взломы и утечки данных сотен тысяч и миллионов пользователей.

В этом уроке поговорим о том, как стоит поступать, чтобы злоумышленники не получили данные пользователей, и как обезопасить свой сайт от атак. Об этой теме нужно говорить как можно раньше, что позволит избежать фатальных ошибок.

Защищаем сайт от атак

Чтобы сайты были защищены, нужно соблюдать первое главное правило безопасности — никогда не доверяйте пользователям. В первую очередь это правило касается данных, которые они вводят.

Представим, что нам нужно вывести имя пользователя, взятое из адреса: /users/nick. Код, который реализует эту функциональность, рассчитывает на то, что в адресе используются только допустимые имена. Но что произойдет, если попытаться открыть такой адрес:

# Вот, что может произойти, если доверять данным,
# которые ввел пользователь, и не обрабатывать их:
http://localhost:8000/users/%3Cscript%3Ealert('attack!')%3B%3C%2Fscript%3E

Image processing attack

В этом адресе закодирован код на JavaScript, который в оригинале выглядит так:

<script>
  alert('attack!');
</script>

Проблема в том, что этот код не отобразился, а был вставлен в HTML как его часть и выполнился. Для браузера такой JS выглядит как часть страницы. Если попробовать открыть получившийся HTML, то он будет выглядеть так:

<h1><script>alert('attack!');</script></h1>

Совсем не то, что мы ожидали. Такая атака называется XSS или «межсайтовый скриптинг». Она работает так:

  1. На страницу внедряется вредоносный код, который выполняется в браузере пользователя
  2. Этот код отправляет информацию о пользователе на сервер злоумышленника

Специфика подобных атак заключается в том, что вредоносный код может использовать авторизацию пользователя в веб-системе. Так он получает к ней расширенный доступ или авторизационные данные пользователя. XSS относится к одному из самых распространенных типов атак из-за большого количества уязвимостей даже на сайтах больших и серьезных компаний, например, Facebook.

Уязвимость возникает из-за доверия к пользовательским данным. В нашем коде вывод слага делается без предварительной обработки. Но это неправильно.

Дело в том, что браузер пытается интерпретировать как HTML всё, что похоже на него. Если в исходном коде встречается конструкция <текст>, то браузер автоматически считает ее тегом. Чтобы вывести данные, которые не рассматриваются как HTML, нужно использовать специализированные функции для превращения теги в html entities:

import html


text = "A 'quote' is <b>bold</b>"

print(html.escape(text))
# => A 'quote' is &lt;b&gt;bold&lt;/b&gt;

Получившаяся строка содержит безопасное описание тегов в виде html entities. Например, &lt; отобразится как <, а &gt; как >. Используемый нами шаблонизатор Jinja2 внутри Flask уже настроен на автоматическое экранирование всех значений. Поэтому, если применить простой вывод переменной:

<h1>{{ name}}</h1>

Мы получим следующий результат:

Image processing escape

Автоматическое экранирование помогает исключить проблемы с 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. Но чтобы их понимать, важно разобраться в принципе работы базы данных.


Дополнительные материалы

  1. Безопасность приложений на всех фреймворках

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff