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

iOS Basics

iOS Basics

Testing Environment

Nesta página você pode encontrar informações sobre o iOS simulator, emulators e jailbreaking:

iOS Testing Environment

Initial Analysis

Basic iOS Testing Operations

Durante os testes várias operações serão sugeridas (conectar ao dispositivo, ler/gravar/upload/download de arquivos, usar algumas ferramentas…). Portanto, se você não sabe como executar alguma dessas ações, por favor, comece lendo a página:

iOS Basic Testing Operations

Tip

Para os passos seguintes o app deve estar instalado no dispositivo e você deve já ter obtido o IPA file da aplicação.
Leia a página Basic iOS Testing Operations para aprender como fazer isso.

Basic Static Analysis

Alguns decompiladores interessantes de arquivos iOS - IPA:

É recomendado usar a ferramenta MobSF para realizar uma Static Analysis 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 toda vez que é iniciada, tornando mais difícil prever seu endereço inicial na 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

Identificação de Funções Sensíveis/Inseguras

  • 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"

Common Jailbreak detection methods

  • File System Checks: Procure pela presença de arquivos e diretórios comuns de jailbreak, tais como /Applications/Cydia.app ou /Library/MobileSubstrate/MobileSubstrate.dylib.
  • Sandbox Violations: Tente acessar áreas restritas do sistema de arquivos, que deveriam ser bloqueadas em dispositivos não-jailbroken.
  • API Checks: Verifique se é possível usar chamadas proibidas como fork() para criar um processo filho ou system() para ver se /bin/sh existe.
  • Process Checks: Monitore a presença de processos conhecidos relacionados a jailbreak, como Cydia, Substrate, ou ssh.
  • Kernel Exploits: Verifique a presença de exploits de kernel que são comumente usados em jailbreaks.
  • Environment Variables: Inspecione variáveis de ambiente em busca de sinais de jailbreak, como DYLD_INSERT_LIBRARIES.
  • Libraries Check: Verifique as libs que estão carregadas no processo do app.
  • Check schemes: Como canOpenURL(URL(string: "cydia://")).

Common Anti-Debugging detection methods

  • Check for Debugger Presence: Use sysctl ou outros métodos para verificar se um debugger está anexado.
  • Anti-Debugging APIs: Procure por chamadas a APIs anti-debugging como ptrace ou SIGSTOP, por exemplo ptrace(PT_DENY_ATTACH, 0, 0, 0).
  • Timing Checks: Meça o tempo necessário para certas operações e procure por discrepâncias que possam indicar depuração.
  • Memory Checks: Inspecione a memória em busca de artefatos ou modificações conhecidas de debuggers.
  • Environment Variables: 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.

Basic Dynamic Analysis

Confira a dynamic analysis que o MobSF realiza. Você precisará navegar pelas diferentes views e interagir com elas, mas ele fará hook em várias classes durante outras ações e preparará um relatório quando você terminar.

Listing Installed Apps

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

Enumeração Básica & Hooking

Aprenda como enumerar os componentes da aplicação e como hook métodos e classes facilmente com objection:

iOS Hooking With Objection

Estrutura do IPA

A estrutura de um IPA file é essencialmente a de um zipped package. Ao renomear sua extensão para .zip, ele pode ser descomprimido para revelar seu conteúdo. Dentro dessa estrutura, um Bundle representa um aplicativo totalmente empacotado e pronto para instalação. No interior, você encontrará um diretório chamado <NAME>.app, que encapsula os recursos do aplicativo.

  • Info.plist: Este arquivo contém detalhes de configuração específicos do aplicativo.
  • _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 assets como ícones.
  • Frameworks/: Esta pasta abriga as bibliotecas nativas do aplicativo, que podem estar no formato .dylib ou .framework.
  • PlugIns/: Isso pode incluir extensões do aplicativo, 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 cachear dados temporários e para adicionar funcionalidade de desfazer ao 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 para um container CloudKit.
  • PkgInfo: O arquivo PkgInfo é uma maneira alternativa de especificar os códigos de type e creator do seu aplicativo ou bundle.
  • en.lproj, fr.proj, Base.lproj: São os pacotes de idioma que contêm recursos para aquelas línguas específicas, e um recurso padrão caso um idioma não seja suportado.
  • Segurança: 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.
  • Gerenciamento de Assets: O arquivo Assets.car usa compressão para gerenciar eficientemente assets gráficos, sendo crucial para otimizar a performance do aplicativo e reduzir seu tamanho total.
  • Frameworks e 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/).
  • Localização: 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 em pares key-value. Este arquivo é obrigatório não apenas para aplicações, mas também para app extensions e frameworks incluídos no bundle. Ele pode estar estruturado em XML ou em 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 esse arquivo em um formato mais acessível, a conversão para XML pode ser realizada 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:

  • Para 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 para App Transport Security (NSAppTransportSecurity). Essas entradas, juntamente com outras, como tipos de documento customizados exportados/importados (UTExportedTypeDeclarations / UTImportedTypeDeclarations), podem ser facilmente localizadas inspecionando o arquivo ou utilizando um simples comando grep:

$ grep -i <keyword> Info.plist

Caminhos de Dados

No ambiente iOS, os diretórios são designados especificamente para aplicativos do sistema e aplicativos instalados pelo usuário. Aplicativos do sistema residem no diretório /Applications, enquanto aplicativos instalados pelo usuário ficam sob /var/mobile/containers/Data/Application/. Esses aplicativos 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 as aplicações em iOS devem ser sandboxed, cada app também terá uma pasta dentro de $HOME/Library/Containers com o CFBundleIdentifier do app como nome da pasta.

Entretanto, ambas as pastas (data & container folders) possuem o arquivo .com.apple.mobile_container_manager.metadata.plist que vincula ambos os arquivos na chave MCMetadataIdentifier).

Para facilitar a descoberta do diretório de instalação de um aplicativo instalado pelo usuário, a ferramenta objection fornece um comando útil, env. Esse comando revela informações detalhadas de diretórios 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 app 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 da aplicação:

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 como visto anteriormente no IPA; contém dados essenciais da aplicação, conteúdo estático, assim como o binário compilado da aplicação.
  • Este diretório é visível para os usuários, mas os usuários não podem escrever nele.
  • O conteúdo deste diretório não é incluído em backups.
  • 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 aos usuários e os usuários podem escrever nele.
  • O conteúdo deste diretório é incluído em backups.
  • O app pode desabilitar caminhos 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).
  • Apps iOS normalmente usam os subdiretórios Application Support e Caches, mas o app pode criar subdiretórios personalizados.
  • Library/Caches/
  • Contém arquivos de cache semi-persistentes.
  • Invisível aos usuários e os usuários não podem escrever nele.
  • O conteúdo deste diretório não é incluído em backups.
  • O SO pode excluir 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 arquivos persistentes necessários para executar o app.
  • Invisível aos usuários e os usuários não podem escrever nele.
  • O conteúdo neste diretório é incluído em backups.
  • O app pode desabilitar caminhos 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 NSUserDefaults podem ser encontrados neste 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 em backups.
  • O SO pode excluir 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

Binary Reversing

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)
[...]

Verificar se o app está criptografado

Veja se há alguma saída para:

otool -l <app-binary> | grep -A 4 LC_ENCRYPTION_INFO

Desassemblando o binário

Desmonte a seção .text:

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 segmento Objective-C do aplicativo de amostra 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;
};

No entanto, as melhores opções para desmontar o binário são: Hopper e IDA.

Data Storage

Para aprender como o iOS armazena dados no dispositivo, leia esta página:

iOS Basics

Warning

