iOS Pentesting

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

iOS - Nozioni di base

iOS Basics

Ambiente di test

In questa pagina puoi trovare informazioni sul simulatore iOS, emulatori e jailbreaking:

iOS Testing Environment

Analisi iniziale

Operazioni base di testing iOS

Durante il testing verranno suggerite diverse operazioni (connettersi al device, leggere/scrivere/caricare/scaricare file, usare alcuni tool…). Pertanto, se non sai come eseguire una di queste azioni, inizia a leggere la pagina:

iOS Basic Testing Operations

Tip

Per i passaggi seguenti l’app deve essere installata nel dispositivo e deve aver già ottenuto il file IPA dell’applicazione.
Leggi la pagina Basic iOS Testing Operations per imparare come farlo.

Analisi statica di base

Alcuni decompilatori interessanti per i file iOS - IPA:

Si consiglia di usare lo strumento MobSF per eseguire un’Analisi Statica automatica sul file IPA.

Identificazione delle protezioni presenti nel binario:

  • PIE (Position Independent Executable): Quando abilitato, l’applicazione viene caricata in un indirizzo di memoria casuale ogni volta che viene avviata, rendendo più difficile prevederne l’indirizzo iniziale.
otool -hv <app-binary> | grep PIE   # It should include the PIE flag
  • Stack Canaries: Per validare l’integrità dello stack, un valore ‘canary’ viene inserito nello stack prima della chiamata a una funzione e viene validato nuovamente alla fine della funzione.
otool -I -v <app-binary> | grep stack_chk   # It should include the symbols: stack_chk_guard and stack_chk_fail
  • ARC (Automatic Reference Counting): Per prevenire comuni difetti di corruzione della memoria
otool -I -v <app-binary> | grep objc_release   # It should include the _objc_release symbol
  • Encrypted Binary: Il binario dovrebbe essere criptato
otool -arch all -Vl <app-binary> | grep -A5 LC_ENCRYPT   # The cryptid should be 1

Identificazione di Funzioni Sensibili/Insicure

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

Metodi comuni di rilevamento del jailbreak

  • File System Checks: Cerca la presenza di file e directory comuni del jailbreak, come /Applications/Cydia.app o /Library/MobileSubstrate/MobileSubstrate.dylib.
  • Sandbox Violations: Prova ad accedere ad aree ristrette del file system, che dovrebbero essere bloccate sui dispositivi non jailbroken.
  • API Checks: Verifica se è possibile usare chiamate proibite come fork() per creare un processo figlio o system() per vedere se /bin/sh esiste.
  • Process Checks: Monitora la presenza di processi noti legati al jailbreak, come Cydia, Substrate, o ssh.
  • Kernel Exploits: Controlla la presenza di exploit del kernel comunemente usati nei jailbreak.
  • Environment Variables: Ispeziona le variabili d’ambiente per segnali di jailbreak, come DYLD_INSERT_LIBRARIES.
  • Libraries Check: Controlla le librerie caricate nel processo dell’app.
  • Check schemes: Come canOpenURL(URL(string: "cydia://")).

Metodi comuni di rilevamento anti-debugging

  • Check for Debugger Presence: Usa sysctl o altri metodi per verificare se un debugger è attaccato.
  • Anti-Debugging APIs: Cerca chiamate ad API anti-debugging come ptrace o SIGSTOP come ptrace(PT_DENY_ATTACH, 0, 0, 0).
  • Timing Checks: Misura il tempo impiegato per certe operazioni e cerca discrepanze che possano indicare un debug.
  • Memory Checks: Ispeziona la memoria per artefatti o modifiche note dei debugger.
  • Environment Variables: Controlla le variabili d’ambiente che possano indicare una sessione di debug.
  • Mach Ports: Rileva se mach exception ports sono utilizzati dai debugger.

Anti-Debugging & Anti-Tamper Techniques (Layered Checks)

Le app reali spesso stratificano controlli pre-exec, on-attach e controlli continui. Modelli comuni da cercare (e come neutralizzarli durante i test):

  • Private API side-channel fingerprinting: le private launch API (es., SBSLaunchApplicationWithIdentifierAndURLAndLaunchOptions) vengono sfruttate per sondare bundle ID installati (com.opa334.TrollStore, org.coolstar.SileoStore, com.tigisoftware.Filza, ecc.) basandosi sui codici di ritorno/log. Effettua un hook della chiamata e sanitizza argomenti/valori di ritorno per emulare un dispositivo pulito.
  • Self-attestation via code-signing state: csops() con CS_OPS_ENTITLEMENTS_BLOB legge gli entitlements; valori inaspettati causano l’uscita. Abbina questo a controlli di integrità (CRC32/MD5 delle risorse, validazione del certificato, metadata Mach-O come LC_ENCRYPTION_INFO_64) per rilevare re-signing o patching. Strumenta queste routine e forza risultati “attesi” durante l’analisi.
  • Kill-on-attach: ptrace(PT_DENY_ATTACH) combinato con abort()/exit() all’attach. Bypassa neutralizzando il percorso di terminazione o effettuando hook su ptrace per farlo avere successo senza imporre il diniego.
  • Crash forensics sabotage: sovrascrivere i registri CPU prima del crash per distruggere i backtrace. Preferisci breakpoint/hook più precoci nel percorso di rilevamento invece di fare affidamento sui log di crash.
  • Jetsam-based termination: pressione di memoria deliberata per innescare jetsam, che non produce un normale log di crash. Cerca grandi allocazioni intorno alla logica di rilevamento e limita/accorcia queste per mantenere i log.
  • Continuous checks with delayed enforcement: timer heartbeat rieseguono il rilevamento e applicano la politica in un secondo momento. Traccia timers/dispatch sources e mantieni il processo vivo bypassando il percorso di kill ritardato.

Analisi dinamica di base

Dai un’occhiata all’analisi dinamica che MobSF esegue. Dovrai navigare tra le diverse viste e interagire con esse, ma effettuerà hook su diverse classi mentre svolge altre azioni e preparerà un report al termine.

Elencare le app installate

Usa il comando frida-ps -Uai per determinare il bundle identifier delle app installate:

$ 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

Enumerazione di base & Hooking

Impara come enumerate the components of the application e come facilmente hook methods and classes con objection:

iOS Hooking With Objection

Struttura IPA

La struttura di un IPA file è essenzialmente quella di un zipped package. Rinominando la sua estensione in .zip, può essere decompressed per rivelarne il contenuto. All’interno di questa struttura, un Bundle rappresenta un’applicazione completamente impacchettata e pronta per l’installazione. Al suo interno troverai una directory chiamata <NAME>.app, che racchiude le risorse dell’applicazione.

  • Info.plist: Questo file contiene dettagli di configurazione specifici dell’applicazione.
  • _CodeSignature/: Questa directory include un file plist che contiene una signature, garantendo l’integrità di tutti i file nel bundle.
  • Assets.car: Un archivio compresso che memorizza file di asset come le icone.
  • Frameworks/: Questa cartella ospita le native libraries dell’applicazione, che possono essere nella forma di file .dylib o .framework.
  • PlugIns/: Può includere estensioni dell’applicazione, conosciute come file .appex, anche se non sono sempre presenti. * Core Data: Viene usato per salvare i dati permanenti della tua applicazione per l’uso offline, per fare cache di dati temporanei e per aggiungere funzionalità di undo nella tua app su un singolo dispositivo. Per sincronizzare i dati su più dispositivi nello stesso account iCloud, Core Data rispecchia automaticamente il tuo schema in un contenitore CloudKit.
  • PkgInfo: Il file PkgInfo è un modo alternativo per specificare i type e creator codes della tua applicazione o bundle.
  • en.lproj, fr.proj, Base.lproj: Sono i language packs che contengono risorse per quelle specifiche lingue, e una risorsa di default nel caso una lingua non sia supportata.
  • Sicurezza: La directory _CodeSignature/ gioca un ruolo critico nella sicurezza dell’app verificando l’integrità di tutti i file inclusi tramite signature digitali.
  • Gestione degli asset: Il file Assets.car usa la compressione per gestire in modo efficiente gli asset grafici, cruciale per ottimizzare le performance dell’applicazione e ridurne la dimensione complessiva.
  • Frameworks e PlugIns: Queste directory sottolineano la modularità delle applicazioni iOS, permettendo agli sviluppatori di includere librerie di codice riutilizzabili (Frameworks/) ed estendere la funzionalità dell’app (PlugIns/).
  • Localizzazione: La struttura supporta più lingue, facilitando la diffusione globale dell’app includendo risorse per specifici language pack.

Info.plist

L’Info.plist serve come pietra angolare per le applicazioni iOS, racchiudendo dati di configurazione chiave sotto forma di coppie key-value. Questo file è obbligatorio non solo per le applicazioni ma anche per le app extensions e i framework inclusi nel bundle. È strutturato in formato XML o binario e contiene informazioni critiche che vanno dalle permission dell’app alle configurazioni di sicurezza. Per un’esplorazione dettagliata delle chiavi disponibili, è possibile fare riferimento alla Apple Developer Documentation.

Per chi desidera lavorare con questo file in un formato più accessibile, la conversione in XML può essere ottenuta facilmente usando plutil su macOS (disponibile nativamente su versioni 10.2 e successive) o plistutil su Linux. I comandi per la conversione sono i seguenti:

  • Per macOS:
$ plutil -convert xml1 Info.plist
  • Per Linux:
$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist

Tra la miriade di informazioni che il file Info.plist può rivelare, voci notevoli includono le stringhe di permessi dell’app (UsageDescription), schemi URL personalizzati (CFBundleURLTypes) e configurazioni per App Transport Security (NSAppTransportSecurity). Queste voci, insieme ad altre come tipi di documenti personalizzati esportati/importati (UTExportedTypeDeclarations / UTImportedTypeDeclarations), possono essere facilmente individuate ispezionando il file o usando un semplice comando grep:

$ grep -i <keyword> Info.plist

Percorsi dei dati

Nell’ambiente iOS, le directory sono designate specificamente per le applicazioni di sistema e le app installate dall’utente. Le applicazioni di sistema risiedono nella directory /Applications, mentre le app installate dall’utente sono posizionate sotto /var/mobile/containers/Data/Application/. A queste applicazioni viene assegnato un identificatore univoco noto come 128-bit UUID, rendendo difficile individuare manualmente la cartella di un’app a causa della casualità dei nomi delle directory.

Warning

