Pull to refresh

Evasi0n под микроскопом

Reading time8 min
Views38K
Original author: Peter Morgan, Ryan Smith, Braden Thomas, & Josh Thomas
Совсем недавно вышел свежий набор утилит для «джейла» iOS. Пришло время разобрать его и посмотреть, какие эксплойты и механизмы проникновения он использует. Сейчас «джейлить» iOS стало настолько просто, что люди забывают, насколько это сложный процесс. Механизмы защиты, встроенные в пространство пользователя, такие как песочница, ASLR (Address Space Layout Randomisation – рандомизация расположения в адресном пространстве) и механим цифровых подписей, делают процесс написания «джейла» невероятно сложным.

Стоит отметить, что, в отличие от предыдущих эксплойтов jailbreak.me, которые можно было использовать на ничего не подозревающих жертвах, «джейлы», которые требуют подключения по USB, обычно несут меньшие угрозы безопасности, и типично полезны только самому владельцу устройства. Злоумышленники заинтересованы в них меньше, так как айфон с установленным пин-кодом откажется общаться по USB, если он заблокирован, если он, конечно, ранее не был синхронизирован с компьютером, куда его подключают. Таким образом, если телефон был украден и на нем был установлен пин-код, злоумышленник не сможет «джейлнуть» его. Только вредоносный код, выполняемый на вашем компьютере, может иметь хоть какую-то возможность выполнить «джейл» незаметно.

Evasi0n в пространстве пользователя


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

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

MobileBackup использует домен, например MediaDomain, и относительный путь в пределах домена для идентификации каждого файла. За каждым доменом константно зафиксирована определенная директория, и комбинация из пути к этой директории и относительного пути к файлу дает полный путь. Evasi0n создает все рабочие файлы в домене MediaDomain, таким образом у всех файлов рабочий префикс это /var/mobile/Media.

Этап 1


Во время первого этапа, Evasi0n создает новую пустую архивную копию для восстановления на устройство, содержащую следующие файлы:

directory: Media/
directory: Media/Recordings/
symlink:   Media/Recordings/.haxx -> /var/mobile
directory: Media/Recordings/.haxx/DemoApp.app/
file:      Media/Recordings/.haxx/DemoApp.app/Info.plist
file:      Media/Recordings/.haxx/DemoApp.app/DemoApp
file:      Media/Recordings/.haxx/DemoApp.app/Icon.png
file:      Media/Recordings/.haxx/DemoApp.app/Icon@2x.png
file:      Media/Recordings/.haxx/DemoApp.app/Icon-72.png
file:      Media/Recordings/.haxx/DemoApp.app/Icon-72@2x.png
file:      Media/Recordings/.haxx/Library/Caches/com.apple.mobile.installation.plist


Символьная ссылка из .haxx в /var/mobile создается для обхода ограничения работы с файлами только в пределах домена, т.е. хотя стандартное ограничение не допустит копирования фалов вне /var/mobile/Media, но с помощью символьной ссылки файлы фактически попадают в /var/mobile. Этот подход уже использовался в «джейлах» и ранее.

Далее, DemoApp.app, обычное iOS приложение, создается в /var/mobile. Это обычное приложение, с иконками и прочими сопроводительными файлами. Так же обновляется файл com.apple.mobile.installation.plist, где Springboard хранит кеш путей к приложениям, чтобы иконка DemoApp появилась среди остальных.

В отличие от обычного iOS приложения, у этого основной выполняемый файл несколько нетипичен и содержит следующее:

#!/bin/launchctl submit -l remount -o /var/mobile/Media/mount.stdout -e /var/mobile/Media/mount.stderr -- /sbin/mount -v -t hfs -o rw /dev/disk0s1s1


Фактически, при запуске программы DemoApp, на самом деле запускается launchctl с заданными аргументами.

Помимо этого, в com.apple.mobile.installation.plist немного модифицируется окружение для запуска DemoApp:

<key>EnvironmentVariables</key>
<dict>
  <key>LAUNCHD_SOCKET</key>
  <string>/private/var/tmp/launchd/sock</string>
</dict>


Устройство перезагружается, Springboard перечитывает кеш и отображает иконку.

Этап 2.1


