А что бы сделали вы, если бы могли публиковать записи в Twitter от имени
любого пользователя социально сети? Представили? Тогда прошу вас под кат за деталями.
Предисловие
В ходе исследования безопасности социальной сети Twitter в рамках BugBounty-программы мной была обнаружена уязвимость, которая позволяла злоумышленнику размещать записи в Твиттере от имени любого пользователя сервиса, не имея при этом доступ к аккаунту жертвы. Данная бага представляет особую опасность в связи с тем, что огромное количество как представителей СМИ, так и других известных личностей, имеет аккаунты в Твиттере и использует их для публикации различных новостей. А обнаруженная проблема безопасности позволяет разместить заведомо ложную информацию не в одном, а сразу в нескольких крупных аккаунтах (например, новостных изданий), и публика с большой долей вероятности поверит в неё. Имеются реальные примеры, когда с помощью дезинформации злоумышленники серьёзно влияли на цену акций определённых компаний ради собственной выгоды. Подробнее о таких прецедентах можно прочитать тут: (https://habrahabr.ru/company/itinvest/blog/270487/).
Данная уязвимость была обнаружена 26 февраля 2017 года и исправлена 28 февраля 2017 года.
Перейдём к техническим подробностям уязвимости.
Введение
В Твиттере есть такой сервис, как ads.twitter.com, в нем расположена медиа-библиотека с возможностью загружать медиа-файлы (видео, картинки, gif-ки), а также смотреть ранее загруженные медиа-файлы, которые были использованы при публикации твита. Библиотека доступна по ссылке вида: ads.twitter.com/accounts/ид_вашего_аккаунта/media. Теперь к делу.
Осматриваемся
Перейдя в библиотеку, мы видим функцию загрузки медиа-файлов:
После того, как мы нажимаем на кнопку «Загрузить медиа-файл» и выбираем его, нам будет видна следующая картина:
По нажатию на загруженное изображение мы видим следующее:
- Возможность твитнуть наш медиа-файл.
- Возможность поделиться медиафайлом с любым пользователем.
Так, хорошо, посмотрим на функцию твита поближе:
Что мы видим? Предположительно, следующее:
- account_id — id аккаунта конкретно в библиотеке
- owner_id — id владельца изображения
- user_id — id юзера, которому, собственно, и опубликуется твит
- media_key — id нашего медиафайла (на скриншоте №3, в адресной строке, он отображен)
Введём некоторые обозначения:
- аккаунт №1 — первый мой аккаунт
- аккаунт №2 — второй мой аккаунт
Поскольку я не помню точные формулировки выдаваемых ошибок, будем называть их
«ошибка №1» и «ошибка №2».
Пробуем
Что было сделано мной для обнаружения уязвимости:
Сначала я перехватил запрос на публикацию твитта и подменил параметры owner_id и user_id в GET и в json-е, который отправлялся методом POST, с id аккаунта №1 на соответствующие id аккаунта №2, но ожидаемого результата я не получил, лишь ошибку №1.
После этого я решил заменить owner_id и user_id только в POST, на что получил ошибку №2, насколько я помню, текст был примерно таким: «Пользователь с owner_id *тот id на который я заменял* не является владельцем медиа *тут media_key*».
«Хорошо», — подумал я, и сделал следующее:
Я воспользовался аккаунтом №2, зашёл в сервис ads.twitter.com, в библиотеку, и загрузил изображение для того, чтобы заранее знать media_key.
Пошло-поехало
Возвращаемся на аккаунт №1:
Перехватываем запрос на твит и подменяем owner_id, user_id в GET и POST на соответствующие данные аккаунта №2 и media_key на тот, который мы узнали, загрузив изображение на аккаунте №2. Иииии… видим ошибку №1. Грусть, печаль, тоска, хотя подождите. Когда мы ранее заменяли owner_id и user_id в GET и POST, ошибка была одна (ошибка №1), а в случае замены owner_id и user_id только в POST, ошибка была другая (ошибка №2). Попробуем?
Заменяем в запросе owner_id, user_id и media_key в POST, ииии… видим response, сообщающий, что публикация твита прошла успешно! Перейдя на аккаунт №2, мы видим, что был размещен твит с ранее загруженной картинкой аккаунта №2, хотя сам аккаунт №2 ничего не публиковал.
Пробуем усерднее
Итак, на данный момент мы имеем возможность публиковать твиты от имени любого пользователя, но у нас есть жёсткое ограничение, которое серьезно снижает impact(критичность уязвимости), а именно, нам нужно, чтобы у пользователя, от имени которого мы собираемся делать публикацию, был загружен медиа-файл. Более того, необходимо знать media_key этого файла, который подобрать не получится, поскольку он состоит из 18 цифр. Что ж, будем искать возможность узнать media_key. В процессе поисков я не обнаружил 100%-ного способа узнать этот media_key, всегда были какие-то ограничения в виде определённых обстоятельств, при которых, возможно, удалось бы получить тот самый media_key. Всё кончено? Выхода нет? Репортить, как есть? Ну уж нет! Внутреннее чувство мне подсказало, что эту уязвимость можно довести до апогея критичности! Помните возможность делиться загруженным медиа-файлом? Мне пришла в голову мысль, что, возможно, когда мы поделимся нашим медиа-файлом с пользователем, от имени которого мы хотим сделать публикацию, он будет также считаться владельцем медиа-файла, ошибка №2 не возникнет и твит успешно опубликуется. И именно так и произошло:)
Для успешной эксплуатации уязвимости нам не хватало media_key, но в случае, когда мы являемся владельцем файла, мы можем видеть его media_key (скриншот №3).
Теперь сценарий выглядит следующим образом:
- Мы загружаем наш медиа-файл.
- Делимся этим файлом с пользователем, от имени которого хотим опубликовать запись.
- Перехватываем запрос публикации твита и просто подменяем в POST owner_id и user_id на id twitter аккаунта жертвы (узнать его просто, есть много онлайн сервисов).
- Получаем сообщение об успешной публикации твита.
Вот теперь можно со спокойной душой репортить об уязвимости.
Выводы:
RCE, SQLi, XSS — это всё конечно очень здорово и опасно, но порой логические уязвимости несут не меньшую угрозу для безопасности и зачастую гораздо более просты в эксплуатации нежели вышеперечисленные. На это стоит обращать пристальное внимание и при этом внимание живых специалистов, ведь автоматизированные сканеры не способны на такое. А что касается Twitter, то еще не известно сколько подобных уязвимостей в нем сейчас есть и может появиться по мере его развития и добавления функциональности. Удачного всем bughunting'а!
Автор: Digital Security