iOS Pentesting
Tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
Noções básicas do iOS
Ambiente de Teste
Nesta página você pode encontrar informações sobre o simulador iOS, emuladores e jailbreaking:
Análise Inicial
Operações básicas de teste em iOS
Durante os testes várias operações serão sugeridas (conectar ao dispositivo, ler/escrever/enviar/baixar arquivos, usar algumas ferramentas…). Portanto, se você não souber como executar alguma dessas ações, por favor, comece lendo a página:
Tip
Para os próximos passos o app deve estar instalado no dispositivo e já deve ter sido obtido o arquivo IPA da aplicação.
Leia a página Basic iOS Testing Operations para aprender como fazer isso.
Análise Estática Básica
Alguns decompilers interessantes de arquivos IPA do iOS:
Recomenda-se usar a ferramenta MobSF para realizar uma Análise Estática automática do arquivo IPA.
Identificação de proteções presentes no binário:
- PIE (Position Independent Executable): Quando ativado, a aplicação é carregada em um endereço de memória aleatório a cada execução, dificultando predizer o endereço inicial de memória.
otool -hv <app-binary> | grep PIE # It should include the PIE flag
- Stack Canaries: Para validar a integridade da stack, um valor ‘canary’ é colocado na stack antes de chamar uma função e é validado novamente quando a função termina.
otool -I -v <app-binary> | grep stack_chk # It should include the symbols: stack_chk_guard and stack_chk_fail
- ARC (Automatic Reference Counting): Para prevenir falhas comuns de corrupção de memória
otool -I -v <app-binary> | grep objc_release # It should include the _objc_release symbol
- Encrypted Binary: O binário deve estar criptografado
otool -arch all -Vl <app-binary> | grep -A5 LC_ENCRYPT # The cryptid should be 1
Identification of Sensitive/Insecure Funcions
- Weak Hashing Algorithms
# On the iOS device
otool -Iv <app> | grep -w "_CC_MD5"
otool -Iv <app> | grep -w "_CC_SHA1"
# On linux
grep -iER "_CC_MD5"
grep -iER "_CC_SHA1"
- Insecure Random Functions
# On the iOS device
otool -Iv <app> | grep -w "_random"
otool -Iv <app> | grep -w "_srand"
otool -Iv <app> | grep -w "_rand"
# On linux
grep -iER "_random"
grep -iER "_srand"
grep -iER "_rand"
- Insecure ‘Malloc’ Function
# On the iOS device
otool -Iv <app> | grep -w "_malloc"
# On linux
grep -iER "_malloc"
- Insecure and Vulnerable Functions
# On the iOS device
otool -Iv <app> | grep -w "_gets"
otool -Iv <app> | grep -w "_memcpy"
otool -Iv <app> | grep -w "_strncpy"
otool -Iv <app> | grep -w "_strlen"
otool -Iv <app> | grep -w "_vsnprintf"
otool -Iv <app> | grep -w "_sscanf"
otool -Iv <app> | grep -w "_strtok"
otool -Iv <app> | grep -w "_alloca"
otool -Iv <app> | grep -w "_sprintf"
otool -Iv <app> | grep -w "_printf"
otool -Iv <app> | grep -w "_vsprintf"
# On linux
grep -R "_gets"
grep -iER "_memcpy"
grep -iER "_strncpy"
grep -iER "_strlen"
grep -iER "_vsnprintf"
grep -iER "_sscanf"
grep -iER "_strtok"
grep -iER "_alloca"
grep -iER "_sprintf"
grep -iER "_printf"
grep -iER "_vsprintf"
Métodos comuns de detecção de Jailbreak
- Verificações no sistema de arquivos: Procure pela presença de arquivos e diretórios comuns de jailbreak, como
/Applications/Cydia.appou/Library/MobileSubstrate/MobileSubstrate.dylib. - Violações de Sandbox: Tente acessar áreas restritas do sistema de arquivos, que deveriam ser bloqueadas em dispositivos não-jailbroken.
- Verificações de API: Verifique se é possível usar chamadas proibidas como
fork()para criar um processo filho ousystem()para ver se /bin/sh existe. - Verificações de Processos: Monitore a presença de processos conhecidos relacionados a jailbreak, como
Cydia,Substrateoussh. - Exploits do Kernel: Verifique a presença de exploits de kernel comumente usados em jailbreaks.
- Variáveis de Ambiente: Inspecione variáveis de ambiente em busca de sinais de jailbreak, como
DYLD_INSERT_LIBRARIES. - Verificação de Libraries: Verifique as libs que estão carregadas no processo do app.
- Verificar schemes: Como
canOpenURL(URL(string: "cydia://")).
Métodos comuns de detecção Anti-Debugging
- Verificar presença de debugger: Use
sysctlou outros métodos para checar se um debugger está anexado. - APIs Anti-Debugging: Procure chamadas a APIs anti-debugging como
ptraceouSIGSTOP, por exemploptrace(PT_DENY_ATTACH, 0, 0, 0). - Checagens de tempo: Meça o tempo gasto em certas operações e procure discrepâncias que possam indicar debugging.
- Verificações de memória: Inspecione a memória em busca de artefatos conhecidos de debuggers ou modificações.
- Variáveis de ambiente: Verifique variáveis de ambiente que possam indicar uma sessão de debugging.
- Mach Ports: Detecte se mach exception ports estão sendo usados por debuggers.
Técnicas Anti-Debugging & Anti-Tamper (Checagens em Camadas)
Aplicações do mundo real costumam empilhar checagens pre-exec, on-attach e contínuas. Padrões comuns a serem observados (e como neutralizá-los durante os testes):
- Private API side-channel fingerprinting: private launch APIs (e.g.,
SBSLaunchApplicationWithIdentifierAndURLAndLaunchOptions) são abusadas para sondar bundle IDs instalados (com.opa334.TrollStore,org.coolstar.SileoStore,com.tigisoftware.Filza, etc.) com base em códigos de retorno/log. Faça hook na chamada e sanitizeie os argumentos/valores de retorno para emular um dispositivo limpo. - Self-attestation via code-signing state:
csops()comCS_OPS_ENTITLEMENTS_BLOBlê entitlements; valores inesperados disparam exit. Combine isso com checagens de integridade (CRC32/MD5 de recursos, validação de certificados, metadados Mach-O comoLC_ENCRYPTION_INFO_64) para detectar re-signing ou patching. Instrumente essas rotinas e force resultados “esperados” durante a análise. - Kill-on-attach:
ptrace(PT_DENY_ATTACH)combinado comabort()/exit()ao anexar. Bypasse neutralizando o caminho de terminação ou fazendo hook emptracepara retornar sucesso sem impor a negação. - Sabotagem de forense de crash: sobrescrever registradores da CPU antes de travar para destruir backtraces. Prefira breakpoints/hooks mais cedo no caminho de detecção ao invés de depender de logs de crash.
- Terminação baseada em jetsam: pressão deliberada de memória para acionar jetsam, o que não gera um log de crash normal. Procure por grandes alocações ao redor da lógica de detecção e limite/curto-circuite-as para manter os logs.
- Checagens contínuas com aplicação tardia: timers heartbeat re-executam detecção e aplicam a ação mais tarde. Trace timers/dispatch sources e mantenha o processo vivo contornando o caminho de kill atrasado.
Análise Dinâmica Básica
Confira a análise dinâmica que MobSF realiza. Você precisará navegar pelas diferentes views e interagir com elas; ele fará hook em várias classes e gerará um relatório quando terminar.
Listando Apps Instalados
Use o comando frida-ps -Uai para determinar o bundle identifier dos apps instalados:
$ frida-ps -Uai
PID Name Identifier
---- ------------------- -----------------------------------------
6847 Calendar com.apple.mobilecal
6815 Mail com.apple.mobilemail
- App Store com.apple.AppStore
- Apple Store com.apple.store.Jolly
- Calculator com.apple.calculator
- Camera com.apple.camera
- iGoat-Swift OWASP.iGoat-Swift
Basic Enumeration & Hooking
Aprenda como enumerate os componentes do aplicativo e como facilmente hook métodos e classes com objection:
IPA Structure
A estrutura de um IPA file é essencialmente a de um zipped package. Ao renomear sua extensão para .zip, ele pode ser decomprimido para revelar seu conteúdo. Dentro dessa estrutura, um Bundle representa uma aplicação totalmente empacotada pronta para instalação. No interior, você encontrará um diretório chamado <NAME>.app, que encapsula os recursos da aplicação.
Info.plist: Este arquivo contém detalhes de configuração específicos da aplicação._CodeSignature/: Este diretório inclui um arquivo plist que contém uma assinatura, garantindo a integridade de todos os arquivos no bundle.Assets.car: Um arquivo comprimido que armazena arquivos de asset como ícones.Frameworks/: Esta pasta abriga as bibliotecas nativas da aplicação, que podem estar na forma de arquivos.dylibou.framework.PlugIns/: Pode incluir extensões da aplicação, conhecidas como arquivos.appex, embora nem sempre estejam presentes. *Core Data: É usado para salvar os dados permanentes da sua aplicação para uso offline, para armazenar em cache dados temporários e para adicionar funcionalidade de undo no seu app em um único dispositivo. Para sincronizar dados entre múltiplos dispositivos em uma única conta iCloud, o Core Data espelha automaticamente seu esquema em um container CloudKit.PkgInfo: O arquivoPkgInfoé uma forma alternativa de especificar os códigos de tipo e creator da sua aplicação ou bundle.- en.lproj, fr.proj, Base.lproj: São os pacotes de idioma que contêm recursos para esses idiomas específicos, e um recurso padrão caso um idioma não seja suportado.
- Security: O diretório
_CodeSignature/desempenha um papel crítico na segurança do app ao verificar a integridade de todos os arquivos empacotados por meio de assinaturas digitais. - Asset Management: O arquivo
Assets.carusa compressão para gerenciar eficientemente assets gráficos, crucial para otimizar o desempenho da aplicação e reduzir seu tamanho total. - Frameworks and PlugIns: Esses diretórios ressaltam a modularidade das aplicações iOS, permitindo que desenvolvedores incluam bibliotecas de código reutilizáveis (
Frameworks/) e estendam a funcionalidade do app (PlugIns/). - Localization: A estrutura suporta múltiplos idiomas, facilitando o alcance global da aplicação ao incluir recursos para pacotes de idioma específicos.
Info.plist
O Info.plist serve como uma pedra angular para aplicações iOS, encapsulando dados de configuração chave na forma de pares key-value. Este arquivo é obrigatório não apenas para aplicações, mas também para extensões de app e frameworks incluídos no bundle. Ele é estruturado em XML ou em um formato binário e contém informações críticas que vão desde permissões do app até configurações de segurança. Para uma exploração detalhada das chaves disponíveis, consulte a Apple Developer Documentation.
Para quem deseja trabalhar com este arquivo em um formato mais acessível, a conversão para XML pode ser feita facilmente usando plutil no macOS (disponível nativamente nas versões 10.2 e posteriores) ou plistutil no Linux. Os comandos para conversão são os seguintes:
- For macOS:
$ plutil -convert xml1 Info.plist
- Para Linux:
$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist
Entre a miríade de informações que o arquivo Info.plist pode revelar, entradas notáveis incluem strings de permissão do app (UsageDescription), esquemas de URL personalizados (CFBundleURLTypes) e configurações do App Transport Security (NSAppTransportSecurity). Essas entradas, juntamente com outras como tipos de documento personalizados exportados/importados (UTExportedTypeDeclarations / UTImportedTypeDeclarations), podem ser facilmente localizadas inspecionando o arquivo ou usando um simples comando grep:
$ grep -i <keyword> Info.plist
Caminhos de Dados
No ambiente iOS, diretórios são designados especificamente para system applications e user-installed applications. System applications residem em /Applications, enquanto apps instalados pelo usuário são colocados em /var/mobile/containers/Data/Application/. Essas aplicações recebem um identificador único conhecido como 128-bit UUID, tornando a tarefa de localizar manualmente a pasta de um app desafiadora devido à aleatoriedade dos nomes dos diretórios.
Warning
Como aplicações em iOS devem ser sandboxed, cada app também terá uma pasta dentro de
$HOME/Library/Containerscom oCFBundleIdentifierdo app como nome da pasta.No entanto, ambas as pastas (data & container folders) têm o arquivo
.com.apple.mobile_container_manager.metadata.plistque liga ambos os arquivos na chaveMCMetadataIdentifier).
Para facilitar a descoberta do diretório de instalação de um app instalado pelo usuário, a ferramenta objection fornece um comando útil, env. Esse comando revela informações detalhadas de diretório para o app em questão. Abaixo está um exemplo de como usar esse comando:
OWASP.iGoat-Swift on (iPhone: 11.1.2) [usb] # env
Name Path
----------------- -------------------------------------------------------------------------------------------
BundlePath /var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app
CachesDirectory /var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8EF8-8F5560EB0693/Library/Caches
DocumentDirectory /var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8EF8-8F5560EB0693/Documents
LibraryDirectory /var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8EF8-8F5560EB0693/Library
Alternativamente, o nome do aplicativo pode ser pesquisado dentro de /private/var/containers usando o comando find:
find /private/var/containers -name "Progname*"
Comandos como ps e lsof também podem ser utilizados para identificar o processo do app e listar arquivos abertos, respectivamente, fornecendo informações sobre os caminhos de diretório ativos do app:
ps -ef | grep -i <app-name>
lsof -p <pid> | grep -i "/containers" | head -n 1
Diretório do Bundle:
- AppName.app
- Este é o Application Bundle visto antes no IPA, ele contém dados essenciais do aplicativo, conteúdo estático, assim como o binário compilado do aplicativo.
- Este diretório é visível para os usuários, mas os usuários não podem escrever nele.
- Conteúdo neste diretório não é incluído no backup.
- O conteúdo desta pasta é usado para validar a assinatura de código.
Diretório de Dados:
- Documents/
- Contém todos os dados gerados pelo usuário. O usuário final do aplicativo inicia a criação desses dados.
- Visível para os usuários e os usuários podem escrever nele.
- Conteúdo neste diretório é incluído no backup.
- O app pode excluir caminhos do backup definindo
NSURLIsExcludedFromBackupKey. - Library/
- Contém todos os arquivos que não são específicos do usuário, como caches, preferências, cookies, e arquivos de configuração property list (plist).
- iOS apps usually use the
Application SupportandCachessubdirectories, but the app can create custom subdirectories. - Library/Caches/
- Contém arquivos de cache semi-persistentes.
- Invisível para os usuários e os usuários não podem escrever nele.
- O conteúdo deste diretório não é incluído no backup.
- O SO pode deletar automaticamente os arquivos deste diretório quando o app não estiver em execução e o espaço de armazenamento estiver baixo.
- Library/Application Support/
- Contém persistentes arquivos necessários para executar o app.
- Invisível para usuários e os usuários não podem escrever nele.
- Conteúdo neste diretório é incluído no backup.
- O app pode excluir caminhos do backup definindo
NSURLIsExcludedFromBackupKey. - Library/Preferences/
- Usado para armazenar propriedades que podem persistir mesmo após o aplicativo ser reiniciado.
- As informações são salvas, sem criptografia, dentro do sandbox do aplicativo em um arquivo plist chamado [BUNDLE_ID].plist.
- Todos os pares chave/valor armazenados usando
NSUserDefaultspodem ser encontrados nesse arquivo. - tmp/
- Use este diretório para gravar arquivos temporários que não precisam persistir entre execuções do app.
- Contém arquivos de cache não persistentes.
- Invisível para os usuários.
- O conteúdo deste diretório não é incluído no backup.
- O SO pode deletar automaticamente os arquivos deste diretório quando o app não estiver em execução e o espaço de armazenamento estiver baixo.
Vamos dar uma olhada mais de perto no Application Bundle (.app) do iGoat-Swift dentro do diretório Bundle (/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app):
OWASP.iGoat-Swift on (iPhone: 11.1.2) [usb] # ls
NSFileType Perms NSFileProtection ... Name
------------ ------- ------------------ ... --------------------------------------
Regular 420 None ... rutger.html
Regular 420 None ... mansi.html
Regular 420 None ... splash.html
Regular 420 None ... about.html
Regular 420 None ... LICENSE.txt
Regular 420 None ... Sentinel.txt
Regular 420 None ... README.txt
Reversão de Binários
Dentro da pasta <application-name>.app você encontrará um arquivo binário chamado <application-name>. Este é o arquivo que será executado. Você pode realizar uma inspeção básica do binário com a ferramenta otool:
otool -Vh DVIA-v2 #Check some compilation attributes
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
MH_MAGIC_64 ARM64 ALL 0x00 EXECUTE 65 7112 NOUNDEFS DYLDLINK TWOLEVEL WEAK_DEFINES BINDS_TO_WEAK PIE
otool -L DVIA-v2 #Get third party libraries
DVIA-v2:
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.1)
/usr/lib/libsqlite3.dylib (compatibility version 9.0.0, current version 274.6.0)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
@rpath/Bolts.framework/Bolts (compatibility version 1.0.0, current version 1.0.0)
[...]
Verifique se o app está criptografado
Veja se há alguma saída para:
otool -l <app-binary> | grep -A 4 LC_ENCRYPTION_INFO
Desmontando o binary
Desmonte a text section:
otool -tV DVIA-v2
DVIA-v2:
(__TEXT,__text) section
+[DDLog initialize]:
0000000100004ab8 sub sp, sp, #0x60
0000000100004abc stp x29, x30, [sp, #0x50] ; Latency: 6
0000000100004ac0 add x29, sp, #0x50
0000000100004ac4 sub x8, x29, #0x10
0000000100004ac8 mov x9, #0x0
0000000100004acc adrp x10, 1098 ; 0x10044e000
0000000100004ad0 add x10, x10, #0x268
Para imprimir o Objective-C segment da aplicação de exemplo, pode-se usar:
otool -oV DVIA-v2
DVIA-v2:
Contents of (__DATA,__objc_classlist) section
00000001003dd5b8 0x1004423d0 _OBJC_CLASS_$_DDLog
isa 0x1004423a8 _OBJC_METACLASS_$_DDLog
superclass 0x0 _OBJC_CLASS_$_NSObject
cache 0x0 __objc_empty_cache
vtable 0x0
data 0x1003de748
flags 0x80
instanceStart 8
Para obter um código Objective-C mais compacto, você pode usar class-dump:
class-dump some-app
//
// Generated by class-dump 3.5 (64 bit).
//
// class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard.
//
#pragma mark Named Structures
struct CGPoint {
double _field1;
double _field2;
};
struct CGRect {
struct CGPoint _field1;
struct CGSize _field2;
};
struct CGSize {
double _field1;
double _field2;
};
However, the best options to disassemble the binary are: Hopper and IDA.
Armazenamento de Dados
Para aprender sobre como o iOS armazena dados no dispositivo leia esta página:
Warning
Os seguintes locais para armazenar informação devem ser verificados right after installing the application, after checking all the functionalities of the application e mesmo após login out from one user and login into a different one.
O objetivo é encontrar unprotected sensitive information da aplicação (passwords, tokens), do usuário atual e de usuários que fizeram login anteriormente.
Plist
plist files are structured XML files that contains key-value pairs. É uma forma de armazenar dados persistentes, então às vezes você pode encontrar sensitive information in these files. Recomenda-se verificar esses arquivos após instalar a aplicação e após usá-la intensivamente para ver se novos dados são gravados.
A forma mais comum de persistir dados em arquivos plist é através do uso de NSUserDefaults. Este arquivo plist é salvo dentro do app sandbox em Library/Preferences/<appBundleID>.plist
The NSUserDefaults class provides a programmatic interface for interacting with the default system. O sistema padrão permite que uma aplicação personalize seu comportamento de acordo com as user preferences. Dados salvos por NSUserDefaults podem ser visualizados no bundle da aplicação. Esta classe armazena data em um plist file, mas é destinada a ser usada com pequenas quantidades de dados.
These data cannot be longer accessed directly via a trusted computer, but can be accessed performing a backup.
You can dump the information saved using NSUserDefaults using objection’s ios nsuserdefaults get
To find all the plist of used by the application you can access to /private/var/mobile/Containers/Data/Application/{APPID} and run:
find ./ -name "*.plist"
Para converter arquivos do formato XML ou binário (bplist) para XML, existem vários métodos disponíveis dependendo do seu sistema operacional:
Para usuários do macOS: Utilize o comando plutil. É uma ferramenta integrada no macOS (10.2+), projetada para esse propósito:
$ plutil -convert xml1 Info.plist
Para usuários Linux: Instale libplist-utils primeiro, depois use plistutil para converter seu arquivo:
$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist
Dentro de uma sessão Objection: Para analisar aplicações móveis, um comando específico permite converter arquivos plist diretamente:
ios plist cat /private/var/mobile/Containers/Data/Application/<Application-UUID>/Library/Preferences/com.some.package.app.plist
Core Data
Core Data é um framework para gerenciar a camada de modelo de objetos na sua aplicação. Core Data can use SQLite as its persistent store, mas o framework em si não é um banco de dados.
CoreData não criptografa seus dados por padrão. Entretanto, uma camada adicional de criptografia pode ser adicionada ao CoreData. See the GitHub Repo for more details.
Você pode encontrar as informações do Core Data (SQLite) de uma aplicação no caminho /private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support
Se você conseguir abrir o SQLite e acessar informações sensíveis, então encontrou uma configuração incorreta.
-(void)storeDetails {
AppDelegate * appDelegate = (AppDelegate *)(UIApplication.sharedApplication.delegate);
NSManagedObjectContext *context =[appDelegate managedObjectContext];
User *user = [self fetchUser];
if (user) {
return;
}
user = [NSEntityDescription insertNewObjectForEntityForName:@"User"
inManagedObjectContext:context];
user.email = CoreDataEmail;
user.password = CoreDataPassword;
NSError *error;
if (![context save:&error]) {
NSLog(@"Error in saving data: %@", [error localizedDescription]);
}else{
NSLog(@"data stored in core data");
}
}
YapDatabase
YapDatabase é um armazenamento chave/valor construído sobre o SQLite.\ Como os bancos de dados Yap são bancos de dados SQLite, você pode encontrá-los usando o comando proposto na seção anterior.
Outros bancos de dados SQLite
É comum que aplicações criem seu próprio banco de dados SQLite. Elas podem estar armazenando dados sensíveis neles e deixá-los sem criptografia. Portanto, é sempre interessante verificar cada banco de dados dentro do diretório da aplicação. Vá para o diretório da aplicação onde os dados são salvos (/private/var/mobile/Containers/Data/Application/{APPID})
find ./ -name "*.sqlite" -or -name "*.db"
Firebase Real-Time Databases
Desenvolvedores podem armazenar e sincronizar dados em um banco de dados NoSQL hospedado na nuvem através do Firebase Real-Time Databases. Armazenados em formato JSON, os dados são sincronizados com todos os clientes conectados em tempo real.
Você pode encontrar como verificar bancos de dados Firebase mal configurados aqui:
Bancos de dados Realm
Realm Objective-C e Realm Swift oferecem uma alternativa poderosa para armazenamento de dados, não fornecida pela Apple. Por padrão, eles armazenam dados sem criptografia, com criptografia disponível por meio de configuração específica.
Os bancos de dados estão localizados em: /private/var/mobile/Containers/Data/Application/{APPID}. Para explorar esses arquivos, pode-se utilizar comandos como:
iPhone:/private/var/mobile/Containers/Data/Application/A079DF84-726C-4AEA-A194-805B97B3684A/Documents root# ls
default.realm default.realm.lock default.realm.management/ default.realm.note|
$ find ./ -name "*.realm*"
Para visualizar esses arquivos de banco de dados, a ferramenta Realm Studio é recomendada.
Para implementar criptografia em um banco de dados Realm, o seguinte trecho de código pode ser usado:
// Open the encrypted Realm file where getKey() is a method to obtain a key from the Keychain or a server
let config = Realm.Configuration(encryptionKey: getKey())
do {
let realm = try Realm(configuration: config)
// Use the Realm as normal
} catch let error as NSError {
// If the encryption key is wrong, `error` will say that it's an invalid database
fatalError("Error opening realm: \(error)")
}
Bancos de Dados Couchbase Lite
Couchbase Lite é descrito como um mecanismo de banco de dados leve e embutido que segue a abordagem orientada a documentos (NoSQL). Projetado para ser nativo do iOS e macOS, oferece a capacidade de sincronizar dados de forma transparente.
Para identificar possíveis bancos de dados Couchbase em um dispositivo, o seguinte diretório deve ser inspecionado:
ls /private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support/
Cookies
iOS armazena os cookies dos apps em Library/Cookies/cookies.binarycookies dentro de cada pasta do app. No entanto, desenvolvedores às vezes decidem salvá-los no keychain, pois o mencionado arquivo de cookie pode ser acessado em backups.
Para inspecionar o arquivo de cookies você pode usar this python script ou usar objection’s ios cookies get.
Você também pode usar objection para converter esses arquivos para o formato JSON e inspecionar os dados.
...itudehacks.DVIAswiftv2.develop on (iPhone: 13.2.3) [usb] # ios cookies get --json
[
{
"domain": "highaltitudehacks.com",
"expiresDate": "2051-09-15 07:46:43 +0000",
"isHTTPOnly": "false",
"isSecure": "false",
"name": "username",
"path": "/",
"value": "admin123",
"version": "0"
}
]
Cache
Por padrão NSURLSession armazena dados, tais como HTTP requests and responses in the Cache.db database. Esse database pode conter dados sensíveis, se tokens, usernames ou qualquer outra informação sensível tiver sido cached. Para encontrar a informação cached abra o data directory do app (/var/mobile/Containers/Data/Application/<UUID>) e vá para /Library/Caches/<Bundle Identifier>. O WebKit cache is also being stored in the Cache.db file. Objection pode abrir e interagir com o database com o comando sqlite connect Cache.db, como ele é uma normal SQLite database.
É recomendado desabilitar o Caching desses dados, pois podem conter informação sensível na request ou response. A lista abaixo mostra diferentes formas de conseguir isso:
- É recomendado remover Cached responses após logout. Isso pode ser feito com o método fornecido pela Apple chamado
removeAllCachedResponsesVocê pode chamar esse método da seguinte forma:
URLCache.shared.removeAllCachedResponses()
Esse método irá remover todas as cached requests e responses do arquivo Cache.db.
- Se você não precisa da vantagem dos cookies, é recomendado usar a propriedade de configuração .ephemeral do URLSession, que desabilitará o salvamento de cookies e Caches.
An ephemeral session configuration object is similar to a default session configuration (see default), except that the corresponding session object doesn’t store caches, credential stores, or any session-related data to disk. Instead, session-related data is stored in RAM. The only time an ephemeral session writes data to disk is when you tell it to write the contents of a URL to a file.
- Cache também pode ser desabilitado definindo o Cache Policy para .notAllowed. Isso irá desabilitar o armazenamento de Cache de qualquer forma, seja em memória ou em disco.
Snapshots
Sempre que você aperta o home button, iOS tira um snapshot da tela atual para conseguir fazer a transição para o aplicativo de forma mais suave. Entretanto, se houver dados sensíveis na tela atual, eles serão salvos na imagem (que persiste através de reboots). Esses são os snapshots que você também pode acessar dando duplo toque no home screen para trocar entre apps.
A menos que o iPhone esteja jailbroken, o atacante precisa ter acesso ao device desbloqueado para ver essas screenshots. Por padrão o último snapshot é armazenado no sandbox da aplicação em Library/Caches/Snapshots/ ou na pasta Library/SplashBoard/Snapshots (os trusted computers não conseguem acessar o filesystem desde iOX 7.0).
Uma forma de prevenir esse comportamento ruim é colocar uma tela em branco ou remover os dados sensíveis antes de tirar o snapshot usando a função ApplicationDidEnterBackground().
A seguir está um método de remediação de exemplo que irá definir uma screenshot padrão.
Swift:
private var backgroundImage: UIImageView?
func applicationDidEnterBackground(_ application: UIApplication) {
let myBanner = UIImageView(image: #imageLiteral(resourceName: "overlayImage"))
myBanner.frame = UIScreen.main.bounds
backgroundImage = myBanner
window?.addSubview(myBanner)
}
func applicationWillEnterForeground(_ application: UIApplication) {
backgroundImage?.removeFromSuperview()
}
Objective-C:
@property (UIImageView *)backgroundImage;
- (void)applicationDidEnterBackground:(UIApplication *)application {
UIImageView *myBanner = [[UIImageView alloc] initWithImage:@"overlayImage.png"];
self.backgroundImage = myBanner;
self.backgroundImage.bounds = UIScreen.mainScreen.bounds;
[self.window addSubview:myBanner];
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
[self.backgroundImage removeFromSuperview];
}
Isto define a imagem de fundo como overlayImage.png sempre que a aplicação é enviada para segundo plano. Isso previne sensitive data leaks porque overlayImage.png sempre irá sobrescrever a view atual.
Keychain
Para acessar e gerenciar o iOS keychain, ferramentas como Keychain-Dumper estão disponíveis, adequadas para dispositivos jailbroken. Além disso, Objection fornece o comando ios keychain dump para fins semelhantes.
Armazenando Credenciais
A classe NSURLCredential é ideal para salvar informações sensíveis diretamente no keychain, evitando a necessidade de NSUserDefaults ou outros wrappers. Para armazenar credenciais após o login, o seguinte código Swift é usado:
NSURLCredential *credential;
credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistencePermanent];
[[NSURLCredentialStorage sharedCredentialStorage] setCredential:credential forProtectionSpace:self.loginProtectionSpace];
Para extrair essas credenciais armazenadas, o comando do Objection ios nsurlcredentialstorage dump é utilizado.
Teclados personalizados e cache do teclado
Com o iOS 8.0 em diante, os usuários podem instalar extensões de teclado personalizadas, que são gerenciáveis em Settings > General > Keyboard > Keyboards. Embora esses teclados ofereçam funcionalidades estendidas, eles apresentam risco de keylogging e transmissão de dados para servidores externos, embora os usuários sejam notificados sobre teclados que requerem acesso à rede. Apps podem, e devem, restringir o uso de teclados personalizados para a entrada de informações sensíveis.
Recomendações de segurança:
- É aconselhável desativar teclados de terceiros para aumentar a segurança.
- Tenha atenção aos recursos de autocorreção e sugestões automáticas do teclado padrão do iOS, que podem armazenar informações sensíveis em arquivos de cache localizados em
Library/Keyboard/{locale}-dynamic-text.datou/private/var/mobile/Library/Keyboard/dynamic-text.dat. Esses arquivos de cache devem ser verificados regularmente em busca de dados sensíveis. Recomenda-se resetar o dicionário do teclado via Settings > General > Reset > Reset Keyboard Dictionary para limpar os dados em cache. - Interceptar o tráfego de rede pode revelar se um teclado personalizado está transmitindo toques de tecla remotamente.
Prevenção do cache de campos de texto
O UITextInputTraits protocol oferece propriedades para gerenciar autocorreção e entrada de texto segura, essenciais para prevenir o cache de informações sensíveis. Por exemplo, desativar a autocorreção e ativar a entrada de texto segura pode ser feito com:
textObject.autocorrectionType = UITextAutocorrectionTypeNo;
textObject.secureTextEntry = YES;
Além disso, os desenvolvedores devem garantir que os campos de texto, especialmente aqueles para inserir informações sensíveis como passwords e PINs, desativem o caching definindo autocorrectionType como UITextAutocorrectionTypeNo e secureTextEntry como YES.
UITextField *textField = [[UITextField alloc] initWithFrame:frame];
textField.autocorrectionType = UITextAutocorrectionTypeNo;
Logs
Depurar código frequentemente envolve o uso de logging. Há um risco envolvido, pois logs podem conter informações sensíveis. Anteriormente, no iOS 6 e em versões anteriores, os logs eram acessíveis a todos os apps, representando um risco de vazamento de dados sensíveis. Agora, as aplicações estão restritas a acessar apenas seus próprios logs.
Apesar dessas restrições, um atacante com acesso físico a um dispositivo desbloqueado ainda pode explorar isso conectando o dispositivo a um computador e lendo os logs. É importante notar que os logs permanecem no disco mesmo após a desinstalação do app.
Para mitigar os riscos, é aconselhável interagir minuciosamente com o app, explorando todas as suas funcionalidades e entradas para garantir que nenhuma informação sensível esteja sendo registrada inadvertidamente.
Ao revisar o código-fonte do app em busca de possíveis vazamentos, procure tanto por declarações de logging predefinidas quanto personalizadas usando palavras-chave como NSLog, NSAssert, NSCAssert, fprintf para funções internas, e quaisquer menções de Logging ou Logfile para implementações customizadas.
Monitoring System Logs
Apps logam várias informações que podem ser sensíveis. Para monitorar esses logs, ferramentas e comandos como:
idevice_id --list # To find the device ID
idevicesyslog -u <id> (| grep <app>) # To capture the device logs
são úteis. Além disso, Xcode fornece uma maneira de coletar logs do console:
- Abra o Xcode.
- Conecte o dispositivo iOS.
- Navegue até Window -> Devices and Simulators.
- Selecione seu dispositivo.
- Reproduza o problema que você está investigando.
- Use o botão Open Console para visualizar os logs em uma nova janela.
Para um monitoramento de logs mais avançado, conectar-se ao shell do dispositivo e usar socat pode fornecer monitoramento de logs em tempo real:
iPhone:~ root# socat - UNIX-CONNECT:/var/run/lockdown/syslog.sock
Seguido por comandos para observar atividades de log, que podem ser inestimáveis para diagnosticar problemas ou identificar potenciais data leak nos logs.
Backups
Recursos de backup automático estão integrados ao iOS, facilitando a criação de cópias dos dados do dispositivo via iTunes (até macOS Catalina), Finder (a partir do macOS Catalina) ou iCloud. Esses backups englobam quase todos os dados do dispositivo, excluindo elementos altamente sensíveis como detalhes do Apple Pay e configurações do Touch ID.
Riscos de Segurança
A inclusão de apps instalados e seus dados nos backups levanta a questão de potencial data leakage e o risco de que modificações no backup possam alterar a funcionalidade do app. Recomenda-se não armazenar informações sensíveis em plaintext dentro do diretório de qualquer app ou seus subdiretórios para mitigar esses riscos.
Excluindo Arquivos dos Backups
Arquivos em Documents/ e Library/Application Support/ são incluídos no backup por padrão. Desenvolvedores podem excluir arquivos ou diretórios específicos dos backups usando NSURL setResourceValue:forKey:error: com a NSURLIsExcludedFromBackupKey. Essa prática é crucial para proteger dados sensíveis de serem incluídos nos backups.
Testando para Vulnerabilidades
Para avaliar a segurança do backup de um app, comece por criar um backup usando o Finder, então localize-o seguindo as instruções da documentação oficial da Apple. Analise o backup em busca de dados sensíveis ou configurações que possam ser alteradas para afetar o comportamento do app.
Informações sensíveis podem ser procuradas usando ferramentas de linha de comando ou aplicações como iMazing. Para backups encriptados, a presença de criptografia pode ser confirmada verificando a chave “IsEncrypted” no arquivo “Manifest.plist” na raiz do backup.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
...
<key>Date</key>
<date>2021-03-12T17:43:33Z</date>
<key>IsEncrypted</key>
<true/>
...
</plist>
Para lidar com backups criptografados, scripts Python disponíveis no repositório do GitHub da DinoSec (https://github.com/dinosec/iphone-dataprotection/tree/master/python_scripts), como backup_tool.py e backup_passwd.py, podem ser úteis, embora possam requerer ajustes para compatibilidade com as versões mais recentes do iTunes/Finder. A ferramenta iOSbackup é outra opção para acessar arquivos dentro de backups protegidos por senha.
Modificando o comportamento do aplicativo
Um exemplo de alteração do comportamento do aplicativo por meio de modificações no backup é demonstrado no Bither bitcoin wallet app, onde o PIN de bloqueio da UI é armazenado dentro de net.bither.plist sob a chave pin_code. Remover essa chave do plist e restaurar o backup remove a exigência do PIN, proporcionando acesso irrestrito.
Resumo sobre Teste de Memória para Dados Sensíveis
Ao lidar com informações sensíveis armazenadas na memória de um aplicativo, é crucial limitar o tempo de exposição desses dados. Existem duas abordagens principais para investigar o conteúdo da memória: criar um dump de memória e analisar a memória em tempo real. Ambos os métodos têm seus desafios, incluindo a possibilidade de perder dados críticos durante o processo de dump ou análise.
Recuperando e Analisando um Dump de Memória
Tanto para dispositivos jailbroken quanto não-jailbroken, ferramentas como objection e Fridump permitem o dump da memória do processo de um aplicativo. Uma vez feito o dump, analisar esses dados requer várias ferramentas, dependendo da natureza das informações que você está buscando.
Para extrair strings de um dump de memória, comandos como strings ou rabin2 -zz podem ser usados:
# Extracting strings using strings command
$ strings memory > strings.txt
# Extracting strings using rabin2
$ rabin2 -ZZ memory > strings.txt
Para uma análise mais detalhada, incluindo a busca por tipos ou padrões de dados específicos, radare2 oferece amplas capacidades de busca:
$ r2 <name_of_your_dump_file>
[0x00000000]> /?
...
Runtime Memory Analysis
r2frida fornece uma alternativa poderosa para inspecionar a memory de um app em real time, sem necessidade de um memory dump. Esta ferramenta permite executar search commands diretamente na memory da aplicação em execução:
$ r2 frida://usb//<name_of_your_app>
[0x00000000]> /\ <search_command>
Criptografia Quebrada
Processos de gerenciamento de chaves inadequados
Alguns desenvolvedores salvam dados sensíveis no armazenamento local e criptografam com uma chave hardcoded/predictable no código. Isso não deve ser feito, pois algum reversing pode permitir que attackers extraiam a informação confidencial.
Uso de algoritmos inseguros e/ou obsoletos
Desenvolvedores não devem usar algoritmos obsoletos para realizar verificações de autorização, armazenar ou enviar dados. Alguns desses algoritmos são: RC4, MD4, MD5, SHA1… Se hashes forem usados para armazenar senhas, por exemplo, devem ser usados hashes resistentes a brute-force com salt.
Verificação
As principais verificações a realizar são para descobrir se você consegue encontrar senhas/segredos hardcoded no código, ou se estes são predictable, e se o código está usando algum tipo de algoritmos de criptografia fracos.
É interessante saber que você pode monitor algumas crypto libraries automaticamente usando objection com:
ios monitor crypt
Para mais informações sobre as APIs e bibliotecas criptográficas do iOS acesse https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06e-testing-cryptography
Autenticação Local
Autenticação local desempenha um papel crucial, especialmente quando se trata de proteger o acesso a um endpoint remoto por meio de métodos criptográficos. A ideia principal é que, sem uma implementação adequada, os mecanismos de autenticação local podem ser contornados.
O Local Authentication framework da Apple e o keychain fornecem APIs robustas para desenvolvedores facilitarem diálogos de autenticação do usuário e lidarem de forma segura com dados secretos, respectivamente. O Secure Enclave protege a identificação por impressão digital do Touch ID, enquanto o Face ID baseia-se no reconhecimento facial sem comprometer os dados biométricos.
Para integrar Touch ID/Face ID, os desenvolvedores têm duas opções de API:
LocalAuthentication.frameworkpara autenticação de usuário em alto nível sem acesso aos dados biométricos.Security.frameworkpara acesso em nível mais baixo aos serviços do keychain, protegendo dados secretos com autenticação biométrica. Various open-source wrappers make keychain access simpler.
Caution
No entanto, tanto
LocalAuthentication.frameworkquantoSecurity.frameworkapresentam vulnerabilidades, pois retornam principalmente valores booleanos sem transmitir dados para processos de autenticação, tornando-os suscetíveis a bypass (consulte Don’t touch me that way, by David Lindner et al).
Implementando Autenticação Local
Para solicitar autenticação dos usuários, os desenvolvedores devem utilizar o método evaluatePolicy na classe LAContext, escolhendo entre:
deviceOwnerAuthentication: solicita Touch ID ou o passcode do dispositivo, falhando se nenhum estiver habilitado.deviceOwnerAuthenticationWithBiometrics: solicita exclusivamente Touch ID.
Uma autenticação bem-sucedida é indicada por um valor booleano retornado por evaluatePolicy, evidenciando uma potencial falha de segurança.
Autenticação Local usando Keychain
Implementar autenticação local em apps iOS envolve o uso das keychain APIs para armazenar com segurança dados secretos, como tokens de autenticação. Esse processo garante que os dados só possam ser acessados pelo usuário, usando o passcode do dispositivo ou autenticação biométrica como Touch ID.
O keychain oferece a capacidade de definir itens com o atributo SecAccessControl, que restringe o acesso ao item até que o usuário autentique com sucesso via Touch ID ou passcode do dispositivo. Esse recurso é crucial para aumentar a segurança.
Abaixo estão exemplos de código em Swift e Objective-C demonstrando como salvar e recuperar uma string no/desde o keychain, aproveitando esses recursos de segurança. Os exemplos mostram especificamente como configurar o controle de acesso para exigir autenticação por Touch ID e garantir que os dados sejam acessíveis apenas no dispositivo em que foram configurados, sob a condição de que um passcode do dispositivo esteja configurado.
// From https://github.com/mufambisi/owasp-mstg/blob/master/Document/0x06f-Testing-Local-Authentication.md
// 1. create AccessControl object that will represent authentication settings
var error: Unmanaged<CFError>?
guard let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
SecAccessControlCreateFlags.biometryCurrentSet,
&error) else {
// failed to create AccessControl object
return
}
// 2. define keychain services query. Pay attention that kSecAttrAccessControl is mutually exclusive with kSecAttrAccessible attribute
var query: [String: Any] = [:]
query[kSecClass as String] = kSecClassGenericPassword
query[kSecAttrLabel as String] = "com.me.myapp.password" as CFString
query[kSecAttrAccount as String] = "OWASP Account" as CFString
query[kSecValueData as String] = "test_strong_password".data(using: .utf8)! as CFData
query[kSecAttrAccessControl as String] = accessControl
// 3. save item
let status = SecItemAdd(query as CFDictionary, nil)
if status == noErr {
// successfully saved
} else {
// error while saving
}
Agora podemos solicitar o item salvo do keychain. Keychain services irão apresentar o diálogo de autenticação ao usuário e retornar data ou nil dependendo de ter sido fornecido um fingerprint adequado ou não.
// 1. define query
var query = [String: Any]()
query[kSecClass as String] = kSecClassGenericPassword
query[kSecReturnData as String] = kCFBooleanTrue
query[kSecAttrAccount as String] = "My Name" as CFString
query[kSecAttrLabel as String] = "com.me.myapp.password" as CFString
query[kSecUseOperationPrompt as String] = "Please, pass authorisation to enter this area" as CFString
// 2. get item
var queryResult: AnyObject?
let status = withUnsafeMutablePointer(to: &queryResult) {
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
}
if status == noErr {
let password = String(data: queryResult as! Data, encoding: .utf8)!
// successfully received password
} else {
// authorization not passed
}
Detecção
O uso de frameworks em um app também pode ser detectado analisando a lista de bibliotecas dinâmicas compartilhadas do binário do app. Isso pode ser feito usando otool:
$ otool -L <AppName>.app/<AppName>
Se LocalAuthentication.framework for utilizado em um app, a saída conterá ambas as linhas a seguir (lembre-se de que LocalAuthentication.framework usa Security.framework por baixo dos panos):
/System/Library/Frameworks/LocalAuthentication.framework/LocalAuthentication
/System/Library/Frameworks/Security.framework/Security
Se Security.framework estiver em uso, apenas o segundo será exibido.
Local Authentication Framework Bypass
Objection
Através do Objection Biometrics Bypass, localizado em this GitHub page, existe uma técnica para contornar o mecanismo LocalAuthentication. O núcleo dessa abordagem envolve utilizar o Frida para manipular a função evaluatePolicy, garantindo que ela sempre retorne True, independentemente do sucesso real da autenticação. Isso é particularmente útil para burlar processos de autenticação biométrica falhos.
Para ativar este bypass, o seguinte comando é usado:
...itudehacks.DVIAswiftv2.develop on (iPhone: 13.2.3) [usb] # ios ui biometrics_bypass
(agent) Registering job 3mhtws9x47q. Type: ios-biometrics-disable
...itudehacks.DVIAswiftv2.develop on (iPhone: 13.2.3) [usb] # (agent) [3mhtws9x47q] Localized Reason for auth requirement: Please authenticate yourself
(agent) [3mhtws9x47q] OS authentication response: false
(agent) [3mhtws9x47q] Marking OS response as True instead
(agent) [3mhtws9x47q] Biometrics bypass hook complete
Este comando inicia uma sequência em que o Objection registra uma tarefa que efetivamente altera o resultado da verificação evaluatePolicy para True.
Frida
Um exemplo de uso de evaluatePolicy na DVIA-v2 application:
+(void)authenticateWithTouchID {
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
NSString *myLocalizedReasonString = @"Please authenticate yourself";
if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
[myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:myLocalizedReasonString
reply:^(BOOL success, NSError *error) {
if (success) {
dispatch_async(dispatch_get_main_queue(), ^{
[TouchIDAuthentication showAlert:@"Authentication Successful" withTitle:@"Success"];
});
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[TouchIDAuthentication showAlert:@"Authentication Failed !" withTitle:@"Error"];
});
}
}];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[TouchIDAuthentication showAlert:@"Your device doesn't support Touch ID or you haven't configured Touch ID authentication on your device" withTitle:@"Error"];
});
}
}
Para realizar o bypass da Local Authentication, é escrito um script Frida. Este script mira na verificação evaluatePolicy, interceptando seu callback para garantir que retorne success=1. Ao alterar o comportamento do callback, a verificação de autenticação é efetivamente bypassed.
O script abaixo é injetado para modificar o resultado do método evaluatePolicy. Ele altera o resultado do callback para sempre indicar sucesso.
// from https://securitycafe.ro/2022/09/05/mobile-pentesting-101-bypassing-biometric-authentication/
if(ObjC.available) {
console.log("Injecting...");
var hook = ObjC.classes.LAContext["- evaluatePolicy:localizedReason:reply:"];
Interceptor.attach(hook.implementation, {
onEnter: function(args) {
var block = new ObjC.Block(args[4]);
const callback = block.implementation;
block.implementation = function (error, value) {
console.log("Changing the result value to true")
const result = callback(1, null);
return result;
};
},
});
} else {
console.log("Objective-C Runtime is not available!");
}
Para injetar o Frida script e bypass a autenticação biométrica, o seguinte comando é usado:
frida -U -f com.highaltitudehacks.DVIAswiftv2 --no-pause -l fingerprint-bypass-ios.js
Exposição de Funcionalidade Sensível via IPC
Custom URI Handlers / Deeplinks / Custom Schemes
iOS Custom URI Handlers / Deeplinks / Custom Schemes
Universal Links
UIActivity Sharing
UIPasteboard
App Extensions
WebViews
Serialisation and Encoding
iOS Serialisation and Encoding
Network Communication
É importante verificar se não existe comunicação ocorrendo sem encriptação e também se a aplicação está a validar corretamente o certificado TLS do servidor.
Para verificar este tipo de problemas pode usar um proxy como o Burp:
Hostname check
Um problema comum ao validar o certificado TLS é verificar que o certificado foi assinado por uma CA confiável, mas não verificar se o hostname do certificado é o hostname que está a ser acedido.
Para checar este problema usando o Burp, depois de confiar no Burp CA no iPhone, pode criar um novo certificado com o Burp para um hostname diferente e usá-lo. Se a aplicação continuar a funcionar, então está vulnerável.
Certificate Pinning
Se uma aplicação estiver a usar corretamente SSL Pinning, então a aplicação só funcionará se o certificado for o esperado. Quando se testa uma aplicação isto pode ser um problema porque o Burp irá servir o seu próprio certificado.
Para contornar esta proteção num dispositivo jailbroken, pode instalar a aplicação SSL Kill Switch ou instalar Burp Mobile Assistant
Também pode usar objection’s ios sslpinning disable
Misc
- Em
/System/Librarypode encontrar os frameworks instalados no telefone usados pelas aplicações do sistema - As aplicações instaladas pelo utilizador a partir da App Store estão localizadas dentro de
/User/Applications - E
/User/Librarycontém dados guardados pelas aplicações a nível de utilizador - Pode aceder a
/User/Library/Notes/notes.sqlitepara ler as notas guardadas dentro da aplicação. - Dentro da pasta de uma aplicação instalada (
/User/Applications/<APP ID>/) pode encontrar alguns ficheiros interessantes: iTunesArtwork: O ícone usado pela appiTunesMetadata.plist: Informação da app usada na App Store/Library/*: Contém as preferences e cache. Em/Library/Cache/Snapshots/*pode encontrar o snapshot realizado à aplicação antes de a enviar para o background.
Hot Patching/Enforced Updateing
Os developers podem remotamente patchar todas as instalações da sua app instantaneamente sem ter de reenviar a aplicação para a App Store e esperar que seja aprovada.
Para este propósito é geralmente usado JSPatch. Mas existem outras opções também, como Siren e react-native-appstore-version-checker.
Este é um mecanismo perigoso que pode ser abusado por SDKs de terceiros maliciosos; por isso é recomendado verificar que método é usado para atualização automática (se houver) e testá-lo. Pode tentar descarregar uma versão anterior da app para este fim.
Third Parties
Um desafio significativo com 3rd party SDKs é a falta de controlo granular sobre as suas funcionalidades. Os developers enfrentam uma escolha: integrar o SDK e aceitar todas as suas funcionalidades, incluindo potenciais vulnerabilidades de segurança e preocupações de privacidade, ou renunciar completamente aos seus benefícios. Frequentemente, os developers não conseguem corrigir vulnerabilidades dentro desses SDKs por si próprios. Além disso, à medida que os SDKs ganham confiança na comunidade, alguns podem começar a conter malware.
Os serviços providos por SDKs de terceiros podem incluir tracking do comportamento do utilizador, exibição de anúncios ou melhorias na experiência do utilizador. No entanto, isto introduz um risco, pois os developers podem não estar totalmente cientes do código executado por estas bibliotecas, levando a potenciais riscos de privacidade e segurança. É crucial limitar a informação partilhada com serviços de terceiros ao que for estritamente necessário e garantir que nenhum dado sensível é exposto.
A implementação de serviços de terceiros geralmente surge em duas formas: uma biblioteca standalone ou um SDK completo. Para proteger a privacidade do utilizador, quaisquer dados partilhados com estes serviços devem ser anonimizados para evitar a divulgação de Personal Identifiable Information (PII).
Para identificar as libraries que uma aplicação utiliza, o comando otool pode ser utilizado. Esta ferramenta deve ser executada contra a aplicação e cada shared library que ela usa para descobrir bibliotecas adicionais.
otool -L <application_path>
Vulnerabilidades Interessantes e Estudos de Caso
Air Keyboard Remote Input Injection
Itunesstored Bookassetd Sandbox Escape
Zero Click Messaging Image Parser Chains
Referências e Mais Recursos
- https://blog.calif.io/p/taking-apart-ios-apps-anti-debugging
- https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06b-basic-security-testing#information-gathering
- iOS & Mobile App Pentesting - INE
- https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0057/
- https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0058/
- https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0059/
- https://mas.owasp.org/MASTG/iOS/0x06d-Testing-Data-Storage
- https://coderwall.com/p/kjb3lw/storing-password-in-keychain-the-smart-way
- https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0055/
- https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0053
- https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0060/
- https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0058
- https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0060
- https://mas.owasp.org/MASTG/Android/0x05f-Testing-Local-Authentication/
- https://mas.owasp.org/MASTG/tests/ios/MASVS-AUTH/MASTG-TEST-0064
- https://medium.com/securing/bypassing-your-apps-biometric-checks-on-ios-c2555c81a2dc
- https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0054
- https://github.com/ivRodriguezCA/RE-iOS-Apps/ Curso iOS gratuito(https://syrion.me/blog/ios-swift-antijailbreak-bypass-frida/)
- https://www.sans.org/reading-room/whitepapers/testing/ipwn-apps-pentesting-ios-applications-34577
- https://www.slideshare.net/RyanISI/ios-appsecurityminicourse
- https://github.com/prateek147/DVIA
- https://github.com/prateek147/DVIA-v2
- https://github.com/OWASP/MSTG-Hacking-Playground%20
- OWASP iGoat https://github.com/OWASP/igoat <<< versão Objective-C https://github.com/OWASP/iGoat-Swift <<< versão Swift
- https://github.com/authenticationfailure/WheresMyBrowser.iOS
- https://github.com/nabla-c0d3/ssl-kill-switch2
Tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.


