hacktricks/mobile-pentesting/ios-pentesting
2024-02-09 08:11:01 +00:00
..
basic-ios-testing-operations.md Translated ['forensics/basic-forensic-methodology/README.md', 'forensics 2024-02-09 01:31:34 +00:00
burp-configuration-for-ios.md Translated ['forensics/basic-forensic-methodology/README.md', 'forensics 2024-02-09 01:31:34 +00:00
extracting-entitlements-from-compiled-application.md Translated ['forensics/basic-forensic-methodology/README.md', 'forensics 2024-02-09 01:31:34 +00:00
frida-configuration-in-ios.md Translated ['forensics/basic-forensic-methodology/README.md', 'forensics 2024-02-09 01:31:34 +00:00
ios-app-extensions.md Translated ['forensics/basic-forensic-methodology/README.md', 'forensics 2024-02-09 01:31:34 +00:00
ios-basics.md Translated ['forensics/basic-forensic-methodology/README.md', 'forensics 2024-02-09 01:31:34 +00:00
ios-custom-uri-handlers-deeplinks-custom-schemes.md Translated ['forensics/basic-forensic-methodology/README.md', 'forensics 2024-02-09 01:31:34 +00:00
ios-hooking-with-objection.md Translated ['forensics/basic-forensic-methodology/README.md', 'forensics 2024-02-09 01:31:34 +00:00
ios-protocol-handlers.md Translated ['mobile-pentesting/ios-pentesting/ios-protocol-handlers.md', 2024-02-09 08:11:01 +00:00
ios-serialisation-and-encoding.md Translated ['mobile-pentesting/android-app-pentesting/README.md', 'mobil 2024-02-08 04:38:25 +00:00
ios-testing-environment.md Translated ['mobile-pentesting/android-app-pentesting/README.md', 'mobil 2024-02-08 04:38:25 +00:00
ios-uiactivity-sharing.md Translated ['mobile-pentesting/android-app-pentesting/README.md', 'mobil 2024-02-08 04:38:25 +00:00
ios-uipasteboard.md Translated ['mobile-pentesting/android-app-pentesting/README.md', 'mobil 2024-02-08 04:38:25 +00:00
ios-universal-links.md Translated ['mobile-pentesting/android-app-pentesting/README.md', 'mobil 2024-02-08 04:38:25 +00:00
ios-webviews.md Translated ['mobile-pentesting/android-app-pentesting/README.md', 'mobil 2024-02-08 04:38:25 +00:00
README.md Translated ['mobile-pentesting/android-app-pentesting/README.md', 'mobil 2024-02-08 04:38:25 +00:00

iOS Pentesting


Utilisez Trickest pour construire facilement et automatiser des flux de travail alimentés par les outils communautaires les plus avancés au monde.
Accédez dès aujourd'hui à :

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

Apprenez le piratage AWS de zéro à héros avec htARTE (Expert de l'équipe rouge HackTricks AWS)!

Autres façons de soutenir HackTricks :

Bases d'iOS

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

Environnement de test

Sur cette page, vous trouverez des informations sur le simulateur iOS, les émulateurs et le jailbreak :

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

Analyse initiale

Opérations de test iOS de base

Pendant le test, plusieurs opérations seront suggérées (connexion à l'appareil, lecture/écriture/téléchargement de fichiers, utilisation de certains outils...). Par conséquent, si vous ne savez pas comment effectuer l'une de ces actions, veuillez commencer par lire la page :

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

{% hint style="info" %} Pour les étapes suivantes, l'application doit être installée sur l'appareil et vous devez déjà avoir obtenu le fichier IPA de l'application.
Consultez la page Opérations de test iOS de base pour apprendre comment faire cela. {% endhint %}

Analyse statique de base

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 (Executable Position Independent) : Lorsqu'il est activé, l'application se charge à une adresse mémoire aléatoire à chaque lancement, ce qui rend plus difficile de prédire son adresse mémoire initiale.
otool -hv <app-binary> | grep PIE   # Il devrait inclure le drapeau PIE
  • Canaries de pile : Pour valider l'intégrité de la pile, une valeur de « canary » est placée sur la pile avant d'appeler une fonction et est validée à nouveau une fois que la fonction se termine.
otool -I -v <app-binary> | grep stack_chk   # Il devrait inclure les symboles : stack_chk_guard et stack_chk_fail
  • ARC (Comptage automatique des références) : Pour prévenir les défauts courants de corruption de mémoire
otool -I -v <app-binary> | grep objc_release   # Il devrait inclure le symbole _objc_release
  • Binaire chiffré : Le binaire devrait être chiffré
otool -arch all -Vl <app-binary> | grep -A5 LC_ENCRYPT   # Le cryptid devrait être 1

Identification des fonctions sensibles/non sécurisées

  • Algorithmes de hachage faibles
# Sur l'appareil iOS
otool -Iv <app> | grep -w "_CC_MD5"
otool -Iv <app> | grep -w "_CC_SHA1"

# Sur Linux
grep -iER "_CC_MD5"
grep -iER "_CC_SHA1"
  • Fonctions de génération aléatoire non sécurisées
# Sur l'appareil iOS
otool -Iv <app> | grep -w "_random"
otool -Iv <app> | grep -w "_srand"
otool -Iv <app> | grep -w "_rand"

# Sur Linux
grep -iER "_random"
grep -iER "_srand"
grep -iER "_rand"
  • Fonction 'Malloc' non sécurisée
# Sur l'appareil iOS
otool -Iv <app> | grep -w "_malloc"

# Sur Linux
grep -iER "_malloc"
  • Fonctions non sécurisées et vulnérables
# Sur l'appareil iOS
otool -Iv <app> | grep -w "_gets"
otool -Iv <app> | grep -w "_memcpy"
otool -Iv <app> | grep -w "_strncpy"
otool -Iv <app> | grep -w "_strlen"
otool -Iv <app> | grep -w "_vsnprintf"
otool -Iv <app> | grep -w "_sscanf"
otool -Iv <app> | grep -w "_strtok"
otool -Iv <app> | grep -w "_alloca"
otool -Iv <app> | grep -w "_sprintf"
otool -Iv <app> | grep -w "_printf"
otool -Iv <app> | grep -w "_vsprintf"

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

Analyse dynamique de base

Consultez l'analyse dynamique effectuée par MobSF. Vous devrez naviguer à travers les différentes vues et interagir avec elles, mais il accrochera plusieurs classes en effectuant d'autres actions et préparera un rapport une fois que vous aurez terminé.

Liste des applications installées

Utilisez la commande frida-ps -Uai pour déterminer l'identifiant de bundle des applications 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 à énumérer les composants de l'application et comment accrocher facilement les méthodes et les classes avec objection:

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

Structure de l'IPA

La structure d'un fichier IPA est essentiellement celle d'un paquet compressé. 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 pour l'installation. À l'intérieur, vous trouverez un répertoire nommé <NOM>.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 dans le bundle.
  • Assets.car: Une archive compressée qui stocke des fichiers d'actifs tels que des icônes.
  • Frameworks/: Ce dossier contient les bibliothèques natives de l'application, qui peuvent être sous forme de fichiers .dylib ou .framework.
  • PlugIns/: Cela peut inclure des extensions de l'application, connues sous le nom de fichiers .appex, bien qu'ils ne soient pas toujours présents. * 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 des fonctionnalités d'annulation à votre application sur un seul appareil. Pour synchroniser des données sur plusieurs appareils dans un seul compte iCloud, Core Data reflète automatiquement votre schéma dans un conteneur CloudKit.
  • PkgInfo: Le fichier PkgInfo est 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: Sont les packs de langues 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.
  • Sécurité: Le répertoire _CodeSignature/ joue un rôle critique dans la sécurité de l'application en vérifiant l'intégrité de tous les fichiers regroupés grâce à des signatures numériques.
  • Gestion des actifs: Le fichier Assets.car utilise la compression pour gérer efficacement les actifs graphiques, crucial pour optimiser les performances de l'application et réduire sa taille globale.
  • Cadres et 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'application (PlugIns/).
  • Localisation: 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 les 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'application et les frameworks inclus. Il est structuré en XML ou en format binaire et contient des informations critiques allant des autorisations d'application aux configurations de sécurité. Pour une exploration détaillée des clés disponibles, on peut se référer à la Documentation du développeur Apple.

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, les entrées notables incluent les chaînes d'autorisation de l'application (UsageDescription), les schémas d'URL personnalisés (CFBundleURLTypes), et les configurations pour la sécurité du transport de l'application (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 des données

Dans l'environnement iOS, les répertoires sont spécifiquement désignés pour les applications système et les 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 /private/var/containers/. Ces applications se voient attribuer un identifiant unique connu sous le nom d'UUID de 128 bits, rendant la tâche de localiser manuellement le dossier d'une application difficile en raison du caractère aléatoire des noms de répertoire.

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 le répertoire de l'application en question. 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*"

Les 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 d'accès actifs de l'application :

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

Répertoire du bundle :

  • AppName.app
  • Il s'agit du Bundle de l'application tel que vu précédemment dans l'IPA, il contient des données d'application essentielles, du 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.

Répertoire des données :

  • 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'application peut désactiver les 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 de liste de propriétés (plist).
  • Les applications iOS utilisent généralement les sous-répertoires Application Support et Caches, mais l'application 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 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'application ne s'exécute pas et que l'espace de stockage est insuffisant.
  • Library/Application Support/
  • Contient des fichiers persistants nécessaires à l'exécution de l'application.
  • Invisible pour les utilisateurs et les utilisateurs ne peuvent pas y écrire.
  • Le contenu de ce répertoire est sauvegardé.
  • L'application peut désactiver les chemins en définissant NSURLIsExcludedFromBackupKey.
  • Library/Preferences/
  • Utilisé pour stocker des propriétés qui peuvent persister même après le redémarrage d'une application.
  • Les informations sont enregistrées, non chiffrées, à l'intérieur du bac à sable de l'application dans un fichier plist appelé [BUNDLE_ID].plist.
  • Toutes les paires clé/valeur stockées à l'aide de NSUserDefaults peuvent être trouvées 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 mis en 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 ne s'exécute pas et que l'espace de stockage est insuffisant.

Jetons un coup d'œil plus attentif au répertoire du Bundle de l'Application (.app) d'iGoat-Swift à 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

Réversing binaire

À l'intérieur du dossier <nom-de-l'application>.app, vous trouverez un fichier binaire appelé <nom-de-l'application>. C'est le fichier qui sera exécuté. Vous pouvez effectuer une inspection de base 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'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ésassemblez la section du texte :

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 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.


Utilisez Trickest pour créer facilement et automatiser des workflows alimentés par les outils communautaires les plus avancés au monde.
Accédez dès aujourd'hui :

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

Stockage de données

Pour en savoir plus sur la manière dont iOS stocke les données sur l'appareil, consultez cette page :

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

{% hint style="warning" %} Les emplacements suivants pour stocker des informations doivent être vérifiés juste après l'installation de l'application, après avoir vérifié toutes les fonctionnalités de l'application et même après déconnexion d'un utilisateur et connexion d'un autre.
L'objectif est de trouver des informations sensibles non protégées de l'application (mots de passe, jetons), de l'utilisateur actuel et des utilisateurs précédemment connectés. {% endhint %}

Plist

Les fichiers plist sont des fichiers XML structurés qui contiennent des paires clé-valeur. C'est une façon de stocker des données persistantes, donc parfois vous pouvez trouver des informations sensibles dans ces fichiers. Il est recommandé de vérifier ces fichiers après l'installation de l'application et après l'avoir utilisée intensivement pour voir si de nouvelles données sont écrites.

La manière la plus courante de persister les données dans les fichiers plist est par l'utilisation de NSUserDefaults. Ce fichier plist est enregistré à l'intérieur du bac à sable de l'application dans Library/Preferences/<appBundleID>.plist

La classe NSUserDefaults fournit une interface programmatique pour interagir avec le système par défaut. Le système par défaut permet à une application de personnaliser son comportement en fonction des préférences de l'utilisateur. Les données enregistrées par NSUserDefaults peuvent être consultées dans le bundle de l'application. Cette classe stocke des données dans un fichier plist, mais elle est destinée à être utilisée avec de petites quantités de données.

Ces données ne peuvent pas être directement consultées via un ordinateur de confiance, mais peuvent être consultées en effectuant une sauvegarde.

Vous pouvez extraire les informations enregistrées en utilisant NSUserDefaults en utilisant ios nsuserdefaults get d'objection.

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 du format XML ou binaire (bplist) en XML, diverses méthodes sont disponibles en fonction de votre système d'exploitation :

Pour les utilisateurs de macOS : Utilisez la commande plutil. C'est un outil intégré dans macOS (10.2+), conçu à cet effet :

$ plutil -convert xml1 Info.plist

Pour les utilisateurs de 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 session Objection : 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 dans votre application. Core Data peut utiliser SQLite comme son magasin persistant, 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 d'encryption supplémentaire peut être ajoutée à CoreData. Consultez 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 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");
}
}

{% endcode %}

YapDatabase

YapDatabase est un magasin de clés/valeurs construit sur SQLite.
Comme les bases de données Yap sont des bases de données sqlite, vous pouvez les trouver en utilisant la commande proposée 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 stocker des données sensibles et les laisser non cryptées. Par conséquent, il est toujours intéressant de vérifier chaque base de données à l'intérieur du répertoire des applications. 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"

Bases de données en temps réel Firebase

Les développeurs peuvent stocker et synchroniser des données dans une base de données hébergée dans le cloud NoSQL via Firebase Real-Time Databases. Stockées au format JSON, les données sont synchronisées en temps réel avec tous les clients connectés.

Vous pouvez trouver comment vérifier les bases de données Firebase mal configurées ici:

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

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 non chiffrées, avec le chiffrement 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, le 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 intégré qui suit l'approche orientée document (NoSQL). Conçu pour être natif d'iOS et macOS, il offre la capacité de synchroniser les données de manière transparente.

Pour identifier les bases de données Couchbase potentielles 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, les développeurs décident parfois de les sauvegarder dans le trousseau 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 également utiliser objection pour convertir ces fichiers en 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 les requêtes HTTP et les réponses dans la base de données Cache.db. Cette base de données peut contenir des données sensibles, si des jetons, 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'application (/var/mobile/Containers/Data/Application/<UUID>) et allez à /Library/Caches/<Bundle Identifier>. Le cache WebKit 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, car il s'agit d'une base de données SQLite normale.

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 ci-dessous montre différentes façons d'y parvenir :

  1. 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 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. 2. Si vous n'avez pas besoin d'utiliser les 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.

Documentation Apple:

Un objet de configuration de session éphémère est similaire à un objet de configuration de session par défaut (voir default), sauf que l'objet de session correspondant ne stocke pas de caches, de magasins de certificats ou de données liées à la session sur le disque. Au lieu de cela, les données liées à la session sont stockées en RAM. La seule fois où une session éphémère écrit des données sur le disque est lorsque vous lui demandez d'écrire le contenu d'une URL dans un fichier. 3. Le cache peut également être désactivé en définissant la politique de cache sur .notAllowed. Cela désactivera le stockage du cache de quelque manière que ce soit, que ce soit en mémoire ou sur disque.

Snapshots

Chaque fois que vous appuyez sur le bouton d'accueil, iOS prend un instantané de l'écran actuel pour pouvoir effectuer la transition vers l'application de manière plus fluide. Cependant, si des données sensibles sont présentes à l'écran actuel, elles seront enregistrées dans l'image (qui persiste après les redémarrages). Ce sont les instantanés auxquels vous pouvez également accéder en double-cliquant sur l'écran d'accueil pour basculer entre les applications.

Sauf si l'iPhone est jailbreaké, l'attaquant doit avoir accès au dispositif débloqué pour voir ces captures d'écran. Par défaut, le dernier instantané est stocké dans le sandbox de l'application dans le dossier Library/Caches/Snapshots/ ou Library/SplashBoard/Snapshots (les ordinateurs de confiance ne peuvent pas accéder au système de fichiers à partir de iOS 7.0).

Une façon de prévenir ce comportement indésirable est de mettre un écran vide ou de supprimer les données sensibles avant de prendre l'instantané en utilisant la fonction ApplicationDidEnterBackground().

Voici une méthode de remédiation d'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 d'arrière-plan sur overlayImage.png chaque fois que l'application passe en arrière-plan. Cela empêche les fuites de données sensibles car overlayImage.png remplacera toujours la vue actuelle.

Trousseau

Pour accéder et gérer le trousseau iOS, des outils comme Keychain-Dumper sont disponibles, adaptés aux appareils jailbreakés. De plus, Objection fournit la commande ios keychain dump à des fins similaires.

Stockage des identifiants

La classe NSURLCredential est idéale pour enregistrer des informations sensibles directement dans le trousseau, contournant ainsi le besoin de 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 informations d'identification stockées, la commande ios nsurlcredentialstorage dump d'Objection est utilisée.

Claviers personnalisés et cache du clavier

À partir d'iOS 8.0, les utilisateurs peuvent installer des extensions de clavier personnalisées, gérables sous Réglages > Général > Clavier > Claviers. Bien que ces claviers offrent une fonctionnalité étendue, ils posent un risque de journalisation des frappes et de transmission de données à des serveurs externes, bien que les utilisateurs soient informés des claviers nécessitant un accès réseau. Les applications peuvent, et doivent, restreindre l'utilisation des claviers personnalisés pour la saisie d'informations sensibles.

Recommandations en matière de sécurité :

  • Il est conseillé de désactiver les claviers tiers pour une sécurité renforcée.
  • Soyez conscient des fonctionnalités de correction automatique 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.dat ou /private/var/mobile/Library/Keyboard/dynamic-text.dat. Ces fichiers cache doivent être régulièrement vérifiés pour 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 frappes à distance.

Prévention de la mise en cache des champs de texte

Le protocole UITextInputTraits offre des propriétés pour gérer la correction automatique et la saisie de texte sécurisée, essentielles pour prévenir la mise en cache d'informations sensibles. Par exemple, la désactivation de la correction automatique et l'activation de la saisie de texte sécurisée peuvent être réalisées 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 telles que des mots de passe et des NIP, 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;

Journaux

Le débogage du code implique souvent l'utilisation de logs. Il y a un risque car les logs peuvent contenir des informations sensibles. Auparavant, dans iOS 6 et les versions antérieures, les logs étaient accessibles à toutes les applications, posant un risque de fuite de données sensibles. Maintenant, les applications sont limitées à l'accès uniquement à 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'application.

Pour atténuer les risques, il est conseillé d'interagir pleinement avec l'application, en explorant toutes ses fonctionnalités et ses entrées pour s'assurer qu'aucune information sensible n'est enregistrée involontairement.

Lors de l'examen du code source de l'application pour des fuites potentielles, recherchez à la fois les déclarations de logging prédéfinies 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 journaux système

Les applications enregistrent diverses informations qui peuvent être sensibles. Pour surveiller ces logs, des outils et des commandes comme :

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 des journaux de console :

  1. Ouvrez Xcode.
  2. Connectez l'appareil iOS.
  3. Accédez à Fenêtre -> Appareils et simulateurs.
  4. Sélectionnez votre appareil.
  5. Déclenchez le problème que vous étudiez.
  6. Utilisez le bouton Ouvrir la console pour afficher les journaux dans une nouvelle fenêtre.

Pour des journaux plus avancés, se connecter à l'invite de commande de l'appareil et utiliser socat peut fournir une surveillance des journaux en temps réel :

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

Suivi des commandes pour observer les activités de journal, qui peuvent être inestimables pour diagnostiquer les problèmes ou identifier des fuites de données potentielles dans les journaux.



Utilisez Trickest pour construire facilement et automatiser des workflows alimentés par les outils communautaires les plus avancés au monde.
Obtenez l'accès aujourd'hui :

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

Sauvegardes

Les fonctionnalités de sauvegarde automatique sont intégrées à iOS, facilitant la création de copies de 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 hautement sensibles tels que les détails d'Apple Pay et les configurations Touch ID.

Risques de sécurité

L'inclusion des applications installées et de leurs données dans les sauvegardes soulève la question d'une fuite de données potentielle et du risque que les modifications de sauvegarde puissent altérer la fonctionnalité de l'application. Il est conseillé de ne pas stocker d'informations sensibles en texte clair dans le répertoire d'une application 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 des répertoires spécifiques des sauvegardes en utilisant NSURL setResourceValue:forKey:error: avec la clé NSURLIsExcludedFromBackupKey. Cette pratique est cruciale pour protéger les données sensibles contre leur inclusion dans les sauvegardes.

Test des vulnérabilités

Pour évaluer la sécurité de la sauvegarde d'une application, 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 pour y repérer des données sensibles ou des configurations qui pourraient être modifiées pour affecter le comportement de l'application.

Les 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 de 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 traiter les sauvegardes chiffrées, les scripts Python disponibles dans le dépôt GitHub de DinoSec, tels que backup_tool.py et backup_passwd.py, peuvent être utiles, bien qu'ils nécessitent potentiellement 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 dans les sauvegardes protégées par mot de passe.

Modification du Comportement de l'Application

Un exemple de modification du comportement de l'application via des modifications de sauvegarde est démontré dans l'application de portefeuille bitcoin Bither (https://github.com/bither/bither-ios), où le code PIN de verrouillage de l'interface utilisateur est stocké dans net.bither.plist sous la clé pin_code. En supprimant cette clé du plist et en restaurant la sauvegarde, l'exigence du code PIN est supprimée, offrant un accès illimité.

Résumé sur les Tests de Mémoire pour les Données Sensibles

Lorsqu'il s'agit d'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 enquêter sur le contenu de la mémoire : créer un vidage de mémoire et analyser 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 lors du processus de vidage ou d'analyse.

Récupération et Analyse d'un Vidage de Mémoire

Pour les appareils jailbreakés et non jailbreakés, des outils tels que objection et Fridump permettent de faire un vidage de la mémoire du processus d'une application. Une fois le vidage effectué, l'analyse de ces données nécessite divers outils, en fonction de la nature des informations recherchées.

Pour extraire des chaînes d'un vidage de mémoire, 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 en temps d'exécution

r2frida offre une puissante alternative pour inspecter la mémoire d'une application en temps réel, sans avoir besoin d'un vidage de mémoire. 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>

Cryptographie Défaillante

Processus de Gestion de Clés Médiocres

Certains développeurs enregistrent des données sensibles dans le stockage local et les cryptent avec une clé codée/prévisible dans le code. Cela ne devrait pas être fait car une rétro-ingénierie pourrait permettre aux attaquants d'extraire les informations confidentielles.

Utilisation d'Algorithmes Insécurisés et/ou Obsolètes

Les développeurs ne devraient pas utiliser des algorithmes obsolètes 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, des hashes résistants aux attaques par force brute devraient être utilisés avec du sel.

Vérification

Les principales vérifications à effectuer consistent à rechercher des mots de passe/secrets codés en dur dans le code, ou si ceux-ci sont prévisibles, et si le code utilise une sorte d'algorithmes de cryptographie faibles.

Il est intéressant de savoir que vous pouvez surveiller automatiquement certaines bibliothèques de cryptographie en utilisant objection avec :

ios monitor crypt

Pour plus d'informations sur les API et bibliothèques cryptographiques iOS, accédez à 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, surtout lorsqu'il s'agit de protéger l'accès à un point d'extrémité distant à travers des méthodes cryptographiques. L'essence ici est qu'une implémentation correcte est essentielle, sinon les mécanismes d'authentification locale peuvent être contournés.

Le framework d'authentification locale d'Apple et le trousseau fournissent des API robustes aux développeurs pour faciliter les dialogues d'authentification utilisateur et gérer de manière sécurisée des données secrètes, respectivement. L'Enclave sécurisée sécurise 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.framework pour une authentification utilisateur de haut niveau sans accès aux données biométriques.
  • Security.framework pour un accès aux services de trousseau de bas niveau, sécurisant les données secrètes avec une authentification biométrique. Divers enveloppes open-source rendent l'accès au trousseau plus simple.

{% hint style="danger" %} Cependant, à la fois LocalAuthentication.framework et Security.framework présentent des vulnérabilités, car ils retournent principalement des valeurs booléennes sans transmettre de données pour les processus d'authentification, les rendant susceptibles d'être contournés (voir Ne me touchez pas de cette façon, par David Lindner et al). {% endhint %}

Implémentation de l'authentification locale

Pour demander aux utilisateurs une authentification, les développeurs devraient utiliser la méthode evaluatePolicy au sein de la classe LAContext, en choisissant entre :

  • deviceOwnerAuthentication : Demande l'empreinte digitale ou le code d'accès de l'appareil, échouant si aucun des deux n'est activé.
  • deviceOwnerAuthenticationWithBiometrics : Demande exclusivement l'empreinte digitale.

Une authentification réussie est indiquée par une valeur de retour booléenne de evaluatePolicy, mettant en évidence une faille de sécurité potentielle.

Authentification locale en utilisant le trousseau

L'implémentation de l'authentification locale dans les applications iOS implique l'utilisation des API du trousseau pour stocker de manière sécurisée des données secrètes telles que des jetons d'authentification. Ce processus garantit que les données ne peuvent être accédées que par l'utilisateur, en utilisant son code d'accès de l'appareil ou une authentification biométrique comme Touch ID.

Le trousseau offre la possibilité de définir des éléments avec l'attribut SecAccessControl, qui restreint l'accès à l'élément jusqu'à ce que l'utilisateur s'authentifie avec succès via Touch ID ou le code d'accès de l'appareil. Cette fonctionnalité est cruciale pour renforcer la sécurité.

Ci-dessous se trouvent des exemples de code en Swift et en Objective-C démontrant comment enregistrer et récupérer une chaîne dans/depuis le trousseau, 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 une authentification Touch ID et garantir 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 configuré.

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

// From https://github.com/mufambisi/owasp-mstg/blob/master/Document/0x06f-Testing-Local-Authentication.md

// 1. create AccessControl object that will represent authentication settings

var error: Unmanaged<CFError>?

guard let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
SecAccessControlCreateFlags.biometryCurrentSet,
&error) else {
// failed to create AccessControl object

return
}

// 2. define keychain services query. Pay attention that kSecAttrAccessControl is mutually exclusive with kSecAttrAccessible attribute

var query: [String: Any] = [:]

query[kSecClass as String] = kSecClassGenericPassword
query[kSecAttrLabel as String] = "com.me.myapp.password" as CFString
query[kSecAttrAccount as String] = "OWASP Account" as CFString
query[kSecValueData as String] = "test_strong_password".data(using: .utf8)! as CFData
query[kSecAttrAccessControl as String] = accessControl

// 3. save item

let status = SecItemAdd(query as CFDictionary, nil)

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

{% endtab %}

{% tab title="Objective-C" %}

iOS Application Pentesting

Setting up the Environment

To start iOS application pentesting, you need a macOS system with Xcode installed. Xcode is the official IDE for developing iOS applications and comes with all the necessary tools for iOS pentesting.

Jailbreaking the Device

To perform in-depth testing, you may need to jailbreak the iOS device. Jailbreaking allows you to bypass Apple's restrictions and access the device's file system, enabling you to perform advanced security testing.

Tools for iOS Pentesting

There are various tools available for iOS application pentesting, such as:

  • Cycript: A powerful runtime manipulation and scripting tool for iOS apps.
  • Clutch: Used for decrypting iOS applications.
  • Frida: Dynamic instrumentation toolkit for developers, reverse engineers, and security researchers.
  • MobSF: Mobile Security Framework is an automated, all-in-one mobile application (Android/iOS/Windows) pen-testing framework capable of performing static, dynamic analysis, and web API testing.

Common Vulnerabilities to Look For

During iOS application pentesting, you should pay attention to common vulnerabilities like insecure data storage, improper session management, insecure communication, and lack of binary protections.

Reporting

After conducting the pentest, it is crucial to prepare a detailed report outlining the vulnerabilities discovered, their impact, and recommendations for mitigation. This report helps developers and organizations improve the security of their iOS applications.

Conclusion

iOS application pentesting is essential to identify and address security weaknesses in iOS apps. By following the right methodology and using appropriate tools, you can enhance the security posture of iOS applications and protect user data effectively.

{% endtab %}

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

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

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

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

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

{% endtab %} {% endtabs %}

Maintenant, nous pouvons demander l'élément enregistré dans le trousseau. Les services du trousseau présenteront le dialogue d'authentification à l'utilisateur et renverront des données ou nil en fonction de la fourniture ou non d'une empreinte digitale appropriée.

// 1. define query
var query = [String: Any]()
query[kSecClass as String] = kSecClassGenericPassword
query[kSecReturnData as String] = kCFBooleanTrue
query[kSecAttrAccount as String] = "My Name" as CFString
query[kSecAttrLabel as String] = "com.me.myapp.password" as CFString
query[kSecUseOperationPrompt as String] = "Please, pass authorisation to enter this area" as CFString

// 2. get item
var queryResult: AnyObject?
let status = withUnsafeMutablePointer(to: &queryResult) {
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
}

if status == noErr {
let password = String(data: queryResult as! Data, encoding: .utf8)!
// successfully received password
} else {
// authorization not passed
}

{% endtab %}

{% tab title="Objective-C" %}

iOS Application Pentesting

Setting up the Environment

To start iOS application pentesting, you need a macOS machine with Xcode installed. Xcode is the official IDE for developing iOS applications and comes with a built-in iOS simulator. You can use the simulator to run and test applications without needing a physical iOS device.

Tools for iOS Application Pentesting

  1. Cycript: A runtime manipulation tool that allows you to explore and modify running applications.
  2. Clutch: A tool used to decrypt iOS applications.
  3. Dumpdecrypted: Another tool for decrypting iOS applications.
  4. class-dump-z: Used to generate headers from Objective-C runtime information.
  5. Hopper Disassembler: A reverse engineering tool for macOS and iOS applications.
  6. MobSF: Mobile Security Framework, which can be used for static and dynamic analysis of iOS applications.

Common Vulnerabilities in iOS Applications

  1. Insecure Data Storage: Storing sensitive data in an insecure manner.
  2. Insecure Communication: Transmitting data over unencrypted channels.
  3. Insecure Authentication: Weak authentication mechanisms.
  4. Improper Session Handling: Incorrect session management.
  5. Code Injection: Allowing injection of malicious code.
  6. Sensitive Information Exposure: Revealing sensitive information to unauthorized users.

Testing Methodology

  1. Static Analysis: Reviewing the application without executing it.
  2. Dynamic Analysis: Analyzing the application while it is running.
  3. Runtime Analysis: Monitoring the application's behavior at runtime.
  4. Data Storage Analysis: Checking how data is stored and secured.
  5. Network Analysis: Inspecting network traffic for vulnerabilities.

Reporting

After conducting the pentest, prepare a detailed report outlining the vulnerabilities discovered, their impact, and recommendations for mitigation. This report is crucial for developers to understand and fix the identified security issues.

Ensure that you have proper authorization before conducting any pentesting activities. Unauthorized pentesting is illegal and can lead to severe consequences.

{% endtab %}

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

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

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

Détection

L'utilisation de frameworks dans une application peut également être détectée en analysant la liste des bibliothèques dynamiques partagées de l'application binaire. 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 (n'oubliez pas 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é.

Contournement du Framework d'Authentification Locale

Objection

Grâce au Contournement Biométrique Objection, situé sur cette page GitHub, une technique est disponible pour contourner le mécanisme LocalAuthentication. L'essence de cette approche consiste à exploiter Frida pour manipuler la fonction evaluatePolicy, garantissant ainsi un résultat True constant, indépendamment de la réussite de l'authentification réelle. Ceci est particulièrement utile pour contourner les processus d'authentification biométrique défectueux.

Pour activer ce contournement, 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

Ce commandement déclenche une séquence où Objection enregistre une tâche qui modifie efficacement le résultat de la vérification evaluatePolicy en True.

Frida

Un exemple d'utilisation de evaluatePolicy de l'application DVIA-v2 :

+(void)authenticateWithTouchID {
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
NSString *myLocalizedReasonString = @"Please authenticate yourself";

if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
[myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:myLocalizedReasonString
reply:^(BOOL success, NSError *error) {
if (success) {
dispatch_async(dispatch_get_main_queue(), ^{
[TouchIDAuthentication showAlert:@"Authentication Successful" withTitle:@"Success"];
});
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[TouchIDAuthentication showAlert:@"Authentication Failed !" withTitle:@"Error"];
});
}
}];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[TouchIDAuthentication showAlert:@"Your device doesn't support Touch ID or you haven't configured Touch ID authentication on your device" withTitle:@"Error"];
});
}
}

Pour réaliser le contournement de l'Authentification Locale, un script Frida est écrit. Ce script cible la vérification evaluatePolicy, interceptant son rappel pour s'assurer qu'il renvoie success=1. En modifiant le comportement du rappel, la vérification d'authentification est contournée de manière efficace.

Le script ci-dessous est injecté pour modifier le résultat de la méthode evaluatePolicy. Il modifie le résultat du rappel pour indiquer toujours 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

Gestionnaires d'URI personnalisés / Liens profonds / Schémas personnalisés

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

Liens universels

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

Partage UIActivity

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

UIPasteboard

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

Extensions d'application

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

WebViews

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

Sérialisation et Encodage

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

Communication réseau

Il est important de vérifier qu'aucune communication ne se fait sans chiffrement et également 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 :

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

Vérification du nom d'hôte

Un problème courant lors de la validation du certificat TLS est de vérifier si le certificat a été signé par une AC de confiance, mais de ne pas vérifier si le nom d'hôte du certificat est le nom d'hôte auquel on accède.
Pour vérifier ce problème en utilisant Burp, après avoir fait confiance à l'AC de Burp 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 quelque chose est vulnérable.

Épinglage de certificat

Si une application utilise correctement l'épinglage SSL, alors l'application ne fonctionnera que si le certificat est celui attendu. Lors du test d'une application, cela peut poser problème car Burp servira son propre certificat.
Pour contourner cette protection à l'intérieur d'un appareil jailbreaké, vous pouvez installer l'application SSL Kill Switch ou installer Burp Mobile Assistant

Vous pouvez également utiliser la commande ios sslpinning disable de objection

Divers

  • Dans /System/Library, vous pouvez trouver les frameworks installés dans le téléphone utilisés par les applications système
  • Les applications installées par l'utilisateur depuis l'App Store se trouvent dans /User/Applications
  • Et le /User/Library contient les données enregistrées par les applications de niveau utilisateur
  • Vous pouvez accéder à /User/Library/Notes/notes.sqlite pour lire les notes enregistrées dans l'application.
  • À l'intérieur du dossier d'une application installée (/User/Applications/<ID APP>/), vous pouvez trouver des fichiers intéressants :
    • iTunesArtwork : L'icône utilisée par l'application
    • iTunesMetadata.plist : Infos de l'application utilisées dans l'App Store
    • /Library/* : Contient les préférences et le cache. Dans /Library/Cache/Snapshots/* vous pouvez trouver la capture d'écran effectuée par l'application avant de l'envoyer en arrière-plan.

Patching à chaud / Mises à jour forcées

Les développeurs peuvent patcher à distance toutes les installations de leur application instantanément sans avoir à soumettre à nouveau l'application à l'App Store et attendre son approbation.
À cette fin, on utilise généralement JSPatch. Mais il existe également d'autres options telles que Siren et react-native-appstore-version-checker.
Il s'agit d'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 (le cas échéant) et de la tester. Vous pourriez essayer de télécharger une version antérieure de l'application à cette fin.

Tiers

Un défi significatif 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 vulnérabilités potentielles en matière de sécurité et les préoccupations en matière de confidentialité, ou renoncer entièrement à 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 que les SDK gagnent la confiance au sein de la communauté, certains peuvent commencer à contenir des logiciels malveillants.

Les services fournis par les SDK tiers peuvent inclure le suivi du comportement des utilisateurs, l'affichage de publicités ou des améliorations de l'expérience utilisateur. Cependant, cela introduit un risque car les développeurs peuvent ne pas être pleinement conscients du code exécuté par ces bibliothèques, ce qui peut entraîner des risques potentiels en matière de confidentialité et de sécurité. Il est crucial de limiter les informations partagées avec les services tiers à ce qui est nécessaire et de s'assurer qu'aucune donnée sensible n'est exposée.

L'implémentation des services tiers se présente généralement sous deux formes : une bibliothèque autonome ou un SDK complet. Pour protéger la vie privée des utilisateurs, toutes les données partagées avec ces services doivent être anonymisées pour éviter la divulgation d'informations personnellement identifiables (PII).

Pour identifier les bibliothèques qu'une application utilise, 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 d'autres bibliothèques.

otool -L <application_path>

Références et Ressources Supplémentaires


Utilisez Trickest pour construire facilement et automatiser des workflows alimentés par les outils communautaires les plus avancés au monde.
Accédez dès aujourd'hui :

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

Apprenez le piratage AWS de zéro à héros avec htARTE (HackTricks AWS Red Team Expert)!

Autres façons de soutenir HackTricks :