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.
Bases iOS
Environnement de test
Sur cette page, vous trouverez des informations sur le iOS simulator, emulators et jailbreaking :
Analyse initiale
Opérations de test iOS de base
Pendant les tests, plusieurs opérations vont être suggérées (se connecter à l’appareil, lire/écrire/upload/download des fichiers, utiliser certains 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 vous devez déjà avoir obtenu le IPA file de l’application.
Read the Basic iOS Testing Operations page to learn how to do this.
Analyse statique de base
Quelques décompilateurs intéressants pour iOS - fichiers IPA :
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) : Lorsque 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 ‘canary’ est placée sur la pile avant l’appel d’une fonction et est vérifiée à nouveau une fois la fonction terminée.
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 corruptions mémoire courantes
otool -I -v <app-binary> | grep objc_release # It should include the _objc_release symbol
- Encrypted Binary : Le binaire devrait être chiffré
otool -arch all -Vl <app-binary> | grep -A5 LC_ENCRYPT # The cryptid should be 1
Identification des fonctions sensibles/insécurisées
- 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"
Méthodes courantes de détection de jailbreak
- File System Checks : Rechercher la présence de fichiers et répertoires classiques de jailbreak, tels que
/Applications/Cydia.appou/Library/MobileSubstrate/MobileSubstrate.dylib. - Sandbox Violations : Tenter d’accéder à des zones restreintes du système de fichiers, qui devraient être bloquées sur des 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 ousystem()pour voir si /bin/sh existe. - Process Checks : Surveiller la présence de processus connus liés au jailbreak, tels que
Cydia,Substrate, oussh. - Kernel Exploits : Vérifier la présence d’exploits 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 process de l’app.
- Check schemes : Comme
canOpenURL(URL(string: "cydia://")).
Méthodes courantes de détection Anti-Debugging
- Check for Debugger Presence : Utiliser
sysctlou d’autres méthodes pour vérifier si un Debugger est attaché. - Anti-Debugging APIs : Rechercher des appels à des API anti-debugging comme
ptraceouSIGSTOPcommeptrace(PT_DENY_ATTACH, 0, 0, 0). - Timing Checks : Mesurer le temps nécessaire pour certaines opérations et rechercher des écarts pouvant indiquer un debugging.
- Memory Checks : Inspecter la mémoire pour des artefacts ou modifications connus des Debuggers.
- Environment Variables : Vérifier les variables d’environnement qui peuvent indiquer une session de debugging.
- Mach Ports : Détecter si des mach exception ports sont utilisés par des Debuggers.
Analyse dynamique de base
Consultez l’analyse dynamique que MobSF effectue. Vous devrez naviguer entre les différentes vues et interagir avec elles ; cependant, il effectuera du hooking de plusieurs classes tout en faisant d’autres choses et préparera un rapport une fois terminé.
Lister les apps installées
Utilisez la commande frida-ps -Uai pour déterminer le bundle identifier des apps installées :
$ 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 hooker les méthodes et classes facilement avec objection:
Structure de l’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 en révéler le contenu. Dans cette structure, un Bundle représente une application entièrement packagé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, assurant l’intégrité de tous les fichiers du bundle.Assets.car: Une archive compressée qui stocke des fichiers d’assets comme des icônes.Frameworks/: Ce dossier contient les bibliothèques natives de l’application, qui peuvent être au format.dylibou.framework.PlugIns/: Cela peut inclure des extensions de l’application, connues sous le nom 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, pour mettre en cache les données temporaires, et pour ajouter la fonctionnalité d’annulation à votre app sur un seul appareil. Pour synchroniser des données entre plusieurs appareils sur un même compte iCloud, Core Data réplique automatiquement votre schéma dans un conteneur CloudKit.PkgInfo: Le fichierPkgInfoest une manière alternative de spécifier les codes de type et de créateur de votre application ou bundle.- en.lproj, fr.proj, Base.lproj: 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, crucial pour optimiser les performances de l’application et réduire sa taille totale. - 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 linguistiques spécifiques.
Info.plist
Le fichier Info.plist sert de pierre angulaire pour les applications iOS, encapsulant les données de configuration clés sous forme de paires key-value. Ce fichier est requis non seulement pour les applications mais aussi pour les extensions d’app et les frameworks inclus. Il est structuré soit en XML soit en format binaire et contient des informations critiques allant des permissions de l’app 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 à l’aide de plutil sur macOS (disponible nativement sur les versions 10.2 et ultérieures) ou plistutil sur Linux. Les commandes pour la 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 multitude d’informations que le fichier Info.plist peut divulguer, on trouve notamment des chaînes de permission d’application (UsageDescription), des schémas d’URL personnalisés (CFBundleURLTypes) et des 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 localisées en inspectant le fichier ou en utilisant une simple commande grep :
$ grep -i <keyword> Info.plist
Chemins de données
Dans l’environnement iOS, les répertoires sont spécifiquement destinés aux applications système et aux applications installées par l’utilisateur. Les applications système résident dans le répertoire /Applications, tandis que les applications installées par l’utilisateur sont placées sous /var/mobile/containers/Data/Application/. Ces applications se voient attribuer un identifiant unique connu sous le nom de 128-bit UUID, ce qui rend la tâche de localisation manuelle du dossier d’une application difficile en raison de l’aléa des noms de répertoires.
Warning
Comme les applications sur iOS doivent être sandboxées, chaque application aura également un dossier dans
$HOME/Library/Containersportant comme nom de dossier l’CFBundleIdentifierde l’application.Cependant, les deux dossiers (dossiers de données et de conteneurs) possèdent le fichier
.com.apple.mobile_container_manager.metadata.plistqui relie les deux fichiers dans la cléMCMetadataIdentifier).
Pour faciliter la découverte du répertoire d’installation d’une application 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’application concernée. Voici un exemple d’utilisation de 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épertoires actifs de l’application :
ps -ef | grep -i <app-name>
lsof -p <pid> | grep -i "/containers" | head -n 1
Bundle directory:
- AppName.app
- Ceci est le bundle de l’application tel que 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 y écrire.
- Le contenu de ce répertoire n’est pas sauvegardé.
- Le contenu de ce dossier est utilisé pour valider la signature du code.
Data directory:
- 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 y écrire.
- Le contenu de ce répertoire est sauvegardé.
- L’app peut exclure des chemins en définissant
NSURLIsExcludedFromBackupKey. - Library/
- Contient tous les fichiers qui ne sont pas spécifiques à l’utilisateur, tels que les caches, préférences, cookies, et fichiers de configuration property list (plist).
- Les apps iOS utilisent généralement les sous-répertoires
Application SupportetCaches, mais l’application peut créer des sous-répertoires personnalisés. - Library/Caches/
- Contient des fichiers de cache semi-persistants.
- Invisible pour les utilisateurs et les utilisateurs ne peuvent pas y écrire.
- Le contenu de ce répertoire n’est pas sauvegardé.
- Le système d’exploitation 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 les fichiers persistants nécessaires au fonctionnement de l’application.
- Invisible pour les utilisateurs et les utilisateurs ne peuvent pas y écrire.
- Le contenu de ce répertoire est sauvegardé.
- L’app peut exclure 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.
- Les informations sont enregistrées, non chiffrées, à 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’application.
- Contient des fichiers de cache non persistants.
- Invisible pour les utilisateurs.
- Le contenu de ce répertoire n’est pas sauvegardé.
- Le système d’exploitation peut supprimer automatiquement les fichiers de ce répertoire lorsque l’application n’est pas en cours d’exécution et que l’espace de stockage est faible.
Examinons de plus près le répertoire bundle de l’application (.app) d’iGoat-Swift à l’intérieur du Bundle directory (/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app):
OWASP.iGoat-Swift on (iPhone: 11.1.2) [usb] # ls
NSFileType Perms NSFileProtection ... Name
------------ ------- ------------------ ... --------------------------------------
Regular 420 None ... rutger.html
Regular 420 None ... mansi.html
Regular 420 None ... splash.html
Regular 420 None ... about.html
Regular 420 None ... LICENSE.txt
Regular 420 None ... Sentinel.txt
Regular 420 None ... README.txt
Analyse binaire
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érifier si l’application 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 imprimer le segment Objective-C de l’application 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.
Stockage des données
To learn about how iOS stores data in the device read this 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 s’être connecté avec un autre.
L’objectif est de trouver 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. It’s a way to store persistent data, so sometimes you may find sensitive information in these files. It’s recommended to check these files after installing the app and after using intensively it to see if new data is written.
La façon la plus courante de persister des données dans des fichiers plist est l’utilisation de NSUserDefaults. Ce fichier plist est enregistré dans le sandbox de l’app dans 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 préférences utilisateur. Data saved by NSUserDefaults can be viewed in the application bundle. Cette classe stocke des données dans un fichier plist, mais elle est conçue pour être utilisée avec de petites quantités de données.
Ces données ne peuvent plus être consultées directement via un ordinateur de confiance, mais sont accessibles en effectuant une backup.
Vous pouvez dump les informations enregistrées via NSUserDefaults en utilisant objection’s ios nsuserdefaults get
Pour trouver tous les plist utilisés par l’application vous pouvez accéder à /private/var/mobile/Containers/Data/Application/{APPID} et exécuter :
find ./ -name "*.plist"
Pour convertir des fichiers au format XML ou binaire (bplist) en XML, plusieurs méthodes sont disponibles selon votre système d’exploitation :
Pour les utilisateurs macOS : Utilisez la commande plutil. C’est un outil intégré à macOS (10.2+), conçu à cet effet :
$ 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
Dans une 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 ne chiffre 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 clé/valeur construit sur SQLite.
Comme les bases YapDatabase sont des bases SQLite, vous pouvez les trouver en utilisant la commande fournie dans la section précédente.
Autres bases de données SQLite
Il est courant que les applications créent leur propre base de données SQLite. Elles peuvent y stocker des données sensibles et les laisser non chiffrées. Il est donc toujours intéressant de vérifier chaque base de données dans le répertoire de l’application. Allez dans le répertoire de l’application où les données sont sauvegardé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 avec tous les clients connectés en temps réel.
Vous pouvez trouver comment vérifier les bases de données Firebase mal configurées ici :
Bases de données Realm
Realm Objective-C et Realm Swift offrent une alternative puissante pour le stockage de données, non fournie par Apple. Par défaut, elles stockent les données sans chiffrement, le chiffrement étant disponible via une configuration spécifique.
Les bases de données se trouvent à : /private/var/mobile/Containers/Data/Application/{APPID}. Pour explorer ces fichiers, on peut utiliser des commandes telles que :
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, l’extrait 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 l’approche orientée document (NoSQL). Conçu pour être natif sur iOS et macOS, il offre la capacité de synchroniser les données de manière 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 accédé dans les sauvegardes.
Pour inspecter le fichier de cookies, vous pouvez utiliser ce script Python ou utiliser la commande ios cookies get d’objection.
Vous pouvez aussi utiliser objection pour convertir ces fichiers au format JSON et inspecter 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 requêtes et réponses HTTP dans le 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 est également stocké dans le fichier Cache.db. Objection peut ouvrir et interagir avec la base de données avec la commande sqlite connect Cache.db, as it is a 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 le logout. Cela peut être fait avec la méthode fournie par Apple appelée
removeAllCachedResponses. Vous 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 l’avantage des cookies, il est recommandé d’utiliser simplement 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 aussi être désactivé en réglant la Cache Policy sur .notAllowed. Cela désactivera le stockage du Cache de toute manière, que ce soit en mémoire ou sur disque.
Snapshots
Chaque fois que vous appuyez sur le bouton Home, iOS prend un snapshot de l’écran courant pour permettre une transition beaucoup plus fluide vers l’application. Cependant, si des données sensibles sont présentes à l’écran, elles seront enregistrées dans l’image (qui persiste à travers les reboots). Ce sont les snapshots auxquels vous pouvez aussi accéder en double-tapant le bouton Home pour passer d’une app à l’autre.
À moins que l’iPhone ne soit jailbroken, l’attaquant doit avoir accès au device déverrouillé pour voir ces captures d’écran. Par défaut, le dernier snapshot est stocké dans le sandbox de l’application dans le dossier 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 mauvais comportement est d’afficher un écran vierge ou de retirer les données sensibles avant la prise du snapshot en utilisant la fonction ApplicationDidEnterBackground().
Ce qui suit est une méthode d’atténuation exemple qui définira une capture d’écran par défaut.
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];
}
Cela définit l’image de fond sur overlayImage.png chaque fois que l’application passe 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 le keychain iOS, 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 la nécessité d’utiliser 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, gérables via Réglages > Général > Clavier > Claviers. Bien que ces claviers offrent des fonctionnalités étendues, ils présentent un risque de keystroke logging et d’envoi de données vers des serveurs externes, bien que les utilisateurs soient avertis lorsque les claviers requièrent 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é.
- Soyez conscient des fonctions d’autocorrection et de suggestions automatiques du clavier iOS par défaut, qui pourraient 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 y détecter des données sensibles. Il est recommandé de réinitialiser le dictionnaire du clavier via Réglages > Général > Réinitialiser > Réinitialiser le dictionnaire du clavier 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évention de la mise en cache des champs de texte
Le UITextInputTraits protocol offre des propriétés pour gérer l’autocorrection et la saisie sécurisée, essentielles pour empêcher la mise en cache d’informations sensibles. Par exemple, désactiver l’autocorrection 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 à saisir des informations sensibles comme les mots de passe et les codes PIN, désactivent la mise en cache en positionnant 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, posant un risque de leak de données sensibles. Désormais, les applications sont limitées à l’accès uniquement à leurs logs.
Malgré ces restrictions, un attaquant disposant d’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é d’interagir soigneusement avec l’app, en explorant toutes ses fonctionnalités et entrées pour s’assurer qu’aucune information sensible n’est enregistrée dans les logs par inadvertance.
Lors de la revue du code source de l’app pour d’éventuels leaks, recherchez à la fois des instructions de logging prédefinies et personnalisées 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 des implémentations personnalisées.
Monitoring System Logs
Les apps enregistrent diverses informations pouvant ê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 fournit un moyen de collecter les logs de la console :
- Ouvrez Xcode.
- Connectez l’appareil iOS.
- Accédez à Window -> Devices and Simulators.
- Sélectionnez votre appareil.
- Reproduisez le problème que vous analysez.
- Utilisez le bouton Open 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 de log, ce qui peut être inestimable pour diagnostiquer des problèmes ou identifier une éventuelle data leakage dans les logs.
Sauvegardes
Fonctionnalités d’auto-sauvegarde sont intégrées dans 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 englobent 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 question d’une éventuelle data leakage 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 texte clair dans le répertoire d’une app ou ses sous-répertoires pour atténuer ces risques.
Exclure des 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 dossiers 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 avec 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 qui pourraient être modifiées pour affecter le comportement de l’app.
On peut rechercher des informations sensibles à 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 backups chiffrés, des scripts Python disponibles dans le repo GitHub de DinoSec (https://github.com/dinosec/iphone-dataprotection/tree/master/python_scripts), comme backup_tool.py et backup_passwd.py, peuvent être utiles, bien qu’ils puissent nécessiter des ajustements pour la compatibilité avec les dernières versions d’iTunes/Finder. L’outil iOSbackup est une autre option pour accéder aux fichiers contenus dans des backups protégés par mot de passe.
Modifier le comportement de l’application
Un exemple d’altération du comportement d’une app via des modifications du backup est démontré dans le 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 le backup supprime l’exigence du PIN, donnant un accès sans restriction.
Résumé sur le test de la 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 : la création d’un dump mémoire et l’analyse de la mémoire en temps réel. Les deux méthodes présentent des défis, y compris le risque de manquer des données critiques pendant le processus de dump ou l’analyse.
Récupération et analyse d’un dump mémoire
Pour les appareils jailbroken et non-jailbroken, des outils comme objection et Fridump permettent de dumper la mémoire du processus d’une app. Une fois la mémoire dumpée, l’analyse de ces données nécessite divers outils, en fonction de la nature des informations recherchées.
Pour extraire des strings d’un dump mémoire, des commandes comme 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 approfondie, 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 l’exécution de 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>
Broken Cryptography
Poor Key Management Processes
Certains développeurs enregistrent des données sensibles dans le stockage local et les chiffrent avec une clé hardcoded/prévisible dans le code. Cela ne devrait pas être fait car du reversing peut permettre à des attaquants d’extraire les informations confidentielles.
Use of Insecure and/or Deprecated Algorithms
Les développeurs ne devraient pas utiliser des algorithmes dépréciés pour effectuer des vérifications 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, ils doivent être résistants au brute-force et accompagnés d’un salt.
Check
Les principales vérifications à effectuer sont de rechercher si vous pouvez trouver des mots de passe/secrets hardcoded dans le code, s’ils sont prévisibles, et si le code utilise un type d’algorithmes faibles de cryptography.
Il est intéressant de savoir que vous pouvez surveiller certaines crypto libraries automatiquement en utilisant objection avec:
ios monitor crypt
Pour 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
L’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 implémentation correcte, les mécanismes d’authentification locale peuvent être contournés.
Le Local Authentication framework d’Apple et le keychain fournissent respectivement des API robustes permettant aux développeurs d’afficher des dialogues d’authentification utilisateur et de gérer de manière sécurisée des données secrètes. 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 keychain, sécurisant les données secrètes avec une authentification biométrique. Plusieurs wrappers open-source rendent l’accès au keychain plus simple.
Caution
Cependant, les deux
LocalAuthentication.frameworketSecurity.frameworkprésentent des vulnérabilités, car elles renvoient principalement des valeurs booléennes sans transmettre de données pour les processus d’authentification, ce qui les rend susceptibles d’être contournées (voir Don’t touch me that way, by David Lindner et al).
Implémentation de l’authentification locale
Pour inviter l’utilisateur à s’authentifier, les développeurs doivent utiliser la méthode evaluatePolicy de la classe LAContext, en choisissant entre :
deviceOwnerAuthentication: invite à utiliser Touch ID ou le code d’accès de l’appareil, échoue si aucun n’est activé.deviceOwnerAuthenticationWithBiometrics: invite exclusivement à utiliser Touch ID.
Une authentification réussie est indiquée par une valeur booléenne retourné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 keychain APIs 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 le code d’accès de l’appareil 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 tant que l’utilisateur ne s’est pas authentifié avec succès via Touch ID ou le code d’accès de l’appareil. Cette fonctionnalité est cruciale pour renforcer la sécurité.
Vous trouverez ci-dessous des exemples de code en Swift et Objective-C montrant comment sauvegarder et récupérer une chaîne vers/depuis le keychain, en tirant parti de ces fonctionnalités de sécurité. Les exemples montrent précisément comment configurer le contrôle d’accès pour exiger l’authentification Touch ID et s’assurer que les données ne sont accessibles que sur l’appareil où elles ont été configurées, à condition qu’un code d’accès de l’appareil soit défini.
// 1. create AccessControl object that will represent authentication settings
var error: Unmanaged
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
}
Nous pouvons maintenant récupérer l’élément enregistré depuis le keychain. Les services Keychain afficheront la boîte de dialogue d’authentification à l’utilisateur et renverront data or nil selon qu’une fingerprint appropriée ait été fournie 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’application. Cela peut être fait en utilisant otool:
$ otool -L <AppName>.app/<AppName>
Si LocalAuthentication.framework est utilisé dans une app, 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
Si Security.framework est utilisé, seul le second sera affiché.
Local Authentication Framework Bypass
Objection
Grâce à Objection Biometrics Bypass, disponible sur cette page GitHub, une technique permet de contourner le mécanisme LocalAuthentication.
Le cœur de cette approche consiste à utiliser Frida pour manipuler la fonction evaluatePolicy, en veillant à ce 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, la commande suivante est utilisée :
...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 du contrôle evaluatePolicy en 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 effectuer le bypass de Local Authentication, un script Frida est écrit. Ce script cible la vérification evaluatePolicy, en interceptant son callback pour s’assurer qu’il renvoie success=1. En modifiant le comportement du callback, on permet le bypass de la vérification d’authentification.
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 le succès.
// 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
Communication réseau
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 :
Vérification du nom d’hôte
Un problème fréquent lors de la validation du certificat TLS est de vérifier que le certificat a été signé par une CA de confiance, mais de ne pas vérifier si le nom d’hôte du certificat correspond bien au nom d’hôte auquel on accède.
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 nom d’hôte différent et l’utiliser. Si l’application fonctionne toujours, alors l’application est vulnérable.
Certificate Pinning
Si une application utilise correctement le SSL Pinning, l’application ne fonctionnera que si le certificat est bien celui attendu. Lors du test d’une application, cela peut poser problème car Burp présentera son propre certificat.
Pour contourner cette protection sur un appareil jailbroken, vous pouvez installer l’application SSL Kill Switch ou installer Burp Mobile Assistant
Vous pouvez aussi utiliser objection’s ios sslpinning disable
Divers
- In
/System/Libraryyou can find the frameworks installed in the phone used by system applications - The applications installed by the user from the App Store are located inside
/User/Applications - And the
/User/Librarycontains data saved by the user level applications - You can access
/User/Library/Notes/notes.sqliteto read the notes saved inside the application. - Inside the folder of an installed application (
/User/Applications/<APP ID>/) you can find some interesting files: iTunesArtwork: The icon used by the appiTunesMetadata.plist: Info of the app used in the App Store/Library/*: Contains the preferences and cache. In/Library/Cache/Snapshots/*you can find the snapshot performed to the application before sending it to the background.
Hot Patching/Enforced Updateing
Les développeurs peuvent patcher à distance toutes les installations de leur app instantanément sans avoir à resoumettre 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 la mise à jour automatique (si elle existe) et de la tester. Vous pouvez essayer de télécharger une version précédente de l’app pour cela.
Third Parties
Un défi majeur avec les SDK tiers est le manque de contrôle granulaire sur leurs fonctionnalités. Les développeurs sont confrontés à un choix : 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 à ses bénéfices. Souvent, les développeurs ne peuvent pas corriger les vulnérabilités présentes dans ces SDK. De plus, à mesure que des SDK gagnent la confiance de la communauté, certains peuvent commencer à contenir des 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 puisque les développeurs ne connaissent pas toujours entièrement le code exécuté par ces bibliothèques, ce qui peut entraîner 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 des services tiers se fait généralement sous forme de bibliothèque autonome ou de SDK complet. Pour protéger la vie privée des utilisateurs, les données partagées avec ces services doivent être anonymisées afin d’éviter la divulgation d’informations personnelles identifiables (PII).
Pour identifier les bibliothèques utilisées par une application, la commande otool peut être employée. Cet outil doit être exécuté contre l’application et chaque librairie partagée utilisée pour découvrir des bibliothèques additionnelles.
otool -L <application_path>
Vulnérabilités intéressantes & études de cas
Air Keyboard Remote Input Injection
Itunesstored Bookassetd Sandbox Escape
Références & Ressources supplémentaires
- 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/ IOS cours 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.
HackTricks

