Ось готовий урок, створений спеціально для тебе у стилі David Malan. Вмикай уяву, ніби ти зараз в аудиторії Sanders Theatre в Гарварді!
🛡️ Тема уроку: Безпека Django-додатків
1. 🔥 Вступ: Чому ми не залишаємо ключі під килимком?
Привіт, друзі! 👋
Уявіть собі таку ситуацію. Ви збудували неймовірний будинок. У ньому зручні меблі, розумне світло, повний холодильник їжі. Ви запрошуєте друзів на вечірку. Але є одна деталь: ви забули поставити вхідні двері.
Будь-хто з вулиці може зайти, з’їсти ваш бутерброд, переставити меблі або, що гірше, винести телевізор.
З веб-додатками — те саме. Ви можете написати геніальний код, створити красивий інтерфейс, але якщо ви проігнорували безпеку — ваш додаток це "прохідний двір".
Скажіть мені чесно: Ви б ввели номер своєї кредитної картки на сайті, який написав ваш сусід-першокурсник за одну ніч?
Отож-бо.
Сьогодні ми говоримо про Безпеку в Django. Чому саме Django? Тому що розробники цього фреймворку дотримуються філософії "batteries included" (все включено), і одна з найпотужніших "батарейок" — це вбудована система безпеки.
Наша мета сьогодні: Навчитися не залишати ключі під килимком і зрозуміти, як Django допомагає нам захищатися від "поганих хлопців" в інтернеті.
2. 🧠 Теоретична база: Три вершники апокаліпсису
Давайте не будемо занурюватися в нудні стандарти ISO, а розберемося інтуїтивно. У світі веб-безпеки є три найпопулярніші способи зломати ваш сайт. Django вміє з ними боротися, якщо ви йому не заважаєте.
1. SQL Injection (SQL-ін'єкція) — "Шпигун у ресторані"
Аналогія: Ви в ресторані. Ви пишете на папірці замовлення для офіціанта: "Принеси мені борщ". Офіціант несе папірець кухарю. Але уявіть, що хитрий хакер пише: "Принеси мені борщ; А ТАКОЖ віддай всі гроші з каси". Якщо кухар (база даних) наївний, він зробить і те, і інше.
Як це працює: Зловмисник вводить SQL-код у поле вводу (наприклад, логін), і база даних виконує цей код. Захист Django: Django ORM (Object-Relational Mapping). Він автоматично "екранує" (знешкоджує) все, що вводить користувач, перш ніж відправити запит у базу.
2. XSS (Cross-Site Scripting) — "Отруйний графіті"
Аналогія: Хакер малює на стіні вашого під'їзду (вашого сайту) оголошення: "Безкоштовні айфони тут!". Ваші сусіди (користувачі) вірять, йдуть туди й втрачають гаманці.
Як це працює: Хакер вставляє шкідливий JavaScript-код у коментар чи повідомлення на форумі. Коли інші користувачі відкривають сторінку, цей скрипт запускається в їхньому браузері і краде їхні дані (cookies, сесії). Захист Django: Шаблонізатор Django за замовчуванням не виконує те, що введено користувачем, а просто показує це як текст.
3. CSRF (Cross-Site Request Forgery) — "Підроблений підпис"
Аналогія: Хакер підсовує вам документ на підпис, прикривши текст іншим папірцем. Ви думаєте, що підписуєте доставку піци, а насправді — переписуєте квартиру на хакера.
Як це працює: Зловмисник створює фейкову форму на своєму сайті, яка відправляє запит на ваш банківський сайт, де ви зараз залогінені. Захист Django: CSRF-токен. Це як секретне рукостискання. Кожна форма, яку видає Django, має унікальний код. Якщо сервер отримує форму без цього коду — він її викидає.
3. 🧪 Приклади: Від небезпечного до надійного
Сценарій №1: Пошук користувача (SQL Injection)
Припустимо, ми шукаємо користувача за іменем.
🔴 Поганий код (ніколи так не робіть!):
def search_user(request):
username = request.GET.get('name')
# Ми склеюємо рядки прямо в SQL. Це дірка в безпеці!
query = f"SELECT * FROM auth_user WHERE username = '{username}'"
cursor.execute(query)
# ...
Запитання до вас: Що буде, якщо я введу ім'я ' OR '1'='1?
Відповідь: Запит перетвориться на SELECT * FROM auth_user WHERE username = '' OR '1'='1'. Умова 1=1 завжди істинна. База даних поверне всіх користувачів!
🟢 Хороший код (Django Style):
def search_user(request):
username = request.GET.get('name')
# Використовуємо ORM. Django сам перевірить, що username — це просто текст.
users = User.objects.filter(username=username)
# ...
Сценарій №2: Відображення коментаря (XSS)
Користувач залишає коментар: <script>alert('Hacked!');</script>.
🔴 Поганий код (в шаблоні HTML):
<!-- Фільтр safe каже Django: "Вір цьому тексту, він безпечний".
Це брехня! Не робіть цього з даними користувача. -->
<div>
{{ comment.text|safe }}
</div>
Результат: У кожного, хто зайде на сторінку, вискочить вікно "Hacked!".
🟢 Хороший код:
<!-- Django автоматично перетворить <script> на безпечні символи <script> -->
<div>
{{ comment.text }}
</div>
Результат: Користувачі просто побачать текст <script>... на екрані, але код не виконається.
Сценарій №3: Форма переказу грошей (CSRF)
Ви робите форму для переказу коштів.
🔴 Поганий код (форма в шаблоні):
<form method="post" action="/transfer/">
<input type="text" name="amount">
<button type="submit">Надіслати</button>
</form>
Проблема: Інший сайт може створити таку ж форму і відправити POST-запит на /transfer/ від вашого імені.
🟢 Хороший код:
<form method="post" action="/transfer/">
{% csrf_token %} <!-- Ось наш щит! -->
<input type="text" name="amount">
<button type="submit">Надіслати</button>
</form>
Результат: Django згенерує приховане поле з унікальним ключем. Якщо запит прийде без нього — помилка 403 Forbidden.
4. 🛠 Практична частина: Час захищати фортецю!
Спробуйте вирішити ці завдання. Уявіть, що ви проводите аудит безпеки.
Завдання 1: Знайди шпигуна У коді нижче є вразливість. Яка саме?
def profile_view(request):
user_id = request.GET.get('id')
# raw() дозволяє писати сирий SQL
user = User.objects.raw('SELECT * FROM auth_user WHERE id = %s' % user_id)
return render(request, 'profile.html', {'user': user})
Завдання 2: Лагодження дверей
У вас є шаблон, який виводить біографію користувача. Розробник хотів, щоб користувачі могли виділяти текст жирним (<b>), але випадково дозволив і скрипти.
{{ user.bio|safe }}
Завдання: Як змінити цей код, щоб він був безпечним, але все ще дозволяв тільки просте форматування? (Підказка: погугліть django-bleach або стандартні фільтри, але найпростіше рішення — просто прибрати safe).
Завдання 3: DEBUG = True
Ви залили сайт на реальний сервер (Production), але залишили в налаштуваннях settings.py:
DEBUG = True
ALLOWED_HOSTS = []
Питання: Чому це катастрофа? Що побачить хакер, якщо викличе помилку на сайті?
Завдання 4: Міні-кейс
Ви створюєте форму для зміни пароля.
1. Який метод HTTP ви повинні використати (GET чи POST)? Чому?
2. Який тег шаблону обов’язково треба додати всередину <form>?
5. 💡 Мислення як у розробника
Ось секрет, який відрізняє новачків від профі:
Новачок думає: "Як зробити так, щоб це працювало?" Профі думає: "Як це можуть зламати?"
Типові помилки новачків:
- Сліпа довіра: Думати, що користувачі будуть вводити тільки правильні дані. Спойлер: ніколи не довіряйте вводу користувача (Never Trust User Input).
- Винахід велосипеда: Писати власну систему шифрування паролів. Ні! Використовуйте те, що є в Django (
make_password,check_password). - Зберігання секретів у коді: Заливати
SECRET_KEYабо паролі від бази даних прямо в GitHub.
Як думає Senior:
- "Я використовую змінні оточення (Environment Variables) для секретів".
- "Я завжди оновлюю Django до останньої версії, бо там є патчі безпеки".
- "Я знаю, що безпека — це не стан, а процес".
6. 🧩 Підсумок
Отже, що ми сьогодні дізналися?
- SQL Injection — це спроба керувати вашою базою даних через поля вводу. Ліки: Django ORM.
- XSS — це спроба виконати чужий код у браузері ваших користувачів. Ліки: Автоматичне екранування шаблонів.
- CSRF — це спроба діяти від вашого імені без вашого відома. Ліки:
{% csrf_token %}.
Тепер ви не просто пишете код, який працює. Ви пишете код, який тримає удар. Ви стали охоронцями даних своїх користувачів. Це велика відповідальність, але я знаю, що ви впораєтесь!
А наступного разу... Ми поговоримо про те, як зробити наш безпечний додаток ще й швидким. Ми заглянемо у світ Кешування та Оптимізації. Чи готові ви розігнати свій код до швидкості світла?
Побачимось на наступній лекції! Це був CS50. 💻❤️