Grabduck

CSRF уязвимости на примере ХабраХабра

:

Уязвимости уже нет — её исправили задолго до появления этого топика.

Очень часто многие веб-разработчики забывают о существовании этого метода взлома, а некоторые даже не знают о нём.

К сожалению, подобные уязвимости встречаются даже в таких крупных системах, как ХабраХабр.

С чего всё начиналось


Всё началось с того, что мою карму быстро слили до -16 единиц из-за вполне нормального, как я считаю, комментария. Мне стало обидно, ведь я регистрировался на этом ресурсе чтобы писать интересные всем топики, а теперь я не могу этого сделать.

Я листал ленту, просматривая топики, и думал о том, как же хорошо их авторам, которые быстро набирают рейтинг и светятся в лучах славы. Без всякой надежды я ткнул в стрелочку, чтобы поставить плюсик топику. Как не трудно догадаться, я получил ошибку типа «Вашей кармы не достаточно для голосования».

Ищем уязвимости


Я сразу обратил внимание на то, что страница не обновляется а, значит, используется AJAX.

Тут же вспомнилось про малоизвестные CSRF, или как их ещё называют XSRF уязвимости.

Я стал FireBug'ом смотреть куда и как отправляются запросы. В первую очередь смутило то, что передавались только оценка (за или против), тип записи (топик) и id. Никаких дополнительных полей типа hash или token не передавалось.

Не всё так просто


Возможно, нетерпеливый читатель уже решил, что я нашёл элементарную, очевидную каждому дыру? Как бы ни так! Все мои попытки подделать запрос приводили к одному и тому же:

Вначале я решил, что где-то ошибся. Но нет, я слал запрос на нужный адрес и передавал нужным образом все параметры. Но когда это делал скрипт ХабраХабра, то получал статус ответа 200, а я 404.

Я стал внимательно проверять HTTP заголовки, и тут бросилось в глаза это:

Что это за такой странный заголовок, которого не оказалось в моём запросе?

Немного погуглив я узнал, что этот заголовок по-умолчанию передаётся при AJAX'е, а при запросе из формы, самой собой, не передаётся.

Сделать AJAX запрос я не мог, т.к. Хабр находится на другом домене и меня бы просто не пустил туда браузер. И тут я вспомнил про заброшенный мною давным давно FlashPlayer. Быстро погуглив я вскрикнул ура!

Да, товарищи, этот так многими не любимый аддон к браузеру может слать любые запросы на любой домен если… Если есть в корне этого домена правильный файл crossdomain.xml.

Вы верите в судьбу? Я — нет. Но я был просто шокирован, когда нашёл в корне ХабраХабра этот заветный файл, который разрешал слать ему запросы на 80-ый порт с любого домена!

Пишем эксплоит


Я выбрал ActionScript версии 2 во-первых, потому что его лучше знал, а во-вторых, потому что можно захватить с собой на корабль и пользователей старого FlashPlayer (начиная с версии 7).
var req:LoadVars = new LoadVars();
req.addRequestHeader("X-Requested-With","XMLHttpRequest");
req.addRequestHeader("Referer","http://habrahabr.ru/"); // на всякий случай
req.decode("ti=666&tt=2&v=1"); // вместо 666 id вашего топика
req.send("http://habrahabr.ru/json/vote/",  "_blank", "POST"); 

Что делать с эксплоитом?


Всё, теперь дело за малым. Если у вас есть свой сайт, то не думая заливаем код туда и ставим в iframe.

Если у вас нет сайта, то думая договариваемся за Profit с владельцем крупного приложения ВКонтакте и заливаем код к нему. Охват 50% пользователей гарантирован.

Всё, теперь любой пользователь, если он не голосовал за ваш топик ранее, ставит вам + сам того не зная.

Кроме того голосовать можно не только за топики, но и за комментарии, вопросы и КАРМУ!

На память


Ломать сайты — очень не хорошо. За это могут сделать ата-та-та по заднему месту.

В случае с данной уязвимостью я быстро написал письмо в службу поддержки и уязвимость закрыли (исправив crossdomain.xml).