Os seguintes locais de armazenamento de informação devem ser verificados logo após instalar a aplicação, após testar todas as funcionalidades da aplicação e até mesmo após sair de um usuário e entrar com outro.
O objetivo é encontrar informações sensíveis não protegidas da aplicação (senhas, 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. It’s a way to store persistent data, so sometimes you may find sensitive information in these files. It’s recommended to check these files after installing the app and after using intensively it to see if new data is written.

A forma mais comum de persistir dados em arquivos plist é através do uso de NSUserDefaults. Este arquivo plist é salvo dentro do sandbox do aplicativo em Library/Preferences/<appBundleID>.plist

The NSUserDefaults class provides a programmatic interface for interacting with the default system. The default system allows an application to customize its behaviour according to user preferences. Data saved by NSUserDefaults can be viewed in the application bundle. This class stores data in a plist file, but it’s meant to be used with small amounts of data.

Esses dados não podem mais ser acessados diretamente via um computador confiável, mas podem ser acessados realizando um backup.

Você pode dump as informações salvas usando NSUserDefaults com o comando do objection ios nsuserdefaults get

Para encontrar todos os plist usados pela aplicação, você pode acessar /private/var/mobile/Containers/Data/Application/{APPID} e executar:

find ./ -name "*.plist"

Para converter arquivos do formato XML ou binário (bplist) para XML, existem vários métodos dependendo do seu sistema operacional:

Para usuários macOS: Utilize o comando plutil. É uma ferramenta nativa do 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 Objection Session: Para analisar aplicativos 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 dos objetos na sua aplicação. Core Data can use SQLite as its persistent store, mas o próprio framework não é um banco de dados.
CoreData não criptografa seus dados por padrão. No entanto, uma camada adicional de criptografia pode ser adicionada ao CoreData. Veja o GitHub Repo para mais detalhes.

Você pode encontrar as informações do SQLite Core Data 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 má configuração.

-(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 seus próprios bancos de dados SQLite. Elas podem estar armazenando dados sensíveis neles e deixando-os 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

Os 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:

Firebase Database

Realm databases

Realm Objective-C and Realm Swift oferecem uma alternativa poderosa para armazenamento de dados, não fornecida pela Apple. Por padrão, eles armazenam os dados sem criptografia, com criptografia disponível mediante configuração específica.

Os bancos de dados estão localizados em: /private/var/mobile/Containers/Data/Application/{APPID}. Para explorar esses arquivos, é possível 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)")
}

Couchbase Lite Bancos de Dados

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 em iOS e macOS, oferece a capacidade de sincronizar dados de forma transparente.

Para identificar potenciais 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

O iOS armazena os cookies dos apps em Library/Cookies/cookies.binarycookies dentro da pasta de cada app. Contudo, alguns desenvolvedores às vezes optam por salvá-los no keychain, já que o mencionado arquivo de cookies pode ser acessado em backups.

Para inspecionar o arquivo de cookies você pode usar this python script ou usar o ios cookies get do objection.
Você também pode usar o objection para converter esses arquivos para um 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 o NSURLSession armazena dados, tais como requisições e respostas HTTP no banco de dados Cache.db. Este banco de dados pode conter dados sensíveis, se tokens, nomes de usuário ou qualquer outra informação sensível tiver sido armazenada em cache. Para encontrar as informações em cache, abra o diretório de dados do app (/var/mobile/Containers/Data/Application/<UUID>) e vá para /Library/Caches/<Bundle Identifier>. O cache do WebKit também é armazenado no arquivo Cache.db. Objection pode abrir e interagir com o banco de dados com o comando sqlite connect Cache.db, já que se trata de um banco de dados SQLite normal.

É recomendado desabilitar o cache desses dados, pois podem conter informações sensíveis na requisição ou na resposta. A lista abaixo mostra diferentes maneiras de conseguir isso:

  1. Recomenda-se remover respostas em cache após o logout. Isso pode ser feito com o método fornecido pela Apple chamado removeAllCachedResponses Você pode chamar esse método da seguinte forma:

URLCache.shared.removeAllCachedResponses()

Este método removerá todas as requisições e respostas em cache do arquivo Cache.db.

  1. Se você não precisa dos benefícios dos cookies, recomenda-se usar a propriedade de configuração .ephemeral do URLSession, que desativa o salvamento de cookies e caches.

Apple documentation:

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.

  1. O cache também pode ser desabilitado definindo a Cache Policy para .notAllowed. Isso impedirá o armazenamento de cache de qualquer forma, tanto na memória quanto no disco.

Snapshots

Sempre que você pressiona o botão Home, o iOS tira um snapshot da tela atual para permitir uma transição entre aplicativos mais suave. Porém, se houver dados sensíveis presentes na tela atual, eles serão salvos na imagem (que persiste através de reinicializações). Esses são os snapshots que você também pode acessar ao dar um duplo toque no botão Home para alternar entre apps.

A menos que o iPhone esteja jailbroken, o atacante precisa ter o dispositivo 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 computadores confiáveis não conseguem acessar o filesystem a partir do iOX 7.0).

Uma forma de evitar esse comportamento indesejado é colocar uma tela em branco ou remover os dados sensíveis antes de tirar o snapshot usando a função ApplicationDidEnterBackground().

A seguir há um método de remediação de exemplo que definirá um 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];
}

Isso define a imagem de fundo para overlayImage.png sempre que o aplicativo for enviado para segundo plano. Previne leak de dados sensíveis porque overlayImage.png sempre vai 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 finalidades similares.

Armazenando Credenciais

A classe NSURLCredential é ideal para salvar informações sensíveis diretamente no keychain, evitando a necessidade de NSUserDefaults ou de 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, utiliza-se o comando do Objection ios nsurlcredentialstorage dump.

Teclados Personalizados e Cache do Teclado

A partir do iOS 8.0, os usuários podem instalar extensões de teclado personalizadas, que podem ser gerenciadas em Ajustes > Geral > Teclado > Teclados. Embora esses teclados ofereçam funcionalidades estendidas, eles apresentam risco de keystroke logging e de transmitir dados para servidores externos, sendo que os usuários são avisados sobre teclados que requerem acesso à rede. Os apps podem, e devem, restringir o uso de teclados personalizados para a entrada de informações sensíveis.

Recomendações de Segurança:

  • É recomendável desativar teclados de terceiros para maior segurança.
  • Esteja ciente dos 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.dat ou /private/var/mobile/Library/Keyboard/dynamic-text.dat. Esses arquivos de cache devem ser verificados regularmente quanto a dados sensíveis. Recomenda-se redefinir o dicionário do teclado via Ajustes > Geral > Redefinir > Redefinir Dicionário do Teclado para limpar os dados em cache.
  • Interceptar o tráfego de rede pode revelar se um teclado personalizado está transmitindo keystrokes remotamente.

Evitando o 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, desabilitar a autocorreção e habilitar 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 senhas e PINs, desativem o cache definindo autocorrectionType para UITextAutocorrectionTypeNo e secureTextEntry para YES.

UITextField *textField = [[UITextField alloc] initWithFrame:frame];
textField.autocorrectionType = UITextAutocorrectionTypeNo;

Logs

Depuração de 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 versões anteriores, os logs eram acessíveis a todos os apps, apresentando 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 riscos, recomenda-se interagir minuciosa e completamente com o app, explorando todas as 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 potenciais leaks, procure tanto declarações de predefinidas quanto custom logging statements usando palavras-chave como NSLog, NSAssert, NSCAssert, fprintf para funções built-in, e qualquer menção de Logging ou Logfile para implementações customizadas.

Monitoring System Logs

Apps log various pieces of information which can be sensitive. To monitor these logs, tools and commands like:

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:

  1. Abra o Xcode.
  2. Conecte o dispositivo iOS.
  3. Navegue em Window -> Devices and Simulators.
  4. Selecione seu dispositivo.
  5. Reproduza o problema que você está investigando.
  6. Use o botão Open Console para ver os logs em uma nova janela.

Para registros mais avançados, 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 de comandos para observar atividades de log, que podem ser inestimáveis para diagnosticar problemas ou identificar potenciais data leakage nos logs.

Backups

Recursos de auto-backup estão integrados ao iOS, facilitando a criação de cópias dos dados do dispositivo através do 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.

Security Risks

A inclusão de aplicativos instalados e seus dados nos backups levanta a questão de potencial data leakage e o risco de que backup modifications could alter app functionality. 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.

Excluding Files from Backups

Arquivos em Documents/ e Library/Application Support/ são incluídos nos backups por padrão. Desenvolvedores podem excluir arquivos ou diretórios específicos dos backups usando NSURL setResourceValue:forKey:error: com a chave NSURLIsExcludedFromBackupKey. Essa prática é crucial para proteger dados sensíveis de serem incluídos nos backups.

Testing for Vulnerabilities

Para avaliar a segurança do backup de um app, comece criando um backup usando o Finder, depois localize-o seguindo as orientações em Apple’s official documentation. 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 buscadas usando ferramentas de linha de comando ou aplicações como iMazing. Para backups criptografados, 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 em DinoSec’s GitHub repo, 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. O iOSbackup tool é 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 em Bither bitcoin wallet app, onde o UI lock PIN é armazenado dentro de net.bither.plist sob a chave pin_code. Remover essa chave do plist e restaurar o backup remove o requisito do PIN, proporcionando acesso irrestrito.

