mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
1089 lines
62 KiB
Markdown
1089 lines
62 KiB
Markdown
# iOS Pentesting
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|
||
|
||
## iOS Basics
|
||
|
||
{{#ref}}
|
||
ios-basics.md
|
||
{{#endref}}
|
||
|
||
## Testing Environment
|
||
|
||
In questa pagina puoi trovare informazioni sul **simulatore iOS**, **emulatori** e **jailbreaking:**
|
||
|
||
{{#ref}}
|
||
ios-testing-environment.md
|
||
{{#endref}}
|
||
|
||
## Initial Analysis
|
||
|
||
### Basic iOS Testing Operations
|
||
|
||
Durante il testing **verranno suggerite diverse operazioni** (connettersi al dispositivo, leggere/scrivere/caricare/scaricare file, utilizzare alcuni strumenti...). Pertanto, se non sai come eseguire una di queste azioni, per favore, **inizia a leggere la pagina**:
|
||
|
||
{{#ref}}
|
||
basic-ios-testing-operations.md
|
||
{{#endref}}
|
||
|
||
> [!TIP]
|
||
> Per i passaggi successivi **l'app dovrebbe essere installata** nel dispositivo e dovrebbe aver già ottenuto il **file IPA** dell'applicazione.\
|
||
> Leggi la pagina [Basic iOS Testing Operations](basic-ios-testing-operations.md) per sapere come fare.
|
||
|
||
### Basic Static Analysis
|
||
|
||
Alcuni interessanti decompilatori iOS - IPA:
|
||
|
||
- [https://github.com/LaurieWired/Malimite](https://github.com/LaurieWired/Malimite)
|
||
- [https://ghidra-sre.org/](https://ghidra-sre.org/)
|
||
|
||
È consigliato utilizzare lo strumento [**MobSF**](https://github.com/MobSF/Mobile-Security-Framework-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.
|
||
|
||
```bash
|
||
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.
|
||
|
||
```bash
|
||
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
|
||
|
||
```bash
|
||
otool -I -v <app-binary> | grep objc_release # Dovrebbe includere il simbolo _objc_release
|
||
```
|
||
|
||
- **Encrypted Binary**: Il binario dovrebbe essere crittografato
|
||
|
||
```bash
|
||
otool -arch all -Vl <app-binary> | grep -A5 LC_ENCRYPT # Il cryptid dovrebbe essere 1
|
||
```
|
||
|
||
**Identificazione di Funzioni Sensibili/Insecure**
|
||
|
||
- **Weak Hashing Algorithms**
|
||
|
||
```bash
|
||
# 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"
|
||
```
|
||
|
||
- **Insecure Random Functions**
|
||
|
||
```bash
|
||
# 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"
|
||
```
|
||
|
||
- **Insecure ‘Malloc’ Function**
|
||
|
||
```bash
|
||
# Sul dispositivo iOS
|
||
otool -Iv <app> | grep -w "_malloc"
|
||
|
||
# Su linux
|
||
grep -iER "_malloc"
|
||
```
|
||
|
||
- **Insecure and Vulnerable Functions**
|
||
|
||
```bash
|
||
# 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**](https://github.com/MobSF/Mobile-Security-Framework-MobSF) esegue. Dovrai navigare tra le diverse visualizzazioni e interagire con esse, ma si occuperà di collegare 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:
|
||
```bash
|
||
$ frida-ps -Uai
|
||
PID Name Identifier
|
||
---- ------------------- -----------------------------------------
|
||
6847 Calendar com.apple.mobilecal
|
||
6815 Mail com.apple.mobilemail
|
||
- App Store com.apple.AppStore
|
||
- Apple Store com.apple.store.Jolly
|
||
- Calculator com.apple.calculator
|
||
- Camera com.apple.camera
|
||
- iGoat-Swift OWASP.iGoat-Swift
|
||
```
|
||
### Basic Enumeration & Hooking
|
||
|
||
Impara come **enumerare i componenti dell'applicazione** e come **hookare metodi e classi** con objection:
|
||
|
||
{{#ref}}
|
||
ios-hooking-with-objection.md
|
||
{{#endref}}
|
||
|
||
### IPA Structure
|
||
|
||
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`**](https://developer.apple.com/documentation/coredata): 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`**](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPRuntimeConfig/Articles/ConfigApplications.html): 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 di lingua che contengono risorse per quelle lingue specifiche e una risorsa predefinita nel caso in cui una lingua non sia supportata.
|
||
- **Security**: La directory `_CodeSignature/` gioca un ruolo critico nella sicurezza dell'app verificando l'integrità di tutti i file inclusi attraverso firme digitali.
|
||
- **Asset Management**: 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 and 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/`).
|
||
- **Localization**: La struttura supporta più lingue, facilitando la portata globale dell'applicazione includendo risorse per pacchetti di lingue specifiche.
|
||
|
||
**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, si può fare riferimento alla [**Apple Developer Documentation**](https://developer.apple.com/documentation/bundleresources/information_property_list?language=objc).
|
||
|
||
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**:
|
||
```bash
|
||
$ plutil -convert xml1 Info.plist
|
||
```
|
||
- **Per Linux**:
|
||
```bash
|
||
$ apt install libplist-utils
|
||
$ plistutil -i Info.plist -o Info_xml.plist
|
||
```
|
||
Tra la miriade di informazioni che il file **Info.plist** può rivelare, voci notevoli includono le stringhe di 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`:
|
||
```bash
|
||
$ 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.
|
||
|
||
> [!WARNING]
|
||
> Poiché le applicazioni in iOS devono essere sandboxed, ogni app avrà anche una cartella all'interno di **`$HOME/Library/Containers`** con **`CFBundleIdentifier`** dell'app come nome della cartella.
|
||
>
|
||
> Tuttavia, entrambe le cartelle (cartelle dati e cartelle contenitore) hanno il file **`.com.apple.mobile_container_manager.metadata.plist`** che collega entrambi i file nella chiave `MCMetadataIdentifier`.
|
||
|
||
Per facilitare la scoperta della directory di installazione di un'app installata dall'utente, lo strumento **objection** fornisce un comando utile, `env`. Questo comando rivela informazioni dettagliate sulla directory per l'app in questione. Di seguito è riportato un esempio di come utilizzare questo comando:
|
||
```bash
|
||
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`:
|
||
```bash
|
||
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:
|
||
```bash
|
||
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.
|
||
- Tutte le 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 di iGoat-Swift (.app) all'interno della directory del pacchetto (`/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app`):
|
||
```bash
|
||
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`**:
|
||
```bash
|
||
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**
|
||
|
||
Verifica se c'è qualche output per:
|
||
```bash
|
||
otool -l <app-binary> | grep -A 4 LC_ENCRYPTION_INFO
|
||
```
|
||
**Disassemblare il binario**
|
||
|
||
Disassemblare la sezione di testo:
|
||
```bash
|
||
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:
|
||
```bash
|
||
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**](http://stevenygard.com/projects/class-dump/):
|
||
```bash
|
||
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**](https://www.hopperapp.com/download.html?) e [**IDA**](https://www.hex-rays.com/products/ida/support/download_freeware/).
|
||
|
||
## Archiviazione Dati
|
||
|
||
Per saperne di più su come iOS memorizza i dati nel dispositivo, leggi questa pagina:
|
||
|
||
{{#ref}}
|
||
ios-basics.md
|
||
{{#endref}}
|
||
|
||
> [!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 usciti 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.
|
||
|
||
### 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 averlo utilizzato intensamente 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`](https://developer.apple.com/documentation/foundation/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`** con il comando `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:
|
||
```bash
|
||
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:
|
||
```bash
|
||
$ plutil -convert xml1 Info.plist
|
||
```
|
||
**Per gli utenti Linux:** Installa prima `libplist-utils`, poi usa `plistutil` per convertire il tuo file:
|
||
```bash
|
||
$ 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 direttamente i file plist:
|
||
```bash
|
||
ios plist cat /private/var/mobile/Containers/Data/Application/<Application-UUID>/Library/Preferences/com.some.package.app.plist
|
||
```
|
||
### Core Data
|
||
|
||
[`Core Data`](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/nsfetchedresultscontroller.html#//apple_ref/doc/uid/TP40001075-CH8-SW1) è un framework per gestire il livello del modello degli oggetti nella tua applicazione. [Core Data può utilizzare SQLite come suo archivio persistente](https://cocoacasts.com/what-is-the-difference-between-core-data-and-sqlite/), 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](https://github.com/project-imas/encrypted-core-data) 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.**
|
||
```objectivec: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");
|
||
}
|
||
}
|
||
```
|
||
### YapDatabase
|
||
|
||
[YapDatabase](https://github.com/yapstudios/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}`)
|
||
```bash
|
||
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:
|
||
|
||
{{#ref}}
|
||
../../network-services-pentesting/pentesting-web/buckets/firebase-database.md
|
||
{{#endref}}
|
||
|
||
### Realm databases
|
||
|
||
[Realm Objective-C](https://realm.io/docs/objc/latest/) e [Realm Swift](https://realm.io/docs/swift/latest/) 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:
|
||
```bash
|
||
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**](https://github.com/realm/realm-studio).
|
||
|
||
Per implementare la crittografia all'interno di un database Realm, è possibile utilizzare il seguente frammento di codice:
|
||
```swift
|
||
// 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](https://github.com/couchbase/couchbase-lite-ios) è 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 problemi.
|
||
|
||
Per identificare potenziali database Couchbase su un dispositivo, la seguente directory dovrebbe essere ispezionata:
|
||
```bash
|
||
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**](https://github.com/mdegrazia/Safari-Binary-Cookie-Parser) o usare **`ios cookies get`** di objection.\
|
||
**Puoi anche usare objection per** convertire questi file in un formato JSON e ispezionare i dati.
|
||
```bash
|
||
...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`](https://developer.apple.com/documentation/foundation/urlcache/1417802-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](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1410529-ephemeral) di URLSession, che disabiliterà il salvataggio di cookie e cache.
|
||
|
||
[Documentazione Apple](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1410529-ephemeral):
|
||
|
||
`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](https://developer.apple.com/documentation/foundation/urlcache/storagepolicy/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 toccando due volte la 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 iOS 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:
|
||
```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. 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**](https://github.com/ptoomey3/Keychain-Dumper), adatti per dispositivi jailbroken. Inoltre, [**Objection**](https://github.com/sensepost/objection) fornisce il comando `ios keychain dump` per scopi simili.
|
||
|
||
#### **Storing Credentials**
|
||
|
||
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:
|
||
```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 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 nella cache.
|
||
- 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](https://developer.apple.com/reference/uikit/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:
|
||
```objectivec
|
||
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`.
|
||
```objectivec
|
||
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:
|
||
```bash
|
||
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:
|
||
```bash
|
||
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.
|
||
|
||
## 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à delle 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.
|
||
|
||
### Esclusione di 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 il `NSURLIsExcludedFromBackupKey`. Questa pratica è cruciale per proteggere i dati sensibili dall'essere inclusi nei backup.
|
||
|
||
### Testare le Vulnerabilità
|
||
|
||
Per valutare la sicurezza del backup di un'app, inizia con il **creare un backup** utilizzando Finder, quindi localizzalo seguendo le indicazioni della [documentazione ufficiale di Apple](https://support.apple.com/en-us/HT204215). 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](https://imazing.com). Per i backup crittografati, la presenza di crittografia può essere confermata controllando la chiave "IsEncrypted" nel file "Manifest.plist" alla radice del backup.
|
||
```xml
|
||
<?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](https://github.com/dinosec/iphone-dataprotection/tree/master/python_scripts), 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**](https://pypi.org/project/iOSbackup/) è un'altra opzione per accedere ai file all'interno dei backup protetti da password.
|
||
|
||
### Modificare il Comportamento dell'App
|
||
|
||
Un esempio di modifica del comportamento dell'app attraverso modifiche ai backup è dimostrato nell'[app Bither bitcoin wallet](https://github.com/bither/bither-ios), 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 rimuove il requisito del PIN, fornendo accesso illimitato.
|
||
|
||
## Riepilogo sul Test della 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 della memoria** e **analizzare la memoria in tempo reale**. Entrambi i metodi presentano le proprie sfide, inclusa la possibilità di perdere dati critici durante il processo di dump o analisi.
|
||
|
||
## **Recuperare e Analizzare un Dump della Memoria**
|
||
|
||
Per dispositivi jailbroken e non jailbroken, strumenti come [objection](https://github.com/sensepost/objection) e [Fridump](https://github.com/Nightbringer21/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 della memoria, possono essere utilizzati comandi come `strings` o `rabin2 -zz`:
|
||
```bash
|
||
# 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:
|
||
```bash
|
||
$ 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:
|
||
```bash
|
||
$ r2 frida://usb//<name_of_your_app>
|
||
[0x00000000]> /\ <search_command>
|
||
```
|
||
## Broken Cryptography
|
||
|
||
### Poor Key Management Processes
|
||
|
||
Alcuni sviluppatori salvano dati sensibili nello storage locale e li crittografano con una chiave hardcoded/predicibile nel codice. Questo non dovrebbe essere fatto poiché alcune operazioni di reverse engineering potrebbero consentire agli attaccanti di estrarre le informazioni riservate.
|
||
|
||
### Use of Insecure and/or Deprecated Algorithms
|
||
|
||
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 i **hash** vengono utilizzati per memorizzare le password, ad esempio, dovrebbero essere utilizzati hash resistenti al brute-force con sale.
|
||
|
||
### Check
|
||
|
||
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:
|
||
```swift
|
||
ios monitor crypt
|
||
```
|
||
Per **maggiori informazioni** sulle API e le librerie crittografiche iOS, accedi a [https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06e-testing-cryptography](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**](https://developer.apple.com/documentation/localauthentication) di Apple e il [**keychain**](https://developer.apple.com/library/content/documentation/Security/Conceptual/keychainServConcepts/01introduction/introduction.html) 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](https://www.raywenderlich.com/147308/secure-ios-user-data-keychain-touch-id) semplificano l'accesso al keychain.
|
||
|
||
> [!CAUTION]
|
||
> Tuttavia, sia `LocalAuthentication.framework` che `Security.framework` presentano vulnerabilità, poiché restituiscono principalmente valori booleani senza trasmettere dati per i processi di autenticazione, rendendoli suscettibili a bypass (fare riferimento a [Don't touch me that way, di David Lindner et al](https://www.youtube.com/watch?v=XhXIHVGCFFM)).
|
||
|
||
### 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 i 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 name="Swift"}}
|
||
```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 name="Objective-C"}}
|
||
```objectivec
|
||
// 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 autenticazione all'utente e restituiranno i dati o nil a seconda che sia stata fornita o meno un'impronta digitale adeguata.
|
||
|
||
{{#tabs}}
|
||
{{#tab name="Swift"}}
|
||
```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 name="Objective-C"}}
|
||
```objectivec
|
||
// 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`:
|
||
```bash
|
||
$ 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):
|
||
```bash
|
||
/System/Library/Frameworks/LocalAuthentication.framework/LocalAuthentication
|
||
/System/Library/Frameworks/Security.framework/Security
|
||
```
|
||
Se viene utilizzato `Security.framework`, solo il secondo verrà mostrato.
|
||
|
||
### Bypass del Framework di Autenticazione Locale
|
||
|
||
#### **Objection**
|
||
|
||
Attraverso il **Bypass Biometrics di Objection**, situato a [questa pagina di GitHub](https://github.com/sensepost/objection/wiki/Understanding-the-iOS-Biometrics-Bypass), è disponibile una tecnica per superare il meccanismo di **LocalAuthentication**. Il nucleo di questo approccio implica l'uso di **Frida** per manipolare la funzione `evaluatePolicy`, assicurando 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:
|
||
```bash
|
||
...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](https://github.com/prateek147/DVIA-v2):
|
||
```swift
|
||
+(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**. Alterando il comportamento del callback, il controllo di autenticazione viene effettivamente bypassato.
|
||
|
||
Lo script sottostante viene iniettato per modificare il risultato del metodo **evaluatePolicy**. Cambia il risultato del callback per indicare sempre il successo.
|
||
```swift
|
||
// 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:
|
||
```bash
|
||
frida -U -f com.highaltitudehacks.DVIAswiftv2 --no-pause -l fingerprint-bypass-ios.js
|
||
```
|
||
## Esposizione di Funzionalità Sensibili Tramite IPC
|
||
|
||
### Gestori URI Personalizzati / Deeplinks / Schemi Personalizzati
|
||
|
||
{{#ref}}
|
||
ios-custom-uri-handlers-deeplinks-custom-schemes.md
|
||
{{#endref}}
|
||
|
||
### Link Universali
|
||
|
||
{{#ref}}
|
||
ios-universal-links.md
|
||
{{#endref}}
|
||
|
||
### Condivisione UIActivity
|
||
|
||
{{#ref}}
|
||
ios-uiactivity-sharing.md
|
||
{{#endref}}
|
||
|
||
### UIPasteboard
|
||
|
||
{{#ref}}
|
||
ios-uipasteboard.md
|
||
{{#endref}}
|
||
|
||
### Estensioni dell'App
|
||
|
||
{{#ref}}
|
||
ios-app-extensions.md
|
||
{{#endref}}
|
||
|
||
### WebViews
|
||
|
||
{{#ref}}
|
||
ios-webviews.md
|
||
{{#endref}}
|
||
|
||
### Serializzazione e Codifica
|
||
|
||
{{#ref}}
|
||
ios-serialisation-and-encoding.md
|
||
{{#endref}}
|
||
|
||
## 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**:
|
||
|
||
{{#ref}}
|
||
burp-configuration-for-ios.md
|
||
{{#endref}}
|
||
|
||
### 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 funziona ancora, 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**](https://github.com/nabla-c0d3/ssl-kill-switch2) o installare [**Burp Mobile Assistant**](https://portswigger.net/burp/documentation/desktop/mobile/config-ios-device)
|
||
|
||
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 ripresentare l'applicazione all'App Store e aspettare che venga approvata.\
|
||
A questo scopo si utilizza solitamente [**JSPatch**](https://github.com/bang590/JSPatch)**.** Ma ci sono anche altre opzioni come [Siren](https://github.com/ArtSabintsev/Siren) e [react-native-appstore-version-checker](https://www.npmjs.com/package/react-native-appstore-version-checker).\
|
||
**Questo è un meccanismo pericoloso che potrebbe essere abusato da SDK di terze parti malevoli, pertanto è 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 funzionalità, 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.
|
||
```bash
|
||
otool -L <application_path>
|
||
```
|
||
## **Riferimenti e Altre Risorse**
|
||
|
||
- [https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06b-basic-security-testing#information-gathering](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06b-basic-security-testing#information-gathering)
|
||
- [iOS & Mobile App Pentesting - INE](https://my.ine.com/CyberSecurity/courses/089d060b/ios-mobile-app-pentesting)
|
||
- [https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0057/](https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0057/)
|
||
- [https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0058/](https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0058/)
|
||
- [https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0059/](https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0059/)
|
||
- [https://mas.owasp.org/MASTG/iOS/0x06d-Testing-Data-Storage](https://mas.owasp.org/MASTG/iOS/0x06d-Testing-Data-Storage)
|
||
- [https://coderwall.com/p/kjb3lw/storing-password-in-keychain-the-smart-way](https://coderwall.com/p/kjb3lw/storing-password-in-keychain-the-smart-way)
|
||
- [https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0055/](https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0055/)
|
||
- [https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0053](https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0053)
|
||
- [https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0060/](https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0060/)
|
||
- [https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0058](https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0058)
|
||
- [https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0060](https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0060)
|
||
- [https://mas.owasp.org/MASTG/Android/0x05f-Testing-Local-Authentication/](https://mas.owasp.org/MASTG/Android/0x05f-Testing-Local-Authentication/)
|
||
- [https://mas.owasp.org/MASTG/tests/ios/MASVS-AUTH/MASTG-TEST-0064](https://mas.owasp.org/MASTG/tests/ios/MASVS-AUTH/MASTG-TEST-0064)
|
||
- [https://medium.com/securing/bypassing-your-apps-biometric-checks-on-ios-c2555c81a2dc](https://medium.com/securing/bypassing-your-apps-biometric-checks-on-ios-c2555c81a2dc)
|
||
- [https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0054](https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0054)
|
||
- [https://github.com/ivRodriguezCA/RE-iOS-Apps/](https://github.com/ivRodriguezCA/RE-iOS-Apps/) Corso gratuito IOS([https://syrion.me/blog/ios-swift-antijailbreak-bypass-frida/](https://syrion.me/blog/ios-swift-antijailbreak-bypass-frida/))
|
||
- [https://www.sans.org/reading-room/whitepapers/testing/ipwn-apps-pentesting-ios-applications-34577](https://www.sans.org/reading-room/whitepapers/testing/ipwn-apps-pentesting-ios-applications-34577)
|
||
- [https://www.slideshare.net/RyanISI/ios-appsecurityminicourse](https://www.slideshare.net/RyanISI/ios-appsecurityminicourse)
|
||
- [https://github.com/prateek147/DVIA](https://github.com/prateek147/DVIA)
|
||
- [https://github.com/prateek147/DVIA-v2](https://github.com/prateek147/DVIA-v2)
|
||
- [https://github.com/OWASP/MSTG-Hacking-Playground%20](https://github.com/OWASP/MSTG-Hacking-Playground)
|
||
- OWASP iGoat [_https://github.com/OWASP/igoat_](https://github.com/OWASP/igoat) <<< Versione Objective-C [_https://github.com/OWASP/iGoat-Swift_](https://github.com/OWASP/iGoat-Swift) <<< Versione Swift
|
||
- [https://github.com/authenticationfailure/WheresMyBrowser.iOS](https://github.com/authenticationfailure/WheresMyBrowser.iOS)
|
||
- [https://github.com/nabla-c0d3/ssl-kill-switch2](https://github.com/nabla-c0d3/ssl-kill-switch2)
|
||
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|