hacktricks/mobile-pentesting/ios-pentesting
2024-06-19 10:55:45 +00:00
..
basic-ios-testing-operations.md Translated to Italian 2024-02-10 13:03:23 +00:00
burp-configuration-for-ios.md Translated ['crypto-and-stego/certificates.md', 'generic-methodologies-a 2024-05-06 11:09:55 +00:00
extracting-entitlements-from-compiled-application.md Translated to Italian 2024-02-10 13:03:23 +00:00
frida-configuration-in-ios.md Translated ['README.md', 'binary-exploitation/arbitrary-write-2-exec/aw2 2024-05-05 22:09:41 +00:00
ios-app-extensions.md Translated to Italian 2024-02-10 13:03:23 +00:00
ios-basics.md Translated to Italian 2024-02-10 13:03:23 +00:00
ios-custom-uri-handlers-deeplinks-custom-schemes.md Translated to Italian 2024-02-10 13:03:23 +00:00
ios-hooking-with-objection.md Translated to Italian 2024-02-10 13:03:23 +00:00
ios-protocol-handlers.md Translated to Italian 2024-02-10 13:03:23 +00:00
ios-serialisation-and-encoding.md Translated to Italian 2024-02-10 13:03:23 +00:00
ios-testing-environment.md Translated ['README.md', 'binary-exploitation/arbitrary-write-2-exec/aw2 2024-05-05 22:09:41 +00:00
ios-uiactivity-sharing.md Translated to Italian 2024-02-10 13:03:23 +00:00
ios-uipasteboard.md Translated ['binary-exploitation/rop-return-oriented-programing/ret2lib/ 2024-05-02 15:07:01 +00:00
ios-universal-links.md Translated ['mobile-pentesting/ios-pentesting/ios-universal-links.md'] t 2024-06-19 10:55:45 +00:00
ios-webviews.md Translated to Italian 2024-02-10 13:03:23 +00:00
README.md Translated ['crypto-and-stego/certificates.md', 'generic-methodologies-a 2024-05-06 11:09:55 +00:00

iOS Pentesting


Utilizza Trickest per creare e automatizzare flussi di lavoro con gli strumenti della community più avanzati al mondo.
Ottieni l'accesso oggi:

{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=ios-pentesting" %}

Impara l'hacking di AWS da zero a eroe con htARTE (Esperto Red Team di HackTricks AWS)!

Altri modi per supportare HackTricks:

Concetti di base di iOS

{% content-ref url="ios-basics.md" %} ios-basics.md {% endcontent-ref %}

Ambiente di Testing

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

{% content-ref url="ios-testing-environment.md" %} ios-testing-environment.md {% endcontent-ref %}

Analisi Iniziale

Operazioni di Base di Testing su iOS

Durante il testing saranno suggerite diverse operazioni (connettersi al dispositivo, leggere/scrivere/caricare/scaricare file, utilizzare alcuni strumenti...). Pertanto, se non sai come eseguire una di queste azioni, inizia leggendo la pagina:

{% content-ref url="basic-ios-testing-operations.md" %} basic-ios-testing-operations.md {% endcontent-ref %}

{% hint style="info" %} Per i passaggi seguenti l'applicazione dovrebbe essere installata sul dispositivo e dovresti aver già ottenuto il file IPA dell'applicazione.
Leggi la pagina Operazioni di Base di Testing su iOS per imparare come fare. {% endhint %}

Analisi Statica di Base

Si consiglia di utilizzare lo strumento MobSF per eseguire un'Analisi Statica automatica del file IPA.

Identificazione delle protezioni presenti nel binario:

  • PIE (Position Independent Executable): Quando abilitato, l'applicazione si carica in un indirizzo di memoria casuale ogni volta che viene avviata, rendendo più difficile prevedere il suo indirizzo di memoria iniziale.
otool -hv <app-binary> | grep PIE   # Dovrebbe includere il flag PIE
  • Stack Canaries: Per convalidare l'integrità dello stack, viene inserito un valore 'canary' nello stack prima di chiamare una funzione e viene convalidato nuovamente una volta che la funzione termina.
otool -I -v <app-binary> | grep stack_chk   # Dovrebbe includere i simboli: stack_chk_guard e stack_chk_fail
  • ARC (Automatic Reference Counting): Per prevenire comuni difetti di corruzione della memoria
otool -I -v <app-binary> | grep objc_release   # Dovrebbe includere il simbolo _objc_release
  • Binario Crittografato: Il binario dovrebbe essere crittografato
otool -arch all -Vl <app-binary> | grep -A5 LC_ENCRYPT   # Il cryptid dovrebbe essere 1

Identificazione di Funzioni Sensibili/Non Sicure

  • Algoritmi di Hashing Deboli
# Sul dispositivo iOS
otool -Iv <app> | grep -w "_CC_MD5"
otool -Iv <app> | grep -w "_CC_SHA1"

# Su Linux
grep -iER "_CC_MD5"
grep -iER "_CC_SHA1"
  • Funzioni Random Non Sicure
# Sul dispositivo iOS
otool -Iv <app> | grep -w "_random"
otool -Iv <app> | grep -w "_srand"
otool -Iv <app> | grep -w "_rand"

# Su Linux
grep -iER "_random"
grep -iER "_srand"
grep -iER "_rand"
  • Funzione 'Malloc' Non Sicura
# Sul dispositivo iOS
otool -Iv <app> | grep -w "_malloc"

# Su Linux
grep -iER "_malloc"
  • Funzioni Non Sicure e Vulnerabili
# Sul dispositivo iOS
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"

# Su 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"

Analisi Dinamica di Base

Controlla l'analisi dinamica che MobSF esegue. Dovrai navigare attraverso le diverse viste e interagire con esse, ma aggancerà diverse classi e farà altre cose e preparerà un report una volta completato.

Elencazione delle App Installate

Utilizza il comando frida-ps -Uai per determinare l'identificatore del bundle 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

Scopri come enumerare i componenti dell'applicazione e come agganciare facilmente metodi e classi con objection:

{% content-ref url="ios-hooking-with-objection.md" %} ios-hooking-with-objection.md {% endcontent-ref %}

Struttura dell'IPA

La struttura di un file IPA è essenzialmente quella di un pacchetto compresso. Rinominando l'estensione in .zip, è possibile decomprimere il file per rivelarne i contenuti. All'interno di questa struttura, un Bundle rappresenta un'applicazione completamente confezionata pronta per l'installazione. All'interno, troverai una directory chiamata <NOME>.app, che racchiude le risorse dell'applicazione.

  • Info.plist: Questo file contiene dettagli specifici di configurazione dell'applicazione.
  • _CodeSignature/: Questa directory include un file plist che contiene una firma, garantendo l'integrità di tutti i file nel bundle.
  • Assets.car: Un archivio compresso che memorizza file di risorse come icone.
  • Frameworks/: Questa cartella contiene le librerie native dell'applicazione, che possono essere sotto forma di file .dylib o .framework.
  • PlugIns/: Questo può includere estensioni dell'applicazione, note come file .appex, anche se non sono sempre presenti.
  • Core Data: Viene utilizzato per salvare i dati permanenti dell'applicazione per un utilizzo offline, per memorizzare dati temporanei e per aggiungere funzionalità di annullamento all'app su un singolo dispositivo. Per sincronizzare i dati su più dispositivi in un singolo account iCloud, Core Data replica automaticamente lo schema in un contenitore CloudKit.
  • PkgInfo: Il file PkgInfo è un modo alternativo per specificare i codici di tipo e creatore della tua applicazione o bundle.
  • en.lproj, fr.proj, Base.lproj: Sono i pacchetti linguistici che contengono risorse per quelle lingue specifiche e una risorsa predefinita nel caso in cui una lingua non sia supportata.
  • Sicurezza: La directory _CodeSignature/ svolge un ruolo critico nella sicurezza dell'app verificando l'integrità di tutti i file inclusi attraverso firme digitali.
  • Gestione delle Risorse: Il file Assets.car utilizza la compressione per gestire efficientemente le risorse grafiche, essenziale per ottimizzare le performance dell'applicazione e ridurne le dimensioni complessive.
  • Frameworks e PlugIns: Queste directory sottolineano la modularità delle applicazioni iOS, consentendo agli sviluppatori di includere librerie di codice riutilizzabili (Frameworks/) ed estendere la funzionalità dell'app (PlugIns/).
  • Localizzazione: La struttura supporta più lingue, facilitando il raggiungimento globale dell'applicazione includendo risorse per pacchetti linguistici specifici.

Info.plist

L'Info.plist funge da fondamento per le applicazioni iOS, racchiudendo dati di configurazione chiave sotto forma di coppie chiave-valore. Questo file è un requisito non solo per le applicazioni ma anche per le estensioni dell'app e i framework inclusi. È strutturato in formato XML o binario e contiene informazioni critiche che vanno dalle autorizzazioni dell'app alle configurazioni di sicurezza. Per una dettagliata esplorazione delle chiavi disponibili, si può fare riferimento alla Documentazione per Sviluppatori Apple.

Per coloro che desiderano lavorare con questo file in un formato più accessibile, la conversione in XML può essere ottenuta facilmente tramite l'uso di plutil su macOS (disponibile nativamente nelle 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 le miriadi di informazioni che il file Info.plist può divulgare, le voci degne di nota includono le stringhe delle autorizzazioni dell'app (UsageDescription), gli schemi URL personalizzati (CFBundleURLTypes), e le configurazioni per la Sicurezza del Trasporto dell'App (NSAppTransportSecurity). Queste voci, insieme ad altre come i tipi di documento personalizzati esportati/importati (UTExportedTypeDeclarations / UTImportedTypeDeclarations), possono essere facilmente individuate ispezionando il file o utilizzando un semplice comando grep:

$ grep -i <keyword> Info.plist

Percorsi dei dati

Nell'ambiente iOS, ci sono directory designate specificamente per le applicazioni di sistema e le applicazioni installate dall'utente. Le applicazioni di sistema risiedono nella directory /Applications, mentre le app installate dall'utente sono collocate sotto /var/mobile/containers/Data/Application/. Queste applicazioni sono assegnate un identificatore univoco noto come un UUID a 128 bit, rendendo difficile il compito di individuare manualmente la cartella di un'app a causa della casualità dei nomi delle directory.

{% hint style="warning" %} Poiché le applicazioni in iOS devono essere sandboxate, ogni app avrà anche una cartella all'interno di $HOME/Library/Containers con l'CFBundleIdentifier dell'app come nome della cartella.

Tuttavia, entrambe le cartelle (cartelle dati e container) contengono il file .com.apple.mobile_container_manager.metadata.plist che collega entrambi i file nella chiave MCMetadataIdentifier). {% endhint %}

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 sulla directory dell'app in questione. Di seguito è riportato 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

Oppure, il nome dell'app può essere cercato all'interno di /private/var/containers utilizzando il comando find:

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

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

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

Directory del bundle:

  • AppName.app
  • Questo è il Bundle dell'Applicazione come visto in precedenza nell'IPA, contiene dati dell'applicazione essenziali, contenuti statici e il binario compilato dell'applicazione.
  • Questa directory è visibile agli utenti, ma gli utenti non possono scriverci.
  • I contenuti in questa directory non vengono salvati.
  • I contenuti di questa cartella vengono utilizzati per validare la firma del codice.

Directory dei dati:

  • Documents/
  • Contiene tutti i dati generati dall'utente. L'utente finale dell'applicazione inizia la creazione di questi dati.
  • Visibile agli utenti e gli utenti possono scriverci.
  • I contenuti in questa directory vengono salvati.
  • L'applicazione può disabilitare i percorsi impostando NSURLIsExcludedFromBackupKey.
  • Library/
  • Contiene tutti i file che non sono specifici dell'utente, come cache, preferenze, cookie e file di configurazione della lista delle proprietà (plist).
  • Le app iOS di solito utilizzano le sottodirectory Application Support e Caches, ma l'applicazione può creare sottodirectory personalizzate.
  • Library/Caches/
  • Contiene file memorizzati in cache semi-persistenti.
  • Invisibile agli utenti e gli utenti non possono scriverci.
  • I contenuti in questa directory non vengono salvati.
  • Il sistema operativo potrebbe eliminare automaticamente i file di questa directory quando l'applicazione non è in esecuzione e lo spazio di archiviazione è scarso.
  • Library/Application Support/
  • Contiene file persistenti necessari per l'esecuzione dell'applicazione.
  • Invisibile agli utenti e gli utenti non possono scriverci.
  • I contenuti in questa directory vengono salvati.
  • L'applicazione può disabilitare i percorsi impostando NSURLIsExcludedFromBackupKey.
  • Library/Preferences/
  • Utilizzato per memorizzare proprietà che possono persistere anche dopo il riavvio di un'applicazione.
  • Le informazioni vengono salvate, non crittografate, all'interno del sandbox dell'applicazione in un file plist chiamato [BUNDLE_ID].plist.
  • Tutte le coppie chiave/valore memorizzate utilizzando NSUserDefaults possono essere trovate in questo file.
  • tmp/
  • Utilizzare questa directory per scrivere file temporanei che non devono persistere tra i lanci dell'applicazione.
  • Contiene file memorizzati in cache non persistenti.
  • Invisibile agli utenti.
  • I contenuti in questa directory non vengono salvati.
  • Il sistema operativo potrebbe eliminare automaticamente i file di questa directory quando l'applicazione non è in esecuzione e lo spazio di archiviazione è scarso.

Diamo un'occhiata più da vicino alla directory dell'Applicazione iGoat-Swift (.app) all'interno della directory 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

Analisi Binaria

All'interno della cartella <nome-applicazione>.app troverai un file binario chiamato <nome-applicazione>. 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 è crittografata

Controlla se c'è un output per:

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

Disassemblare il binario

Disassembla la sezione di testo:

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 segmento Objective-C dell'applicazione di esempio si può utilizzare:

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, è possibile utilizzare 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 binario sono: Hopper e IDA.


Utilizza Trickest per creare facilmente e automatizzare flussi di lavoro supportati dagli strumenti della community più avanzati al mondo.
Ottieni l'accesso oggi:

{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=ios-pentesting" %}

Archiviazione dei dati

Per apprendere come iOS archivia i dati nel dispositivo, leggi questa pagina:

{% content-ref url="ios-basics.md" %} ios-basics.md {% endcontent-ref %}

{% hint style="warning" %} I seguenti luoghi di archiviazione delle informazioni dovrebbero essere controllati subito dopo l'installazione dell'applicazione, dopo aver verificato tutte le funzionalità dell'applicazione e anche dopo essere usciti da un utente e aver effettuato l'accesso con un utente diverso.
L'obiettivo è trovare informazioni sensibili non protette dell'applicazione (password, token), dell'utente corrente e degli utenti precedentemente registrati. {% endhint %}

Plist

I file plist sono file XML strutturati che contengono coppie chiave-valore. È un modo per archiviare dati persistenti, quindi a volte potresti trovare informazioni sensibili in questi file. È consigliabile controllare questi file dopo l'installazione dell'app e dopo averlo utilizzato intensivamente per vedere se vengono scritti nuovi dati.

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

La classe NSUserDefaults fornisce un'interfaccia programmatica per interagire con il sistema predefinito. Il sistema predefinito consente a un'applicazione di personalizzare il suo 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 è destinata ad essere utilizzata con piccole quantità di dati.

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

Puoi estrarre le informazioni salvate utilizzando NSUserDefaults utilizzando ios nsuserdefaults get di objection.

Per trovare tutti i plist utilizzati dall'applicazione, puoi accedere a /private/var/mobile/Containers/Data/Application/{APPID} e eseguire:

find ./ -name "*.plist"

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

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

$ plutil -convert xml1 Info.plist

Per gli utenti Linux: Installare prima libplist-utils, quindi utilizzare 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 consente 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 gestire il livello di modello degli oggetti nella tua applicazione. Core Data può utilizzare SQLite come archivio persistente, ma il framework stesso non è un database.
CoreData non crittografa i suoi dati per impostazione predefinita. Tuttavia, è possibile aggiungere uno strato di crittografia aggiuntivo a CoreData. Consulta il GitHub Repo per ulteriori dettagli.

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

Se riesci ad aprire il file SQLite e accedere a informazioni sensibili, allora hai trovato una configurazione errata.

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

{% endcode %}

YapDatabase

YapDatabase è un archivio chiave/valore costruito sopra SQLite.
Poiché i database Yap sono database sqlite, è possibile trovarli utilizzando il comando apposito nella sezione precedente.

Altri Database SQLite

È comune che le applicazioni creino il proprio database sqlite. Potrebbero memorizzare dati sensibili al loro interno e lasciarli non crittografati. Pertanto, è sempre interessante controllare ogni database all'interno della directory delle applicazioni. Quindi vai alla directory dell'applicazione dove i dati sono salvati (/private/var/mobile/Containers/Data/Application/{APPID})

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

Database in tempo reale di Firebase

Ai developer è consentito memorizzare e sincronizzare dati all'interno di un database ospitato su cloud NoSQL tramite il Database in tempo reale di Firebase. Memorizzati in formato JSON, i dati vengono sincronizzati in tempo reale su tutti i client connessi.

Puoi scoprire come verificare la presenza di database Firebase configurati in modo errato qui:

{% content-ref url="../../network-services-pentesting/pentesting-web/buckets/firebase-database.md" %} firebase-database.md {% endcontent-ref %}

Database Realm

Realm Objective-C e Realm Swift offrono un'alternativa potente per lo storage dei dati, non fornita da Apple. Per impostazione predefinita, essi memorizzano dati non crittografati, con la crittografia disponibile tramite configurazioni specifiche.

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, è consigliato utilizzare lo strumento Realm Studio.

Per implementare la crittografia all'interno di un database Realm, è possibile utilizzare il seguente frammento 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 di Couchbase Lite

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

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

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

Cookies

iOS memorizza i cookie delle app nella cartella Library/Cookies/cookies.binarycookies all'interno di ciascuna cartella dell'app. Tuttavia, a volte gli sviluppatori decidono di salvarli nell'portachiavi poiché il suddetto file dei cookie può essere accessibile nei backup.

Per ispezionare il file dei cookie puoi utilizzare questo script python o utilizzare il comando ios cookies get di objection.
Puoi anche utilizzare 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

Di default NSURLSession memorizza i dati, come le richieste e le risposte HTTP nel database Cache.db. Questo database può contenere dati sensibili, se token, nomi utente o altre informazioni sensibili sono stati memorizzati nella cache. Per trovare le informazioni memorizzate aprire la directory dei dati dell'app (/var/mobile/Containers/Data/Application/<UUID>) e andare a /Library/Caches/<Bundle Identifier>. Anche la cache di WebKit viene memorizzata nel file Cache.db. Objection può aprire e interagire con il database con il comando sqlite connect Cache.db, poiché si tratta di un normale database SQLite.

È consigliabile disabilitare la memorizzazione nella cache di questi dati, poiché potrebbero contenere informazioni sensibili nella richiesta o nella risposta. Di seguito sono elencati diversi modi per ottenere questo:

  1. Si consiglia di rimuovere le risposte memorizzate dopo il logout. Questo può essere fatto con il metodo fornito da Apple chiamato removeAllCachedResponses È possibile chiamare questo metodo nel seguente modo:

URLCache.shared.removeAllCachedResponses()

Questo metodo rimuoverà tutte le richieste e risposte memorizzate dal file Cache.db. 2. Se non è necessario utilizzare i vantaggi dei cookie, sarebbe consigliabile utilizzare la proprietà di configurazione .ephemeral di URLSession, che disabiliterà il salvataggio dei cookie e della cache.

Documentazione Apple:

Un oggetto di configurazione della sessione effimera è simile a una configurazione di sessione predefinita (vedi predefinito), tranne che l'oggetto di sessione corrispondente non memorizza cache, archivi di credenziali o dati correlati alla sessione su disco. Invece, i dati correlati alla sessione sono memorizzati in RAM. L'unica volta in cui una sessione effimera scrive dati su disco è quando gli si dice di scrivere i contenuti di un URL su un file. 3. La cache può essere disabilitata anche impostando la Policy della Cache su .notAllowed. Questo disabiliterà la memorizzazione della cache in qualsiasi modo, sia in memoria che su disco.

Snapshots

Ogni volta che si preme il pulsante home, iOS fa uno snapshot dello schermo corrente per poter effettuare la transizione all'applicazione in modo più fluido. Tuttavia, se sono presenti dati sensibili nello schermo corrente, verranno salvati nell'immagine (che persiste attraverso riavvii). Questi sono gli snapshot a cui è possibile accedere anche facendo doppio tap sullo schermo home per passare tra le app.

A meno che l'iPhone non sia jailbroken, l'attaccante deve avere accesso al dispositivo sbloccato per vedere queste schermate. Di default, l'ultimo snapshot è memorizzato nella sandbox dell'applicazione in Library/Caches/Snapshots/ o nella cartella Library/SplashBoard/Snapshots (i computer fidati non possono accedere al filesystem da iOS 7.0).

Un modo per prevenire questo comportamento indesiderato è quello di mettere uno schermo vuoto o rimuovere i dati sensibili prima di fare lo snapshot utilizzando la funzione ApplicationDidEnterBackground().

Di seguito è riportato un metodo di rimedio di esempio che imposterà uno screenshot predefinito.

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 messa in background. Ciò impedisce perdite di dati sensibili perché overlayImage.png sovrascriverà sempre la vista corrente.

Portachiavi

Per accedere e gestire il portachiavi iOS, sono disponibili strumenti come Keychain-Dumper, adatti per 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 portachiavi, evitando la necessità di NSUserDefaults o 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 ios nsurlcredentialstorage dump di Objection.

Tastiere personalizzate e cache della tastiera

Con iOS 8.0 in poi, gli utenti possono installare estensioni di tastiera personalizzate, gestibili in Impostazioni > Generale > Tastiera > Tastiere. Anche se queste tastiere offrono funzionalità estese, pongono il rischio di registrazione dei tasti premuti e di trasmissione dei dati a server esterni, anche se agli utenti viene notificato riguardo alle tastiere che richiedono l'accesso alla rete. Le app possono, e dovrebbero, limitare l'uso delle tastiere personalizzate per l'inserimento di informazioni sensibili.

Raccomandazioni di sicurezza:

  • Si consiglia di disabilitare le tastiere di terze parti per una maggiore sicurezza.
  • Prestare attenzione alle funzionalità di autocorrezione e suggerimenti automatici della tastiera predefinita di iOS, che potrebbero memorizzare informazioni sensibili nei 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 verificare la presenza di dati sensibili. Si consiglia di ripristinare il dizionario della tastiera tramite Impostazioni > Generale > Ripristina > Ripristina dizionario tastiera per eliminare i dati memorizzati nella cache.
  • Intercettare il traffico di rete può rivelare se una tastiera personalizzata sta trasmettendo i tasti premuti in remoto.

Prevenire la memorizzazione nella cache dei campi di testo

Il protocollo UITextInputTraits offre proprietà per gestire l'autocorrezione e l'inserimento di testo sicuro, essenziali per prevenire la memorizzazione di informazioni sensibili. Ad esempio, è possibile disabilitare l'autocorrezione e abilitare l'inserimento di testo sicuro con:

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

Inoltre, gli sviluppatori dovrebbero assicurarsi che i campi di testo, specialmente quelli per inserire 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;

Log

Il debug del codice spesso implica l'uso del logging. C'è un rischio in quanto i log possono contenere informazioni sensibili. In precedenza, in iOS 6 e nelle versioni precedenti, i log erano accessibili a tutte le app, creando un rischio di perdita di dati sensibili. Ora, le applicazioni sono limitate ad accedere solo ai propri log.

Nonostante queste restrizioni, un attaccante con accesso fisico a un dispositivo sbloccato può ancora sfruttarlo collegando il dispositivo a un computer e leggendo i log. È importante notare che i log rimangono sul disco anche dopo la disinstallazione dell'app.

Per mitigare i rischi, si consiglia di interagire approfonditamente con l'app, esplorando tutte le sue funzionalità e input per garantire che non vengano registrate informazioni sensibili per errore.

Nel momento in cui si esamina il codice sorgente dell'app per potenziali fughe, cercare sia istruzioni di logging predefinite che personalizzate utilizzando parole chiave come NSLog, NSAssert, NSCAssert, fprintf per le funzioni integrate, e qualsiasi menzione di Logging o Logfile per implementazioni personalizzate.

Monitoraggio dei Log di Sistema

Le app registrano varie informazioni sensibili. Per monitorare questi log, 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 fornisce un modo per raccogliere i log della console:

  1. Apri Xcode.
  2. Collega il dispositivo iOS.
  3. Vai su Finestra -> Dispositivi e Simulatori.
  4. Seleziona il tuo dispositivo.
  5. Attiva il problema che stai investigando.
  6. Usa il pulsante Apri Console per visualizzare i log in una nuova finestra.

Per una registrazione più avanzata, connettersi alla shell del dispositivo e utilizzare socat può fornire il monitoraggio dei log in tempo reale:

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

Seguito dai comandi per osservare le attività di log, che possono essere preziose per diagnosticare problemi o identificare potenziali fughe di dati nei log.



Utilizza Trickest per creare e automatizzare flussi di lavoro con facilità, supportati dagli strumenti della comunità più avanzati al mondo.
Ottieni l'accesso oggi:

{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=ios-pentesting" %}

Backup

Le 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 includono 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 delle app installate e dei loro dati nei backup solleva il problema di potenziali fughe di dati e del rischio che le modifiche al backup possano alterare la funzionalità dell'app. Si consiglia di non memorizzare informazioni sensibili in chiaro 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 automaticamente inclusi nei backup. Gli sviluppatori possono escludere file o directory specifiche dai backup utilizzando NSURL setResourceValue:forKey:error: con la chiave NSURLIsExcludedFromBackupKey. Questa pratica è cruciale per proteggere i dati sensibili dall'inclusione nei backup.

Test per le Vulnerabilità

Per valutare la sicurezza del backup di un'app, inizia con la creazione di un backup utilizzando Finder, quindi individualo seguendo le indicazioni della documentazione ufficiale di Apple. Analizza il backup per individuare dati sensibili o configurazioni che potrebbero essere modificate per influenzare il comportamento dell'app.

Le informazioni sensibili possono essere individuate utilizzando strumenti a riga di comando o applicazioni come iMazing. Per i backup criptati, la presenza di crittografia può essere confermata controllando la chiave "IsEncrypted" nel file "Manifest.plist" nella 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>

Per gestire i backup crittografati, gli script Python disponibili nel repository GitHub di DinoSec, come backup_tool.py e backup_passwd.py, potrebbero essere utili, sebbene potenzialmente richiedano modifiche per la compatibilità con le ultime versioni di iTunes/Finder. Lo strumento iOSbackup è un'altra opzione per accedere ai file all'interno dei backup protetti da password.

Modifica del Comportamento dell'App

Un esempio di modifica del comportamento dell'app attraverso modifiche al backup è dimostrato nell'app del portafoglio bitcoin Bither, dove il PIN di blocco dell'interfaccia utente è memorizzato all'interno di net.bither.plist sotto la chiave pin_code. Rimuovendo questa chiave dal plist e ripristinando il backup si elimina il requisito del PIN, fornendo accesso illimitato.

Riassunto sul Testing della Memoria per Dati Sensibili

Quando si tratta di informazioni sensibili memorizzate nella memoria di un'applicazione, è cruciale limitare il tempo di esposizione di questi dati. Ci sono due approcci principali per investigare il contenuto della memoria: creare un dump della memoria e analizzare la memoria in tempo reale. Entrambi i metodi hanno le loro sfide, inclusa la possibilità di perdere dati critici durante il processo di dump o di analisi.

Recupero e Analisi di un Dump della Memoria

Per dispositivi jailbroken e non jailbroken, strumenti come objection e Fridump consentono il dump della memoria del processo di un'app. Una volta effettuato il dump, l'analisi di questi dati richiede vari strumenti, a seconda della natura delle informazioni che si sta cercando.

Per estrarre stringhe da un dump di memoria, possono essere utilizzati comandi come strings o rabin2 -zz:

# 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]> /?
...

Analisi della Memoria in Esecuzione

r2frida fornisce un'alternativa potente per ispezionare la memoria di un'app in tempo reale, senza la necessità di un dump di memoria. Questo strumento consente l'esecuzione di comandi di ricerca direttamente sulla memoria dell'applicazione in esecuzione:

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

Crittografia Danneggiata

Processi di Gestione delle Chiavi Scadenti

Alcuni sviluppatori salvano dati sensibili nello storage locale e li crittografano con una chiave codificata/prevedibile nel codice. Questo non dovrebbe essere fatto poiché un'operazione di reverse engineering potrebbe consentire agli attaccanti di estrarre le informazioni confidenziali.

Utilizzo di Algoritmi Insicuri e/o Deprecati

Gli sviluppatori non dovrebbero utilizzare algoritmi deprecati per eseguire controlli di autorizzazione, memorizzare o inviare dati. Alcuni di questi algoritmi sono: RC4, MD4, MD5, SHA1... Se vengono utilizzati hash per memorizzare le password, ad esempio, dovrebbero essere utilizzati hash resistenti agli attacchi di forza bruta con salt.

Controllo

I principali controlli da effettuare sono per verificare se è possibile trovare password/segnreti codificati nel codice, o se questi sono prevedibili, e se il codice sta utilizzando qualche tipo di algoritmi di crittografia deboli.

È interessante sapere che è possibile monitorare automaticamente alcune librerie di crittografia utilizzando objection con:

ios monitor crypt

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

Autenticazione Locale

L'autenticazione locale svolge un ruolo cruciale, specialmente quando si tratta di proteggere l'accesso a un endpoint remoto attraverso metodi crittografici. L'essenza qui è che senza un'implementazione corretta, i meccanismi di autenticazione locale possono essere aggirati.

Il framework di autenticazione locale di Apple e il portachiavi forniscono API robuste per consentire agli sviluppatori di facilitare i dialoghi di autenticazione degli utenti e gestire in modo sicuro dati segreti, rispettivamente. Il Secure Enclave protegge l'ID dell'impronta digitale per il Touch ID, mentre il Face ID si basa sul riconoscimento facciale senza compromettere i dati biometrici.

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

  • LocalAuthentication.framework per l'autenticazione dell'utente a livello elevato senza accesso ai dati biometrici.
  • Security.framework per l'accesso ai servizi di portachiavi a livello inferiore, proteggendo i dati segreti con autenticazione biometrica. Vari wrapper open-source semplificano l'accesso al portachiavi.

{% hint style="danger" %} Tuttavia, sia LocalAuthentication.framework che Security.framework presentano vulnerabilità, poiché restituiscono principalmente valori booleani senza trasmettere dati per i processi di autenticazione, rendendoli suscettibili all'aggiramento (fare riferimento a Don't touch me that way, di David Lindner et al). {% endhint %}

Implementazione dell'Autenticazione Locale

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

  • deviceOwnerAuthentication: Richiede l'ID dell'impronta digitale o il codice di accesso del dispositivo, fallendo se nessuno dei due è abilitato.
  • deviceOwnerAuthenticationWithBiometrics: Richiede esclusivamente il Touch ID.

Un'autenticazione riuscita è indicata da un valore booleano restituito da evaluatePolicy, evidenziando una potenziale falla di sicurezza.

Autenticazione Locale utilizzando il Portachiavi

L'implementazione dell'autenticazione locale nelle app iOS coinvolge l'uso delle API del portachiavi per memorizzare in modo sicuro dati segreti come token di autenticazione. Questo processo garantisce che i dati possano essere accessibili solo dall'utente, utilizzando il codice di accesso del dispositivo o l'autenticazione biometrica come il Touch ID.

Il portachiavi offre la capacità di impostare elementi con l'attributo SecAccessControl, che limita l'accesso all'elemento fino a quando l'utente autentica con successo tramite il Touch ID o il codice di accesso del dispositivo. Questa funzionalità è cruciale per migliorare la sicurezza.

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

{% tabs %} {% tab title="Swift" %}

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

{% endtab %}

{% tab title="Objective-C" %}Translate the relevant English text to Italian and return the translation keeping excatly the same markdown and html syntax. Do not translate things like code, hacking technique names, hacking word, cloud/SaaS platform names (like Workspace, aws, gcp...), the word 'leak', pentesting, and markdown tags. Also don't add any extra stuff apart from the translation and markdown syntax.

// 1. create AccessControl object that will represent authentication settings
CFErrorRef *err = nil;

SecAccessControlRef sacRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
kSecAccessControlUserPresence,
err);

// 2. define keychain services query. Pay attention that kSecAttrAccessControl is mutually exclusive with kSecAttrAccessible attribute
NSDictionary* query = @{
(_ _bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrLabel: @"com.me.myapp.password",
(__bridge id)kSecAttrAccount: @"OWASP Account",
(__bridge id)kSecValueData: [@"test_strong_password" dataUsingEncoding:NSUTF8StringEncoding],
(__bridge id)kSecAttrAccessControl: (__bridge_transfer id)sacRef
};

// 3. save item
OSStatus status = SecItemAdd((__bridge CFDictionaryRef)query, nil);

if (status == noErr) {
// successfully saved
} else {
// error while saving
}

{% endtab %} {% endtabs %}

Ora possiamo richiedere l'elemento salvato dal portachiavi. I servizi del portachiavi presenteranno il dialogo di autenticazione all'utente e restituiranno i dati o nil a seconda che sia stata fornita un'impronta digitale adeguata o meno.

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

{% endtab %}

{% tab title="Objective-C" %}Translate the relevant English text to Italian and return the translation keeping excatly the same markdown and html syntax. Do not translate things like code, hacking technique names, hacking word, cloud/SaaS platform names (like Workspace, aws, gcp...), the word 'leak', pentesting, and markdown tags. Also don't add any extra stuff apart from the translation and markdown syntax.

// 1. define query
NSDictionary *query = @{(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecReturnData: @YES,
(__bridge id)kSecAttrAccount: @"My Name1",
(__bridge id)kSecAttrLabel: @"com.me.myapp.password",
(__bridge id)kSecUseOperationPrompt: @"Please, pass authorisation to enter this area" };

// 2. get item
CFTypeRef queryResult = NULL;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &queryResult);

if (status == noErr){
NSData* resultData = ( __bridge_transfer NSData* )queryResult;
NSString* password = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];
NSLog(@"%@", password);
} else {
NSLog(@"Something went wrong");
}

{% endtab %} {% endtabs %}

Rilevamento

L'utilizzo di framework in un'app può anche essere rilevato analizzando l'elenco delle librerie dinamiche condivise dell'applicazione binaria. Questo può essere fatto utilizzando otool:

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

Se LocalAuthentication.framework viene utilizzato in un'applicazione, l'output conterrà entrambe le seguenti righe (ricorda che LocalAuthentication.framework utilizza Security.framework sotto il cofano):

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

Se viene utilizzato Security.framework, verrà mostrato solo il secondo.

Bypass del Framework di Autenticazione Locale

Obiezione

Attraverso il Bypass Biometrico di Obiezione, situato in questa pagina GitHub, è disponibile una tecnica per superare il meccanismo di LocalAuthentication. Il cuore di questo approccio coinvolge l'utilizzo di Frida per manipolare la funzione evaluatePolicy, garantendo che produca sempre un risultato True, indipendentemente dal successo effettivo dell'autenticazione. Questo è particolarmente utile per aggirare processi di autenticazione biometrica difettosi.

Per attivare questo bypass, viene utilizzato 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'attività che modifica efficacemente l'esito del controllo evaluatePolicy a True.

Frida

Un esempio di utilizzo di evaluatePolicy dall'applicazione DVIA-v2:

+(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 dell'Autenticazione Locale, viene scritto uno script Frida. Questo script mira al controllo evaluatePolicy, intercettando il suo callback per garantire che restituisca success=1. Modificando il comportamento del callback, il controllo di autenticazione viene bypassato in modo efficace.

Lo script di seguito viene iniettato per modificare il risultato del metodo evaluatePolicy. Cambia il risultato del callback per indicare 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 di Frida e bypassare l'autenticazione biometrica, viene utilizzato il seguente comando:

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

Esposizione di Funzionalità Sensibili Attraverso IPC

{% content-ref url="ios-custom-uri-handlers-deeplinks-custom-schemes.md" %} ios-custom-uri-handlers-deeplinks-custom-schemes.md {% endcontent-ref %}

Collegamenti Universali

{% content-ref url="ios-universal-links.md" %} ios-universal-links.md {% endcontent-ref %}

Condivisione UIActivity

{% content-ref url="ios-uiactivity-sharing.md" %} ios-uiactivity-sharing.md {% endcontent-ref %}

UIPasteboard

{% content-ref url="ios-uipasteboard.md" %} ios-uipasteboard.md {% endcontent-ref %}

Estensioni dell'App

{% content-ref url="ios-app-extensions.md" %} ios-app-extensions.md {% endcontent-ref %}

WebViews

{% content-ref url="ios-webviews.md" %} ios-webviews.md {% endcontent-ref %}

Serializzazione e Codifica

{% content-ref url="ios-serialisation-and-encoding.md" %} ios-serialisation-and-encoding.md {% endcontent-ref %}

Comunicazione di Rete

È importante verificare che non ci siano comunicazioni senza crittografia e che l'applicazione stia correttamente validando il certificato TLS del server.
Per verificare questo tipo di problemi, è possibile utilizzare un proxy come Burp:

{% content-ref url="burp-configuration-for-ios.md" %} burp-configuration-for-ios.md {% endcontent-ref %}

Controllo del Nome Host

Un problema comune nella convalida del certificato TLS è controllare che il certificato sia stato firmato da una CA attendibile, ma non controllare se il nome host del certificato corrisponde all'host a cui si accede.
Per verificare questo problema utilizzando Burp, dopo aver fidato della CA di Burp sull'iPhone, è possibile creare un nuovo certificato con Burp per un nome host diverso e utilizzarlo. Se l'applicazione funziona ancora, allora c'è una vulnerabilità.

Pinning del Certificato

Se un'applicazione utilizza correttamente il Pinning SSL, l'applicazione funzionerà solo se il certificato è quello atteso. Durante il test di un'applicazione questo potrebbe essere un problema poiché Burp servirà il proprio certificato.
Per aggirare questa protezione all'interno di un dispositivo jailbroken, è possibile installare l'applicazione SSL Kill Switch o installare Burp Mobile Assistant

È inoltre possibile utilizzare il comando ios sslpinning disable di objection

Varie

  • In /System/Library è possibile trovare i framework installati nel telefono utilizzati dalle applicazioni di sistema
  • Le applicazioni installate dall'utente dall'App Store si trovano all'interno di /User/Applications
  • E /User/Library contiene i dati salvati dalle applicazioni a livello utente
  • È possibile accedere a /User/Library/Notes/notes.sqlite per leggere le note salvate all'interno dell'applicazione.
  • All'interno della cartella di un'applicazione installata (/User/Applications/<ID APP>/) è possibile trovare alcuni file interessanti:
    • iTunesArtwork: L'icona utilizzata dall'app
    • iTunesMetadata.plist: Informazioni dell'app utilizzate nell'App Store
    • /Library/*: Contiene le preferenze e la cache. In /Library/Cache/Snapshots/* è possibile trovare lo snapshot eseguito dall'applicazione prima di inviarla in background.

Patching in Tempo Reale/Aggiornamenti Forzati

Gli sviluppatori possono applicare patch remotamente a tutte le installazioni della propria app istantaneamente senza dover sottomettere nuovamente l'applicazione allo Store e attendere l'approvazione.
Per questo scopo di solito si utilizza JSPatch. Ma ci sono anche altre opzioni come Siren e react-native-appstore-version-checker.
Si tratta di un meccanismo pericoloso che potrebbe essere abusato da SDK di terze parti malintenzionati, pertanto è consigliabile verificare quale metodo viene utilizzato per l'aggiornamento automatico (se presente) e testarlo. Si potrebbe provare a scaricare una versione precedente dell'app a questo scopo.

Terze Parti

Una sfida significativa con SDK di terze parti è la mancanza di controllo granulare sulle loro funzionalità. Gli sviluppatori si trovano di fronte a una scelta: integrare lo SDK e accettare tutte le sue funzionalità, comprese potenziali vulnerabilità di sicurezza e preoccupazioni sulla privacy, oppure rinunciare completamente ai suoi benefici. Spesso, gli sviluppatori non sono in grado di correggere le vulnerabilità all'interno di questi SDK da soli. Inoltre, poiché gli SDK guadagnano fiducia nella comunità, alcuni potrebbero iniziare a contenere malware.

I servizi forniti dagli SDK di terze parti possono includere il tracciamento del comportamento dell'utente, la visualizzazione di annunci o il miglioramento 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 rischi per la privacy e la sicurezza. È cruciale limitare le informazioni condivise con i servizi di terze parti a ciò che è necessario e garantire che nessun dato sensibile venga esposto.

L'implementazione dei servizi di terze parti di solito avviene in due forme: una libreria autonoma o uno SDK completo. Per proteggere la privacy dell'utente, qualsiasi dato condiviso con questi servizi dovrebbe essere anonimizzato per evitare la divulgazione di Informazioni di Identificazione Personale (PII).

Per identificare le librerie utilizzate da un'applicazione, è possibile utilizzare il comando otool. Questo strumento dovrebbe essere eseguito contro l'applicazione e ciascuna libreria condivisa utilizzata per scoprire eventuali librerie aggiuntive.

otool -L <application_path>

Riferimenti e Altri Risorse


Utilizza Trickest per costruire facilmente e automatizzare flussi di lavoro supportati dagli strumenti della comunità più avanzati al mondo.
Ottieni l'Accesso Oggi:

{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=ios-pentesting" %}

Impara l'hacking di AWS da zero a eroe con htARTE (HackTricks AWS Red Team Expert)!

Altri modi per supportare HackTricks: