На пентесте iOS-приложения финтех-сервиса в прошлом квартале мы вытащили auth-токены из Keychain одной командой через objection - разработчики выставили
[URL='https://developer.apple.com/documentation/security/ksecattraccessiblealways']kSecAttrAccessibleAlways[/URL], и токены читались на заблокированном устройстве. Обход Face ID занял один Frida-скрипт на шесть строк - Шесть! Строк! Ребята полагались на платформенную безопасность iOS и не закладывали сценарий джейлбрейкнутого устройства в модель угроз - а зря. Эта статья - пошаговое руководство по пентесту iOS приложений: от подготовки устройства через jailbreak до извлечения секретов из бинарников и обхода биометрической аутентификации. Каждый шаг привязан к MITRE ATT&CK и OWASP MASVS, с конкретными командами и объяснением, почему они работают.Карта атаки: где iOS pentest вписывается в kill chain
Пентест iOS приложений - цепочка техник, где каждый шаг зависит от результатов предыдущего. Без jailbreak нет runtime-анализа. Без расшифровки IPA нет осмысленного реверса. Вот как это ложится на MITRE ATT&CK:| Этап пентеста | MITRE ATT&CK | Что делаем |
|---|---|---|
| Jailbreak устройства | Exploitation for Privilege Escalation (T1068) | Root-доступ через checkra1n / palera1n |
| Расшифровка IPA | Deobfuscate/Decode Files or Information (T1140) | frida-ios-dump для дампа декриптованного бинарника |
| Анализ бинарника | Obfuscated Files or Information (T1027) | Проверка PIE, ARC, stack canaries, реверс в Hopper/Ghidra |
| Дамп Keychain | Keychain (T1555.001, credential-access) | Извлечение токенов, паролей, ключей через objection |
| Анализ файловой системы | Data from Local System (T1005, collection) | Поиск секретов в plist, SQLite, NSUserDefaults |
| Обход биометрии | Multi-Factor Authentication Interception (T1111) | Патч LAContext через Frida |
| Обход jailbreak detection | Связано с MASVS-RESILIENCE | Runtime-хуки для обхода проверок среды |
Контекст применения, эта цепочка работает при внутреннем пентесте мобильного приложения (grey/white box, есть доступ к IPA или App Store аккаунту). При black box добавляется этап получения IPA - через iTunes-бэкап или перехват загрузки.
Jailbreak для пентеста iOS: выбор инструмента
Требования к окружению
- ОС хоста: macOS (рекомендуется) или GNU\Linux. Windows не поддерживает работу с checkra1n и palera1n
- Устройство: физический iPhone или iPad. iOS-симулятор Xcode бесполезен - бинарники компилируются под x86, а не ARM, App Store приложения на нём не запускаются. Согласно OWASP MASTG, единственный публичный iOS-эмулятор - Corellium
- Кабель: USB-A to Lightning. С USB-C кабелем ввод в DFU-режим часто зависает - берите переходник USB-C на USB-A, сэкономите себе нервы
- На хосте:
pip install frida-tools objection. Версии Frida на хосте и устройстве должны совпадать - несовпадение ломает взаимодействие. Проверено на собственных граблях: потратил полчаса на дебаг, пока не понял, что на устройстве 16.1.4, а на хосте 16.2.1
checkra1n vs palera1n: decision tree
Выбор jailbreak определяется чипом устройства и версией iOS:| Условие | Инструмент | Тип | Особенности |
|---|---|---|---|
| Чип A5–A11, iOS до 14.x | checkra1n | Semi-tethered | Аппаратный эксплойт checkm8 в BootROM - Apple не может закрыть софтверным обновлением |
| Чип A8–A11, iOS 15–16.x | palera1n | Semi-tethered | Тоже на базе checkm8, поддержка iOS 15–16 |
| Чип A12+ (iPhone XS и новее), iOS 17+ | Нет публичного jailbreak | - | Вариант: Corellium или ждать публичного эксплойта |
Согласно OWASP MASTG, checkm8 затрагивает BootROM всех процессоров до A12 - аппаратная уязвимость, которая не закрывается обновлениями iOS. Для тестирования безопасности iOS это значит: iPhone 6s через iPhone X - надёжные рабочие лошадки, которые будут джейлбрейкаться при любой версии iOS.
Установка palera1n (для iOS 15–16, с официального сайта и подтверждено RU-источниками):
Bash:
sudo /bin/sh -c "$(curl -fsSL https://static.palera.in/scripts/install.sh)"
palera1n
frida-server. Версию frida-server подбираем строго под версию frida-tools на хосте!Критический нюанс: semi-tethered jailbreak слетает при перезагрузке. Для повторной активации нужно подключить устройство к Mac и запустить palera1n заново. После jailbreak SSH-доступ со стандартными credentials:
root / alpine - менять на тестовом устройстве не обязательно, но в публичные Wi-Fi сети с таким паролем лезть нельзя.Статический анализ IPA: что скрывает бинарник
Статический анализ - fingerprinting приложения до его запуска. Извлекаем бинарник, проверяем защиты, ищем захардкоженные секреты. Это этап T1027/T1140 по MITRE ATT&CK.Извлечение и расшифровка IPA
App Store приложения зашифрованы FairPlay DRM. Без расшифровки дизассемблирование покажет мусор. Для расшифровки качаем frida-ios-dump(GitHub - AloneMonkey/frida-ios-dump: pull decrypted ipa from jailbreak device) - Python-скрипт, который через Frida дампит расшифрованный бинарник из памяти работающего приложения:python dump.py com.example.app. Получаем готовый IPA.IPA - ZIP-архив. Распаковываем:
unzip target.ipa -d output/. Структура:Payload/App.app/AppBinary- основной бинарник ARM64Info.plist- конфигурация: URL-схемы, разрешения, адреса бэкендовFrameworks/- встроенные фреймворки, часто со своими уязвимостями
/var/containers/Bundle/Application/<UID>/, данные - в /var/mobile/Containers/Data/Application/<UID>/, shared data - в /var/mobile/Containers/Shared/AppGroup/<UID>/. UID генерируется при установке и меняется при переустановке - для поиска нужного приложения сортируйте по дате создания.Анализ бинарников iOS: проверка защит и реверс-инжиниринг
Перед глубоким реверсом проверяем бинарные защиты. Занимает минуту сotool (стандартная утилита Xcode Command Line Tools):
Bash:
otool -hv AppBinary | grep PIE # ASLR: Position Independent Executable
otool -Iv AppBinary | grep stack_chk # Stack canaries
otool -l AppBinary | grep cryptid # cryptid 0 = расшифровано
__stack_chk_fail) - защита от buffer overflow, отсутствие - повод копнуть глубже; cryptid 0 - frida-ios-dump отработал, cryptid 1 - бинарник ещё зашифрован.Для извлечения Objective-C интерфейсов:
class-dump -H AppBinary -o headers/ генерирует заголовочные файлы всех классов. Имена методов часто напрямую выдают логику: isJailbroken, validatePurchase, checkBiometricAuth. Для Swift-бинарников class-dump менее эффективен - Swift-символы обфусцированы по умолчанию, тут нужен дизассемблер.Инструменты для глубокого reverse engineering iOS:
- Hopper Disassembler (~$100, macOS) - нативная поддержка Objective-C и Swift, удобная навигация по классам. Мой основной инструмент для ios pentest работы (активно поддерживается, версия 5.x)
- Ghidra (бесплатно, NSA) - мощный декомпилятор ARM64. По данным Corellium, Ghidra восстанавливает логику обфусцированного кода через mapping control flow и реверс Objective-C class structures (активно поддерживается, версия 11.x). Бесплатный - и очень хорош
- R2Frida - связка radare2 и Frida. Одновременно читаем дизассемблированный код и трейсим вызовы функций на живом устройстве. Штука специфическая, но когда нужно разобраться в обфусцированной логике на лету - незаменима
canOpenURL: c cydia://); криптографические константы - слабые алгоритмы, хардкод IV и ключей; логику проверки подписки на клиенте вместо сервера.Динамический анализ iOS приложений: Frida и objection в деле
Динамический анализ - работа с запущенным приложением: перехват трафика, дамп хранилищ, runtime manipulation. Ключевая часть mobile pentest iOS.SSL Pinning bypass
Без обхода SSL Pinning мы не увидим трафик приложения. Последовательность:
- В Burp Suite Pro:
Proxy → Options → Bind to address: All interfaces- открываем прокси в локальной сети - На устройстве:
Settings → Wi-Fi → HTTP Proxy → Manual → IP_хоста : порт_Burp - Установка сертификата: в Safari идём по
http://burp, скачиваем CA Certificate, доверяем вSettings → General → VPN & Device Management - Проверяем связь:
frida-ps -Uiaна хосте - должен показать список процессов на устройстве - Подключаемся к приложению:
objection -g com.target.app explore - В консоли objection:
ios sslpinning disable
Альтернатива - tweak SSL Kill Switch 2 через Sileo: отключает pinning на системном уровне для всех приложений, не требует запуска objection каждый раз. Но менее контролируемый: нельзя включать/отключать для конкретного приложения.
По классификации OWASP MASVS-NETWORK, certificate pinning - обязательное требование. На самом деле, примерно половина приложений, попадавших ко мне на тестирование безопасности iOS, либо не реализуют его, либо проверяют только leaf-сертификат и ломаются при подмене intermediate. Грустная статистика.
Дамп Keychain и анализ хранилища данных
Keychain - рекомендованное Apple хранилище для чувствительных данных. Но как оно всегда и бывает рекомендация и реализация - разные вещи. В консоли objection:ios keychain dump - выводит все доступные элементы с атрибутами доступности.Что искать (по MASVS-STORAGE):
kSecAttrAccessibleAlways- данные доступны даже на заблокированном устройстве. Самая частая ошибка в финтех-приложениях- Пароли и токены в открытом виде - без дополнительного шифрования поверх Keychain
- Элементы без привязки к биометрии - если разработчик не задал
kSecAccessControlBiometryAny, данные читаются без аутентификации пользователя
ios nsuserdefaults get в objection - часто тут лежат feature flags, а иногда и токены), SQLite базы в директории данных приложения (незашифрованные), plist-файлы с кэшем и конфигурацией. Всё это - T1005 (Data from Local System) и T1555.001 (Keychain) по MITRE ATT&CK.Обход биометрии iOS: патчим LAContext через Frida
Touch ID и Face ID используют фреймворк LocalAuthentication - методLAContext.evaluatePolicy:localizedReason:reply:. Метод принимает reply block с двумя аргументами: success (Bool) и error (NSError?). Если success == true - пользователь аутентифицирован.Атака:
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
evaluatePolicy, подменяет callback и вызывает оригинал с result = 1. Приложение считает, что биометрия пройдена. По MITRE ATT&CK - Multi-Factor Authentication Interception (T1111).Где обход биометрии iOS не работает
| Реализация | Обходится Frida | Почему |
|---|---|---|
| LAContext.evaluatePolicy (UI-проверка) | Да | Логика целиком в userland, патчится хуком |
| Keychain + kSecAccessControlBiometryAny | Нет | Валидация в Secure Enclave, Frida не имеет доступа к TEE |
| CryptoKit + LAContext binding | Нет | Ключ разблокируется только после аппаратной биометрии |
Большинство приложений используют первый вариант - чистый LAContext без привязки к Keychain. Проверка «прошёл ли пользователь биометрию» сводится к boolean в userland. Архитектурная ошибка, которую я вижу раз за разом: любая проверка, результат которой - true/false в клиентском коде - обходится runtime-хуком - всегда.
Jailbreak detection и его обход
MASVS-RESILIENCE требует от приложений проверять целостность среды. Типичные методы: проверка файлов (
/Applications/Cydia.app, /usr/sbin/sshd, /etc/apt), URL-схемы (cydia:// через canOpenURL:), попытка записи вне sandbox, проверка dyld на инъецированные библиотеки, сканирование порта 27042 (дефолтный порт frida-server).| Метод обхода | Подход | Когда использовать | Ограничения |
|---|---|---|---|
ios jailbreak disable (objection) | Runtime-хуки через Frida | Первый шаг, работает для большинства приложений | Работает пока активна сессия, слетает при рестарте |
| Liberty Lite | Системный tweak | Персистентный обход без ручных действий | Давно не обновлялся, конфликтует с другими tweaks |
| A-Bypass | Современный tweak | Когда Liberty Lite не справляется | Поддержка ограничена конкретными версиями iOS |
| Кастомный Frida-скрипт | Точечные хуки конкретных проверок | Нестандартные проверки (socket-based, dyld-based) | Требует реверса логики детекта в конкретном приложении |
По данным Corellium, одна из техник обхода port-based detection - запуск frida-server на нестандартном порту:
frida-server -l 0.0.0.0:1337. Приложение проверяет 27042 - а frida-server слушает на другом. Примитивно, но работает.Мой подход на практике: начинаю с
ios jailbreak disable в objection. Если приложение продолжает детектить jailbreak - через class-dump ищу методы с характерными именами (isJailbroken, detectJailbreak), потом пишу точечный Frida-скрипт для их патча. Тот же подход работает для anti-debugging: если приложение вызывает приватный API ptrace с PT_DENY_ATTACH, это видно в Hopper и патчится аналогично.Большинство iOS-приложений, которые попадают на пентест, реализуют один-два пункта из OWASP MASVS-RESILIENCE. Jailbreak detection есть - но обходится objection за секунду. SSL Pinning есть - но только на leaf-сертификат. Биометрия есть - но через LAContext без привязки к Keychain.
Разработчики воспринимают iOS как безопасную платформу из коробки и не закладывают adversary model с root-доступом к устройству. На джейлбрейкнутом iPhone каждый из описанных шагов отрабатывает без серьёзного сопротивления. Единственное, что реально усложняет работу - Keychain items с привязкой к Secure Enclave и биометрией на аппаратном уровне. Таких реализаций за последние два года я встретил три из двадцати с лишним проектов.
Frida и objection работают отлично - не в них проблема. Проблема в архитектуре приложений, где безопасность делегируется платформе вместо того, чтобы закладываться в код. Пока защита сводится к проверке
isJailbroken() и boolean-флагу от LAContext, iOS-пентест будет оставаться предсказуемо результативным - и для охотников за уязвимостями, и для тех, кто попробует собрать описанную цепочку самостоятельно. На WAPT эту цепочку проходят в течение двух модулей с лабами.
Последнее редактирование модератором: