E-mail Пароль
Забыли пароль?
Ardzo.Serenity - защита сайта от вирусов, троянов и внедрений

Защита сайта от CSRF (межсайтовая подделка запроса)

К списку статей

Существуют некоторые сходства между атаками с помощью межсайтового скриптинга (XSS) и атаками Cross-Site Request Forgeries (CSPF). Однако основной принцип у них все же разный и последние являются более серьезной угрозой, которую будет труднее отразить. При CSPF-атаке эксплуатируется доверие сетевого ресурса к пользователю.

CSPF-атаки характеризуются:

-Уязвимостями в привилегиях пользователя

Суть заключается в том, что зарегистрированным пользователям позволено осуществлять некоторые действия на сайте и если у них слишком высокие привилегии они автоматически подвергаются угрозе со стороны злоумышленников.

-Ложные пользователи

Хакер может взломать аккаунт доверенного пользователя и от его имени выполнять какие-то действия. Сайт при этом не будет ничего знать о подмене и по-прежнему будет ему доверять.

-Применение HTTP-запросов

Наиболее опасный и, пожалуй, самый распространенный признак CSRF-атаки. Пользователи будут выполнять запросы хакера, даже не догадываясь об этом.

По сути, ваш браузер это и есть HTTP-клиент, который взаимодействует с HTTP-сервером (веб-сервером). Рассмотрим пример отправки браузером запроса на сервер:

GET / HTTP/1.1
Host: example.org
User-Agent: Mozilla/5.0 Gecko
Accept: text/xml, image/png, image/jpeg, image/gif, */*
Здесь мы видим в первой строке: метод запроса и версию HTTP. Далее идут HTTP-заголовки и значения запроса после двоеточия.

Ответ сервера на такой запрос будет выглядеть так:

 HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 57

< html>
	< img src="http://example.org/image.png" />
< /html>
Здесь тег показывает браузеру, как корректно показать страницу. При этом браузер будет запрашивать URL, который прописан в атрибуте SRC и воспримет его как будто пользователь его сам задал. Браузер в таком случае не может знать, что от этого запроса ожидается.

А теперь представьте, насколько может быть опасной для пользователя ссылка такого вида:

http://stocks.example.org/buy.php?symbol=SCOX&quantity=1000
GET-метод в этом случае не отличается от простого запроса изображения. При этом, когда включена функция register_globals, для злоумышленника будет неважен даже метод.

Пользователь может купить себе 1000 акций компании SCOX, даже не зная об этом. Для этого ему нужно просто посетить страницу с тегом < img src="http://stocks.example.org/buy.php?symbol=SCOX&quantity=1000" />

В конечном итоге HTTP-запрос такого вида:

GET /buy.php?symbol=SCOX&quantity=1000 HTTP/1.1
Host: stocks.example.org
User-Agent: Mozilla/5.0 Gecko
Accept: text/xml, image/png, image/jpeg, image/gif, */*
Cookie: PHPSESSID=1234
Будет приравниваться к тому, что вы заполнили такую форму:
< p>Buy Stocks Instantly!< /p>
< form action="/buy.php">
	< p>Symbol: < input type="text" name="symbol" />< /p>
	< p>Quantity:< input type="text" name="quantity" />< /p>
	< input type="submit" />
< /form>
Где Symbol = акции компании SCOX, а Quantity= количество равно 1000.

Защита от CSRF-атак

При составлении форм применяйте в их атрибутах POST-метод. Для простых форм, как в рассмотренном выше примере он вполне подойдет. Также не забывайте отключать register_globals. Вы должны понимать, что не следует давать пользователям слишком большие привилегии, ради удобства в использовании сайта. Если какое-то важное действие может быть совершено одним кликом - это будет целью №1 для CSRF-атаки.

Дабы усложнить жизнь хакеру используйте старую добрую капчу в отдельном окне идентификатора сессии. И если взять рассмотренный сайт объявлений из статьи о XSS-атаке и немного доработать ее, мы получим такой вид:

< ?php
$token = md5(time());

$fp = fopen('./tokens.txt', 'a');
fwrite($fp, "$token\n");
fclose($fp);
?>

< form method="POST">
< input type="hidden" name="token" value="" />
< input type="text" name="message">< br />
< input type="submit">
< /form>

< ?php
$tokens = file('./tokens.txt');

if (in_array($_POST['token'], $tokens))
{
if (isset($_POST['message']))
{
$message = htmlentities($_POST['message']);

$fp = fopen('./messages.txt', 'a');
fwrite($fp, "$message
"); fclose($fp); } } readfile('./messages.txt'); ?>
Однако хакер может заполучить токен, просто посетив эту страницу, он будет указан в HTML-коде. Так же можно заменить предсказуемую функцию "time()" допустим на iniqid() и rand(). Учитывая вышесказанное код должен выглядеть вот так:
< ?php
session_start();

if (isset($_POST['message']))
{
if (isset($_SESSION['token']) && $_POST['token'] == $_SESSION['token'])
{
$message = htmlentities($_POST['message']);

$fp = fopen('./messages.txt', 'a');
fwrite($fp, "$message
"); fclose($fp); } } $token = md5(uniqid(rand(), true)); $_SESSION['token'] = $token; ?> < form method="POST"> < input type="hidden" name="token" value="" /> < input type="text" name="message">< br /> < input type="submit"> < /form>