Resumo sobre Testes 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 apresentam 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

Para dispositivos jailbroken e non-jailbroken, ferramentas como objection e Fridump permitem o dump da memória do processo de um app. Uma vez feito o dump, analisar esses dados requer várias ferramentas, dependendo da natureza das informações que você procura.

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 de dados ou padrões específicos, radare2 oferece amplos recursos de busca:

$ r2 <name_of_your_dump_file>
[0x00000000]> /?
...

Análise de Memória em Tempo de Execução

r2frida fornece uma alternativa poderosa para inspecionar a memória de um app em tempo real, sem precisar de um memory dump. Essa ferramenta permite a execução de comandos de busca diretamente na memória do aplicativo em execução:

$ r2 frida://usb//<name_of_your_app>
[0x00000000]> /\ <search_command>

Criptografia Quebrada

Processos Fracos de Gerenciamento de Chaves

Alguns desenvolvedores salvam dados sensíveis no armazenamento local e os criptografam com uma chave hardcoded/predictable no código. Isso não deve ser feito, pois algum reversing pode permitir que atacantes extraiam a informação confidencial.

Uso de Algoritmos Inseguros e/ou Obsoletos

Os 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, hashes brute-force resistant devem ser usados com salt.

Verificação

As principais verificações a realizar são encontrar se você consegue localizar senhas/segredos hardcoded no código, se esses são predictable, e se o código está usando algum tipo de weak cryptography algorithms.

É interessante saber que você pode monitor algumas crypto libraries automaticamente usando objection com:

ios monitor crypt

Para mais informações sobre iOS cryptographic APIs e bibliotecas 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 em um endpoint remoto por meio de métodos criptográficos. O ponto principal é que, sem uma implementação adequada, os mecanismos de autenticação local podem ser contornados.

Apple’s Local Authentication framework and the keychain fornecem APIs robustas para que desenvolvedores facilitem diálogos de autenticação do usuário e manipulem dados secretos de forma segura, respectivamente. O Secure Enclave protege a identificação por impressão digital do Touch ID, enquanto o Face ID depende do reconhecimento facial sem comprometer os dados biométricos.

Para integrar Touch ID/Face ID, os desenvolvedores têm duas opções de API:

  • LocalAuthentication.framework para autenticação de usuário em alto nível sem acesso aos dados biométricos.
  • Security.framework para acesso de baixo nível aos serviços do keychain, protegendo dados secretos com autenticação biométrica. Vários open-source wrappers tornam o acesso ao keychain mais simples.

Caution

No entanto, tanto o LocalAuthentication.framework quanto o Security.framework apresentam 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 dentro da 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 possível falha de segurança.

Autenticação Local usando Keychain

Implementar autenticação local em apps iOS envolve o uso das keychain APIs para armazenar de forma segura 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-se 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 apresentarão o diálogo de autenticação ao usuário e retornarão data ou nil, dependendo de ter sido fornecida uma impressão digital adequada 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 usado em um app, a saída conterá as duas 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

Por meio do Objection Biometrics Bypass, localizado em this GitHub page, existe uma técnica para contornar o mecanismo LocalAuthentication. O núcleo dessa abordagem envolve o uso de Frida para manipular a função evaluatePolicy, garantindo que ela retorne consistentemente um valor True, independentemente do sucesso real da autenticação. Isso é particularmente útil para contornar processos de autenticação biométrica falhos.

Para ativar esse bypass, o seguinte comando é utilizado:

...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 Objection registra uma tarefa que efetivamente altera o resultado da verificação evaluatePolicy para True.

Frida

Um exemplo de uso de evaluatePolicy da 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 alcançar o bypass da Local Authentication, um script Frida é escrito. Este script tem como alvo a 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 bypass.

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 script do Frida e realizar um bypass na autenticação biométrica, o seguinte comando é usado:

frida -U -f com.highaltitudehacks.DVIAswiftv2 --no-pause -l fingerprint-bypass-ios.js

Sensitive Functionality Exposure Through IPC

iOS Custom URI Handlers / Deeplinks / Custom Schemes

iOS Universal Links

UIActivity Sharing

iOS UIActivity Sharing

UIPasteboard

