Разбор уязвимости LibreOffice и OpenOffice CVE-2018-16858

уязвимость LibreOffice OpenOffice

Фишинговые кампании — классическое начало многих хакерских атак. Они направлены на доставку вредоносного файла потенциальной жертве и обычно ведутся по электронной почте. Чаще всего оболочкой для боевой нагрузки служит офисный документ, при открытии которого выполняются нестандартные действия. Мы рассмотрим, как выполнить произвольный код с помощью модифицированного файла OpenDocument Text.

Еще по теме: Как хакеры скрывают вирусы в документах Office

Большинство фишинговых приемов направлены на эксплуатацию уязвимостей в Microsoft Office, так как это самый популярный офисный пакет. Однако сейчас многие фирмы переходят на LibreOffice и OpenOffice, в том числе ошибочно считая их неуязвимыми.

С ростом популярности этих программных пакетов они тоже стали привлекать внимание хакеров и независимых исследователей. Просто, в отличие от набивших оскомину багов MS Office, информации об уязвимостях в опенсорсных пакетах пока накопилось не так уж много. Целью моего исследования будет не столько рассмотреть уязвимость какой-то конкретной версии программы, сколько разобрать формат ODT и особенности его обработки.

Эксплуатация CVE-2018-16858

Теория

Найденная уязвимость позволяет выполнить несанкционированный доступ к файловой системе, используя атаку обхода пути (path traversal attack). Это одна из самых часто встречающихся уязвимостей и канонический тип атаки. В данном случае злонамеренно модифицированный файл ODT может загрузить за пределами родительского каталога скрипт на Python, который получит доступ к файловой системе и выполнит любые указанные действия с правами текущего пользователя.

Первым данную уязвимость обнаружил старший пентестер немецкой фирмы Cure53 Алекс Инфур (Alex Infuhr). Он предал свою находку огласке, и LibreOffice пропатчили, однако все версии до 6.0.7 (крайне популярные сейчас) по-прежнему уязвимы.

Немного размытой остается ситуация с Apache OpenOffice. Отдельного патча нет, и текущая версия 4.1.6 уязвима до сих пор. Сторонняя компания ACROS Security включила в свой агент 0patch заплатку для данной уязвимости, но только в версиях OpenOffice и LibreOffice для Windows. Более подробно см. на их сайте.

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

Ответ разработчиков агента
Ответ разработчиков агента

Наш микропатч для LibreOffice и OpenOffice просто проверяет, что [в документе] нет типичных шаблонов для выполнения атаки «обход пути», таких как «../», «\..» или «..|».

Интересно, что некоторые антивирусы также ищут признаки эксплоита по всему документу, включая его текстовые поля и игнорируя формат. Например, «Антивирус Касперского» ругается даже на эту статью, если попытаться открыть ее черновик в OpenOffice как .odt или в MS Office как .docx.

Ложноположительный детект
Ложноположительный детект

Практика

Разберем суть уязвимости. Во время инсталляции LibreOffice в Windows также устанавливается интерпретатор Python 3. Он находится по известному адресу C:\Program Files\LibreOffice\program\python-core-3.5.5\bin. Офисный пакет может исполнить Python-скрипт, если указать ссылку на него внутри документа и правильно сослаться на него.

Документы .odt основаны на XML (как и .docx), поэтому их внутреннюю структуру легко изучать и модифицировать. Здесь открывается большой простор для разных вариантов атак, но в общем случае нам необходимо создать в документе какую-либо задачу, которая запустит скрипт на Python.

Вот тут и наступает самое интересное. Если подменить путь к исполняемому коду и он будет соответствовать правилам исполнения, то LibreOffice выполнит его, не проверяя путь к скрипту. Например, мы можем выйти за рамки рабочей директории, и ничего нам за это не будет… а вот жертве — будет!

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

Все тесты проведены на Windows 10 версия 1803 сборка 17134.523. За основу взят пакет LibreOffice последней уязвимой версии 6.0.6.2.

Создаем вредоносный файл

Открываем LibreOffice и создаем документ .odt с помощью Writer. Теперь нам необходимо добавить вызов любого Python-скрипта. На помощь приходит событие OnMouseOver, которое возникает при простом наведении курсора мыши на гиперссылку в документе. Преимущество состоит в том, что жертве даже кликать никуда не придется: навести курсор на ссылку в документе можно и случайно, особенно если она занимает весь лист и такого же белого цвета.

Идем в меню «Вставка → Гиперссылка». Заполняем поле URL любой ссылкой (неважно какой). В дополнительных настройках, напротив «Фрейм:», в конце окна есть кнопка «События», которая вызывает настройки макроса. В поле «Назначения» выбираем «Мышь над объектом» (то, о чем и было сказано). И в поле «Существующие макросы» добавим createTable (находится в ветке «Макросы LibreOffice → pythonSample»). Назначаем нужное нам событие.

Создание события OnMouseOver
Создание события OnMouseOver

Теперь заполняем поле «Текст» и кликаем «Применить». На листе появляется гиперссылка, при наведении на которую исполняется макрос. В моем примере так открывается еще один документ с информацией о первом в виде таблицы и парой примеров из руководства.

Документ, сформированный макросом при наведении курсора на гиперссылку
Документ, сформированный макросом при наведении курсора на гиперссылку

Сохраняем документ и закрываем. Упрощенно ODT — это XML в ZIP, поэтому посетить «недра» нашего файла можно с помощью любого архиватора с поддержкой ZIP. Я использую WinRAR. Открываем ODT как архив и смотрим структуру.

В корневом каталоге нас интересует файл content. Разархивируем его и откроем в любом текстовом редакторе (я использую Notepad++). В конце разметки (на скриншоте выделил это в отдельную строку) видно, что явно указывается скрипт, который будет исполняться. Имя ему TableSample.py.

Содержимое файла content
Содержимое файла content

Располагается данный файл (как и все примеры скриптов) по пути C:\Program Files\LibreOffice\share\Scripts\python\pythonSamples. Если открыть его и посмотреть на исходный код, то можно заметить, что название одной из двух функций (а именно createTable()) совпадает со словами в теле content после названия выполняемого скрипта. Это значит, что в файле разметки указано не только название файла со скриптом, но и функция, которую необходимо выполнить!

Содержимое файла TableSample.py
Содержимое файла TableSample.py

Проведем эксперимент: заменим в TableSample.py функцию createTable() на insertTextIntoCell(), не вписывая ее параметры. При открытии файла получим ошибку с названием новой функции.

Ошибка после изменения функции
Ошибка после изменения функции

Отлично! Сообщения об ошибках — это та обратная связь, которая поможет сделать правильный вызов «боевой нагрузки». Добавим параметры для insertTextIntoCell() и запустим снова. Теперь возникает другая ошибка. Она показывает, что параметры неверны, а значит, принимались на исполнение и проверялись. Довольно приятные новости!

Ошибка после добавления параметров функции
Ошибка после добавления параметров функции

Идем дальше. Восстановим документ в первоначальное состояние и попробуем изменить путь к скрипту (для этого я просто скопировал скрипт на уровень выше, а в файле content перед именем скрипта добавил ../). В этот раз файл отработал как надо, без единой ошибки.

Подведем промежуточный итог: мы можем явно указать в документе ODT загрузку любого скрипта на питоне по известному адресу и вызывать его функцию по стандартному событию (например, OnMouseOver). В использовавшемся для примера TableSample.py никаких потенциально опасных функций нет, а вот в каком-то другом скрипте из стандартной подборки они могут быть.

Алекс Инфур нашел такой — pydoc.py, который находится в C:\Program Files\LibreOffice\program\python-core-3.5.5\lib. В нем есть функция tempfilepager(). С ее помощью через вызов os.system()можно запустить любой исполняемый файл, причем с произвольными аргументами — достаточно передать их в строчку

[/crayon]

Код функции tempfilepager() в файле pydoc.py
Код функции tempfilepager() в файле pydoc.py

Чтобы все заработало, нам необходимо лишь прописать путь до скрипта и вызывать опасную функцию с нужными параметрами.

Отредактированный файл content
Отредактированный файл content

Запуск эксплоита

Настал момент X! Мы открываем модифицированный документ ODT, курсор оказывается наведенным на скрытую ссылку, и происходит магия — без разрешения пользователя запускается произвольный файл (злобный пейлоад или простой калькулятор в качестве PoC).

Для OpenOffice строка будет выглядеть так:

В LibreOffice она же записывается так:

Вот и вся разница.

Неуязвимые версии

После проделанных опытов я начал изучать заплатку этой уязвимости. В LibreOffice версии 6.0.7 я заметил ошибку, которая стала возникать при запуске скрипта, до этого работавшего в LibreOffice 6.0.6.2. Она ссылается на строку 998 файла pythonscript.py, расположенного в папке C:\Program Files\LibreOffice\program.

Исходный код pythonscript.py
Исходный код pythonscript.py

Как видно на скриншоте, функция getScript() просит параметр scriptUri. Как раз в этом параметре и возникает ошибка в строке

Та же самая ошибка возникает в OpenOffice, если эксплуатационный файл сконфигурирован неправильно (неверно указан путь к скрипту). Эта ошибка возникала и когда я пытался вызвать скрипт на удаленной машине по SMB-протоколу в формате \\\server\pydoc.py.

Изучив код pythonscript.py, я увидел, что функция scriptURI2StorageUri() (214-я строка файла) претерпела кардинальные изменения. Теперь она проверяет, находится ли скрипт в рабочей директории или нет. Выглядит этот фрагмент так:

Более подробное сравнение приводится на скриншоте.

Добавленная проверка пути
Добавленная проверка пути

Сама функция tempfilepager() никак не изменилась вплоть до LibreOffice v.6.2.1 (на момент написания статьи — последняя из стабильных). Строчку обращения к операционной системе по заданным параметрам все так же можно использовать. Если удастся обойти запрет на указание местоположения файла, то можно будет эксплуатировать очередную уязвимость, изменив лишь название папки на python-core-3.5.6.

Заключение

Мы разобрали уязвимость CVE-2018-16858, эксплуатация которой считается очень легкой. Проблема в том, что дырявые версии LibreOffice продолжают широко использоваться, а OpenOffice не пропатчен до сих пор. Поэтому не откладывай обновление LibreOffice и озаботься дополнительным уровнем защиты для OpenOffice.

ВКонтакте
OK
Telegram
WhatsApp
Viber

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

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