Содержание статьи
Что мы знаем
Этот вектор атак возможен из-за уязвимостей, обнаруженных в популярных стриминговых платформах, включая VLC, Kodi (XBMC), Popcorn Time и strem.io. Перед злоумышленником он открывает безграничные возможности: кражу конфиденциальной информации, установку программ-вымогателей, массовые DDoS-атаки и многое другое.
К счастью, эти уязвимости были устранены очень быстро после публикации первых материалов, поэтому теперь мы можем рассказать о проблеме во всех подробностях.
Popcorn Time
Созданная всего за несколько недель как проект open source мультиплатформа «Netflix для пиратов» оказалась гремучей смесью из BitTorrent-клиента, медиаплеера и бесконечных возможностей скрейпинга (сбора данных при помощи скриптов), объединенных очень привлекательным графическим интерфейсом.
Хотя программа стала очень популярна благодаря простоте использования и хорошей коллекции видеофильмов, разработчики неожиданно закрыли проект из-за давления со стороны Американской ассоциации кинокомпаний (MPAA).
После этого разные инициативные группы создали форки Popcorn Time для поддержки программы и разработки новых функций. Создатели оригинального Popcorn Time поддержали версию popcorntime.io (позднее — popcorntime.sh) как преемника своего закрытого проекта.
Интерфейс на основе WebKit содержит гору информации о фильмах и метаданные. Здесь есть трейлеры, краткое содержание сюжета, информация об актерах, фотографии обложек, рейтинги IMDb и многое другое.
Субтитры в Popcorn Time
Чтобы еще больше облегчить жизнь пользователя, субтитры к фильмам подгружаются автоматически. Можно ли использовать это в своих целях? (Подсказка: да.)
Без ведома пользователя Popcorn Time получает субтитры с единственного поставщика — OpenSubtitles. Более четырех миллионов субтитров и очень удобный API делают этот репозиторий суперпопулярным. В нем есть алгоритм выдачи рекомендаций, помогающий пользователю выбрать файл для конкретного фильма и релиза.
Поверхность атаки
Как упоминалось, Popcorn Time работает на движке WebKit, а именно NW.js. Ранее известная как node-webkit, платформа NW.js позволяет разработчику использовать веб-технологии — например, HTML5, CSS3 и WebGL — в своих родных приложениях. Более того, обращаться к API Node.js и модулям третьих сторон можно напрямую из DOM.
В сущности, приложение NW.js — это веб-страница с произвольным содержимым, написанная на JavaScript или HTML и оформленная с помощью CSS. Как всякая веб-страница, приложение может подвергаться XSS-атакам. В данном случае из-за того, что программа работает на Node.js, XSS позволяет использовать возможности серверной части. Иными словами, запросы XSS в реальности становятся запросами RCE (на выполнение удаленного кода).
На старт, внимание, марш!
Наше приключение начинается, как только пользователь включает воспроизведение фильма. Popcorn Time делает запрос через упомянутый API и скачивает рекомендованные субтитры (мы опишем этот процесс в деталях ниже). Затем Popcorn Time пытается перекодировать полученный файл в формат SRT.
После перекодировок и парсинга созданный элемент (субтитр) прикрепляется к экрану в нужный момент, опираясь на массив «подсказок».
Это дает нам возможность добавить к отображаемому виду любой HTML-объект. Очевидно, что полный контроль над каким-либо HTML-элементом — это уже опасно. Однако, когда мы имеем дело с приложениями на основе узлов (node-based), важно понимать, что XSS равен RCE. Системные команды легко запускаются через модули типа child_process. Как только наш непроверенный JavaScript загружается на экран, до запуска вредоносного кода остается всего лишь несколько строк.
Обычный SRT-файл выглядит примерно так:
1
00:00:01,000 –> 00:00:05,000
Hello World
Вместо текста Hello World мы можем использовать HTML-тег изображения.
Мы пытаемся загрузить несуществующее изображение с атрибутом событий onerror, который позволяет задать срабатывание скрипта при возникновении ошибки во время загрузки внешнего файла.
Мы используем функцию JavaScript, связанную с атрибутом onerror
, чтобы удалить компрометирующий нас значок отсутствующего изображения и прикрепить к странице нашу вредоносную удаленную полезную нагрузку (payload). Само собой, наш скрипт evil.js всего лишь запустит окно стандартного калькулятора calc.exe.
OpenSubtitles
Итак, мы можем исполнять код на Popcorn Time. Уязвимости на стороне клиента ценны, но их эксплуатация, как правило, требует какого-либо взаимодействия пользователя с системой — он должен кликнуть на ссылку, прочитать PDF-файл или зайти на взломанный сайт. В случае с субтитрами пользователь должен загрузить вредоносный файл. Можно ли как-то пропустить этот шаг?
Мы знаем, что юзеры беспечно скачивают субтитры из открытых источников в интернете и считают их безобидными текстовыми файлами. Более четырех миллионов файлов и около пяти миллионов ежедневных скачиваний делают OpenSubtitles крупнейшим онлайн-хранилищем субтитров. Их многофункциональный API также часто интегрируется во многие другие видеоплееры. Они даже предлагают возможность «умного» поиска: эта цепная функция выбирает наиболее подходящие субтитры по введенной информации.
Возникает вопрос: можно ли вмешаться в этот API и сделать так, чтобы взаимодействовать с пользователем не было необходимости и из базы OpenSubtitles автоматически загружались именно вредоносные субтитры?
Как работает API
Когда пользователь запускает воспроизведение фильма, система автоматически отправляет запрос на поиск субтитров SearchSubtitles — XML, содержащий все объекты субтитра, соответствующие нашим критериям (IMDb ID).
Здесь параметр поиска обозначен как imdbid
. Ответ на запрос содержит все субтитры с данным imdbid
.
А теперь самое интересное. В API имеется алгоритм, который ранжирует субтитры по их названию, IMDb ID, рейтингу загрузчика и другим параметрам. Просмотрев документацию, мы обнаружили схему такого ранжирования.
Здесь видно, сколько баллов добавляется к рейтингу субтитров на основе их соответствия следующим критериям: метка, IMDb ID, пользователь-загрузчик и так далее. Предположим, что мы как анонимные пользователи (user | anon) загрузили наши вредоносные субтитры в базу OpenSubtitles — нашему файлу присвоят всего пять баллов. Вот что мы узнали: недостаточно только читать документацию, поскольку исходный код проявляется в недокументированном поведении.
Запрос, отправленный Popcorn Time, задает только один параметр — IMDb ID, это означает, что условие MatchedBy === 'tag'
(«метка») всегда будет иметь логическое значение «ложь». Это вызовет функцию matchTags()
.
Функция matchTags разбивает название фильма и субтитров на отдельные метки. Метка (тег) — это, как правило, отдельное слово или цифра, обнаруженное в названии файла. Они обычно разделяются точками (.) и дефисами (-). Число общих меток в названии файла с фильмом и названии файла субтитров затем делится на число меток фильма и умножается на показатель maxScore, равный семи. Такое значение maxScore присваивается в случае полного соответствия между двумя именами файлов. Например, если название файла с фильмом Trolls.2016.BDRip.x264-[YTS.AG].mp4, у него будут следующие метки:
[Trolls, 2016, BDRip, x264, YTS, AG, mp4]
Поскольку название файла с фильмом, который скачивается приложением (например, Popcorn Time), узнать достаточно легко (c помощью сниффера), мы можем присвоить нашему файлу с субтитрами точно такое же название, но с расширением srt. Это увеличит рейтинг файла субтитров на целых семь (!) баллов.
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»