Poiché le applicazioni su iOS devono essere sandboxed, ogni app avrà anche una cartella dentro $HOME/Library/Containers con il CFBundleIdentifier dell’app come nome della cartella.

Tuttavia, entrambe le cartelle (cartelle dei dati e cartelle container) contengono il file .com.apple.mobile_container_manager.metadata.plist che collega entrambe le cartelle nella chiave MCMetadataIdentifier).

Per facilitare la scoperta della directory di installazione di un’app installata dall’utente, lo strumento objection fornisce un comando utile, env. Questo comando rivela informazioni dettagliate sulle directory dell’app in questione. Di seguito un esempio di come utilizzare questo 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

In alternativa, il nome dell’app può essere cercato all’interno di /private/var/containers usando il comando find:

find /private/var/containers -name "Progname*"

Comandi come ps e lsof possono anche essere utilizzati per identificare il processo dell’app e elencare i file aperti, rispettivamente, fornendo informazioni sui percorsi di directory attivi dell’applicazione:

ps -ef | grep -i <app-name>
lsof -p <pid> | grep -i "/containers" | head -n 1

Bundle directory:

  • AppName.app
  • Questo è l’Application Bundle come visto prima nell’IPA; contiene dati essenziali dell’applicazione, contenuti statici e il binario compilato dell’app.
  • Questa directory è visibile agli utenti, ma gli utenti non possono scriverci.
  • I contenuti di questa directory non vengono sottoposti a backup.
  • I contenuti di questa cartella vengono usati per convalidare la firma del codice.

Data directory:

  • Documents/
  • Contiene tutti i dati generati dall’utente. L’utente finale dell’applicazione avvia la creazione di questi dati.
  • Visibile agli utenti e gli utenti possono scriverci.
  • I contenuti di questa directory vengono sottoposti a backup.
  • L’app può escludere percorsi impostando NSURLIsExcludedFromBackupKey.
  • Library/
  • Contiene tutti i file non specifici dell’utente, come cache, preferenze, cookie e file di configurazione property list (plist).
  • Le app iOS di solito usano le sottodirectory Application Support e Caches, ma l’app può creare sottodirectory personalizzate.
  • Library/Caches/
  • Contiene file di cache semi-persistenti.
  • Invisibile agli utenti e gli utenti non possono scriverci.
  • I contenuti di questa directory non vengono sottoposti a backup.
  • Il sistema operativo può eliminare automaticamente i file di questa directory quando l’app non è in esecuzione e lo spazio di archiviazione è limitato.
  • Library/Application Support/
  • Contiene file persistenti necessari per l’esecuzione dell’app.
  • Invisibile agli utenti e gli utenti non possono scriverci.
  • I contenuti di questa directory vengono sottoposti a backup.
  • L’app può escludere percorsi impostando NSURLIsExcludedFromBackupKey.
  • Library/Preferences/
  • Usata per memorizzare proprietà che possono persistere anche dopo il riavvio dell’applicazione.
  • Le informazioni sono salvate, non criptate, all’interno del sandbox dell’applicazione in un file plist chiamato [BUNDLE_ID].plist.
  • Tutte le coppie chiave/valore salvate usando NSUserDefaults possono essere trovate in questo file.
  • tmp/
  • Usa questa directory per scrivere file temporanei che non devono persistere tra i lanci dell’app.
  • Contiene file di cache non persistenti.
  • Invisibile agli utenti.
  • I contenuti di questa directory non vengono sottoposti a backup.
  • Il sistema operativo può eliminare automaticamente i file di questa directory quando l’app non è in esecuzione e lo spazio di archiviazione è limitato.

Diamo un’occhiata più da vicino alla Application Bundle di iGoat-Swift (.app) all’interno della Bundle directory (/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

Reverse engineering dei binari

All’interno della cartella <application-name>.app troverai un file binario chiamato <application-name>. Questo è il file che verrà eseguito. Puoi effettuare un’ispezione di base del binario con lo strumento 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)
[...]

Verifica se l’app è criptata

Controlla se c’è qualche output per:

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

Disassemblare il binario

Disassemblare la sezione 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

Per stampare il Objective-C segment dell’applicazione di esempio si può usare:

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

Per ottenere un codice Objective-C più compatto puoi usare 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;
};

Tuttavia, le migliori opzioni per disassemblare il binary sono: Hopper e IDA.

Archiviazione dei dati

To learn about how iOS stores data in the device read this page:

iOS Basics

Warning

I seguenti posti dove memorizzare informazioni dovrebbero essere controllati subito dopo l’installazione dell’applicazione, dopo aver verificato tutte le funzionalità dell’applicazione e persino dopo il logout di un utente e il login con un altro.
L’obiettivo è trovare informazioni sensibili non protette dell’applicazione (passwords, tokens), dell’utente corrente e di utenti precedentemente loggati.

Plist

plist files sono file XML strutturati che contengono coppie chiave-valore. È un modo per memorizzare dati persistenti, quindi a volte potresti trovare informazioni sensibili in questi file. È consigliato controllare questi file dopo l’installazione dell’app e dopo un uso intensivo per vedere se vengono scritti nuovi dati.

Il modo più comune per persistere dati nei file plist è tramite l’uso di NSUserDefaults. Questo file plist viene salvato all’interno della sandbox dell’app in Library/Preferences/<appBundleID>.plist