iOS UIPasteboard

App Extensions

iOS App Extensions

WebViews

iOS WebViews

Serialisation and Encoding

iOS Serialisation and Encoding

Network Communication

É importante verificar se nenhuma comunicação está ocorrendo without encryption e também se a aplicação está corretamente validating the TLS certificate do servidor.
Para verificar esse tipo de problema você pode usar um proxy como Burp:

iOS Burp Suite Configuration

Hostname check

Um problema comum ao validar o certificado TLS é checar que o certificado foi assinado por uma trusted CA, mas não checar se the hostname do certificado é o hostname que está a ser acessado.
Para testar esse problema usando o Burp, depois de confiar na Burp CA no iPhone, você pode criar um novo certificado com Burp para um hostname diferente e usá-lo. Se a aplicação continuar funcionando, então algo está vulnerável.

Certificate Pinning

Se uma aplicação estiver usando SSL Pinning corretamente, então a aplicação só funcionará se o certificado for aquele esperado. Ao testar uma aplicação isso pode ser um problema já que o Burp servirá seu próprio certificado.
A fim de contornar essa proteção em um dispositivo jailbroken, você pode instalar a aplicação SSL Kill Switch ou instalar Burp Mobile Assistant

Você também pode usar o comando do objection ios sslpinning disable

Misc

  • Em /System/Library você pode encontrar os frameworks instalados no telefone usados pelas aplicações do sistema
  • As aplicações instaladas pelo usuário na App Store estão localizadas dentro de /User/Applications
  • E /User/Library contém dados salvos pelas aplicações em nível de usuário
  • Você pode acessar /User/Library/Notes/notes.sqlite para ler as notas salvas dentro do aplicativo.
  • Dentro da pasta de uma aplicação instalada (/User/Applications/<APP ID>/) você pode encontrar alguns arquivos interessantes:
  • iTunesArtwork: O ícone usado pelo app
  • iTunesMetadata.plist: Informações do app usadas na App Store
  • /Library/*: Contém as preferências e cache. Em /Library/Cache/Snapshots/* você pode encontrar o snapshot realizado na aplicação antes de enviá-la para o background.

Hot Patching/Enforced Updateing

Os desenvolvedores podem patch all installations of their app instantly remotamente sem ter que reenviar a aplicação para a App Store e esperar até ser aprovada.
Para esse propósito normalmente é usado JSPatch. Mas existem outras opções também, como Siren e react-native-appstore-version-checker.
Este é um mecanismo perigoso que poderia ser abusado por SDKs de terceiros maliciosos, portanto é recomendado verificar qual método é usado para atualização automática (se houver) e testá-lo. Você poderia tentar baixar uma versão anterior do app para esse propósito.

Third Parties

Um desafio significativo com 3rd party SDKs é a falta de controle granular sobre suas funcionalidades. Os desenvolvedores enfrentam uma escolha: ou integram o SDK e aceitam todas as suas funcionalidades, incluindo potenciais vulnerabilidades de segurança e preocupações de privacidade, ou abrem mão de seus benefícios totalmente. Frequentemente, os desenvolvedores não conseguem corrigir vulnerabilidades dentro desses SDKs por conta própria. Além disso, à medida que os SDKs ganham confiança na comunidade, alguns podem começar a conter malware.

Os serviços fornecidos por SDKs de terceiros podem incluir rastreamento do comportamento do usuário, exibição de anúncios ou melhorias na experiência do usuário. No entanto, isso introduz um risco, pois os desenvolvedores podem não estar totalmente cientes do código executado por essas bibliotecas, levando a potenciais riscos de privacidade e segurança. É crucial limitar as informações compartilhadas com serviços de terceiros ao que é necessário e garantir que nenhum dado sensível seja exposto.

A implementação de serviços de terceiros geralmente vem em duas formas: uma biblioteca standalone ou um SDK completo. Para proteger a privacidade do usuário, qualquer dado compartilhado com esses serviços deve ser anonymized para evitar a divulgação de Personal Identifiable Information (PII).

Para identificar as bibliotecas que uma aplicação usa, o comando otool pode ser empregado. Essa 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 & Estudos de Caso

Air Keyboard Remote Input Injection

Itunesstored Bookassetd Sandbox Escape

Referências & Mais Recursos

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