1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
|
---
title: Безопасность веб-приложения Django
slug: Learn/Server-side/Django/web_application_security
translation_of: Learn/Server-side/Django/web_application_security
---
<div>{{LearnSidebar}}</div>
<div>{{PreviousMenuNext("Learn/Server-side/Django/Deployment", "Learn/Server-side/Django/django_assessment_blog", "Learn/Server-side/Django")}}</div>
<p class="summary">Защита пользовательских данных - важная часть проектирования любого веб-сайта.Ранее мы рассматривали некоторые наиболее распространенные угрозы безопасности в теме <a href="https://developer.mozilla.org/en-US/docs/Web/Security">Веб безопасность</a>. В данной статье будет представлена практическая демонстрация того, как встроенные механизмы защиты Django's обрабатывают подобные угрозы.</p>
<table class="learn-box standard-table">
<tbody>
<tr>
<th scope="row">Требования:</th>
<td>Прочитайте тему <a href="https://developer.mozilla.org/en-US/docs/Web/Security">Веб безопасность</a>. Завершите изучение предыдущих частей руководства до <a href="/en-US/docs/Learn/Server-side/Django/Forms">Руководство часть 9: Работа с формами </a>включительно.</td>
</tr>
<tr>
<th scope="row">Цель:</th>
<td>Понять, что нужно делать (или наоборот не делать), для обеспечения безопасности вашего веб-приложения.</td>
</tr>
</tbody>
</table>
<h2 id="Обзор">Обзор</h2>
<p>Тема <a href="https://developer.mozilla.org/en-US/docs/Web/Security">Веб безопасность</a> рассматривает значение безопасности веб-приложения для проектирования серверного приложения и некоторые из наиболее распространенных угроз, от которых вам может потребоваться защита. Одна из ключевых идей этой темы состоит в том, что практически все атаки будут успешны, если веб-приложение доверяет пользовательским данным (например данным из браузера).</p>
<div class="warning">
<p><strong>Важно:</strong> Наиболее важный урок, который вы должны усвоить, состоит в том - что никогда не стоит доверять переданным пользователем данным. Они включают в себя GET параметры в URL, тело POST запроса, HTTP заголовки, cookies, загруженные пользователем данные и т.д. Всегда проверяйте и обрабатывайте все входные данные. Всегда готовьтесь к худшему.</p>
</div>
<p>Хорошей новостью для всех разработчиков, использующих Django, является то, что большинство известных атак обрабатывается фреймворком! Статья <a href="https://docs.djangoproject.com/en/2.0/topics/security/">Безопасность в Django</a> (Django docs) описывает методы обеспечения безопасности Django и стратегии защиты веб-приложения разработанного на данном фреймворке.</p>
<h2 id="Распространенные_угрозыметоды_защиты">Распространенные угрозы/методы защиты</h2>
<p>Мы не будем дублировать документацию Django и в данной статье продемонстрируем некоторые основные методы обеспечения безопасности в контексте разрабатываемого в данном руководстве приложения <a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">LocalLibrary</a>.</p>
<h3 id="Межсайтовый_скриптинг_(XSS)">Межсайтовый скриптинг (XSS)</h3>
<p>XSS это термин, применяющийся для описания класса атак, позволяющего атакующему, через веб-сайт внедрить скрипты, которые будут выполнены на устройстве зашедшего на страницу пользователя. Часто это происходит через сохранение вредоносного кода в базе данных, откуда данный код будет возвращен и выполнен для запросившего некие данные пользователя (типичный пример - сохранение тега <script> с вредоносным кодом в комментарии, который может увидеть другой пользователь). Другой вектор атаки - в том чтобы сгенерировать определенную ссылку, при клике на которую пользователь запустит выполнение некоего замаскированного кода JavaScript в своем браузере.</p>
<p>Система шаблонов Django защищает от большинства XSS атак, <a href="https://docs.djangoproject.com/en/2.0/ref/templates/language/#automatic-html-escaping">экранируя определенные символы</a>, считающиеся "опасными" в HTML. Мы можем продемонстрировать это, попытавшись внедрить произвольный JavaScript код в наше приложение LocalLibrary через форму добавления автора, созданную в <a href="/en-US/docs/Learn/Server-side/Django/Forms">Руководство часть 9: Работа с формами</a>.</p>
<ol>
<li>Запустите веб-сайт, используя сервер разработки (<code>python3 manage.py runserver</code>).</li>
<li>Откройте сайт в вашем браузере и войдите под аккаунтом супер-пользователя.</li>
<li>Перейдите на страницу добавления автора (она должна быть доступна по URL: <code><a href="http://127.0.0.1:8000/catalog/author/create/">http://127.0.0.1:8000/catalog/author/create/</a></code>).</li>
<li>Введите данные об имени и фамилии, датах рождения и смерти автора. Затем добавьте следующую строку в поле фамилии:<br>
<code><script>alert('Test alert');</script></code>.<br>
<img alt="Author Form XSS test" src="https://mdn.mozillademos.org/files/14305/author_create_form_alert_xss.png" style="border-style: solid; border-width: 1px; height: 245px; width: 594px;">
<div class="note">
<p><strong>Примечание:</strong> Это безобидный скрипт, который, если будет выполнен, отобразит окно с сообщением "Test alert" в вашем браузере. Если данное окно отображается при открытии страницы с созданной подобным образом записью - значит сайт уязвим перед атаками XSS.</p>
</div>
</li>
<li>Нажмите <strong>Submit</strong> для сохранения записи.</li>
<li>После сохранения автора - он должен быть отображен, как показано ниже. Так как сработала защита от XSS - команда <code>alert()</code> не будет запущена. Вместо этого скрипт будет отображаться как обычный текст.<img alt="Author detail view XSS test" src="https://mdn.mozillademos.org/files/14307/author_detail_alert_xss.png" style="border-style: solid; border-width: 1px; height: 248px; width: 986px;"></li>
</ol>
<p>Если вы посмотрите исходный HTML код, вы увидите, что "опасные" символы - например такие как скобки тегов - были заменены на их безопасные эквивалентные html сущности (к примеру <code>></code> на <code>&gt;</code>)</p>
<pre class="brush: html"><h1>Author: Boon&lt;script&gt;alert(&#39;Test alert&#39;);&lt;/script&gt;, David (Boonie) </h1>
</pre>
<p>Использование шаблонов Django защищает вас от большинства XSS атак. Однако существует возможность отключения данной защиты, при котором экранирование не будет автоматически применятся ко всем полям, которые не должны будут заполнятся пользователем(к примеру, поле <code>help_text</code> обычно заполняется не пользователем, поэтому Django не будет экранировать его значение).</p>
<p>Так же XSS атаки могут быть осуществлены через другие ненадежные источники данных, такие как cookies, сторонние сервисы или загруженные файлы (и прочие источники, данные которых не были специально обработаны перед отображением на странице). Если вы отображаете данные из этих источников, вы должны добавить ваш собственный обработчик для фильтрации данных.</p>
<h3 id="Межсайтовая_подделка_запроса_(CSRF)">Межсайтовая подделка запроса (CSRF)</h3>
<p>CSRF атаки позволяют атакующему выполнять действия от имени другого пользователя без его согласия. Например, предположим что есть хакер, который хочет добавить авторов в наше приложение LocalLibrary.</p>
<div class="note">
<p><strong>Примечание:</strong> Очевидно, что наш хакер делает это не ради денег! Более амбициозные хакеры могут использовать описываемый подход для выполнения более опасных задач (например, переводы денег пользователей на их личные счета и т.д).</p>
</div>
<p>Для того, чтобы сделать это, хакер может создать HTML файл, подобный продемонстрированному ниже, который будет содержать форму создания автора (похожую на ту, что мы разрабатывали в предыдущих частях руководства), которая будет отправлена как только данный файл будет загружен в браузер. Хакер отправит данный файл всем Библиотекарям и будет ждать пока кто-либо из них откроет файл (он содержит только безобидную информацию, честно!). Если файл будет открыт любым залогиненным пользователем, с правами Библиотекаря - тогда форма будет отправлена от его имени и создаст нового пользователя.</p>
<pre class="brush: html"><html>
<body onload='document.EvilForm.submit()'>
<form action="http://127.0.0.1:8000/catalog/author/create/" method="post" name='EvilForm'>
<table>
<tr><th><label for="id_first_name">First name:</label></th><td><input id="id_first_name" maxlength="100" name="first_name" type="text" value="Mad" required /></td></tr>
<tr><th><label for="id_last_name">Last name:</label></th><td><input id="id_last_name" maxlength="100" name="last_name" type="text" value="Man" required /></td></tr>
<tr><th><label for="id_date_of_birth">Date of birth:</label></th><td><input id="id_date_of_birth" name="date_of_birth" type="text" /></td></tr>
<tr><th><label for="id_date_of_death">Died:</label></th><td><input id="id_date_of_death" name="date_of_death" type="text" value="12/10/2016" /></td></tr>
</table>
<input type="submit" value="Submit" />
</form>
</body>
</html>
</pre>
<p>Запустите веб-сервер разработки и войдите в аккаунт супер-пользователя. Скопируйте приведенный выше текст в файл и затем откройте его в браузере. Вы должны получить CSRF ошибку, потому что у Django есть защита от атак данного вида!</p>
<p>Механизм защиты заключается в том, что вы добавляете тег шаблона <code>{% csrf_token %}</code> в вашу форму. Этот токен будет отображен в вашем HTML как показано ниже, со значением, уникальным для каждого запрашивающего форму пользователя.</p>
<pre class="brush: html"><input type='hidden' name='csrfmiddlewaretoken' value='0QRWHnYVg776y2l66mcvZqp8alrv4lb8S8lZ4ZJUWGZFA5VHrVfL2mpH29YZ39PW' />
</pre>
<p>Django генерирует уникальный для пользователя/браузера токен и отклоняет все формы, которые не содержат его или содержат его неверное значение.</p>
<p>Для продолжения использования данного вида атак, хакер теперь должен найти и добавить верный CSRF токен для каждого выбранного целью пользователя. Это означает, что хакер теперь не может использовать массовые рассылки одного вредоносного файла всем Библиотекарям, так как для каждого из них CSRF токен будет уникальным.</p>
<p>Защита Django от CSRF атак по умолчанию включена. Вам всегда следует использовать тег<code>{% csrf_token %}</code> в ваших формах и использовать <code>POST</code> для запросов, которые могут изменить или добавить данные в вашу базу данных.</p>
<h3 id="Другие_атаки">Другие атаки</h3>
<p>Django так же предоставляет защиту от других видов атак ( демонстрация большинства из которых была бы сложна новичкам для понимания и не слишком полезна ):</p>
<dl>
<dt>Защита от SQL инъекции</dt>
<dd>Уязвимость SQL инъекции позволяет атакующему выполнить произвольный SQL код в базе данных и получить доступ к данным (прочитать, отредактировать и изменить) независимо от текущих прав доступа пользователя. В большинстве случаев вы будете получать доступ к данным базы данных, используя сущности queryset/model Django. Используя их для генерации SQL запросов, вы получите корректно сформированный и экранированный запрос для выбранной базы данных. Если вам необходимо писать "сырые" запросы, вам так же нужно будет продумать защиту от инъекций.</dd>
<dt><span class="ILfuVd yZ8quc">Защита от Кликджекинга</span></dt>
<dd>В данном виде атак атакующий перехватывает ввод на видимом слое страницы и перенаправляет их на скрытый слой под ним. Этот метод может быть использован к примеру для отображения официального сайта банка, с перехватом данных для входа в невидимом <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe" title="The HTML Inline Frame Element (<iframe>) represents a nested browsing context, effectively embedding another HTML page into the current page. In HTML 4.01, a document may contain a head and a body or a head and a frameset, but not both a body and a frameset. However, an <iframe> can be used within a normal document body. Each browsing context has its own session history and active document. The browsing context that contains the embedded content is called the parent browsing context. The top-level browsing context (which has no parent) is typically the browser window."><code><iframe></code></a>, который контролирует атакующий. Django содержит <a href="https://docs.djangoproject.com/en/2.0/ref/clickjacking/#clickjacking-prevention">защиту от кликджекинга</a> в виде <code><a href="https://docs.djangoproject.com/en/2.0/ref/middleware/#django.middleware.clickjacking.XFrameOptionsMiddleware" title="django.middleware.clickjacking.XFrameOptionsMiddleware">промежуточного програмного обеспечения (middleware) X-Frame-Options</a>,</code> который поддерживается браузерами и может запретить отображение страницы внутри <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe" title="The HTML Inline Frame Element (<iframe>) represents a nested browsing context, effectively embedding another HTML page into the current page. In HTML 4.01, a document may contain a head and a body or a head and a frameset, but not both a body and a frameset. However, an <iframe> can be used within a normal document body. Each browsing context has its own session history and active document. The browsing context that contains the embedded content is called the parent browsing context. The top-level browsing context (which has no parent) is typically the browser window."><code><iframe></code></a>.</dd>
<dt>SSL/HTTPS</dt>
<dd>SSL/HTTPS может быть использован на веб-сервере для шифрования всего трафика между сервером и пользователем, включая данные входа, которые иначе будут отправляться как обычный текст (который сможет прочитать любой перехвативший запрос человек). Использование HTTPS высоко рекомендовано. Если используется HTTPS, Django позволяет использовать следующие методы защиты:</dd>
</dl>
<ul>
<li><a href="https://docs.djangoproject.com/en/2.0/ref/settings/#std:setting-SECURE_PROXY_SSL_HEADER"><code>SECURE_PROXY_SSL_HEADER</code></a> может быть использовано для проверки что всегда используется безопасное подключение, даже если данные поступают из прокси, использующего протокол отличный от HTTP.</li>
<li><a href="https://docs.djangoproject.com/en/2.0/ref/settings/#std:setting-SECURE_SSL_REDIRECT"><code>SECURE_SSL_REDIRECT</code></a> используется для перенаправления всех запросов с HTTP на HTTPS.</li>
<li>Используйте <a href="https://docs.djangoproject.com/en/2.0/ref/middleware/#http-strict-transport-security">HTTP Strict Transport Security</a> (HSTS). Этот HTTP заголовок информирует браузер о том, что все последующие запросы должны всегда использовать HTTPS. Совместно с перенаправлением HTTP запросов на HTTPS, эта опция позволяет обеспечить использование HTTPS в каждом запросе. HSTS может так же быть настроен опциями <a href="https://docs.djangoproject.com/en/2.0/ref/settings/#std:setting-SECURE_HSTS_SECONDS"><code>SECURE_HSTS_SECONDS</code></a> и <a href="https://docs.djangoproject.com/en/2.0/ref/settings/#std:setting-SECURE_HSTS_INCLUDE_SUBDOMAINS"><code>SECURE_HSTS_INCLUDE_SUBDOMAINS</code></a> или на веб-сервере.</li>
<li>Используйте ‘безопасные’ cookies выставив <a href="https://docs.djangoproject.com/en/2.0/ref/settings/#std:setting-SESSION_COOKIE_SECURE"><code>SESSION_COOKIE_SECURE</code></a> и <a href="https://docs.djangoproject.com/en/2.0/ref/settings/#std:setting-CSRF_COOKIE_SECURE"><code>CSRF_COOKIE_SECURE</code></a> в <code>True</code>. Это позволит обеспечить пересылку данных cookies только через протокол HTTPS.</li>
</ul>
<dl>
<dt>Валидация заголовка Host</dt>
<dd>Используйте <a href="https://docs.djangoproject.com/en/2.0/ref/settings/#std:setting-ALLOWED_HOSTS"><code>ALLOWED_HOSTS</code></a> чтобы принимать только запросы от доверенных хостов.</dd>
</dl>
<p>Так же существует множество других техник защиты и указаний по их использованию. Мы надеемся, что данная статья дала вам понимание, какие техники Django предлагает для обеспечения безопасности. Мы надеемся, что вы продолжите изучение этого вопроса по документации Django.</p>
<ul>
</ul>
<h2 id="Подводим_итоги">Подводим итоги</h2>
<p>Django имеет методы обеспечения защиты от распространенных видов атак, включая XSS и CSRF атаки. В данной статье мы продемонстрировали, как различные виды атак обрабатываются Django на примере нашего приложения <em>LocalLibrary</em>. Мы так же кратко рассмотрели другие виды уязвимостей и методы защиты от них.</p>
<p>Это было очень краткое погружение в вопрос веб-безопасности. Мы крайне рекомендуем вам прочитать <a href="https://docs.djangoproject.com/en/2.0/topics/security/">Безопасность в Django</a> для более глубокого понимания.</p>
<p>Следующим и последним шагом в данном руководстве будет выполнение <a href="/en-US/docs/Learn/Server-side/Django/django_assessment_blog">самостоятельной работы</a>.</p>
<h2 id="Смотрите_также">Смотрите также</h2>
<ul>
<li><a href="https://docs.djangoproject.com/en/2.0/topics/security/">Безопасность в Django</a> (Django docs)</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/Security">Веб безопасность</a> (MDN)</li>
<li><a href="/en-US/docs/Web/Security/Securing_your_site">Безопасность вашего сайта</a> (MDN)</li>
</ul>
<p>{{PreviousMenuNext("Learn/Server-side/Django/Deployment", "Learn/Server-side/Django/django_assessment_blog", "Learn/Server-side/Django")}}</p>
<p> </p>
<h2 id="In_this_module">In this module</h2>
<ul>
<li><a href="/en-US/docs/Learn/Server-side/Django/Introduction">Django introduction</a></li>
<li><a href="/en-US/docs/Learn/Server-side/Django/development_environment">Setting up a Django development environment</a></li>
<li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Django Tutorial: The Local Library website</a></li>
<li><a href="/en-US/docs/Learn/Server-side/Django/skeleton_website">Django Tutorial Part 2: Creating a skeleton website</a></li>
<li><a href="/en-US/docs/Learn/Server-side/Django/Models">Django Tutorial Part 3: Using models</a></li>
<li><a href="/en-US/docs/Learn/Server-side/Django/Admin_site">Django Tutorial Part 4: Django admin site</a></li>
<li><a href="/en-US/docs/Learn/Server-side/Django/Home_page">Django Tutorial Part 5: Creating our home page</a></li>
<li><a href="/en-US/docs/Learn/Server-side/Django/Generic_views">Django Tutorial Part 6: Generic list and detail views</a></li>
<li><a href="/en-US/docs/Learn/Server-side/Django/Sessions">Django Tutorial Part 7: Sessions framework</a></li>
<li><a href="/en-US/docs/Learn/Server-side/Django/Authentication">Django Tutorial Part 8: User authentication and permissions</a></li>
<li><a href="/en-US/docs/Learn/Server-side/Django/Forms">Django Tutorial Part 9: Working with forms</a></li>
<li><a href="/en-US/docs/Learn/Server-side/Django/Testing">Django Tutorial Part 10: Testing a Django web application</a></li>
<li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Django Tutorial Part 11: Deploying Django to production</a></li>
<li><a href="/en-US/docs/Learn/Server-side/Django/web_application_security">Django web application security</a></li>
<li><a href="/en-US/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li>
</ul>
<p> </p>
|