Jailbreak Detection es un conjunto de mecanismos que detectan la presencia de un jailbreak en un dispositivo iOS y evitan que la aplicación se ejecute en un entorno con restricciones eliminadas. El jailbreak proporciona acceso al sistema de archivos fuera del sandbox, permitiendo instalar bibliotecas modificadas e interceptar llamadas del sistema. Según Apple Security Documentation (2024), los dispositivos con jailbreak no cumplen con el modelo de seguridad de arranque seguro Secure Boot. Jailbreak Detection combina comprobaciones de indicadores de archivos, análisis de llamadas en tiempo de ejecución y verificación de integridad de la firma del sandbox.
Puntos Clave
Jailbreak Detection es el proceso de identificar dispositivos iOS que han tenido sus restricciones del sistema operativo eliminadas. El jailbreak modifica el kernel de iOS, desactiva la firma de código, proporciona acceso completo al sistema de archivos y permite cargar bibliotecas no autorizadas. Para una aplicación que se ejecuta en dicho dispositivo, no hay garantías de integridad del entorno de ejecución: cualquier proceso puede leer la memoria de la aplicación, interceptar tráfico SSL/TLS instalando sus propios certificados en el almacén de confianza del sistema e inyectar código a través de Cydia Substrate o Substitute.
Las aplicaciones financieras en iOS deben implementar Jailbreak Detection según los estándares PCI DSS — para la certificación, la aplicación debe demostrar que no se ejecuta en un dispositivo comprometido. OWASP Mobile Security (2024) clasifica la ausencia de Jailbreak Detection como vulnerabilidad M8. Para las aplicaciones de App Store, Apple no prohíbe bloquear la funcionalidad en dispositivos con jailbreak, pero recomienda combinar comprobaciones del lado del cliente y del servidor para no depender únicamente del código del cliente que podría ser modificado.
La arquitectura de Jailbreak Detection en iOS es más compleja que Root Detection en Android debido al modelo de sandbox. En Android, una aplicación puede leer /proc para analizar el sistema. El sandbox de iOS bloquea el acceso directo a la mayoría de los indicadores del sistema. Los desarrolladores se ven obligados a usar técnicas alternativas como verificar la disponibilidad de archivos en zonas restringidas a través de la API canAccessFile o lanzar procesos hijos mediante fork() con verificación del código de salida. Las comprobaciones modernas se basan en intentar acciones solo disponibles bajo jailbreak y analizar el resultado.
El enfoque más simple e históricamente primero es verificar la presencia de archivos y aplicaciones que solo se instalan en dispositivos con jailbreak. A pesar de su simplicidad, las comprobaciones de archivos siguen siendo una capa básica de defensa, ya que evadirlas requiere una acción activa del usuario.
En un dispositivo con jailbreak, están presentes aplicaciones como Cydia, Sileo, Zebra o Installer. Su presencia se verifica mediante NSFileManager: [[NSFileManager defaultManager] fileExistsAtPath:@"/Applications/Cydia.app"]. Los paquetes de unc0ver, checkra1n, Taurine y Chimera se verifican de manera similar. Estas comprobaciones se pueden evadir mediante tweaks de HideJB que interceptan las llamadas a NSFileManager.
El jailbreak instala utilidades UNIX no disponibles en iOS estándar: apt, dpkg, ssh, rsync, sftp, dd, readlink y otras. Se verifica la existencia de /usr/bin/ssh, /bin/bash, /bin/sh y /usr/libexec/sftp-server. Si se detecta con éxito alguno de estos archivos, la probabilidad de jailbreak es alta. Para iOS 13–17, también es relevante verificar la presencia de /var/jb — el directorio raíz de bootstrap para unc0ver y Taurine.
MobileSubstrate (CydiaSubstrate.dylib) y Substitute son bibliotecas para inyección de código en procesos. Su presencia se verifica mediante dlopen() con la bandera RTLD_NOLOAD. Si la biblioteca está cargada en el espacio de direcciones — el proceso se ejecuta en un entorno con jailbreak. Esta es una comprobación más fiable, ya que HideJB no puede descargar una biblioteca ya cargada en un proceso.
- (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;
}
Las comprobaciones dinámicas realizan acciones prohibidas en el sandbox de iOS y analizan el resultado. Si la acción no está bloqueada — lo más probable es que el dispositivo tenga jailbreak.
En iOS estándar, la llamada fork() devuelve -1 con errno = EPERM. En un dispositivo con jailbreak, fork() puede ejecutarse ya que las restricciones del sandbox se eliminan. Esta comprobación es fiable pero puede producir falsos positivos en algunas versiones de iOS. fork() también se puede reemplazar con posix_spawn() para verificar la capacidad de lanzar un proceso hijo.
Intento de leer archivos en zonas restringidas: /etc/master.passwd, /var/log/system.log, /private/var/cache. En iOS estándar, estas lecturas devuelven un error. Si la aplicación lee con éxito estos archivos — el sandbox está desactivado. Adicionalmente, se verifica la capacidad de escribir en /private/ — en un sandbox, todas las particiones del sistema están montadas como solo lectura para las aplicaciones normales.
El jailbreak modifica las bibliotecas del sistema, incluida la caché compartida de dyld. Verificar el hash de los frameworks del sistema o de símbolos individuales puede revelar la modificación. Para iOS 14+, se verifica la presencia del símbolo jit_region_create u otros signos de funcionamiento de Fugu14/checkra1n en el espacio de direcciones del kernel mediante la lectura de sysctl kern.version.
- (BOOL)isJailbrokenByRuntime {
// Comprobando fork()
int pid = fork();
if (pid == 0) {
exit(0);
}
if (pid > 0) {
waitpid(pid, NULL, 0);
return YES;
}
// Comprobando acceso a archivos del sistema
FILE *f = fopen("/etc/master.passwd", "r");
if (f) {
fclose(f);
return YES;
}
// Comprobando 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;
}
El código Swift se desensambla y evita fácilmente mediante Substrate. Una implementación nativa en Objective-C con llamadas directas a libobjc y funciones del sistema C hace que las comprobaciones sean significativamente más resistentes a la evasión.
La llamada stat() de libc no puede ser interceptada a nivel de Objective-C. Los tweaks de HideJB que interceptan métodos de NSFileManager no afectan a stat(). Una comprobación nativa con stat() detecta indicadores de archivos incluso en dispositivos con módulos HideJB instalados. La combinación de stat() para archivos y dlopen() con RTLD_NOLOAD para bibliotecas proporciona dos canales de detección no superpuestos.
La función nativa SecStaticCodeCheckValidity verifica la firma de código de la aplicación contra el certificado de Apple. En un dispositivo con jailbreak, esta verificación puede ser falsificada mediante un parche del kernel. Para evitar la falsificación, la verificación debe realizarse desde código nativo con una llamada a través de dlopen() desde Security.framework, en lugar de a través de Swift Bridge.
#import <sys/stat.h>
#import <dlfcn.h>
- (BOOL)nativeCheckForJailbreak {
// stat() evadiendo el hook de NSFileManager
struct stat st;
if (stat("/Applications/Cydia.app", &st) == 0) {
return YES;
}
// dlopen para verificar Substrate sin cargar
void *substrate = dlopen(
"/Library/MobileSubstrate/MobileSubstrate.dylib",
RTLD_NOLOAD
);
if (substrate) {
dlclose(substrate);
return YES;
}
return NO;
}
Comprender las técnicas de evasión es esencial para construir una protección robusta. Las herramientas modernas de evasión evolucionan activamente, y un conjunto estático de comprobaciones se vuelve ineficaz en cuestión de meses.
HideJB es un tweak que intercepta las llamadas a NSFileManager, stat(), dlopen() y fork(), reemplazando los valores de retorno. HideJB funciona a nivel de Cydia Substrate, interceptando tanto funciones de Objective-C como de C. La versión de HideJB para iOS 15–16 (Shadow) utiliza una metodología de hooks a nivel de kernel. Contramedida: realizar la comprobación en un proceso separado con entrega del resultado a través de IPC, lo que rompe la cadena de hooks.
Choicy permite desactivar Substrate para procesos específicos. El usuario simplemente desactiva la inyección para la aplicación protegida — todas las comprobaciones de bibliotecas devuelven false. Liberty Lite es una evasión integral que cubre la mayoría de las comprobaciones de las bibliotecas de protección populares. Contramedida: verificación del lado del servidor mediante DeviceCheck y App Attest — el servidor verifica que el dispositivo tenga un certificado Apple válido que no pueda ser falsificado en un dispositivo con jailbreak.
Los exploits del kernel, como Fugu14 y KFD, ejecutan código en el espacio del kernel, permitiendo interceptar llamadas del sistema antes de que la aplicación las vea. En este nivel, las comprobaciones de stat() y fork() se vuelven ineficaces. La única contramedida fiable es la atestación del lado del servidor con verificación de que el dispositivo ha pasado el procedimiento de Apple Attestation. Este protocolo se basa en claves criptográficas dentro del Secure Enclave, que son ilegibles incluso con un exploit a nivel de kernel.
Para construir una detección de jailbreak efectiva, es necesario entender qué mecanismos de seguridad de iOS se desactivan durante el jailbreak.
iOS arranca a través de una secuencia de verificaciones de firma: Boot ROM → iBoot → iOS Kernel. Si el jailbreak utiliza un exploit de bootrom (checkra1n), toda la cadena de arranque seguro se ve comprometida — las comprobaciones a nivel de aplicación son inútiles. Si se utiliza un exploit solo de software (unc0ver, Taurine, Fugu14), la cadena de arranque no se rompe y servicios de Apple como App Attest siguen siendo de confianza.
A partir de iOS 10, Apple introdujo KPP — protección hardware que vuelve a verificar la integridad del kernel cada 200 ms. Todos los jailbreaks modernos (iOS 14–17) utilizan la evasión de KTRR mediante PAC o APRR, pero KPP deja rastros en forma de tablas de sistema sysctl modificadas. Verificar kern.version en busca de cadenas como pwned, prod o xnu con una versión no estándar puede revelar un parche del kernel.
El sandbox de iOS funciona a nivel de TrustedBSD utilizando entitlements. El jailbreak reemplaza el perfil del sandbox con allow-all. Una aplicación puede verificar el sandbox intentando leer cualquier archivo fuera de su directorio Documents. Si tiene éxito — el sandbox ha sido modificado. La integridad del Sandbox es uno de los pocos indicadores que no se puede falsificar sin un exploit a nivel de kernel, ya que la verificación de permisos se realiza en el kernel antes de que pueda ser interceptada.
Preguntas Frecuentes
Root Detection para Android verifica la presencia del binario su y Magisk. Jailbreak Detection para iOS busca Cydia, Sileo, MobileSubstrate, verifica la capacidad de ejecutar fork() y lee archivos del sistema. La arquitectura del sandbox de iOS es más estricta que la de Android, por lo que las comprobaciones de iOS se basan más en intentar realizar acciones prohibidas que en leer indicadores del sistema.
Sí, los jailbreaks Dopamine, palera1n y checkra1n son relevantes para iOS 16–17. Jailbreak Detection funciona pero requiere actualizar las comprobaciones para las nuevas herramientas. En iOS 17, Apple reforzó el sandbox y muchas comprobaciones antiguas (por ejemplo, fork()) se han vuelto poco fiables debido a cambios en XNU.
La forma más sencilla es HideJB o Shadow, que interceptan las comprobaciones a nivel de bibliotecas. Para una protección más compleja, se utiliza Frida o Choicy para desactivar la inyección para una aplicación específica. La atestación del lado del servidor (App Attest) solo se puede evadir mediante un exploit a nivel de kernel que reemplace la clave hardware de Secure Enclave, lo que es prácticamente inviable.
Cualquier aplicación en un dispositivo con jailbreak puede estar sujeta a: interceptación de tráfico SSL mediante modificación del almacén de confianza, lectura de Keychain a través del acceso al sistema de archivos, inyección de código mediante Substrate con interceptación de métodos de manejo de tokens y volcado de memoria para obtener claves de cifrado.
App Attest es un servicio de Apple para verificar la integridad de la aplicación y el dispositivo. Al iniciar, la aplicación recibe un desafío de atestación del servidor de Apple, lo firma con una clave privada del Secure Enclave y lo envía a su propio servidor. Si el dispositivo tiene jailbreak, Secure Enclave devuelve un fallo de atestación, bloqueando el acceso a funciones protegidas.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también