CSRF является одной из самых распространенных уязвимостей в современных веб-приложениях. Это связано с недооценкой разработчиками степени угрозы CSRF-атак, что выражается в недостаточных мерах защиты против CSRF или вообще в полном их отсутствии. На самом деле, эффективно обезопасить свое веб-приложение от CSRF совсем не сложно: уже достаточно давно практикуется универсальный способ, о котором я хотел бы рассказать в этом посте. Кроме того, будут затронуты уже готовые реализации этого приема: CSRFx и csrf-magic.
Общие сведения
CSRF-атака использует функцию браузера автоматической отправки идентификатора сессии с каждым GET/POST-запросом к веб-приложению. Атакующий находит ссылки, которые могут выполнять определенные операции, причем, как правило, эти функции доступны только для привилегированных пользователей. Это могут быть операции перевода денег, перенаправления почты на другой электронный ящик, сброса пароля, покупки каких-либо товаров и многое другое. Попав на страницу, находящуюся под контролем атакующего, жертва невольно совершит переход по ссылке, уязвимой к CSRF, и выполнит операцию в контексте целевого веб-приложения. Обычно при CSRF-атаках используют тэг <img>, при этом источником изображения является уязвимая ссылка, по которой браузер автоматически перейдет, добавив заголовок Cookie. Примеры:
- <img src=”http://bank/transfer?account=Vasya&amount=10000&for=Oleg”>
- <img src=”http://mail/forward?mail=mymail@mymail”>
- <img src=”http://site/resetpassword?user=admin&password=123″>
- <img src=”http://cms/admin/delete?article=5″>
Несмотря на то, что CSRF-атаки не требуют наличия XSS-уязвимостей, обнаружение XSS также ведет к CSRF, существенно облегчая ее эксплуатацию в том плане, что атакующему не нужно заманивать жертву на его сайт.
Защита
Двумя самыми распространенными заблуждениями касательно способов защиты от CSRF являются:
- Использование POST вместо GET: на самом деле совершить POST-запрос также легко как и GET.
- Реализация страниц подтверждения: данный подход лишь ненамного затрудняет процесс атаки – необходимо делать два запроса вместо одного (переход по ссылке для подтверждения операции и собственно выполнение самой операции)
Грамотная защита основывается на использовании случайного идентификатора, который генерируется для каждой операции и необходим для ее выполнения. Данный идентификатор также называют маркером доступа (token, nonce); он помогает эффективно различать запросы.
Алгоритм защиты:
- создаем случайный маркер доступа и добавляем его в массив $_SESSION
<?php $token = md5(uniqid(mt_rand() . microtime())); $_SESSION['token'] = $token; ?>
- к каждой форме добавляем hidden-поле с идентификатором
<input name="token" type="hidden" value="<?php echo $token ?>" />
- теперь при каждом запросе необходимо проверять корректность маркера доступа
<?php $token = $_POST['token']; if($_SESSION['token'] == $token) { $_SESSION['token'] = ''; /* some actions */ } else { die("404 Not Found!"); } ?>
Существуют и готовые реализации этого метода для PHP, которые надстраиваются над веб-приложениями, как вручную, так и автоматически с помощью директивы auto_prepend_file.
CSRFx
URL: http://code.google.com/p/csrfx/
- Необходима база данных (MySQL)
- Обрабатывает как GET, так и POST-запросы
- Работает только с PHP5
- Не поддерживает AJAX-вызовы
csrf-magic
URL: http://csrf.htmlpurifier.org/
- Работает без БД
- Обрабатывает только POST-запросы
- Работает как с PHP4, так и с PHP5
- Имеет обработчик метода XMLHttpResponse – поддерживает AJAX-вызовы
Тем не менее, начинать стоит с защиты против XSS, так как, обнаружив XSS-уязвимость, атакующий сможет выяснить значение маркера доступа с помощью AJAX.
Leave a Reply