По следам stagefright 2

В начале октября появилась новость о том, что найдена критическая уязвимость в библиотеке libutils. Библиотека libutils входит в состав Android OS, в ней содержится реализация различных примитивов, которыми могут пользоваться другие приложения. Минимальные последствия, к которым могла бы привести эксплуатация этой уязвимости, — падение ПО, использующего библиотеку stagefright и обрабатывающего MP3/MP4-файлы.

Хотя эксплойты к обнаруженным уязвимостям в «дикой природе» появляются не сразу, мы считаем необходимым даже в отсутствие информации об обнаружении эксплойтов быть готовыми к детектированию. Чтобы создать защиту, необходимо иметь в руках рабочий эксплойт, поэтому, как правило, для для реализации детектирования используются PoC-файлы.

В данном случае создание детектирующей логики для возможных эксплойтов к уязвимости осложнял тот факт, что в открытом доступе PoC-файлов не было. В связи с этим мы решили сами произвести исследование и сгенерировать PoC-файл.

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

Для начала мы посмотрели, какие изменения вносились в исходный код libutils для того, чтобы исправить анонсированную уязвимость. Как выяснилось, одним из последних изменений был следующий код:

По следам stagefright 2

Проверка входного параметра в функции allocFromUTF8 класса String8

По коду видно, что если параметр len = SIZE_MAX, то при выделении памяти произойдет integer overflow.

Мы предположили, что для того, чтобы добиться некорректной работы ПО, обрабатывающего MP3-файлы, надо сделать следующее: передать в функцию allocFromUTF8 вторым параметром число, равное значению SIZE_MAX. Данная функция вызывается из нескольких мест класса String8. Если проанализировать реализацию объекта String8, то можно понять, что интересующая нас функция вызывается в следующих местах:

  1. в конструкторе класса String8 (возможны две реализации);
  2. в методе setTo (возможны две реализации).

Еще стоит отметить тот факт, что для одной из реализаций конструктора и для одной из реализаций метода setTo на вход передается параметр, который потом передается allocFromUTF8. Из этого делаем еще один вывод: нас интересует код, который создает объект String8 и явно в конструкторе класса передает размер строки или вызов метода setTo (с указанием размера).

Исходя из информации, которую мы знаем, уязвимоcть эксплуатируется при обработке MP3-файлов, следовательно, надо изучить использование класса String8 в коде, который отвечает за обработку MP3-файлов. Данный код легко найти в следующей ветке — \media\libstagefright\MP3Extractor.cpp.

По следам stagefright 2

Использование класса String8 в коде MP3Extractor.cpp

Одно из первых использований данного класса можно заметить при обработке тега COMM MP3-файла (данный тег хранит информацию о комментариях к MP3-файлу):

По следам stagefright 2

Считывание комментариев из MP3-файла с использованием уязвимого класса String8

Как видно по коду для зачитывания строк используется еще один класс ID3 (нас интересует метод getString), который отвечает за обработку ID3 данных.

Перед тем, как перейти к рассмотрению кода данного компонента, рассмотрим структуру тега COMM (обратимся к официальной документации — http://id3.org/d3v2.3.0).

stagefright_ru_4

Пример тега COMM из обычного MP3-файла

В соответствие с документацией имеем:

COMM – Frame ID
00 00 00 04 – size
00 00 – flags
00 – text encoding
00 00 00 – Language
00 – null terminated short description
74 65 73 74 (test) – actual text

Рассмотрим код обработки парсера ID3:

Как видно по коду, при определенных условиях мы можем вызвать метод setTo класса String8, который в свою очередь позовет allocFromUTF8 с заранее высчитанным n.

Осталось понять, можем ли мы влиять на n. И сделать так, чтобы в результате вычислений в n записалось -1 (0xFFFFFFFF).

Размер заголовка зависит от версии ID3 формата.

Осталось разобраться с mFrameSize. Код, который производит подсчет данного параметра, достаточно большой. Опытным путем было установлено, что значение переменной mFrameSize при обработке файла также зависит от тега COMM и верси обрабатываемого файла.

Из этого следует, что мы можем влиять на две переменные из выражения:

size_t n = mFrameSize — getHeaderLength() – 1

Изменяя данные в теге COMM, мы влияем на mFrameSize. Используя простую математику, мы можем добиться выполнения следующего выражения:

mFrameSize — getHeaderLength() – 1 = -1

В результате выполнения в переменную n запишется следующее значение -1 (0xFFFFFFFF).

Теперь нам осталось только передать это значение в функцию setTo. По коду видно, что данный метод позовется при определенных значениях поля encoding в заголовке тега COMM.

stagefright_ru_5

Вызов метода setTo с передачей размера данных

При соблюдении этих условий, мы получим MP3-файл с некорректным тегом COMM, в результате обработки которого мы сможем наблюдать падение стандартного бразуера и музыкального проигрывателя:

stagefright_ru_6

Стэк трейс падения при обработке MP3-файла с некорректным тегом COMM

Таким образом, мы получили PoC эксплойта к уязвимости.

Продукты «Лаборатории Касперского» детектируют данный эксплойт как HEUR:Exploit.AndroidOS.Stagefright.b

Публикации на схожие темы

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *