Jailbreak Detection — набор механизмов, определяющих наличие джейлбрейка на iOS-устройстве и предотвращающих запуск приложения в среде со снятыми ограничениями. Джейлбрейк даёт доступ к файловой системе вне песочницы, позволяя устанавливать модифицированные библиотеки и перехватывать системные вызовы. По данным Apple Security Documentation (2024), устройства с джейлбрейком не соответствуют модели безопасной загрузки Secure Boot. Jailbreak Detection комбинирует проверки файловых индикаторов, runtime-анализ вызовов и контроль целостности подписи sandbox.
Главное
Jailbreak Detection — процесс идентификации iOS-устройств, на которых сняты ограничения операционной системы. Джейлбрейк модифицирует ядро iOS, отключает код-подпись, предоставляет доступ к полной файловой системе и позволяет загружать неавторизованные библиотеки. Для приложения, работающего на таком устройстве, отсутствуют гарантии целостности среды выполнения: любой процесс может читать память приложения, перехватывать SSL/TLS-трафик через установку собственных сертификатов в хранилище системы и инжектировать код через Cydia Substrate или Substitute.
Финансовые приложения под iOS обязаны внедрять Jailbreak Detection по требованиям стандарта PCI DSS — для сертификации приложение должно доказывать, что не работает на скомпрометированном устройстве. OWASP Mobile Security (2024) классифицирует отсутствие Jailbreak Detection как уязвимость M8. Для приложений App Store Apple не запрещает блокировку функциональности на джейлбрейкнутых устройствах, однако рекомендует сочетать client-side и server-side проверки, чтобы не полагаться исключительно на клиентский код, который может быть модифицирован.
Архитектура Jailbreak Detection в iOS сложнее, чем Root Detection в Android, из-за модели sandbox. На Android приложение может читать /proc для анализа системы. iOS-песочница (sandbox) блокирует прямой доступ к большинству системных индикаторов. Разработчики вынуждены использовать обходные техники, такие как проверка доступности файлов в запрещённых зонах через API canAccessFile или запуск дочерних процессов через fork() с проверкой exit code. Современные проверки строятся на попытке выполнения действий, доступных только при джейлбрейке, и анализе результата.
Самый простой и исторически первый подход — проверка наличия файлов и приложений, которые устанавливаются только на устройствах с джейлбрейком. Несмотря на примитивность, файловые проверки остаются базовым слоем защиты, так как их обход требует активных действий со стороны пользователя.
На джейлбрейкнутом устройстве присутствуют приложения Cydia, Sileo, Zebra или Installer. Их наличие проверяется через NSFileManager: [[NSFileManager defaultManager] fileExistsAtPath:@"/Applications/Cydia.app"]. Аналогично проверяются пакеты от unc0ver, checkra1n, Taurine и Chimera. Эти проверки обходятся через HideJB-твики, которые перехватывают вызовы NSFileManager.
Джейлбрейк устанавливает UNIX-утилиты, недоступные в stock iOS: apt, dpkg, ssh, rsync, sftp, dd, readlink и другие. Проверяется существование /usr/bin/ssh, /bin/bash, /bin/sh и /usr/libexec/sftp-server. При успешном обнаружении любого из этих файлов вероятность джейлбрейка высока. Для iOS 13–17 актуально также проверять наличие /var/jb — корневого каталога bootstrap для unc0ver и Taurine.
MobileSubstrate (CydiaSubstrate.dylib) и Substitute — библиотеки для инжекции кода в процессы. Их наличие проверяется через dlopen() с флагом RTLD_NOLOAD. Если библиотека загружена в адресное пространство — процесс работает в среде с джейлбрейком. Это более надёжная проверка, так как HideJB не может выгрузить уже загруженную в процесс библиотеку.
- (BOOL)isJailbrokenByFiles {
NSArray *paths = @[
@"/Applications/Cydia.app",
@"/Applications/Sileo.app",
@"/Applications/Zebra.app",
@"/usr/bin/ssh",
@"/bin/bash",
@"/var/jb",
@"/etc/apt"
];
for (NSString *path in paths) {
if ([[NSFileManager defaultManager]
fileExistsAtPath:path]) {
return YES;
}
}
return NO;
}
- (BOOL)isSubstrateLoaded {
void *handle = dlopen(
"/Library/MobileSubstrate/MobileSubstrate.dylib",
RTLD_NOLOAD | RTLD_LAZY
);
if (handle) {
dlclose(handle);
return YES;
}
return NO;
}
Динамические проверки выполняют действия, которые в iOS-песочнице запрещены, и анализируют результат. Если действие не заблокировано — устройство, скорее всего, имеет джейлбрейк.
В stock iOS вызов fork() возвращает -1 с errno = EPERM. На джейлбрейкнутом устройстве fork() может выполниться, так как ограничения песочницы сняты. Эта проверка надёжна, но может приводить к ложным срабатываниям на некоторых версиях iOS. fork() также можно заменить на posix_spawn() для проверки возможности запуска дочернего процесса.
Попытка чтения файлов в запрещённых зонах: /etc/master.passwd, /var/log/system.log, /private/var/cache. В stock iOS эти чтения возвращают ошибку. Если приложение успешно читает эти файлы — sandbox отключён. Дополнительно проверяется возможность записи в /private/ — в песочнице все системные разделы смонтированы как read-only для обычных приложений.
Джейлбрейк модифицирует системные библиотеки, включая dyld shared cache. Проверка хеша системных фреймворков или отдельных символов может выявить модификацию. Для iOS 14+ проверяется наличие символа jit_region_create или других признаков работы Fugu14/checkra1n в адресном пространстве ядра через чтение sysctl kern.version.
- (BOOL)isJailbrokenByRuntime {
// Проверка fork()
int pid = fork();
if (pid == 0) {
exit(0);
}
if (pid > 0) {
waitpid(pid, NULL, 0);
return YES;
}
// Проверка доступа к системным файлам
FILE *f = fopen("/etc/master.passwd", "r");
if (f) {
fclose(f);
return YES;
}
// Проверка sysctl kern.version
size_t size = 0;
sysctlbyname("kern.version", NULL, &size, NULL, 0);
if (size > 0) {
char *version = malloc(size);
sysctlbyname("kern.version", version, &size, NULL, 0);
NSString *str = [NSString stringWithUTF8String:version];
free(version);
if ([str containsString:"pwned"]) {
return YES;
}
}
return NO;
}
Swift-код легко дизассемблируется и обходится через Substrate. Нативная реализация на Objective-C с прямыми вызовами libobjc и системных функций C делает проверки значительно устойчивее к обходу.
Вызов stat() из libc не может быть перехвачен на уровне Objective-C. HideJB-твики, перехватывающие методы NSFileManager, не влияют на stat(). Нативная проверка с stat() обнаруживает файловые индикаторы даже на устройствах с установленными HideJB-модулями. Комбинация stat() для файлов и dlopen() с RTLD_NOLOAD для библиотек даёт два непересекающихся канала обнаружения.
Нативная функция SecStaticCodeCheckValidity проверяет код-подпись приложения на соответствие сертификату Apple. На джейлбрейкнутом устройстве эта проверка может быть подменена через kernel-patch. Для обхода подмены следует выполнять проверку из нативного кода с вызовом через dlopen() из Security.framework, а не через Swift Bridge.
#import <sys/stat.h>
#import <dlfcn.h>
- (BOOL)nativeCheckForJailbreak {
// stat() обход NSFileManager hook
struct stat st;
if (stat("/Applications/Cydia.app", &st) == 0) {
return YES;
}
// dlopen для проверки Substrate без загрузки
void *substrate = dlopen(
"/Library/MobileSubstrate/MobileSubstrate.dylib",
RTLD_NOLOAD
);
if (substrate) {
dlclose(substrate);
return YES;
}
return NO;
}
Понимание техник обхода необходимо для построения устойчивой защиты. Современные инструменты обхода активно развиваются, и статический набор проверок становится неэффективным в течение нескольких месяцев.
HideJB — твик, перехватывающий вызовы NSFileManager, stat(), dlopen() и fork() и подменяющий возвращаемые значения. HideJB работает на уровне Cydia Substrate, поэтому перехватывает как Objective-C, так и C-функции. Версия HideJB для iOS 15–16 (Shadow) использует методологию kernel-level hooks. Контр-мера: выполнение проверки в отдельном процессе с передачей результата через IPC, что разрывает цепочку hook.
Choicy позволяет отключать Substrate для конкретных процессов. Пользователь просто отключает инжекцию для защищённого приложения — все проверки на библиотеки возвращают false. Liberty Lite — комплексный обход, закрывающий большинство проверок из популярных библиотек защиты. Контр-мера: серверная верификация через DeviceCheck и App Attest — на сервере проверяется, что устройство имеет валидный Apple-сертификат, который не может быть подделан на джейлбрейкнутом устройстве.
Эксплойты ядра, такие как Fugu14 и KFD, выполняют код в пространстве ядра (kernel-space), что позволяет перехватывать системные вызовы до того, как их увидит приложение. На этом уровне проверки stat() и fork() становятся неэффективными. Единственная надёжная контр-мера — серверная аттестация с проверкой, что устройство прошло процедуру Apple Attestation. Этот протокол основан на криптографических ключах внутри Secure Enclave, которые недоступны для чтения даже при kernel-level эксплойте.
Для построения эффективного Jailbreak Detection необходимо понимать, какие именно механизмы безопасности iOS отключаются при джейлбрейке.
iOS загружается через последовательность проверок подписей: Boot ROM → iBoot → iOS Kernel. Если джейлбрейк использует bootrom exploit (checkra1n), весь Secure Boot Chain скомпрометирован — проверки на прикладном уровне бесполезны. Если используется software-only эксплойт (unc0ver, Taurine, Fugu14), цепочка загрузки не нарушена, и Apple-сервисы, такие как App Attest, остаются доверенными.
Начиная с iOS 10, Apple внедрила KPP — аппаратную защиту, перепроверяющую целостность ядра каждые 200 мс. Все современные джейлбрейки (iOS 14–17) используют KTRR bypass через PAC или APRR, но KPP оставляет следы в виде изменённых системных таблиц sysctl. Проверка kern.version на наличие строк pwned, prod, или xnu с нестандартной версией может выявить наличие kernel patch.
iOS Sandbox работает на уровне TrustedBSD, используя entitlements. Джейлбрейк подменяет sandbox profile на allow-all. Приложение может проверить sandbox через попытку чтения любого файла вне своей директории Documents. Если успешно — sandbox модифицирован. Sandbox Integrity — один из немногих индикаторов, который невозможно подделать без kernel-level эксплойта, так как проверка разрешений выполняется в ядре до того, как она может быть перехвачена.
Часто задаваемые вопросы
Root Detection для Android проверяет наличие su-бинарника и Magisk. Jailbreak Detection для iOS ищет Cydia, Sileo, MobileSubstrate, проверяет возможность fork() и читает системные файлы. Архитектура iOS Sandbox жёстче, чем Android, поэтому iOS-проверки больше полагаются на попытку выполнения запрещённых действий, а не на чтение системных индикаторов.
Да, для iOS 16–17 актуальны джейлбрейки Dopamine, palera1n и checkra1n. Jailbreak Detection работает, но требует обновления проверок под новые инструменты. В iOS 17 Apple усилила sandbox, и многие старые проверки (например, fork()) перестали быть надёжными из-за изменений в XNU
Самый простой способ — HideJB или Shadow, перехватывающие проверки на уровне библиотек. Для более сложной защиты используется Frida или Choicy с отключением инжекции для конкретного приложения. Серверная аттестация (App Attest) обходится только через kernel-level эксплойт с подменой аппаратного ключа Secure Enclave, что практически нереализуемо.
Любое приложение на джейлбрейкнутом устройстве может быть подвергнуто: перехвату SSL-трафика через модификацию доверенного хранилища, чтению Keychain через доступ к файловой системе, инжекции кода через Substrate с перехватом методов работы с токенами, идампингу памяти процесса с получением ключей шифрования.
App Attest — сервис Apple для проверки целостности приложения и устройства. При старте приложение получает от сервера Apple attestation challenge, подписывает его закрытым ключом из Secure Enclave и отправляет на свой сервер. Если устройство джейлбрейкнуто, Secure Enclave отвечает attestation failure, что блокирует доступ к защищённым функциям.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также