Безопасность: XSS, CSRF, SQL-инъекции
Веб полон типовых атак: XSS, CSRF, SQL-инъекции, clickjacking. Django защищает от большинства из них по умолчанию — если вы не отключаете защиту сами.
Суть: автоэкранирование шаблонов гасит XSS, CSRF-токен защищает формы, ORM с параметрами — от SQL-инъекций, middleware добавляет защитные заголовки. Главное — не выключать эти механизмы по незнанию.
Безопасность по умолчанию
Django спроектирован так, что безопасное поведение — поведение по умолчанию. Это огромное преимущество: новичок защищён, даже не зная о большинстве угроз. Но эту защиту можно случайно отключить, поэтому важно понимать, что и от чего вас бережёт.
XSS — межсайтовый скриптинг
XSS — это когда злоумышленник внедряет JavaScript через пользовательский ввод (например, в комментарий), и он выполняется у других посетителей. Django гасит это автоэкранированием: любая переменная в шаблоне по умолчанию экранируется, опасные символы превращаются в безопасные сущности. <script> станет текстом. Опасность появляется только если вы вручную ставите |safe на недоверенные данные.
CSRF — подделка межсайтовых запросов
CSRF — атака, где чужой сайт заставляет браузер пользователя отправить запрос на ваш сайт от его имени (например, перевести деньги). Django защищается токеном: в каждую форму вставляется секретный {% csrf_token %}, который проверяется на POST. Чужой сайт токен не знает — запрос отклоняется.
SQL-инъекции
SQL-инъекция — внедрение SQL через ввод ('; DROP TABLE users; --). ORM защищает автоматически: он передаёт значения как параметры, а не вклеивает в текст запроса. Вот в чём разница на чистом Python:
# Попробуй сам ▶ — почему параметры безопаснее склейки строк
def build_query_unsafe(user_input):
# ОПАСНО: ввод вклеивается прямо в SQL
return f"SELECT * FROM users WHERE name = '{user_input}'"
def build_query_safe(user_input):
# БЕЗОПАСНО: значение идёт отдельным параметром
query = "SELECT * FROM users WHERE name = %s"
params = [user_input]
return query, params
attack = "'; DROP TABLE users; --"
print("Небезопасно:")
print(" ", build_query_unsafe(attack)) # SQL сломан, таблица под угрозой
print("Безопасно (как в ORM):")
q, p = build_query_safe(attack)
print(" запрос:", q)
print(" параметры:", p) # ввод — просто значение, не код
В безопасном варианте драйвер базы передаёт attack как обычную строку-значение, и она никогда не интерпретируется как SQL. Django ORM всегда работает так.
Прочие защиты
Middleware добавляют защитные HTTP-заголовки: X-Frame-Options против clickjacking (встраивания вашего сайта в чужой iframe), SecurityMiddleware для HTTPS-редиректа и HSTS. Django 6.0 принёс встроенную поддержку Content Security Policy (CSP) — политики, ограничивающей источники скриптов. ALLOWED_HOSTS защищает от подмены заголовка Host.
Атака │ Защита Django (по умолчанию)
─────────────────┼──────────────────────────────────
XSS │ автоэкранирование шаблонов
CSRF │ {% csrf_token %} + middleware
SQL-инъекция │ параметризованные запросы ORM
clickjacking │ X-Frame-Options (middleware)
подмена Host │ ALLOWED_HOSTS
внедрение скр. │ Content Security Policy (6.0)
Как это работает под капотом
Защита от XSS — это, по сути, замена опасных символов на безопасные сущности перед выводом. Та самая функция, что Django применяет к каждой переменной шаблона:
# Попробуй сам ▶ — автоэкранирование как в шаблонах
def escape(text):
replacements = {
"&": "&", "<": "<", ">": ">",
'"': """, "'": "'",
}
for char, entity in replacements.items():
text = text.replace(char, entity)
return text
comment = '<script>alert("взлом")</script>'
print("Ввод: ", comment)
print("Вывод: ", escape(comment)) # станет безопасным текстом
Частые ошибки
- Бездумно ставить |safe. Это отключает защиту от XSS на конкретной переменной.
- Отключать CSRF (@csrf_exempt) без понимания. Открывает форму для подделки запросов.
- Собирать SQL строками через raw/extra с f-строками. Возвращает риск инъекций. Используйте параметры.
- Оставлять DEBUG=True и пустой ALLOWED_HOSTS на проде. Утечка трассировок и подмена Host.
Best practices
- Не отключайте встроенные защиты без веской причины и понимания последствий.
- Используйте ORM; для сырого SQL — только параметры, не склейку строк.
- На проде:
DEBUG=False, заполненныйALLOWED_HOSTS, HTTPS, безопасные куки. - Прогоняйте
manage.py check --deploy— он найдёт небезопасные настройки.
Итоги
Django защищает от XSS (автоэкранирование), CSRF (токен), SQL-инъекций (параметры ORM) и других атак по умолчанию. Ваша задача — не отключать эти механизмы по незнанию и соблюдать прод-настройки. Понимание угроз делает вас сильнее самой защиты. Дальше — финальный раздел про деплой и REST API.