CSRF (Сross Site Request Forgery)
Последнее изменение этой страницы: 14:03, 9 июня 2016.
CSRF (англ. Cross Site Request Forgery - Межсайтовая подделка запросов) - атака, которая приводит к тому, что злоумышленник может выполнить в веб-приложении действие от имени авторизованного пользователя. Данная атака использует недостатки протокола HTTP. Впервые теоретические рассуждения по поводу возможности такой атаки появились в 1988 году, а первые уязвимости были обнаружены в 2000 году. Сам термин ввел Peter Watkins в 2001 году. Основные применение CSRF - выполнение действий от лица пользователя, CSRF является client-side уязвимостью.
Пример
Рассмотрим пример базовой CSRF уязвимости, чтобы понять ее принцип. В качестве примера, возьмем Low Level CSRF в веб-приложении DVWA.
Откроем страницу. Используем кольцевой адрес в качестве proxy, запустим Burp, который будет использовать кольцевой адрес для перехвата и модификации запросов. Посмотрим, что же происходит.
Для начала откроем страницу и посмотрим код.
Результат следующий:
- Имеем GET форму, в которой есть 3 элемента: password_new, password_conf, Change.
- При отправке запроса передается PHPSESSID, который отвечает за сессию приложения.
- Введенные параметры передаются в URL в открытой форме.
- При работе с формой нет никаких дополнительных cookies.
Проведем самую простую CSRF атаку.
Отправим цели следующую ссылку:
http://192.168.56.101/crackit/dvwa/vulnerabilities/csrf/?password_new=hacked&password_conf=hacked&Change=Change
При переходе по этой ссылке, пользователь, имеющий сессию на сервере поменяет свой пароль на hacked.
Другой способ: можем поднять сервер, после чего создать там следующую html страницу:
<html>
<head>
<title> PHISHED </title>
</head>
<body>
<img src = "http://192.168.56.101/crackit/dvwa/vulnerabilities/csrf/?password_new=hacked&password_conf=hacked&Change=Change"/>
</body>
</html>
Перейдя на такую страницу, браузер пользователя попытается подгрузить картинку, а значит перейдет по ссылке, после чего пароль поменяется на hacked.
В обоих случаях итог следующий:
Это и был пример простейшей CSRF атаки.
Защита от CSRF
Атака выше использовала слабое звено авторизации. PHPSESSID удостоверял личность пользователя, но не данные, которые он отправлял.
Наиболее популярный способ защиты сайтов - "секретный ключ" (secret), специальное значение, которое генерируется случайным образом и сохраняется в сессии посетителя. Его знает только сервер, посетителю мы его даже не будем показывать.
Затем на основе ключа генерируется "токен" (token). токен делается так, чтобы с одной стороны он был отличен от ключа, в частности, может быть много токенов для одного ключа, с другой - чтобы было легко проверить по токену, сгенерирован ли он на основе данного ключа или нет.
Для каждого токена нужно дополнительное случайное значение, которое называют "соль" salt.
Например, формула вычисления токена:
token = salt + ":" + MD5(salt + ":" + secret)
Далее
- В сессии хранится secret="abcdef", это значение создаётся один раз.
- Для нового токена сгенерируем salt, например пусть salt="1234".
- token = "1234" + ":" + MD5("1234" + ":" + "abcdef") = "1234:5ad02792a3285252e524ccadeeda3401".
Это значение – с одной стороны, случайное, с другой – имея такой token, мы можем взять его первую часть 1234 в качестве salt и, зная secret, проверить по формуле, верно ли он вычислен.
Не зная secret, невозможно сгенерировать token, который сервер воспримет как правильный.
Далее, токен добавляется в качестве скрытого поля к каждой форме, генерируемой на сервере.
То есть, «честная» форма для отсылки сообщений, созданная на http://mail.com, будет выглядеть так:
<form action="http://mail.com/send" method="POST">
<input type="hidden" name="csrf" value="1234:5ad02792a3285252e524ccadeeda3401">
<textarea name="message">
...
</textarea>
</form>
При её отправке сервер проверит поле csrf, удостоверится в правильности токена, и лишь после этого отошлёт сообщение. «Злая страница» при всём желании не сможет сгенерировать подобную форму, так как не владеет secret, и токен будет неверным. Такой токен также называют «подписью» формы, которая удостоверяет, что форма сгенерирована именно на сервере.
Подпись с полями формы
Подпись, представленная выше, говорит о том, что автор формы - сервер, но ничего не гарантирует относительно ее содержания.
Есть ситуации, когда мы хотим быть уверены, что некоторые из полей формы посетитель не изменил самовольно. Тогда мы можем включить в MD5 для формулы токена эти поля, например:
token = salt + ":" + MD5(salt + ":" + secret + ":" + fields.money)
При отправке формы сервер проверит подпись, подставив в неё известный ему secret и присланное значение fields.money. При несовпадении либо secret не тот (хакер), либо fields.money изменено.
Использование AJAX
Теперь перейдём к AJAX-запросам.
Что если посылка сообщений в нашем интерфейсе реализуется через XMLHttpRequest?
Как и в случае с формой, мы должны «подписать» запрос токеном, чтобы гарантировать, что его содержимое прислано на сервер именно интерфейсом сайта, а не «злой страницей».
Здесь возможны варианты, самый простой – это дополнительная кука.
- При авторизации сервер устанавливает куку с именем CSRF-TOKEN, и пишет в неё токен.
- Код, осуществляющий XMLHttpRequest, получает куку и ставит заголовок X-CSRF-TOKEN с ней:
var request = new XMLHttpRequest();
var csrfCookie = document.cookie.match(/CSRF-TOKEN=([\w-]+)/);
if (csrfCookie) {
request.setRequestHeader("X-CSRF-TOKEN", csrfCookie[1]);
}
- Сервер проверяет, есть ли заголовок и содержит ли он правильный токен.
Защита действует потому, что прочитать куку может только JavaScript с того же домена. «Злая страница» не сможет «переложить» куку в заголовок.
Если нужно сделать не XMLHttpRequest, а, к примеру, динамически сгенерировать форму из JavaScript – она также подписывается аналогичным образом, скрытое поле или дополнительный URL-параметр генерируется по куке.
ISSN 2542-0356
Следуй за Полисом
Оставайся в курсе последних событий
Лицензия
Если не указано иное, содержание этой страницы доступно по лицензии Creative Commons «Attribution-NonCommercial-NoDerivatives» 4.0, а примеры кода – по лицензии Apache 2.0. Подробнее см. Условия использования.