La classe NSUserDefaults fornisce un’interfaccia programmatica per interagire con il sistema di default. Il sistema di default permette a un’applicazione di personalizzare il proprio comportamento in base alle preferenze dell’utente. I dati salvati da NSUserDefaults possono essere visualizzati nel bundle dell’applicazione. Questa classe memorizza dati in un file plist, ma è pensata per essere usata con piccole quantità di dati.

Questi dati non possono più essere accessibili direttamente tramite un trusted computer, ma possono essere recuperati eseguendo un backup.

Puoi dump le informazioni salvate con NSUserDefaults usando il comando di objection ios nsuserdefaults get

Per trovare tutti i plist usati dall’applicazione puoi accedere a /private/var/mobile/Containers/Data/Application/{APPID} ed eseguire:

find ./ -name "*.plist"

Per convertire file dal formato XML o binario (bplist) a XML, sono disponibili diversi metodi a seconda del sistema operativo:

Per utenti macOS: Utilizza il comando plutil. È uno strumento integrato in macOS (10.2+), pensato per questo scopo:

$ plutil -convert xml1 Info.plist

Per utenti Linux: Installa prima libplist-utils, poi usa plistutil per convertire il tuo file:

$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist

All’interno di una sessione di Objection: Per analizzare le applicazioni mobili, un comando specifico ti permette di convertire direttamente i file plist:

ios plist cat /private/var/mobile/Containers/Data/Application/<Application-UUID>/Library/Preferences/com.some.package.app.plist

Core Data

Core Data è un framework per la gestione del livello modello degli oggetti nella tua applicazione. Core Data can use SQLite as its persistent store, ma il framework in sé non è un database.
CoreData non cripta i suoi dati per impostazione predefinita. Tuttavia, è possibile aggiungere un ulteriore livello di crittografia a CoreData. Vedi il GitHub Repo per maggiori dettagli.

Puoi trovare le informazioni SQLite Core Data di un’applicazione nel percorso /private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support

Se riesci ad aprire il database SQLite e accedere a informazioni sensibili, allora hai trovato una misconfigurazione.

-(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 è un archivio chiave/valore costruito su SQLite.
Poiché i database Yap sono database sqlite, puoi trovarli usando il comando proposto nella sezione precedente.

Other SQLite Databases

È comune che le applicazioni creino il proprio database sqlite. Potrebbero memorizzare dati sensibili al loro interno lasciandoli non cifrati. Perciò è sempre utile controllare ogni database nella directory dell’applicazione. Vai quindi alla directory dell’applicazione dove i dati sono salvati (/private/var/mobile/Containers/Data/Application/{APPID})

find ./ -name "*.sqlite" -or -name "*.db"

Firebase Real-Time Databases

Gli sviluppatori possono memorizzare e sincronizzare dati all’interno di un database NoSQL ospitato nel cloud tramite Firebase Real-Time Databases. Memorizzati in formato JSON, i dati vengono sincronizzati in tempo reale su tutti i client connessi.

You can find how to check for misconfigured Firebase databases here:

Firebase Database

Realm databases

Realm Objective-C and Realm Swift offrono una potente alternativa per l’archiviazione dei dati, non fornita da Apple. Per impostazione predefinita, memorizzano i dati non crittografati, con la crittografia disponibile tramite una configurazione specifica.

I database si trovano in: /private/var/mobile/Containers/Data/Application/{APPID}. Per esplorare questi file, è possibile utilizzare comandi come:

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

Per visualizzare questi file di database, si raccomanda lo strumento Realm Studio.

Per implementare la crittografia in un Realm database, può essere usato il seguente snippet di codice:

// 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)")
}

Database Couchbase Lite

Couchbase Lite è descritto come un motore di database leggero e incorporato che segue l’approccio orientato ai documenti (NoSQL). Progettato per essere nativo su iOS e macOS, offre la capacità di sincronizzare i dati in modo trasparente.

Per identificare potenziali database Couchbase su un dispositivo, la seguente directory dovrebbe essere ispezionata:

ls /private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support/

Cookies

iOS memorizza i cookies delle app in Library/Cookies/cookies.binarycookies all’interno della cartella di ciascuna app. Tuttavia, gli sviluppatori a volte decidono di salvarli nel keychain poiché il suddetto cookie file può essere accessibile nei backup.

Per ispezionare il cookie file puoi usare this python script o usare objection con ios cookies get.
Puoi anche usare objection per convertire questi file in formato JSON e ispezionare i dati.

...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

Per impostazione predefinita NSURLSession memorizza dati, come HTTP requests and responses in the Cache.db database. Questa database può contenere sensitive data, se token, username o qualsiasi altra informazione sensibile è stata cached. Per trovare le informazioni in cache apri la data directory dell’app (/var/mobile/Containers/Data/Application/<UUID>) e vai in /Library/Caches/<Bundle Identifier>. La WebKit cache è anche memorizzata nel file Cache.db. Objection può aprire e interagire con il database con il comando sqlite connect Cache.db, dato che è un normal SQLite database**.

È consigliabile disabilitare il caching di questi dati, in quanto possono contenere informazioni sensibili nella request o nella response. La lista seguente mostra diversi modi per ottenere questo risultato:

  1. È consigliato rimuovere le Cached responses dopo il logout. Questo può essere fatto con il metodo fornito da Apple chiamato removeAllCachedResponses Puoi chiamare questo metodo come segue:

