Що таке CSRF атака?
Ознайомитися з самою ідеєю атаки CSRF можна на класичних ресурсах:
Витяг з відповіді на SO:
Причина CSRF криється в тому, що браузери не розуміють, як розрізнити, чи було дію явно скоєно користувачем (як, скажімо, натискання кнопки на формі або перехід по посиланню) або користувач ненавмисно виконав цю дію (наприклад, при відвідуванні bad.com. Ресурсом був відправлений запит на good.com/some_action. в той час як користувач вже був залягання на good.com).
Як від неї захиститися?
Ефективним і загальноприйнятим на сьогодні способом захисту від CSRF-Атаки є токен. Під токеном мається на увазі випадковий набір байт, який сервер передає клієнту, а клієнт повертає сервера.
Захист зводиться до перевірки токена, який згенерував сервер, і токена, який надіслав користувач.
А що, власне, захищати?
Якщо ви пишете свій Web-Сервіс у відповідності зі стандартом RFC7231. то методи GET. HEAD. OPTIONS і TRACE є безпечними: вони призначені тільки для отримання інформації та не повинні змінювати стан сервера.
Таким чином, захищати необхідно небезпечні методи, до яких відносяться: POST. PUT. DELETE. PATCH.
Вимоги до токені:
- Унікальний токен для кожної операції # 13;
- діє раз # 13;
- Має розмір, стійкий до підбору # 13;
- Згенерований криптографически стійким генератором псевдовипадкових чисел # 13;
- Має обмежений час життя # 13;
На першому MeetUp'е PDUG Тимур Юнусов (керівник відділу безпеки банківських # 13; систем Positive Technologies) розповідав. чому саме такі вимоги пред'являються до CSRF-токен і чим загрожує нехтування ними.
Вимоги до Web-Сервісу і оточенню:
Відсутність XSS уразливостей
Таким чином, XSS уразливості можуть бути використані для отримання поточного токена.
Відсутність malware на машині клієнта
Якщо зловмисник має можливість запускати софт на машині клієнта, то він може отримати будь-які дані, наявні в браузері.
методи захисту
Існує 3 методи використання токенів для захисту web-сервісів від CSRF атак:
Synchronizer Tokens
Простий підхід, який використовується повсюдно. Вимагає зберігання токена на стороні сервера.
При старті сесії на стороні сервера генерується токен.
Токен кладеться в сховище даних сесії (тобто зберігається на стороні сервера для подальшої перевірки)
У відповідь на запит (який стартував сесію) клієнту повертається токен.
Якщо рендеринг відбувається на сервері. то токен може повертатися всередині HTML, як, наприклад, одне з полів форми, або всередині тега.
У разі, якщо відповідь повертається для JS додатки. токен можна передавати в header (часто для цього використовують X-CSRF-Token)
При повторних запитів клієнт зобов'язаний передати токен сервера для перевірки.
При рендер контенту сервером токен прийнято повертати всередині POST даних форми.
JS програми зазвичай надсилають XHR запити з header (X-CSRF-Token), що містить токен.
При отримання запиту небезпечним методом (POST. PUT. DELETE. PATCH) сервер зобов'язаний перевірити на ідентичність токен з даних сесії і токен, який надіслав клієнт.
Якщо обидва токена збігаються, то клопотання не піддався CSRF-Атаки, в іншому випадку - логіруем подія і відхиляємо запит.
На виході маємо:
Захист від CSRF на хорошому рівні
Токен оновлюється тільки при пересоздании сесії. а це відбувається, коли сесія закінчується
Під час життя однієї сесії всі дії будуть перевірятися по одному токен.
Якщо станеться витік токена, то зловмисник зможе виконати CSRF-Атаку на будь-який запит і протягом довгого терміну. А це не є добре.
Безкоштовна підтримка multi-tab в браузері.
Токен НЕ інвалідіруется після виконання запиту, що дозволяє розробнику не піклуватися про синхронізацію токена в різних табах браузера, так як токен завжди один.
Double Submit Cookie
Цей підхід не вимагає зберігання даних на стороні сервера, а значить, є Stateless. Використовується, якщо ви хочете вміти швидко і якісно масштабувати свій Web-сервіс горизонтально. # 13; Ідея в тому, щоб віддати токен клієнту двома методами: в куках і в одному з параметрів відповіді (header або всередині HTML).
При запиті від клієнта на стороні сервера генерується токен. У відповіді токен повертається в cookie (наприклад, X-CSRF-Token) і в одному з параметрів відповіді (в header або всередині HTML).
У повторних запитів клієнт зобов'язаний надавати обидва отриманих раніше токена. Один як cookie, інший або як header. або всередині POST даних форми.
При отриманні запиту небезпечним методом (POST. PUT. DELETE. PATCH) сервер зобов'язаний перевірити на ідентичність токен з cookie і токен, який явно надіслав клієнт.
Якщо обидва токена збігаються, то клопотання не піддався CSRF-Атаки, в іншому випадку - логіруем подія і відхиляємо запит.
На виході маємо:
Stateless CSRF захист.
Таким чином, якщо ваш сервіс доступний на домені 3-го рівня, а зловмисник має можливість зареєструвати свій ресурс на вашому домені 2-го рівня, то встановлюйте cookie на свій домен явно.
# 13;Encrypted Token
Так само як і Double Submit, є Stateless підходом. Основна - якщо ви зашифруєте надійним алгоритмом якісь дані і передасте їх клієнту, то клієнт не зможе їх підробити, не знаючи ключа. Цей підхід не вимагає використання cookie. Токен передається клієнту тільки в параметрах відповіді.
В даному підході токеном є факти, зашифровані ключем. Мінімально необхідні факти - це ідентифікатор користувача і timestamp часу генерації токена. Ключ не повинен бути відомий клієнту.
При запиті від клієнта на стороні сервера генерується токен.
Генерація токена складається в зашифровки фактів, необхідних для валідації токена надалі.
Мінімально необхідні факти - це ідентифікатор користувача і timestamp. У відповіді токен повертається в одному з параметрів відповіді (В header або всередині HTML).
У повторних запитів клієнт зобов'язаний надавати отриманий раніше токен.
При отримання запиту небезпечним методом (POST. PUT. DELETE. PATCH) сервер зобов'язаний затверджувати токен, отриманий від клієнта.
Валідація токена полягає в його розшифровці і порівняння фактів, отриманих після розшифровки, з реальними. (Перевірка timestamp необхідна для обмеження часу життя токена)
Якщо розшифрувати не вдалося які факти не збігаються, вважається, що запит піддався CSRF-Атаки.
На виході маємо:
Про реалізацію
Давайте генерувати новий токен на кожен запит, не має значення, яким HTTP-методом і з якою метою цей запит зроблено.
Таким чином ми отримуємо токен, який змінюється постійно.
Звичайно, виникає питання організації multi-tab роботи.
Синхронізація токенов між табами може бути реалізована з використанням localStorage і його StorageEvent
Обмежуємо час життя cookie, яке містить токен, розумним значенням. Наприклад 30 хвилин.
Робимо cookie недоступною з JS (ставимо HTTPOnly = true)
Використовуємо TLS для запобігання MITM
При цьому відправляємо cookie тільки по HTTPS (ставимо Secure = true)
Розмір токена не менше 32 байт.
Генеруємо токен криптографически стійким генератором псевдовипадкових чисел.
Для цього можна використовувати системні функції:
Що ще потрібно знати?
Токени - обов'язковий захист від CSRF.
Перевіряйте, але не покладайтеся лише на X-Requested-With: XMLHttpRequest
Перевіряйте, але не покладайтеся лише на заголовки: Host. Origin. Referer
Не передавайте токени в URL
Зараз йде робота над специфікацією атрибута "Same-Site" у cookies (остання версія на момент написання статті).
Такий атрибут дасть можливість розробникам явно вказувати, що cookie не потрібно передавати, якщо запит йде з сайту, відмінного від того, на якому cookie була встановлена. А, значить, у нас з'явиться можливість захищати ресурси від CSRF без використання додаткових інструментів.
Браузер Chrome вже зараз підтримує цю можливість.
Трохи більше інформації про те, як і чому є на Stack Exchange.