[Перевод] Кража закрытых видео YouTube по одному кадру
В декабре 2019 года, спустя несколько месяцев после того, как я занялся хакингом по программе Google VRP, я обратил внимание на YouTube. Мне хотелось найти способ получать доступ к закрытым (
Private
) видео, которыми я не владею.При загрузке видео на YouTube можно выбрать один из трёх параметров доступа. «Открытый» (Public
) позволяет находить и просматривать видео любым пользователям, «Доступ по ссылке» (Unlisted
) позволяет просматривать видео только пользователям, знающим ID видео (URL), «Ограниченный доступ» (Private
) позволяет просматривать видео только вам или другим аккаунтам, которым дано на это разрешение.
Первым делом я загрузил видео на свой второй тестовый канал аккаунта YouTube и переключил параметры доступа видео на Private
, чтобы его можно было использовать для тестирования. (Помните, что тестирование всегда нужно проводить на тех ресурсах/аккаунтах, которыми вы владеете!) Если я смогу найти способ получить доступ к видео с первого тестового аккаунта, то мы выявим наличие бага.
Я открыл YouTube под первым аккаунтом, проверил каждую функцию и нажал на каждую кнопку, которую смог найти. Каждый раз, когда я видел HTTP-запрос с указанием ID видео, я заменял его на тестовое видео с доступом Private
, надеясь, что так утечёт какая-нибудь информация о нём, но успеха не добился. Похоже, что основной веб-сайт YouTube (по крайней мере, все его конечные точки, которые я протестировал) всегда проверяет, находится ли видео в состоянии Private
, и когда пытается выполнить запрос к целевому закрытому видео, он всегда возвращает ошибки наподобие This video is private!
.
Мне нужно найти другой способ.
В подобной ситуации отличным решением может быть проверка других продуктов/сервисов, не являющихся нашей основной целью, но каким-то образом взаимодействующих внутри с её ресурсами. Если они имеют доступ к ресурсам сайта, то есть вероятность, что у них не реализованы все уровни защиты, которые имеются у основного продукта.
Интересной целью, соответствующей этим требованиям, стал Google Ads. Это продукт, который рекламодатели используют для создания рекламы во всех сервисах Google, в том числе и на YouTube. То есть реклама, которую вы смотрите перед видео на YouTube, настраивается рекламодателями здесь, на платформе Google Ads.
Итак, я зарегистрировал аккаунт Google Ads и создал новую рекламу, которая должна воспроизводить для всех пользователей YouTube видео как рекламу с возможностью пропуска. Во время процесса создания рекламы я также повсюду пытался использовать ID целевого закрытого видео, но без малейшего успеха.
После создания рекламы я начал изучать различные функции Google Ads. Это очень масштабный продукт, и он имеет множество различных параметров и инструментов. Я пытался найти что-нибудь связанное с YouTube.
На платформе я нашёл страницу под названием Videos
, где увидел список видео, используемых для моей рекламы. При нажатии на видео открывается раздел аналитики (Analytics
) этого видео. В нём я нашёл встроенный проигрыватель, статистику и интересную функцию под названием Moments
. Она позволяла рекламодателям «помечать» конкретные моменты видео, чтобы, видеть, когда происходят разные вещи (например, метка времени момента появления логотипа компании). Честно говоря, я не совсем понял, зачем рекламодатели используют эту функцию, однако она показалась интересной:
Посмотрев на логи прокси, я заметил, что каждый раз, когда я «помечал момент», передавался
POST
-запрос к конечной точке /GetThumbnails
. Тело этого запроса содержало ID видео: POST /aw_video/_/rpc/VideoMomentService/GetThumbnails HTTP/1.1
Host: ads.google.com
User-Agent: Internet-Explorer-6
Cookie: [удалено]
__ar={"1":"kCTeqs1F4ME","2":"12240","3":"387719230"}
Где в параметре
__ar
значение 1
было идентификатором видео, а значение 2
— временем момента в миллисекундах. В качестве ответа возвращалось изображение в кодировке base64, представлявшее собой миниатюру, используемую платформой Ads.Я повторил то, что делал уже много раз: заменил в запросе ID на идентификатор закрытого видео второго аккаунта, и, к моему удивлению, получил в ответ изображение base64!
Я загуглил «base64 to image» и вставил данные base64 в первый найденный декодер. На изображении оказалась миниатюра целевого закрытого видео! Сработало! Я нашёл работающий баг IDOR (Insecure Direct Object Reference, «незащищённая прямая ссылка на объект»), благодаря которому я мог получать кадр из любого видео на YouTube с ограниченным доступом!
Но я подумал: «Хм, это всего лишь один кадр». Мы можем добиться большего.
Я хотел написать скрипт на Python с proof of concept, генерирующий настоящее движущееся «видео». Поискав информацию, я понял, что если видео записано с частотой 24 FPS, то один кадр находится на экране в течение 33
миллисекунд. То есть мне достаточно скачивать каждое изображение, начиная с 0
и выполняя инкремент на 33
, а затем собрать из всех полученных кадров своего рода видео.
Я быстро написал POC, которое скачивает кадры для первых трёх секунд видео, декодирует их, а затем генерирует GIF. Чтобы протестировать код, я запустил его со своим старым видео, к которому заранее ограничил доступ, потому что мне было за него стыдно:
Итак, при помощи этого бага злоумышленник может скачать любое закрытое видео на YouTube, что, на мой взгляд, является достаточно серьёзной угрозой. Но, разумеется, она имеет некоторые ограничения, которые я не смог преодолеть:
- В реальной ситуации вам нужно знать ID целевого видео. Их массовая утечка сама по себе будет считаться багом.
- Так как мы получаем только изображения, доступа к звуку получить не удастся.
- Разрешение очень низкое (но его достаточно, чтобы понять происходящее в видео).
Можно сделать вывод, что всегда стоит обращаться внимание на ситуации, когда два различных продукта имеют внутреннее взаимодействие друг с другом, так как команды разработчиков обоих продуктов лучше знают свою систему и могут упустить важные подробности при работе с ресурсами другого продукта.
Поиск подобных IDOR может быть очень монотонным и кропотливым трудом, и теперь я пытаюсь не использовать избегать простых слепых замен ID в надежде на лучшее. Если какое-то время потестировать продукт и понять его внутреннее устройство, то будет эффективнее (и интереснее) попытаться подумать о различных неожиданных действиях, о которых могли не подумать разработчики, или сделать упор на недавно реализованных функциях, или просто заняться чем-то, требующим продуманных действий. Возможно, в долговременной перспективе вам это принесёт больше удовольствия. На мой взгляд, чем больше вы понимаете систему, тем больше идей о её взломе приходит в голову естественным образом.
Но даже в самых надёжных и тщательно протестированных системах есть вероятность того, что простая замена ID в запросе позволит получить критически опасный баг.
Как развивалась ситуация
[11 декабря 2019 года] — отправлен отчёт о баге
[12 декабря 2019 года] — первоначальный триаж
[20 декабря 2019 года] — баг принят (P4 → P1)
[08 января 2020 года] — предприняты шаги по устранению бага при помощи временного отключения функции Moments
[17 января 2020 года] — выписана награда в размере 5000 долларов
[??? ? 2020 года] — функция Moments
снова включена, теперь она проверяет наличие доступа к видео.
На правах рекламы
VDSina предлагает VDS с посуточной оплатой, возможностью в пару кликов создать собственную конфигурацию сервера, установить любую операционную систему. Каждый сервер подключён к интернет-каналу в 500 Мегабит и бесплатно защищён от DDoS-атак!
Подписывайтесь на наш чат в Telegram.