URLCache.shared.removeAllCachedResponses()

Questo metodo rimuoverà tutte le richieste e le risposte in cache dal file Cache.db.

  1. Se non hai bisogno di sfruttare i vantaggi dei cookies, è consigliabile usare semplicemente la proprietà di configurazione .ephemeral di URLSession, che disabiliterà il salvataggio di 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. La Cache può essere disabilitata anche impostando il Cache Policy su .notAllowed. Questo disabiliterà lo storage della Cache in qualsiasi modo, sia in memoria che su disco.

Istantanee

Ogni volta che premi il tasto home, iOS scatta una snapshot della schermata corrente per poter effettuare la transizione tra le applicazioni in modo più fluido. Tuttavia, se sono presenti dati sensitive data nella schermata corrente, saranno salvati nell’immagine (che persiste attraverso i reboot). Queste sono le snapshot a cui puoi accedere anche facendo doppio tap sul tasto home per passare tra le app.

A meno che l’iPhone non sia jailbroken, l’attaccante ha bisogno di avere accesso al device sbloccato per vedere questi screenshot. Di default l’ultima snapshot è memorizzata nella sandbox dell’applicazione in Library/Caches/Snapshots/ o nella cartella Library/SplashBoard/Snapshots (i trusted computers non possono accedere al filesystem da iOX 7.0).

Un modo per prevenire questo comportamento indesiderato è mostrare una schermata vuota o rimuovere i dati sensibili prima di scattare la snapshot usando la funzione ApplicationDidEnterBackground().

Di seguito è riportato un esempio di metodo di remediation che imposterà uno screenshot di default.

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];
}

Questo imposta l’immagine di sfondo su overlayImage.png ogni volta che l’applicazione viene mandata in background. Previene i leak di dati sensibili perché overlayImage.png sovrascriverà sempre la vista corrente.

Keychain

Per accedere e gestire l’iOS keychain, sono disponibili strumenti come Keychain-Dumper, adatti a dispositivi jailbroken. Inoltre, Objection fornisce il comando ios keychain dump per scopi simili.

Memorizzazione delle credenziali

La classe NSURLCredential è ideale per salvare informazioni sensibili direttamente nel keychain, evitando la necessità di NSUserDefaults o di altri wrapper. Per memorizzare le credenziali dopo il login, viene utilizzato il seguente codice Swift:

NSURLCredential *credential;
credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistencePermanent];
[[NSURLCredentialStorage sharedCredentialStorage] setCredential:credential forProtectionSpace:self.loginProtectionSpace];

Per estrarre queste credenziali memorizzate viene utilizzato il comando di Objection ios nsurlcredentialstorage dump.

Tastiere personalizzate e cache della tastiera

A partire da iOS 8.0 gli utenti possono installare estensioni di tastiere personalizzate, gestibili tramite Settings > General > Keyboard > Keyboards. Sebbene queste tastiere offrano funzionalità estese, comportano il rischio di keylogging e della trasmissione di dati a server esterni, anche se gli utenti vengono avvisati quando una tastiera richiede l’accesso alla rete. Le app possono, e dovrebbero, limitare l’uso di tastiere personalizzate per l’immissione di informazioni sensibili.

Raccomandazioni sulla sicurezza:

  • Si consiglia di disabilitare le tastiere di terze parti per una maggiore sicurezza.
  • Prestare attenzione alle funzioni di autocorrezione e ai suggerimenti automatici della tastiera iOS predefinita, che potrebbero memorizzare informazioni sensibili in file di cache situati in Library/Keyboard/{locale}-dynamic-text.dat o /private/var/mobile/Library/Keyboard/dynamic-text.dat. Questi file di cache dovrebbero essere controllati regolarmente per dati sensibili. Si raccomanda di resettare il dizionario della tastiera tramite Settings > General > Reset > Reset Keyboard Dictionary per cancellare i dati memorizzati nella cache.
  • Intercettare il traffico di rete può rivelare se una tastiera personalizzata sta trasmettendo i tasti digitati in remoto.

Prevenire la memorizzazione nella cache dei campi di testo

Il UITextInputTraits protocol offre proprietà per gestire l’autocorrezione e il secure text entry, essenziali per prevenire la memorizzazione nella cache di informazioni sensibili. Ad esempio, disabilitare l’autocorrezione e abilitare il secure text entry può essere fatto con:

textObject.autocorrectionType = UITextAutocorrectionTypeNo;
textObject.secureTextEntry = YES;

Inoltre, gli sviluppatori dovrebbero assicurarsi che i campi di testo, in particolare quelli per l’inserimento di informazioni sensibili come password e PIN, disabilitino la memorizzazione nella cache impostando autocorrectionType su UITextAutocorrectionTypeNo e secureTextEntry su YES.

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

Logs

Il debugging del codice spesso implica l’uso di logging. C’è un rischio, poiché i logs possono contenere informazioni sensibili. In passato, in iOS 6 e nelle versioni precedenti, i logs erano accessibili a tutte le app, comportando il rischio di leak di dati sensibili. Ora, le applicazioni sono limitate ad accedere solo ai loro logs.

Nonostante queste restrizioni, un attaccante con accesso fisico a un dispositivo sbloccato può ancora sfruttare questa situazione collegando il dispositivo a un computer e lettura dei logs. È importante notare che i logs rimangono sul disco anche dopo la disinstallazione dell’app.

Per mitigare i rischi, è consigliabile interagire a fondo con l’app, esplorando tutte le sue funzionalità e input per assicurarsi che nessuna informazione sensibile venga logged involontariamente.

Quando si esamina il codice sorgente dell’app alla ricerca di potenziali leak, cerca sia predefinite che dichiarazioni di logging custom usando parole chiave come NSLog, NSAssert, NSCAssert, fprintf per le funzioni built-in, e qualsiasi riferimento a Logging o Logfile per implementazioni custom.

Monitoraggio dei System Logs

Le app registrano varie informazioni che possono essere sensibili. Per monitorare questi logs, strumenti e comandi come:

idevice_id --list   # To find the device ID
idevicesyslog -u <id> (| grep <app>)   # To capture the device logs

sono utili. Inoltre, Xcode offre un modo per raccogliere i log della console:

  1. Apri Xcode.
  2. Collega il dispositivo iOS.
  3. Naviga su Finestra -> Dispositivi e simulatori.
  4. Seleziona il tuo dispositivo.
  5. Riproduci il problema che stai indagando.
  6. Usa il pulsante Open Console per visualizzare i log in una nuova finestra.

Per un logging più avanzato, connettersi alla shell del dispositivo e usare socat può fornire il monitoraggio dei log in tempo reale:

iPhone:~ root# socat - UNIX-CONNECT:/var/run/lockdown/syslog.sock

Seguiti da comandi per osservare le attività di log, che possono rivelarsi preziosi per diagnosticare problemi o identificare potenziali data leakage nei log.

Backup

Funzionalità di auto-backup sono integrate in iOS, facilitando la creazione di copie dei dati del dispositivo tramite iTunes (fino a macOS Catalina), Finder (da macOS Catalina in poi) o iCloud. Questi backup comprendono quasi tutti i dati del dispositivo, escludendo elementi altamente sensibili come i dettagli di Apple Pay e le configurazioni di Touch ID.

Rischi per la sicurezza

L’inclusione di app installate e dei loro dati nei backup solleva la questione di un potenziale data leakage e il rischio che modifiche al backup possano alterare il funzionamento dell’app. Si consiglia di non memorizzare informazioni sensibili in plaintext all’interno della directory di un’app o delle sue sottodirectory per mitigare questi rischi.

Escludere file dai backup

I file in Documents/ e Library/Application Support/ vengono salvati nei backup per impostazione predefinita. Gli sviluppatori possono escludere file o directory specifiche dai backup usando NSURL setResourceValue:forKey:error: con la chiave NSURLIsExcludedFromBackupKey. Questa pratica è fondamentale per proteggere i dati sensibili dall’inclusione nei backup.

Testare per vulnerabilità

Per valutare la sicurezza del backup di un’app, inizia creando un backup usando Finder, poi localizzalo seguendo le indicazioni della Apple’s official documentation. Analizza il backup alla ricerca di dati sensibili o configurazioni che potrebbero essere alterate per influenzare il comportamento dell’app.

Le informazioni sensibili possono essere ricercate usando strumenti da riga di comando o applicazioni come iMazing. Per i backup criptati, la presenza di cifratura può essere confermata controllando la chiave “IsEncrypted” nel file “Manifest.plist” alla radice del 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>

For dealing with encrypted backups, Python scripts available in DinoSec’s GitHub repo, like backup_tool.py and backup_passwd.py, may be useful, albeit potentially requiring adjustments for compatibility with the latest iTunes/Finder versions. The iOSbackup tool is another option for accessing files within password-protected backups.

Modifying App Behavior

An example of altering app behavior through backup modifications is demonstrated in the Bither bitcoin wallet app, where the UI lock PIN is stored within net.bither.plist under the pin_code key. Removing this key from the plist and restoring the backup removes the PIN requirement, providing unrestricted access.

Summary on Memory Testing for Sensitive Data

When dealing with sensitive information stored in an application’s memory, it is crucial to limit the exposure time of this data. There are two primary approaches to investigate memory content: creating a memory dump and analyzing the memory in real time. Both methods have their challenges, including the potential to miss critical data during the dump process or analysis.

Retrieving and Analyzing a Memory Dump

For both jailbroken and non-jailbroken devices, tools like objection and Fridump allow for the dumping of an app’s process memory. Once dumped, analyzing this data requires various tools, depending on the nature of the information you’re searching for.

To extract strings from a memory dump, commands such as strings or rabin2 -zz can be used:

# Extracting strings using strings command
$ strings memory > strings.txt

# Extracting strings using rabin2
$ rabin2 -ZZ memory > strings.txt

Per un’analisi più dettagliata, inclusa la ricerca di tipi di dati o pattern specifici, radare2 offre ampie capacità di ricerca:

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

Runtime Memory Analysis

r2frida offre una potente alternativa per ispezionare la memoria di un’app in tempo reale, senza la necessità di un memory dump. Questo strumento permette l’esecuzione di comandi di ricerca direttamente sulla memoria dell’applicazione in esecuzione:

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

Criptografia compromessa

Processi di gestione delle chiavi inadeguati

Alcuni sviluppatori salvano dati sensibili nello storage locale e li cifrano con una chiave hardcoded/predictable nel codice. Questo non dovrebbe essere fatto, poiché del reversing potrebbe permettere agli attaccanti di estrarre le informazioni riservate.

Uso di algoritmi insicuri e/o deprecati

Gli sviluppatori non dovrebbero usare algoritmi deprecati per eseguire verifiche di autorizzazione, memorizzare o inviare dati. Alcuni di questi algoritmi sono: RC4, MD4, MD5, SHA1… Se vengono usati hashes per memorizzare le password, ad esempio, dovrebbero essere impiegati hash resistenti al brute-force con salt.

Verifica

I principali controlli da eseguire sono verificare se nel codice si trovano password/secrets hardcoded, se queste sono predictable, e se il codice utilizza qualche tipo di weak cryptography.

È interessante sapere che puoi monitorare alcune crypto libraries automaticamente usando objection con:

ios monitor crypt

Per maggiori informazioni sulle API e le librerie crittografiche di iOS consulta https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06e-testing-cryptography

Autenticazione locale

Autenticazione locale gioca un ruolo cruciale, specialmente quando riguarda la protezione dell’accesso a un endpoint remoto mediante metodi crittografici. L’essenziale è che, senza una corretta implementazione, i meccanismi di autenticazione locale possono essere aggirati.

Apple’s Local Authentication framework e il keychain forniscono API robuste rispettivamente per facilitare i dialog di autenticazione dell’utente e per gestire in modo sicuro i dati segreti. Il Secure Enclave protegge l’ID delle impronte per Touch ID, mentre Face ID si basa sul riconoscimento facciale senza compromettere i dati biometrici.

Per integrare Touch ID/Face ID, gli sviluppatori hanno due opzioni di API:

  • LocalAuthentication.framework per l’autenticazione utente di alto livello senza accesso ai dati biometrici.
  • Security.framework per l’accesso a servizi keychain di basso livello, proteggendo i dati segreti con autenticazione biometrica. Vari open-source wrappers rendono più semplice l’accesso al keychain.

Caution

Tuttavia, sia LocalAuthentication.framework che Security.framework presentano vulnerabilità, poiché restituiscono principalmente valori booleani senza trasmettere dati per i processi di autenticazione, rendendoli suscettibili a bypass (vedi Don’t touch me that way, by David Lindner et al).

Implementazione dell’autenticazione locale

Per richiedere l’autenticazione agli utenti, gli sviluppatori dovrebbero utilizzare il metodo evaluatePolicy della classe LAContext, scegliendo tra:

  • deviceOwnerAuthentication: richiede Touch ID o il passcode del dispositivo; la chiamata fallisce se nessuno dei due è abilitato.
  • deviceOwnerAuthenticationWithBiometrics: richiede esclusivamente Touch ID.

Un’autenticazione riuscita è indicata da un valore booleano restituito da evaluatePolicy, evidenziando una potenziale vulnerabilità di sicurezza.

Autenticazione locale usando il keychain

Implementare autenticazione locale nelle app iOS comporta l’uso delle keychain APIs per memorizzare in modo sicuro dati segreti come token di autenticazione. Questo processo garantisce che i dati possano essere accessibili solo dall’utente, tramite il passcode del dispositivo o l’autenticazione biometrica come Touch ID.

Il keychain offre la possibilità di impostare elementi con l’attributo SecAccessControl, che limita l’accesso all’elemento fino a quando l’utente non si autentica con successo tramite Touch ID o il passcode del dispositivo. Questa funzionalità è fondamentale per migliorare la sicurezza.

Di seguito sono riportati esempi di codice in Swift e Objective-C che mostrano come salvare e recuperare una stringa su/dal keychain, sfruttando queste funzionalità di sicurezza. Gli esempi mostrano nello specifico come configurare il controllo di accesso per richiedere l’autenticazione Touch ID e garantire che i dati siano accessibili solo sul dispositivo su cui sono stati creati, a condizione che sia configurato un passcode del dispositivo.

// 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
}

Adesso possiamo richiedere l’elemento salvato dal keychain. I servizi Keychain presenteranno il dialogo di autenticazione all’utente e restituiranno data o nil a seconda che sia stata fornita o meno una fingerprint adatta.

// 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
}

Rilevamento

L’uso di framework in un’app può essere rilevato anche analizzando l’elenco delle librerie dinamiche condivise del binario dell’app. Questo può essere fatto usando otool:

$ otool -L <AppName>.app/<AppName>

Se LocalAuthentication.framework è usato in un’app, l’output conterrà entrambe le seguenti righe (ricorda che LocalAuthentication.framework usa Security.framework sotto il cofano):

/System/Library/Frameworks/LocalAuthentication.framework/LocalAuthentication
/System/Library/Frameworks/Security.framework/Security

If Security.framework is used, only the second one will be shown.

Bypass del Local Authentication Framework

Objection

Attraverso l’Objection Biometrics Bypass, disponibile a questa pagina GitHub, è disponibile una tecnica per superare il meccanismo LocalAuthentication. Il nucleo di questo approccio consiste nell’usare Frida per manipolare la funzione evaluatePolicy, facendo sì che produca sempre True, indipendentemente dal reale successo dell’autenticazione. Questo è particolarmente utile per eludere processi di autenticazione biometrica difettosi.

Per attivare questo bypass, viene impiegato il seguente comando:

...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