Предыдущие файлы остаются на местах, второй этап создает еще одну пустую архивную копию и восстанавливает на устройство еще несколько файлов:

directory: Media/
directory: Media/Recordings/
symlink:   Media/Recordings/.haxx -> /var/db
symlink:   Media/Recordings/.haxx/timezone -> /var/tmp/launchd


Фактически, это просто создание символьной ссылки /var/db/timezone на файл /var/tmp/launchd. Типичные права доступа на /var/tmp/launchd такие:

drwx------ 2 root   wheel  102 Feb  4 12:17 launchd


Эти права доступа не дают обычным приложениям (запущенным от пользователя mobile) исследовать данный каталог.

Следующим шагом, Evasi0n общается c lockdownd, путем отправки неправильно сформированной команды PairRequest. Lockdownd – это основной демон, который выполняет коммуникацию по USB, так же он используется для запуска/остановки других сервисов, таких как MobileBackup и AFC (Apple File Connection – сервис который позволяет обмениватся файлами с iTunes). Поскольку lockdownd работает с правами root-пользователя и пользователь может общаться с ним, злоупотребление его возможностями или уязвимостями стало популярным в последних «джейлах».

Теперь мы подошли к первой уязвимости. Отправка некорректного пакета PairRequest заставляет lockdownd изменить права доступа к /var/db/timezone на 777, таким образом делая /var/tmp/launchd доступным для всех пользователей. Не ясно, уязвимость ли это непосредственно lockdownd или какой-то из библиотек, которуе он использует.

Этап 2.2


Evasi0n проникает вглубь /var/tmp/launchd и модифицирует права доступа таким образом, что сокет launchd становится доступным обычному пользователю. Также на этом этапе обновляется символьная ссылка на timezone:

symlink:   Media/Recordings/.haxx/timezone -> /var/tmp/launchd/sock


Потом Evasi0n повторяет трюк с PairRequest, делая /var/tmp/launchd/sock доступным пользователю mobile.

Этап 2.3


Этот этап начинается с установки Cydia и архива пакетов на устройство. Они не будут использоваться прямо сейчас, но будут доступны уже после «джейла».

Далее, пользователю дается указание запустить приложение Jailbreak (фактически – DemoApp). Напомню еще раз, что оно делает:

#!/bin/launchctl submit -l remount -o /var/mobile/Media/mount.stdout -e /var/mobile/Media/mount.stderr -- /sbin/mount -v -t hfs -o rw /dev/disk0s1s1


с установленным окружением

LAUNCHD_SOCKET = /private/var/tmp/launchd/sock


Если заглянуть в man по launchctl то можно выяснить, что команда submit описана следующим образом:

  submit -l label [-p executable] [-o path] [-e path] -- command [args]
                A simple way of submitting a program to run without a configura-
                tion file. This mechanism also tells launchd to keep the program
                alive in the event of failure.

                -l label
                         What unique label to assign this job to launchd.

                -p program
                         What program to really execute, regardless of what fol-
                         lows the -- in the submit sub-command.

                -o path  Where to send the stdout of the program.

                -e path  Where to send the stderr of the program.


А в man по launchd указано:

ENVIRONMENTAL VARIABLES

LAUNCHD_SOCKET
  This variable is exported when invoking a command via the launchd command line. It informs launchctl how to find the correct launchd to talk to.


В отличие от большинства других вещей в iOS, IPC в launchd основан на unix-сокетах. Так же, есть несколько процессов launchd – по одному для каждого активного пользователя. На iOS один работает с правами root, другой – с правами mobile. Пользователь mobile выполняет launchctl через DemoApp, но этот launchctl общается не с launchd пользователя mobile, вместо этого он общается с launchd пользователя root из-за явно указанного пути к сокету и расширенных прав доступа, полученных через уязвимость с /var/db/timezone.

Поскольку мы работаем с launchd пользователя root, то и задача будет выполенна с правами root, что позволяет ей перемонтировать системный раздел с доступом на запись, чтобы позволить Evasi0n вносить изменения в систему, для выполнения их в раннем загрузочном окружении.

Этап 3


Финальный этап «джейла», и снова используется MobileBackup, но на этот раз уже есть полный доступ в системный раздел:

directory: Media/
directory: Media/Recordings/
symlink:   Media/Recordings/.haxx -> /
symlink:   Media/Recordings/.haxx/private/etc/launchd.conf -> /private/var/evasi0n/launchd.conf
directory: Media/Recordings/.haxx/var/evasi0n
file:      Media/Recordings/.haxx/var/evasi0n/evasi0n
file:      Media/Recordings/.haxx/var/evasi0n/amfi.dylib
file:      Media/Recordings/.haxx/var/evasi0n/udid
file:      Media/Recordings/.haxx/var/evasi0n/launchd.conf


Это выглядит немного запутанным из-за нескольких перенаправлений по символьным ссылкам, но фактически здесь создается каталог /var/evasi0n с приложением и библиотекой, а также новый launchd.conf, в котором хранятся команды, выполняемые при загрузке системы.

Собственно, при загрузке будут выполнены следующие команды:

bsexec .. /sbin/mount -u -o rw,suid,dev /
setenv DYLD_INSERT_LIBRARIES /private/var/evasi0n/amfi.dylib
load /System/Library/LaunchDaemons/com.apple.MobileFileIntegrity.plist
bsexec .. /private/var/evasi0n/evasi0n
unsetenv DYLD_INSERT_LIBRARIES
bsexec .. /bin/rm -f /private/var/evasi0n/sock
bsexec .. /bin/ln -f /var/tmp/launchd/sock /private/var/evasi0n/sock


Сделают они следующее:

  • перемонтируют системный раздел с правами на запись;
  • amfi.dylib будет внедрен в любое приложение, начиная с этого момента;
  • запускается сервис MobileFileIntegrity;
  • запускается «вредоносный» код, записанный на предыдущем этапе;
  • amfi.dylib больше не будет внедрятся;
  • удаляется старая символьная ссылка на сокет в /private/var/evasi0n/sock;
  • обновляется символьная ссылка /private/var/evasi0n/sock указывающая на /var/tmp/launchd/sock, позволяющая другому коду непосредственно взаимодействовать с launchd пользователя root.


Evasi0n перзагружает устройство, что выполняет описанную конфигурацию. Интересный момент связан с тем что ни amfi.dylib, ни evasi0n не содержат цифровой подписи. Если изучить файл amfi.dylib с помощью otool, выясняется что в нем нет секции __text (прим переводчика: в секции __text сегмента __TEXT хранится машинный код). А если нет секции __text – то и подписывать нечего, и проверка на цифровую подпись выполняться не будет. Работает amfi.dylib с помощью информации о позднем связывании:

$ dyldinfo -export amfi.dylib 
export information (from trie):
[re-export] _kMISValidationOptionValidateSignatureOnly (_kCFUserNotificationTokenKey from CoreFoundation)
[re-export] _kMISValidationOptionExpectedHash (_kCFUserNotificationTimeoutKey from CoreFoundation)
[re-export] _MISValidateSignature (_CFEqual from CoreFoundation)


Эта техника рассмотрена в http://networkpx.blogspot.com/2009/09/compiling-iphoneos-31-apps-with-xcode.html:

Если мы сможем заставить MISValidateSignature() всегда возвращать 0, любые файлы пройдут тест. Эта функция – часть libmis.dylib, которая сейчас хранится в разделяемом кеше, так что сложно пропатчить саму функцию. Заменить реализацию этой функции с помощью MobileSubstrate было бы замечательно, но как я ни пытался, MS не мог ее подменить. Тогда я использовал трюк: создал «проксирующую» библиотеку, которая переадресует MISValidateSignature().


С помощью хитрого использования динамической библиотеки без кода, существующие настоящие функции (такие как CFEqual()) повторно экспортируются как другие функции с идентичными аргументами, что приводит к тому, что MISValidateSignature() всегда возвращает 0, позволяя выполнять любой исполняемый файл.

Итог


Evasi0n интересен тем, что он повышает привилегии и получает полный доступ к системному разделу без повреждений памяти процессов. С помощью уязвимости /var/db/timezone он получает доступ к launchd и модифицирует MobileFileIntegrity так, чтобы он всегда подтверждал, что цифровые подписи корректны.
Tags:
Hubs:
+115
Comments46

Articles