Jailbreak Detection é um conjunto de mecanismos que detectam a presença de jailbreak em um dispositivo iOS e impedem a execução do aplicativo em um ambiente com restrições removidas. O jailbreak fornece acesso ao sistema de arquivos fora da sandbox, permitindo instalar bibliotecas modificadas e interceptar chamadas de sistema. De acordo com Apple Security Documentation (2024), dispositivos com jailbreak não estão em conformidade com o modelo de segurança Secure Boot. Jailbreak Detection combina verificações de indicadores de arquivos, análise de chamadas em tempo de execução e verificação de integridade da assinatura da sandbox.
Pontos Principais
Jailbreak Detection é o processo de identificar dispositivos iOS que tiveram suas restrições do sistema operacional removidas. O jailbreak modifica o kernel do iOS, desativa a assinatura de código, fornece acesso ao sistema de arquivos completo e permite carregar bibliotecas não autorizadas. Para um aplicativo executado em tal dispositivo, não há garantias de integridade do ambiente de execução: qualquer processo pode ler a memória do aplicativo, interceptar tráfego SSL/TLS instalando seus próprios certificados no armazenamento confiável do sistema e injetar código via Cydia Substrate ou Substitute.
Aplicativos financeiros no iOS são obrigados a implementar Jailbreak Detection de acordo com os padrões PCI DSS — para certificação, o aplicativo deve provar que não está sendo executado em um dispositivo comprometido. O OWASP Mobile Security (2024) classifica a ausência de Jailbreak Detection como vulnerabilidade M8. Para aplicativos da App Store, a Apple não proíbe bloquear a funcionalidade em dispositivos com jailbreak, mas recomenda combinar verificações do lado do cliente e do servidor para não depender exclusivamente do código do cliente que pode ser modificado.
A arquitetura do Jailbreak Detection no iOS é mais complexa que o Root Detection no Android devido ao modelo de sandbox. No Android, um aplicativo pode ler /proc para analisar o sistema. A sandbox do iOS bloqueia o acesso direto à maioria dos indicadores do sistema. Os desenvolvedores são forçados a usar técnicas alternativas, como verificar a disponibilidade de arquivos em zonas restritas através da API canAccessFile ou iniciar processos filhos via fork() com verificação do código de saída. As verificações modernas são construídas tentando ações disponíveis apenas sob jailbreak e analisando o resultado.
A abordagem mais simples e historicamente primeira é verificar a presença de arquivos e aplicativos que só são instalados em dispositivos com jailbreak. Apesar da simplicidade, as verificações de arquivos continuam sendo uma camada básica de defesa, pois contorná-las exige ação ativa do usuário.
Em um dispositivo com jailbreak, aplicativos como Cydia, Sileo, Zebra ou Installer estão presentes. Sua presença é verificada via NSFileManager: [[NSFileManager defaultManager] fileExistsAtPath:@"/Applications/Cydia.app"]. Pacotes do unc0ver, checkra1n, Taurine e Chimera são verificados de forma similar. Essas verificações podem ser contornadas através de tweaks HideJB que interceptam chamadas do NSFileManager.
O jailbreak instala utilitários UNIX indisponíveis no iOS padrão: apt, dpkg, ssh, rsync, sftp, dd, readlink e outros. A existência de /usr/bin/ssh, /bin/bash, /bin/sh e /usr/libexec/sftp-server é verificada. Se qualquer um desses arquivos for detectado com sucesso, a probabilidade de jailbreak é alta. Para iOS 13–17, também é relevante verificar a presença de /var/jb — o diretório raiz de bootstrap para unc0ver e Taurine.
MobileSubstrate (CydiaSubstrate.dylib) e Substitute são bibliotecas para injeção de código em processos. Sua presença é verificada via dlopen() com a flag RTLD_NOLOAD. Se a biblioteca estiver carregada no espaço de endereços — o processo está executando em um ambiente com jailbreak. Esta é uma verificação mais confiável, pois o HideJB não pode descarregar uma biblioteca já carregada em um processo.
- (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;
}
As verificações dinâmicas realizam ações proibidas na sandbox do iOS e analisam o resultado. Se a ação não for bloqueada — o dispositivo provavelmente está com jailbreak.
No iOS padrão, a chamada fork() retorna -1 com errno = EPERM. Em um dispositivo com jailbreak, fork() pode ser bem-sucedido, pois as restrições da sandbox são removidas. Esta verificação é confiável, mas pode produzir falsos positivos em algumas versões do iOS. fork() também pode ser substituído por posix_spawn() para verificar a capacidade de iniciar um processo filho.
Tentativa de ler arquivos em zonas restritas: /etc/master.passwd, /var/log/system.log, /private/var/cache. No iOS padrão, essas leituras retornam um erro. Se o aplicativo ler esses arquivos com sucesso — a sandbox está desativada. Adicionalmente, a capacidade de escrever em /private/ é verificada — em uma sandbox, todas as partições do sistema são montadas como somente leitura para aplicativos normais.
O jailbreak modifica bibliotecas do sistema, incluindo o cache compartilhado do dyld. Verificar o hash de frameworks do sistema ou símbolos individuais pode revelar a modificação. Para iOS 14+, a presença do símbolo jit_region_create ou outros sinais de operação do Fugu14/checkra1n no espaço de endereço do kernel é verificada através da leitura de sysctl kern.version.
- (BOOL)isJailbrokenByRuntime {
// Verificando fork()
int pid = fork();
if (pid == 0) {
exit(0);
}
if (pid > 0) {
waitpid(pid, NULL, 0);
return YES;
}
// Verificando acesso a arquivos do sistema
FILE *f = fopen("/etc/master.passwd", "r");
if (f) {
fclose(f);
return YES;
}
// Verificando 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;
}
O código Swift é facilmente desmontado e contornado via Substrate. Uma implementação nativa em Objective-C com chamadas diretas ao libobjc e funções do sistema C torna as verificações significativamente mais resistentes a contornos.
A chamada stat() da libc não pode ser interceptada no nível Objective-C. Os tweaks HideJB que interceptam métodos do NSFileManager não afetam stat(). Uma verificação nativa usando stat() detecta indicadores de arquivo mesmo em dispositivos com módulos HideJB instalados. A combinação de stat() para arquivos e dlopen() com RTLD_NOLOAD para bibliotecas fornece dois canais de detecção não sobrepostos.
A função nativa SecStaticCodeCheckValidity verifica a assinatura de código do aplicativo contra o certificado da Apple. Em um dispositivo com jailbreak, esta verificação pode ser falsificada através de um patch do kernel. Para evitar a falsificação, a verificação deve ser realizada a partir de código nativo com uma chamada através de dlopen() do Security.framework, em vez de através do Swift Bridge.
#import <sys/stat.h>
#import <dlfcn.h>
- (BOOL)nativeCheckForJailbreak {
// stat() contornando o hook do NSFileManager
struct stat st;
if (stat("/Applications/Cydia.app", &st) == 0) {
return YES;
}
// dlopen para verificar Substrate sem carregar
void *substrate = dlopen(
"/Library/MobileSubstrate/MobileSubstrate.dylib",
RTLD_NOLOAD
);
if (substrate) {
dlclose(substrate);
return YES;
}
return NO;
}
Compreender as técnicas de evasão é essencial para construir uma proteção robusta. As ferramentas modernas de evasão estão evoluindo ativamente, e um conjunto estático de verificações torna-se ineficaz em questão de meses.
HideJB é um tweak que intercepta chamadas para NSFileManager, stat(), dlopen() e fork(), substituindo os valores de retorno. HideJB funciona no nível do Cydia Substrate, interceptando funções Objective-C e C. A versão do HideJB para iOS 15–16 (Shadow) usa metodologia de hooks em nível de kernel. Contramedida: realize a verificação em um processo separado com entrega do resultado via IPC, o que quebra a cadeia de hooks.
Choicy permite desativar o Substrate para processos específicos. O usuário simplesmente desativa a injeção para o aplicativo protegido — todas as verificações de biblioteca retornam false. Liberty Lite é uma evasão abrangente que cobre a maioria das verificações de bibliotecas de proteção populares. Contramedida: verificação no lado do servidor via DeviceCheck e App Attest — o servidor verifica se o dispositivo possui um certificado Apple válido que não pode ser falsificado em um dispositivo com jailbreak.
Exploits do kernel, como Fugu14 e KFD, executam código no espaço do kernel, permitindo interceptar chamadas de sistema antes que o aplicativo as veja. Neste nível, as verificações stat() e fork() tornam-se ineficazes. A única contramedida confiável é a atestacão no lado do servidor com verificação de que o dispositivo passou pelo procedimento Apple Attestation. Este protocolo é baseado em chaves criptográficas dentro do Secure Enclave, que são ilegíveis mesmo com um exploit em nível de kernel.
Para construir uma detecção de jailbreak eficaz, é necessário entender quais mecanismos de segurança do iOS são desativados durante o jailbreak.
O iOS inicializa através de uma sequência de verificações de assinatura: Boot ROM → iBoot → iOS Kernel. Se o jailbreak usar um exploit de bootrom (checkra1n), toda a cadeia de inicialização segura é comprometida — as verificações em nível de aplicativo são inúteis. Se for usado um exploit apenas de software (unc0ver, Taurine, Fugu14), a cadeia de inicialização não é quebrada e serviços da Apple como App Attest permanecem confiáveis.
A partir do iOS 10, a Apple introduziu o KPP — proteção de hardware que verifica novamente a integridade do kernel a cada 200 ms. Todos os jailbreaks modernos (iOS 14–17) usam bypass de KTRR via PAC ou APRR, mas o KPP deixa rastros na forma de tabelas de sistema sysctl modificadas. Verificar kern.version em busca de strings como pwned, prod ou xnu com uma versão não padrão pode revelar um patch do kernel.
A sandbox do iOS opera no nível TrustedBSD usando entitlements. O jailbreak substitui o perfil da sandbox por allow-all. Um aplicativo pode verificar a sandbox tentando ler qualquer arquivo fora de seu diretório Documents. Se bem-sucedido — a sandbox foi modificada. A integridade da Sandbox é um dos poucos indicadores que não pode ser falsificado sem um exploit em nível de kernel, já que a verificação de permissões é realizada no kernel antes que possa ser interceptada.
Perguntas Frequentes
Root Detection para Android verifica a presença do binário su e do Magisk. Jailbreak Detection para iOS procura por Cydia, Sileo, MobileSubstrate, verifica a capacidade de executar fork() e lê arquivos do sistema. A arquitetura da sandbox do iOS é mais estrita que a do Android, portanto as verificações do iOS dependem mais de tentar executar ações proibidas do que de ler indicadores do sistema.
Sim, os jailbreaks Dopamine, palera1n e checkra1n são relevantes para iOS 16–17. O Jailbreak Detection funciona, mas requer atualização das verificações para novas ferramentas. No iOS 17, a Apple reforçou a sandbox e muitas verificações antigas (por exemplo, fork()) tornaram-se não confiáveis devido a mudanças no XNU.
A maneira mais simples é HideJB ou Shadow, que interceptam as verificações no nível da biblioteca. Para proteção mais complexa, Frida ou Choicy são usados para desativar a injeção para um aplicativo específico. A atestacão no lado do servidor (App Attest) só pode ser contornada através de um exploit em nível de kernel que substitua a chave de hardware do Secure Enclave, o que é praticamente inviável.
Qualquer aplicativo em um dispositivo com jailbreak pode estar sujeito a: interceptação de tráfego SSL através de modificação do armazenamento confiável, leitura do Keychain via acesso ao sistema de arquivos, injeção de código através do Substrate com interceptação de métodos de manipulação de tokens e despejo de memória para obter chaves de criptografia.
App Attest é um serviço da Apple para verificar a integridade do aplicativo e do dispositivo. Na inicialização, o aplicativo recebe um desafio de atestação do servidor da Apple, o assina com uma chave privada do Secure Enclave e o envia para seu próprio servidor. Se o dispositivo estiver com jailbreak, o Secure Enclave retorna uma falha de atestação, bloqueando o acesso a funções protegidas.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também