Questo comando avvia una sequenza in cui Objection registra un task che modifica effettivamente l’esito del controllo evaluatePolicy in True.

Frida

Un esempio d’uso di 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"];
});
}
}

Per ottenere il bypass di Local Authentication, viene scritto uno script Frida. Questo script prende di mira il controllo evaluatePolicy, intercettando la sua callback per assicurarsi che ritorni success=1. Alterando il comportamento della callback, il controllo di autenticazione viene effettivamente bypassato.

Lo script seguente viene iniettato per modificare il risultato del metodo evaluatePolicy. Modifica il risultato della callback in modo che indichi sempre il successo.

// 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!");
}

Per iniettare lo script Frida e bypassare l’autenticazione biometrica, viene usato il seguente comando:

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

Esposizione di funzionalità sensibili tramite 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

Comunicazione di rete

È importante verificare che non ci siano comunicazioni che avvengono senza crittografia e anche che l’applicazione stia correttamente validando il certificato TLS del server.
Per controllare questo tipo di problemi puoi usare un proxy come Burp:

iOS Burp Suite Configuration

Controllo dell’hostname

Un problema comune nella validazione del certificato TLS è verificare che il certificato sia stato firmato da una CA trusted, ma non controllare se l’hostname del certificato corrisponde all’hostname a cui si sta accedendo.
Per verificare questo problema usando Burp, dopo aver trustato la CA di Burp sull’iPhone, puoi creare un nuovo certificato con Burp per un hostname diverso e usarlo. Se l’applicazione continua a funzionare, allora è vulnerabile.

Certificate Pinning

Se un’applicazione usa correttamente SSL Pinning, allora l’app funzionerà solo se il certificato è quello previsto. Quando si testa un’app questo può essere un problema poiché Burp servirà il proprio certificato.
Per bypassare questa protezione su un dispositivo jailbroken, puoi installare l’applicazione SSL Kill Switch o installare Burp Mobile Assistant

Puoi anche usare objection’s ios sslpinning disable

Varie

  • In /System/Library puoi trovare i framework installati nel telefono usati dalle applicazioni di sistema
  • Le applicazioni installate dall’utente dall’App Store si trovano in /User/Applications
  • E /User/Library contiene i dati salvati dalle applicazioni a livello utente
  • Puoi accedere a /User/Library/Notes/notes.sqlite per leggere le note salvate nell’applicazione.
  • All’interno della cartella di un’applicazione installata (/User/Applications/<APP ID>/) puoi trovare alcuni file interessanti:
  • iTunesArtwork: l’icona usata dall’app
  • iTunesMetadata.plist: informazioni dell’app usate nell’App Store
  • /Library/*: contiene le preferenze e la cache. In /Library/Cache/Snapshots/* puoi trovare lo snapshot effettuato sull’applicazione prima di mandarla in background.

Hot Patching/Aggiornamenti forzati

Gli sviluppatori possono patchare remotamente tutte le installazioni della loro app istantaneamente senza dover reinviare l’applicazione all’App Store e aspettare l’approvazione.\ A questo scopo è solitamente usato JSPatch. Ma ci sono anche altre opzioni come Siren e react-native-appstore-version-checker.
Questo è un meccanismo pericoloso che potrebbe essere abusato da SDK di terze parti maligni; pertanto è raccomandato verificare quale metodo venga usato per l’aggiornamento automatico (se presente) e testarlo. Potresti provare a scaricare una versione precedente dell’app per questo scopo.

Terze parti

Una sfida significativa con gli SDK di terze parti è la mancanza di controllo granulare sulle loro funzionalità. Gli sviluppatori si trovano davanti a una scelta: integrare l’SDK e accettare tutte le sue caratteristiche, incluse potenziali vulnerabilità di sicurezza e problemi di privacy, oppure rinunciare completamente ai suoi benefici. Spesso gli sviluppatori non possono correggere le vulnerabilità presenti in questi SDK. Inoltre, man mano che gli SDK guadagnano fiducia nella community, alcuni potrebbero iniziare a contenere malware.

I servizi forniti dagli SDK di terze parti possono includere il tracciamento del comportamento degli utenti, la visualizzazione di pubblicità o miglioramenti dell’esperienza utente. Tuttavia, ciò introduce un rischio poiché gli sviluppatori potrebbero non essere pienamente consapevoli del codice eseguito da queste librerie, portando a potenziali problemi di privacy e sicurezza. È cruciale limitare le informazioni condivise con i servizi di terze parti a ciò che è strettamente necessario e assicurarsi che non vengano esposti dati sensibili.

L’implementazione dei servizi di terze parti solitamente avviene in due forme: una libreria standalone o un SDK completo. Per proteggere la privacy degli utenti, qualsiasi dato condiviso con questi servizi dovrebbe essere anonimizzato per prevenire la divulgazione di Personal Identifiable Information (PII).

Per identificare le librerie usate da un’applicazione, può essere impiegato il comando otool. Questo strumento dovrebbe essere eseguito contro l’applicazione e ciascuna shared library che essa usa per scoprire librerie aggiuntive.

otool -L <application_path>

Vulnerabilità interessanti e casi di studio

Air Keyboard Remote Input Injection

Itunesstored Bookassetd Sandbox Escape

Zero Click Messaging Image Parser Chains

Riferimenti e risorse aggiuntive

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks