iOS Pentesting

Tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks

iOS Grundlagen

iOS Basics

Testumgebung

Auf dieser Seite finden Sie Informationen über den iOS simulator, Emulatoren und jailbreaking:

iOS Testing Environment

Initialanalyse

Grundlegende iOS-Testoperationen

Während der Tests werden verschiedene Operationen vorgeschlagen (mit dem Gerät verbinden, Dateien lesen/schreiben/upload/download, Tools verwenden…). Wenn Sie also nicht wissen, wie eine dieser Aktionen auszuführen ist, lesen Sie bitte die Seite:

iOS Basic Testing Operations

Tip

Für die folgenden Schritte sollte die App auf dem Gerät installiert sein und die IPA file der Anwendung sollte bereits vorliegen.
Read the Basic iOS Testing Operations page to learn how to do this.

Grundlegende statische Analyse

Einige interessante iOS-IPA-Decompiler:

Es wird empfohlen, das Tool MobSF zu verwenden, um eine automatische statische Analyse der IPA-Datei durchzuführen.

Erkennung, welche Schutzmechanismen im Binary vorhanden sind:

  • PIE (Position Independent Executable): Wenn aktiviert, wird die Anwendung bei jedem Start an eine zufällige Speicheradresse geladen, was es erschwert, die anfängliche Speicheradresse vorherzusagen.
otool -hv <app-binary> | grep PIE   # It should include the PIE flag
  • Stack Canaries: Zur Validierung der Integrität des Stacks wird ein „canary“-Wert auf dem Stack platziert, bevor eine Funktion aufgerufen wird, und am Ende der Funktion erneut geprüft.
otool -I -v <app-binary> | grep stack_chk   # It should include the symbols: stack_chk_guard and stack_chk_fail
  • ARC (Automatic Reference Counting): Zur Vermeidung häufiger Speicherfehler
otool -I -v <app-binary> | grep objc_release   # It should include the _objc_release symbol
  • Encrypted Binary: Das Binary sollte verschlüsselt sein
otool -arch all -Vl <app-binary> | grep -A5 LC_ENCRYPT   # The cryptid should be 1

Identifikation sensibler/unsicherer Funktionen

  • 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"
  • Unsichere ‘Malloc’-Funktion
# On the iOS device
otool -Iv <app> | grep -w "_malloc"

# On linux
grep -iER "_malloc"
  • Unsichere und anfällige Funktionen
# 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"

Häufige Jailbreak-Erkennungs-Methoden

  • File System Checks: Prüfen Sie auf das Vorhandensein üblicher Jailbreak-Dateien und -Verzeichnisse, wie /Applications/Cydia.app oder /Library/MobileSubstrate/MobileSubstrate.dylib.
  • Sandbox Violations: Versuchen Sie, auf eingeschränkte Bereiche des Dateisystems zuzugreifen, die auf nicht-jailbroken Geräten gesperrt sein sollten.
  • API Checks: Prüfen Sie, ob es möglich ist, verbotene Aufrufe wie fork() zur Erzeugung eines Kindprozesses oder system() zu verwenden, um zu sehen, ob /bin/sh existiert.
  • Process Checks: Überwachen Sie das Vorhandensein bekannter jailbreak-bezogener Prozesse wie Cydia, Substrate oder ssh.
  • Kernel Exploits: Prüfen Sie auf das Vorhandensein von Kernel-Exploits, die häufig bei Jailbreaks verwendet werden.
  • Environment Variables: Untersuchen Sie Environment-Variablen auf Anzeichen eines Jailbreaks, z. B. DYLD_INSERT_LIBRARIES.
  • Libraries Check: Prüfen Sie die Bibliotheken, die in den App-Prozess geladen sind.
  • Check schemes: Wie canOpenURL(URL(string: "cydia://")).

Häufige Anti-Debugging-Erkennungs-Methoden

  • Check for Debugger Presence: Verwenden Sie sysctl oder andere Methoden, um zu prüfen, ob ein Debugger angehängt ist.
  • Anti-Debugging APIs: Suchen Sie nach Aufrufen zu Anti-Debugging-APIs wie ptrace oder SIGSTOP, z. B. ptrace(PT_DENY_ATTACH, 0, 0, 0).
  • Timing Checks: Messen Sie die Zeit für bestimmte Operationen und suchen Sie nach Abweichungen, die auf Debugging hindeuten könnten.
  • Memory Checks: Untersuchen Sie den Speicher auf bekannte Debugger-Artefakte oder Modifikationen.
  • Environment Variables: Prüfen Sie Environment-Variablen, die auf eine Debugging-Sitzung hinweisen könnten.
  • Mach Ports: Erkennen Sie, ob Mach-Exception-Ports von Debuggern verwendet werden.

Anti-Debugging & Anti-Tamper-Techniken (gestaffelte Prüfungen)

Echte Apps kombinieren häufig pre-exec-, on-attach- und kontinuierliche Prüfungen. Übliche Muster, nach denen man suchen sollte (und wie man sie während des Tests neutralisiert):

  • Private API side-channel fingerprinting: private launch APIs (z. B. SBSLaunchApplicationWithIdentifierAndURLAndLaunchOptions) werden missbraucht, um anhand von Rückgabecodes/Logs auf installierte Bundle-IDs (com.opa334.TrollStore, org.coolstar.SileoStore, com.tigisoftware.Filza usw.) zu prüfen. Hooken Sie den Aufruf und bereinigen Sie Argumente/Rückgabewerte, um ein sauberes Gerät zu emulieren.
  • Self-attestation via code-signing state: csops() mit CS_OPS_ENTITLEMENTS_BLOB liest Entitlements; unerwartete Werte führen zum Exit. Kombiniert mit Integritätsprüfungen (CRC32/MD5 von Ressourcen, Zertifikatsprüfung, Mach-O-Metadaten wie LC_ENCRYPTION_INFO_64) um Re-Signing oder Patchen zu erkennen. Instrumentieren Sie diese Routinen und erzwingen Sie erwartete Ergebnisse während der Analyse.
  • Kill-on-attach: ptrace(PT_DENY_ATTACH) kombiniert mit abort()/exit() beim Attach. Umgehen Sie dies, indem Sie den Terminierungspfad neutralisieren oder ptrace hooken, damit es erfolgreich zurückkehrt, ohne Deny durchzusetzen.
  • Crash forensics sabotage: CPU-Register vor einem Crash überschreiben, um Backtraces zu zerstören. Setzen Sie Breakpoints/Hook früher im Erkennungs-Pfad an, anstatt sich auf Crash-Logs zu verlassen.
  • Jetsam-based termination: Absichtlicher Speicherdruck, um Jetsam auszulösen, der keine normalen Crash-Logs erzeugt. Achten Sie auf große Allokationen um die Erkennungslogik und begrenzen/umgehen Sie diese, um Logs zu erhalten.
  • Continuous checks with delayed enforcement: Heartbeat-Timer führen Erkennungen periodisch neu aus und erzwingen später Maßnahmen. Trace Timer/dispatch sources und halten Sie den Prozess am Leben, indem Sie den verzögerten Kill-Pfad umgehen.

Grundlegende dynamische Analyse

Sehen Sie sich die dynamische Analyse an, die MobSF durchführt. Sie müssen sich durch die verschiedenen Ansichten bewegen und mit ihnen interagieren; es wird dabei mehrere Klassen hooken und andere Aktionen durchführen und am Ende einen Report erstellen.

Auflisten installierter Apps

Verwenden Sie den Befehl frida-ps -Uai, um den bundle identifier der installierten Apps zu bestimmen:

$ frida-ps -Uai
PID  Name                 Identifier
----  -------------------  -----------------------------------------
6847  Calendar             com.apple.mobilecal
6815  Mail                 com.apple.mobilemail
-  App Store            com.apple.AppStore
-  Apple Store          com.apple.store.Jolly
-  Calculator           com.apple.calculator
-  Camera               com.apple.camera
-  iGoat-Swift          OWASP.iGoat-Swift

Basic Enumeration & Hooking

Lerne, wie man enumerate the components of the application und wie man mit objection einfach hook methods and classes:

iOS Hooking With Objection

IPA-Struktur

Die Struktur einer IPA file entspricht im Wesentlichen der eines gezipp­ten Pakets. Durch Umbenennen der Dateiendung in .zip kann es dekomprimiert werden, um seinen Inhalt offenzulegen. Innerhalb dieser Struktur repräsentiert ein Bundle eine vollständig verpackte Anwendung, die zur Installation bereit ist. Innen findest du ein Verzeichnis mit dem Namen <NAME>.app, das die Ressourcen der Anwendung kapselt.

  • Info.plist: Diese Datei enthält spezifische Konfigurationsdetails der Anwendung.
  • _CodeSignature/: Dieses Verzeichnis enthält eine plist-Datei, die eine Signatur beinhaltet und die Integrität aller Dateien im Bundle sicherstellt.
  • Assets.car: Ein komprimiertes Archiv, das Asset-Dateien wie Icons speichert.
  • Frameworks/: Dieser Ordner beherbergt die nativen Bibliotheken der Anwendung, die in Form von .dylib- oder .framework-Dateien vorliegen können.
  • PlugIns/: Dies kann Erweiterungen der Anwendung enthalten, bekannt als .appex-Dateien, obwohl sie nicht immer vorhanden sind. * Core Data: Es wird verwendet, um die dauerhaften Daten deiner Anwendung für die Offline-Nutzung zu speichern, temporäre Daten zwischenzuspeichern und eine Undo-Funktionalität für deine App auf einem einzelnen Gerät bereitzustellen. Um Daten über mehrere Geräte in einem einzelnen iCloud-Account zu synchronisieren, spiegelt Core Data automatisch dein Schema in einen CloudKit-Container.
  • PkgInfo: Die PkgInfo-Datei ist eine alternative Möglichkeit, die Type- und Creator-Codes deiner Anwendung oder deines Bundles anzugeben.
  • en.lproj, fr.proj, Base.lproj: Sind die Sprachpakete, die Ressourcen für diese spezifischen Sprachen enthalten, sowie eine Standardressource für den Fall, dass eine Sprache nicht unterstützt wird.
  • Sicherheit: Das Verzeichnis _CodeSignature/ spielt eine entscheidende Rolle für die Sicherheit der App, indem es die Integrität aller gebündelten Dateien durch digitale Signaturen überprüft.
  • Asset-Management: Die Datei Assets.car verwendet Kompression, um grafische Assets effizient zu verwalten, was entscheidend für die Optimierung der Anwendungsleistung und die Reduzierung der Gesamtgröße ist.
  • Frameworks und PlugIns: Diese Verzeichnisse unterstreichen die Modularität von iOS-Anwendungen, indem sie Entwicklern ermöglichen, wiederverwendbare Codebibliotheken (Frameworks/) einzubinden und die Funktionalität der App (PlugIns/) zu erweitern.
  • Lokalisierung: Die Struktur unterstützt mehrere Sprachen und erleichtert die globale Verbreitung von Anwendungen, indem Ressourcen für spezifische Sprachpakete enthalten sind.

Info.plist

Die Info.plist dient als Eckpfeiler für iOS-Anwendungen und fasst wichtige Konfigurationsdaten in Form von Schlüssel-Wert-Paaren zusammen. Diese Datei ist nicht nur für Anwendungen erforderlich, sondern auch für App-Erweiterungen und Frameworks, die im Bundle enthalten sind. Sie ist entweder im XML- oder im binären Format strukturiert und enthält kritische Informationen von App-Berechtigungen bis hin zu Sicherheitskonfigurationen. Für eine detaillierte Betrachtung der verfügbaren Keys kann die Apple Developer Documentation herangezogen werden.

Für diejenigen, die mit dieser Datei in einem besser lesbaren Format arbeiten möchten, kann die XML-Konvertierung mühelos mit plutil auf macOS (nativ verfügbar ab Version 10.2) oder mit plistutil unter Linux durchgeführt werden. Die Befehle zur Konvertierung sind wie folgt:

  • Für macOS:
$ plutil -convert xml1 Info.plist
  • Für Linux:
$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist

Unter der Vielzahl an Informationen, die die Info.plist-Datei preisgeben kann, gehören zu den auffälligen Einträgen App-Berechtigungs-Strings (UsageDescription), benutzerdefinierte URL-Schemata (CFBundleURLTypes) und Konfigurationen für App Transport Security (NSAppTransportSecurity). Diese Einträge, zusammen mit anderen wie exportierten/importierten benutzerdefinierten Dokumenttypen (UTExportedTypeDeclarations / UTImportedTypeDeclarations), lassen sich mühelos durch Inspektion der Datei oder durch die Verwendung eines einfachen grep-Befehls auffinden:

$ grep -i <keyword> Info.plist

Datenpfade

In der iOS-Umgebung sind Verzeichnisse speziell für Systemanwendungen und benutzerinstallierte Anwendungen vorgesehen. Systemanwendungen befinden sich im Verzeichnis /Applications, während benutzerinstallierte Apps unter /var/mobile/containers/Data/Application/ abgelegt werden. Diese Anwendungen erhalten eine eindeutige Kennung, bekannt als 128-bit UUID, was das manuelle Auffinden des App-Ordners aufgrund der Zufälligkeit der Verzeichnisnamen erschwert.

Warning

Da Anwendungen in iOS sandboxed sein müssen, hat jede App außerdem einen Ordner innerhalb von $HOME/Library/Containers mit dem App-CFBundleIdentifier als Ordnernamen.

Beide Ordner (Data- & Container-Ordner) enthalten jedoch die Datei .com.apple.mobile_container_manager.metadata.plist, die beide Verzeichnisse über den Schlüssel MCMetadataIdentifier verknüpft.)

Um die Auffindung des Installationsverzeichnisses einer benutzerinstallierten App zu erleichtern, stellt das objection tool den nützlichen Befehl env zur Verfügung. Dieser Befehl zeigt detaillierte Verzeichnisinformationen für die betreffende App an. Nachfolgend ein Beispiel, wie man diesen Befehl verwendet:

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

Alternativ kann der App-Name innerhalb von /private/var/containers mit dem find-Befehl gesucht werden:

find /private/var/containers -name "Progname*"

Befehle wie ps und lsof können ebenfalls verwendet werden, um jeweils den Prozess der App zu identifizieren bzw. offene Dateien aufzulisten und so Einblicke in die aktiven Verzeichnispfade der Anwendung zu liefern:

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

Bundle directory:

  • AppName.app
  • Dies ist das Application Bundle wie zuvor in der IPA gesehen; es enthält essentielle Anwendungsdaten, statische Inhalte sowie die kompilierte Binary der Anwendung.
  • Dieses Verzeichnis ist für Benutzer sichtbar, aber Benutzer können nicht darin schreiben.
  • Inhalte in diesem Verzeichnis werden nicht gesichert.
  • Der Inhalt dieses Ordners wird verwendet, um die Code-Signatur zu validieren.

Data directory:

  • Documents/
  • Enthält alle vom Benutzer erzeugten Daten. Der Endanwender der Anwendung initiiert die Erstellung dieser Daten.
  • Für Benutzer sichtbar und Benutzer können darin schreiben.
  • Inhalte in diesem Verzeichnis werden gesichert.
  • Die App kann Pfade von der Sicherung ausschließen, indem sie NSURLIsExcludedFromBackupKey setzt.
  • Library/
  • Enthält alle Dateien, die nicht benutzerspezifisch sind, wie caches, preferences, cookies und Property-List (plist) Konfigurationsdateien.
  • iOS-Apps verwenden normalerweise die Application Support und Caches Unterverzeichnisse, aber die App kann eigene Unterverzeichnisse anlegen.
  • Library/Caches/
  • Enthält semi-persistente Cache-Dateien.
  • Für Benutzer unsichtbar und Benutzer können nicht darin schreiben.
  • Inhalte in diesem Verzeichnis werden nicht gesichert.
  • Das OS kann die Dateien in diesem Verzeichnis automatisch löschen, wenn die App nicht läuft und der Speicherplatz knapp wird.
  • Library/Application Support/
  • Enthält persistente Dateien, die zum Ausführen der App erforderlich sind.
  • Für Benutzer unsichtbar und Benutzer können nicht darin schreiben.
  • Inhalte in diesem Verzeichnis werden gesichert.
  • Die App kann Pfade von der Sicherung ausschließen, indem sie NSURLIsExcludedFromBackupKey setzt.
  • Library/Preferences/
  • Wird verwendet, um Eigenschaften zu speichern, die auch nach einem Neustart der Anwendung bestehen bleiben können.
  • Informationen werden unverschlüsselt innerhalb der Application Sandbox in einer plist-Datei namens [BUNDLE_ID].plist gespeichert.
  • Alle Schlüssel/Wert-Paare, die mit NSUserDefaults gespeichert wurden, sind in dieser Datei zu finden.
  • tmp/
  • Verwenden Sie dieses Verzeichnis, um temporäre Dateien zu schreiben, die zwischen App-Starts nicht erhalten bleiben müssen.
  • Enthält nicht-persistente Cache-Dateien.
  • Für Benutzer unsichtbar.
  • Inhalte in diesem Verzeichnis werden nicht gesichert.
  • Das OS kann die Dateien in diesem Verzeichnis automatisch löschen, wenn die App nicht läuft und der Speicherplatz knapp wird.

Werfen wir einen genaueren Blick auf iGoat-Swift’s Application Bundle (.app) Verzeichnis innerhalb des Bundle-Verzeichnisses (/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app):

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

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

Binary Reversing

Innerhalb des Ordners <application-name>.app finden Sie eine Binärdatei namens <application-name>. Dies ist die Datei, die ausgeführt wird. Sie können eine grundlegende Inspektion der Binärdatei mit dem Tool otool durchführen:

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)
[...]

Prüfe, ob die App verschlüsselt ist

Prüfe, ob es eine Ausgabe für Folgendes gibt:

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

Disassemblieren der Binärdatei

Disassemblieren der text section:

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

Um das Objective-C-Segment der Beispielanwendung auszugeben, kann man Folgendes verwenden:

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

Um einen kompakteren Objective-C-Code zu erhalten, können Sie class-dump verwenden:

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

However, the best options to disassemble the binary are: Hopper and IDA.

Datenspeicherung

Um zu erfahren, wie iOS Daten auf dem Gerät speichert, lies diese Seite:

iOS Basics

Warning

Die folgenden Orte zum Speichern von Informationen sollten direkt nach der Installation der Anwendung, nach Überprüfung aller Funktionalitäten der Anwendung und sogar nach dem Ab- und wieder Einloggen mit einem anderen Benutzer überprüft werden.
Das Ziel ist es, ungeschützte sensible Informationen der Anwendung (Passwörter, Tokens), des aktuellen Benutzers und zuvor eingeloggter Benutzer zu finden.

Plist

plist-Dateien sind strukturierte XML-Dateien, die Schlüssel-Wert-Paare enthalten. Es ist eine Möglichkeit, persistente Daten zu speichern, daher findet man manchmal sensitive information in diesen Dateien. Es wird empfohlen, diese Dateien nach der Installation der App und nach intensiver Nutzung zu überprüfen, um zu sehen, ob neue Daten geschrieben wurden.

Die gebräuchlichste Methode, Daten in plist-Dateien zu persistieren, ist die Verwendung von NSUserDefaults. Diese plist-Datei wird im App-Sandbox in Library/Preferences/<appBundleID>.plist gespeichert.

Die Klasse NSUserDefaults bietet eine programmatische Schnittstelle zur Interaktion mit dem Default-System. Das Default-System erlaubt einer Anwendung, ihr Verhalten entsprechend den Benutzereinstellungen anzupassen. Von NSUserDefaults gespeicherte Daten können im Application Bundle eingesehen werden. Diese Klasse speichert Daten in einer plist-Datei, ist jedoch für geringe Datenmengen ausgelegt.

Auf diese Daten kann nicht mehr direkt über einen vertrauenswürdigen Computer zugegriffen werden, aber sie können durch ein Backup zugänglich gemacht werden.

Sie können die mit NSUserDefaults gespeicherten Informationen mit objection’s ios nsuserdefaults get dumpen

Um alle vom Application verwendeten plist-Dateien zu finden, können Sie auf /private/var/mobile/Containers/Data/Application/{APPID} zugreifen und ausführen:

find ./ -name "*.plist"

Um Dateien vom Format XML oder binär (bplist) nach XML zu konvertieren, stehen je nach Betriebssystem verschiedene Methoden zur Verfügung:

Für macOS-Benutzer: Verwenden Sie den plutil-Befehl. Es ist ein in macOS (10.2+) integriertes Werkzeug, das für diesen Zweck entwickelt wurde:

$ plutil -convert xml1 Info.plist

Für Linux-Benutzer: Installieren Sie zuerst libplist-utils, dann verwenden Sie plistutil, um Ihre Datei zu konvertieren:

$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist

Innerhalb einer Objection Session: Für die Analyse mobiler Anwendungen ermöglicht ein bestimmter Befehl, plist files direkt zu konvertieren:

ios plist cat /private/var/mobile/Containers/Data/Application/<Application-UUID>/Library/Preferences/com.some.package.app.plist

Core Data

Core Data ist ein Framework zur Verwaltung der Modellschicht von Objekten in deiner Anwendung. Core Data can use SQLite as its persistent store, aber das Framework selbst ist keine Datenbank.
CoreData verschlüsselt seine Daten standardmäßig nicht. Allerdings kann eine zusätzliche Verschlüsselungsschicht zu CoreData hinzugefügt werden. Siehe das GitHub Repo für weitere Details.

Die SQLite Core Data-Informationen einer Anwendung findest du im Pfad /private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support

Wenn du die SQLite öffnen und auf sensitive Informationen zugreifen kannst, dann hast du eine Fehlkonfiguration gefunden.

-(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 ist ein key/value store, der auf SQLite aufbaut.
Da die Yap-Datenbanken SQLite-Datenbanken sind, kannst du sie mit dem im vorherigen Abschnitt genannten Befehl finden.

Andere SQLite-Datenbanken

Es ist üblich, dass Anwendungen ihre eigene SQLite-Datenbank erstellen. Sie können dort sensible Daten speichern und diese unverschlüsselt lassen. Daher ist es immer interessant, jede Datenbank im Anwendungsverzeichnis zu überprüfen. Gehe dazu in das Anwendungsverzeichnis, in dem die Daten gespeichert werden (/private/var/mobile/Containers/Data/Application/{APPID})

find ./ -name "*.sqlite" -or -name "*.db"

Firebase Real-Time Databases

Mit Firebase Real-Time Databases können Entwickler Daten in einer NoSQL cloud-hosted database speichern und synchronisieren. Die im JSON-Format gespeicherten Daten werden in Echtzeit an alle verbundenen Clients synchronisiert.

Anleitungen, wie man auf fehlkonfigurierte Firebase-Datenbanken prüft, finden Sie hier:

Firebase Database

Realm databases

Realm Objective-C und Realm Swift bieten eine leistungsstarke Alternative zur Datenspeicherung, die nicht von Apple bereitgestellt wird. Standardmäßig speichern sie Daten unverschlüsselt. Eine Verschlüsselung ist über eine spezielle Konfiguration verfügbar.

Die Datenbanken befinden sich unter: /private/var/mobile/Containers/Data/Application/{APPID}. Um diese Dateien zu untersuchen, kann man Befehle wie die folgenden verwenden:

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*"

Zum Anzeigen dieser Datenbankdateien wird das Tool Realm Studio empfohlen.

Um Verschlüsselung innerhalb einer Realm-Datenbank zu implementieren, kann der folgende Code-Snipsel verwendet werden:

// Open the encrypted Realm file where getKey() is a method to obtain a key from the Keychain or a server
let config = Realm.Configuration(encryptionKey: getKey())
do {
let realm = try Realm(configuration: config)
// Use the Realm as normal
} catch let error as NSError {
// If the encryption key is wrong, `error` will say that it's an invalid database
fatalError("Error opening realm: \(error)")
}

Couchbase Lite Datenbanken

Couchbase Lite wird als leichtgewichtige und eingebettete Datenbank-Engine beschrieben, die dem dokumentenorientierten (NoSQL) Ansatz folgt. Für iOS und macOS entwickelt, bietet sie die Möglichkeit, Daten nahtlos zu synchronisieren.

Um potenzielle Couchbase-Datenbanken auf einem Gerät zu identifizieren, sollte folgendes Verzeichnis inspiziert werden:

ls /private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support/

Cookies

iOS speichert die Cookies der Apps in der Library/Cookies/cookies.binarycookies im jeweiligen App-Ordner. Entwickler speichern sie jedoch manchmal im keychain, da die erwähnte cookie file in Backups zugänglich sein kann.

Um die cookie file zu untersuchen, kannst du this python script verwenden oder objection’s ios cookies get.
Du kannst objection auch verwenden, um diese Dateien in ein JSON-Format zu konvertieren und die Daten zu prüfen.

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

Standardmäßig speichert NSURLSession Daten, wie z. B. HTTP requests and responses in the Cache.db Datenbank. Diese Datenbank kann sensitive data enthalten, wenn tokens, usernames oder andere sensible Informationen zwischengespeichert wurden. Um die gecachten Informationen zu finden, öffne das Data-Verzeichnis der App (/var/mobile/Containers/Data/Application/<UUID>) und gehe zu /Library/Caches/<Bundle Identifier>. Der WebKit cache is also being stored in the Cache.db Datei. Objection kann die Datenbank mit dem Befehl sqlite connect Cache.db öffnen und damit interagieren, da es sich um eine normal SQLite database handelt.

Es wird empfohlen, das Caching dieser Daten zu deaktivieren, da sie sensitive information in der Anfrage oder Antwort enthalten können. Die folgende Liste zeigt verschiedene Möglichkeiten, dies zu erreichen:

  1. Es wird empfohlen, Cached responses nach dem Logout zu entfernen. Das kann mit der von Apple bereitgestellten Methode removeAllCachedResponses erfolgen. Diese Methode kannst du wie folgt aufrufen:

URLCache.shared.removeAllCachedResponses()

Diese Methode entfernt alle gecachten requests und responses aus der Cache.db-Datei.

  1. Falls du die Vorteile von Cookies nicht benötigst, empfiehlt es sich, die Configuration-Eigenschaft .ephemeral von URLSession zu verwenden; dadurch wird das Speichern von Cookies und Caches deaktiviert.

Apple documentation:

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.

  1. Cache kann auch deaktiviert werden, indem die Cache Policy auf .notAllowed gesetzt wird. Dadurch wird das Speichern von Cache in jeglicher Form deaktiviert, weder im Arbeitsspeicher noch auf der Festplatte.

Snapshots

Immer wenn du den Home-Button drückst, iOS takes a snapshot of the current screen, um die Transition zur Anwendung deutlich flüssiger zu gestalten. Befinden sich jedoch sensitive data auf dem aktuellen Bildschirm, werden diese in dem image gespeichert (welches persists across reboots). Diese Snapshots sind dieselben, die du auch durch zweimaliges Tippen des Home-Buttons siehst, wenn du zwischen Apps wechselst.

Sofern das iPhone nicht jailbroken ist, muss der attacker physischen access zum device haben (entsperrt), um diese Screenshots sehen zu können. Standardmäßig wird der letzte Snapshot im Sandbox-Verzeichnis der Anwendung in Library/Caches/Snapshots/ oder Library/SplashBoard/Snapshots gespeichert (trusted computers können seit iOS 7.0 nicht mehr auf das Filesystem zugreifen).

Eine Möglichkeit, dieses unerwünschte Verhalten zu verhindern, ist, vor dem Erstellen des Snapshots einen leeren Bildschirm anzuzeigen oder die sensitiven Daten zu entfernen, zum Beispiel innerhalb der ApplicationDidEnterBackground()-Funktion.

Das folgende Beispiel zeigt eine Remediation-Methode, die einen Standard-Screenshot setzt.

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];
}

Dies setzt das Hintergrundbild auf overlayImage.png, wann immer die Anwendung in den Hintergrund wechselt. Es verhindert sensitive data leaks, da overlayImage.png stets die aktuelle Ansicht überschreibt.

Keychain

Zum Zugriff auf und zur Verwaltung des iOS keychain stehen Tools wie Keychain-Dumper zur Verfügung, die sich für jailbroken devices eignen. Außerdem stellt Objection den Befehl ios keychain dump für ähnliche Zwecke zur Verfügung.

Anmeldeinformationen speichern

Die Klasse NSURLCredential eignet sich ideal, um sensible Informationen direkt im keychain zu speichern und so die Notwendigkeit von NSUserDefaults oder anderen Wrappern zu umgehen. Um Credentials nach dem Login zu speichern, wird der folgende Swift-Code verwendet:

NSURLCredential *credential;
credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistencePermanent];
[[NSURLCredentialStorage sharedCredentialStorage] setCredential:credential forProtectionSpace:self.loginProtectionSpace];

Um diese gespeicherten Anmeldedaten zu extrahieren, wird der Befehl von Objection ios nsurlcredentialstorage dump verwendet.

Benutzerdefinierte Tastaturen und Tastatur-Cache

Ab iOS 8.0 können Benutzer benutzerdefinierte Tastaturerweiterungen installieren, die unter Settings > General > Keyboard > Keyboards verwaltet werden können. Während diese Tastaturen erweiterte Funktionen bieten, bergen sie das Risiko von Keylogging und der Übertragung von Daten an externe Server. Benutzer werden jedoch über Tastaturen informiert, die Netzwerkzugriff benötigen. Apps können und sollten die Verwendung benutzerdefinierter Tastaturen für die Eingabe sensibler Informationen einschränken.

Sicherheitsempfehlungen:

  • Es wird empfohlen, Drittanbieter-Tastaturen zu deaktivieren, um die Sicherheit zu erhöhen.
  • Achten Sie auf die Autokorrektur- und Auto-Vorschlagsfunktionen der Standard-iOS-Tastatur, da diese sensible Informationen in Cache-Dateien speichern könnten, die sich in Library/Keyboard/{locale}-dynamic-text.dat oder /private/var/mobile/Library/Keyboard/dynamic-text.dat befinden. Diese Cache-Dateien sollten regelmäßig auf sensible Daten überprüft werden. Zum Löschen zwischengespeicherter Daten wird empfohlen, das Keyboard Dictionary über Settings > General > Reset > Reset Keyboard Dictionary zurückzusetzen.
  • Das Abfangen von Netzwerkverkehr kann aufdecken, ob eine benutzerdefinierte Tastatur Tastatureingaben an entfernte Server sendet.

Verhinderung des Zwischenspeicherns von Textfeldern

Der UITextInputTraits protocol bietet Eigenschaften zur Steuerung von Autokorrektur und sicherer Texteingabe, die wichtig sind, um das Zwischenspeichern sensibler Informationen zu verhindern. Zum Beispiel kann das Deaktivieren der Autokorrektur und das Aktivieren der sicheren Texteingabe wie folgt erreicht werden:

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

Außerdem sollten Entwickler sicherstellen, dass Textfelder, insbesondere solche zum Eingeben sensibler Informationen wie Passwörter und PINs, das Caching deaktivieren, indem sie autocorrectionType auf UITextAutocorrectionTypeNo und secureTextEntry auf YES setzen.

UITextField *textField = [[UITextField alloc] initWithFrame:frame];
textField.autocorrectionType = UITextAutocorrectionTypeNo;

Logs

Das Debuggen von Code beinhaltet oft die Verwendung von logging. Dabei besteht das Risiko, dass logs sensible Informationen enthalten können. Früher, in iOS 6 und älteren Versionen, waren logs für alle Apps zugänglich, was das Risiko eines sensiblen Datenleaks darstellte. Jetzt dürfen Anwendungen nur auf ihre eigenen logs zugreifen.

Trotz dieser Einschränkungen kann ein Angreifer mit physischem Zugriff auf ein entsperrtes Gerät dies immer noch ausnutzen, indem er das Gerät an einen Computer anschließt und die logs ausliest. Wichtig zu beachten ist, dass logs auf der Festplatte verbleiben, selbst nach der Deinstallation der App.

Um Risiken zu mindern, wird empfohlen, gründlich mit der App zu interagieren, alle Funktionen und Eingaben zu prüfen, um sicherzustellen, dass keine sensiblen Informationen unbeabsichtigt geloggt werden.

Beim Durchsehen des Quellcodes der App auf potenzielle leaks, suchen Sie sowohl nach vordefinierten als auch benutzerdefinierten logging-Anweisungen, wobei Sie nach Schlüsselwörtern wie NSLog, NSAssert, NSCAssert, fprintf für eingebaute Funktionen und nach Erwähnungen von Logging oder Logfile für eigene Implementierungen suchen.

Monitoring System Logs

Apps protokollieren verschiedene Informationen, die sensibel sein können. Um diese logs zu überwachen, eignen sich Tools und Befehle wie:

idevice_id --list   # To find the device ID
idevicesyslog -u <id> (| grep <app>)   # To capture the device logs

sind nützlich. Zusätzlich bietet Xcode eine Möglichkeit, Konsolen-Logs zu sammeln:

  1. Öffne Xcode.
  2. Verbinde das iOS-Gerät.
  3. Gehe zu Window -> Devices and Simulators.
  4. Wähle dein Gerät aus.
  5. Reproduziere das Problem, das du untersuchst.
  6. Verwende den Open Console-Button, um die Logs in einem neuen Fenster anzuzeigen.

Für erweitertes Logging kann das Verbinden mit der Geräte-Shell und die Verwendung von socat eine Überwachung der Logs in Echtzeit ermöglichen:

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

Gefolgt von Befehlen, um Log-Aktivitäten zu beobachten, die sich als äußerst wertvoll beim Diagnostizieren von Problemen oder beim Identifizieren potenzieller data leaks in Logs erweisen können.

Backups

Auto-backup-Funktionen sind in iOS integriert und ermöglichen das Erstellen von Kopien der Gerätedaten über iTunes (bis macOS Catalina), Finder (ab macOS Catalina) oder iCloud. Diese Backups umfassen fast alle Gerätedaten, ausgenommen hochsensible Elemente wie Apple Pay-Details und Touch ID-Konfigurationen.

Sicherheitsrisiken

Die Aufnahme von installierten Apps und deren Daten in Backups wirft das Problem potenzieller data leaks und das Risiko auf, dass Backup-Modifikationen die App-Funktionalität verändern könnten. Es wird empfohlen, sensible Informationen nicht im Klartext innerhalb des App-Verzeichnisses oder dessen Unterverzeichnissen zu speichern, um diese Risiken zu mindern.

Ausschluss von Dateien aus Backups

Dateien in Documents/ und Library/Application Support/ werden standardmäßig gesichert. Entwickler können bestimmte Dateien oder Verzeichnisse mithilfe von NSURL setResourceValue:forKey:error: mit dem NSURLIsExcludedFromBackupKey von Backups ausschließen. Diese Vorgehensweise ist entscheidend, um zu verhindern, dass sensible Daten in Backups aufgenommen werden.

Testen auf Schwachstellen

Um die Backup-Sicherheit einer App zu bewerten, beginnen Sie mit dem Erstellen eines Backups mittels Finder und suchen dieses anschließend gemäß den Anweisungen in Apple’s official documentation. Analysieren Sie das Backup auf sensible Daten oder Konfigurationen, die verändert werden könnten, um das App-Verhalten zu beeinflussen.

Sensible Informationen können mit Kommandozeilen-Tools oder Anwendungen wie iMazing gesucht werden. Bei verschlüsselten Backups kann das Vorhandensein der Verschlüsselung durch Überprüfen des “IsEncrypted”-Schlüssels in der Datei “Manifest.plist” im Root des Backups bestätigt werden.

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

Für den Umgang mit verschlüsselten Backups können Python-Skripte im DinoSec’s GitHub repo, wie backup_tool.py und backup_passwd.py, nützlich sein, erfordern jedoch möglicherweise Anpassungen, um mit den neuesten iTunes/Finder-Versionen kompatibel zu sein. Das iOSbackup tool ist eine weitere Option, um auf Dateien innerhalb passwortgeschützter Backups zuzugreifen.

Modifizieren des App-Verhaltens

Ein Beispiel für das Ändern des App-Verhaltens durch Backup-Modifikationen zeigt die Bither bitcoin wallet app, wo die UI-Lock-PIN innerhalb von net.bither.plist unter dem pin_code-Schlüssel gespeichert ist. Entfernt man diesen Schlüssel aus der plist und stellt das Backup wieder her, entfällt die PIN-Abfrage und es wird uneingeschränkter Zugriff gewährt.

Zusammenfassung zum Memory Testing sensibler Daten

Beim Umgang mit sensiblen Informationen, die im Speicher einer Anwendung abgelegt sind, ist es entscheidend, die Expositionsdauer dieser Daten zu begrenzen. Es gibt zwei primäre Ansätze, um den Speicherinhalt zu untersuchen: creating a memory dump und analyzing the memory in real time. Beide Methoden haben ihre Herausforderungen, einschließlich der Möglichkeit, während des Dump-Vorgangs oder der Analyse kritische Daten zu übersehen.

Abrufen und Analysieren eines Memory Dumps

Sowohl für jailbroken als auch für non-jailbroken Geräte erlauben Tools wie objection und Fridump das Dumpen des Prozessspeichers einer App. Nach dem Dump erfordert die Analyse dieser Daten verschiedene Tools, abhängig von der Art der Informationen, nach denen Sie suchen.

Um Strings aus einem Memory Dump zu extrahieren, können Befehle wie strings oder rabin2 -zz verwendet werden:

# Extracting strings using strings command
$ strings memory > strings.txt

# Extracting strings using rabin2
$ rabin2 -ZZ memory > strings.txt

Für detailliertere Analysen, einschließlich der Suche nach bestimmten Datentypen oder Mustern, bietet radare2 umfangreiche Suchfunktionen:

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

Speicheranalyse zur Laufzeit

r2frida bietet eine leistungsstarke Alternative, um den Speicher einer App in Echtzeit zu untersuchen, ohne einen memory dump zu benötigen. Dieses Tool ermöglicht die Ausführung von Suchbefehlen direkt im Speicher der laufenden Anwendung:

$ r2 frida://usb//<name_of_your_app>
[0x00000000]> /\ <search_command>

Broken Cryptography

Poor Key Management Processes

Einige Entwickler speichern sensible Daten im local storage und verschlüsseln sie mit einem key, der im code hardcoded/predictable ist. Das sollte nicht gemacht werden, da Reversing Angreifern ermöglichen könnte, vertrauliche Informationen zu extrahieren.

Use of Insecure and/or Deprecated Algorithms

Entwickler sollten keine deprecated algorithms verwenden, um Autorisierungs-checks durchzuführen, Daten zu store oder zu send. Einige dieser Algorithmen sind: RC4, MD4, MD5, SHA1… Wenn hashes z. B. zum Speichern von Passwörtern verwendet werden, sollten brute-force-resistant hashes mit salt verwendet werden.

Check

Die wichtigsten Checks bestehen darin herauszufinden, ob hardcoded Passwörter/Secrets im code vorhanden sind, ob diese predictable sind und ob der code irgendeine Art von weak cryptography-Algorithmen verwendet.

Es ist interessant zu wissen, dass man einige crypto libraries automatisch mit objection monitoren kann mit:

ios monitor crypt

Für weitere Informationen zu iOS-kryptografischen APIs und Bibliotheken siehe https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06e-testing-cryptography

Lokale Authentifizierung

Lokale Authentifizierung spielt eine entscheidende Rolle, besonders wenn es darum geht, Zugriff auf einen entfernten Endpunkt mit kryptografischen Methoden zu schützen. Der Kernpunkt ist, dass lokale Authentifizierungsmechanismen bei mangelhafter Implementierung umgangen werden können.

Apples Local Authentication framework und der keychain bieten Entwicklern robuste APIs, um Benutzer-Authentifizierungsdialoge zu ermöglichen bzw. geheime Daten sicher zu verwalten. Die Secure Enclave sichert Fingerabdruck-IDs für Touch ID, während Face ID auf Gesichtserkennung basiert, ohne biometrische Daten zu kompromittieren.

Zur Integration von Touch ID/Face ID haben Entwickler zwei API-Optionen:

  • LocalAuthentication.framework für hochstufige Benutzer-Authentifizierung ohne Zugriff auf biometrische Daten.
  • Security.framework für niedrigere Ebene Zugriff auf keychain-Services, schützt geheime Daten mit biometrischer Authentifizierung. Verschiedene open-source wrappers erleichtern den keychain-Zugriff.

Caution

Allerdings weisen sowohl LocalAuthentication.framework als auch Security.framework Schwachstellen auf, da sie hauptsächlich boolesche Werte zurückgeben, ohne Daten für Authentifizierungsprozesse zu übermitteln, wodurch sie anfällig für Umgehungen sind (siehe Don’t touch me that way, by David Lindner et al).

Implementierung der lokalen Authentifizierung

Um Benutzer zur Authentifizierung aufzufordern, sollten Entwickler die Methode evaluatePolicy der Klasse LAContext verwenden und dabei wählen zwischen:

  • deviceOwnerAuthentication: fordert Touch ID oder Geräte-Passcode an, schlägt fehl, wenn keiner aktiviert ist.
  • deviceOwnerAuthenticationWithBiometrics: fordert ausschließlich Touch ID an.

Eine erfolgreiche Authentifizierung wird durch einen booleschen Rückgabewert von evaluatePolicy angezeigt, was eine potenzielle Sicherheitslücke verdeutlicht.

Lokale Authentifizierung mit Keychain

Die Implementierung von lokaler Authentifizierung in iOS-Apps beinhaltet die Verwendung von keychain APIs, um geheime Daten wie Authentifizierungstoken sicher zu speichern. Dieser Prozess stellt sicher, dass die Daten nur vom Benutzer unter Verwendung seines Geräte-Passcodes oder biometrischer Authentifizierung wie Touch ID abgerufen werden können.

Die keychain bietet die Möglichkeit, Einträge mit dem Attribut SecAccessControl zu setzen, das den Zugriff auf den Eintrag einschränkt, bis sich der Benutzer erfolgreich über Touch ID oder Geräte-Passcode authentifiziert. Diese Funktion ist wichtig zur Erhöhung der Sicherheit.

Nachfolgend finden sich Codebeispiele in Swift und Objective-C, die zeigen, wie eine Zeichenkette in der keychain gespeichert und abgerufen wird, wobei diese Sicherheitsfunktionen genutzt werden. Die Beispiele zeigen speziell, wie Access Control so eingerichtet wird, dass Touch ID-Authentifizierung erforderlich ist und die Daten nur auf dem Gerät zugänglich sind, auf dem sie eingerichtet wurden, vorausgesetzt, es ist ein Geräte-Passcode konfiguriert.

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

Jetzt können wir das gespeicherte Item aus dem Keychain anfordern. Keychain-Services zeigen dem Benutzer den Authentifizierungsdialog und geben Daten oder nil zurück, je nachdem, ob ein geeigneter fingerprint bereitgestellt wurde oder nicht.

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

Erkennung

Die Verwendung von Frameworks in einer App kann auch erkannt werden, indem die Liste der gemeinsam genutzten dynamischen Bibliotheken der App-Binärdatei analysiert wird. Dies kann mit otool erfolgen:

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

Wenn LocalAuthentication.framework in einer App verwendet wird, enthält die Ausgabe beide der folgenden Zeilen (beachte, dass LocalAuthentication.framework Security.framework unter der Haube verwendet):

/System/Library/Frameworks/LocalAuthentication.framework/LocalAuthentication
/System/Library/Frameworks/Security.framework/Security

Wenn Security.framework verwendet wird, wird nur das zweite angezeigt.

LocalAuthentication Framework Bypass

Objection

Durch den Objection Biometrics Bypass, zu finden auf this GitHub page, steht eine Technik zur Verfügung, um den LocalAuthentication-Mechanismus zu überwinden. Der Kern dieses Ansatzes besteht darin, Frida zu nutzen, um die Funktion evaluatePolicy zu manipulieren, sodass sie konsequent True zurückgibt, unabhängig vom tatsächlichen Authentifizierungs-Erfolg. Das ist besonders nützlich, um fehlerhafte biometrische Authentifizierungsprozesse zu umgehen.

Um diesen Bypass zu aktivieren, wird der folgende Befehl verwendet:

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

Dieser Befehl löst eine Sequenz aus, bei der Objection eine Aufgabe registriert, die das Ergebnis der evaluatePolicy-Prüfung effektiv auf True verändert.

Frida

Ein Beispiel für die Verwendung von evaluatePolicy aus 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"];
});
}
}

Um den bypass von Local Authentication zu erreichen, wird ein Frida-Skript geschrieben. Dieses Skript zielt auf die evaluatePolicy-Prüfung ab und fängt dessen Callback ab, um sicherzustellen, dass er success=1 zurückgibt. Durch das Verändern des Verhaltens des Callbacks wird die Authentifizierungsprüfung effektiv bypassed.

Das untenstehende Skript wird injiziert, um das Ergebnis der evaluatePolicy-Methode zu ändern. Es verändert das Ergebnis des Callbacks so, dass es immer Erfolg anzeigt.

// 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!");
}

Um das Frida-Skript zu injizieren und die biometrische Authentifizierung zu umgehen, wird folgender Befehl verwendet:

frida -U -f com.highaltitudehacks.DVIAswiftv2 --no-pause -l fingerprint-bypass-ios.js

Offenlegung sensibler Funktionalität über IPC

iOS Custom URI Handlers / Deeplinks / Custom Schemes

iOS Universal Links

UIActivity Sharing

iOS UIActivity Sharing

UIPasteboard

iOS UIPasteboard

App Extensions

iOS App Extensions

WebViews

iOS WebViews

Serialisation and Encoding

iOS Serialisation and Encoding

Netzwerkkommunikation

Es ist wichtig zu prüfen, dass keine Kommunikation ohne Verschlüsselung stattfindet und dass die Anwendung außerdem das TLS-Zertifikat des Servers korrekt validiert.
Um solche Probleme zu prüfen, kann man einen Proxy wie Burp verwenden:

iOS Burp Suite Configuration

Hostname-Prüfung

Ein häufiges Problem bei der Validierung des TLS-Zertifikats ist, dass geprüft wird, ob das Zertifikat von einer vertrauenswürdigen CA signiert wurde, aber nicht geprüft wird, ob der Hostname des Zertifikats mit dem tatsächlich aufgerufenen Hostname übereinstimmt.
Um dieses Problem mit Burp zu testen, kann man nach dem Vertrauen der Burp-CA auf dem iPhone ein neues Zertifikat mit Burp für einen anderen Hostname erstellen und dieses verwenden. Wenn die Anwendung dann weiterhin funktioniert, ist sie verwundbar.

Certificate Pinning

Wenn eine Anwendung korrekt SSL Pinning verwendet, funktioniert die Anwendung nur, wenn das Zertifikat das erwartete ist. Beim Testen einer Anwendung kann das problematisch sein, da Burp sein eigenes Zertifikat ausliefert.
Um diese Schutzmaßnahme innerhalb eines jailbroken Geräts zu umgehen, kannst du die Anwendung SSL Kill Switch installieren oder Burp Mobile Assistant installieren.

Du kannst außerdem objection’s ios sslpinning disable verwenden.

Sonstiges

  • In /System/Library findet man die Frameworks, die auf dem Telefon installiert sind und von Systemanwendungen verwendet werden.
  • Die vom Benutzer aus dem App Store installierten Anwendungen befinden sich in /User/Applications
  • Und /User/Library enthält Daten, die von Anwendungen auf Benutzerebene gespeichert wurden.
  • Auf /User/Library/Notes/notes.sqlite kann man zugreifen, um die in der Anwendung gespeicherten Notizen zu lesen.
  • Im Ordner einer installierten Anwendung (/User/Applications/<APP ID>/) findet man einige interessante Dateien:
  • iTunesArtwork: Das Icon, das von der App verwendet wird
  • iTunesMetadata.plist: Metadaten der App, die im App Store verwendet werden
  • /Library/*: Enthält die Einstellungen und den Cache. In /Library/Cache/Snapshots/* findet man den Snapshot, der erstellt wird, bevor die Anwendung in den Hintergrund geschickt wird.

Hot Patching/Erzwungene Updates

Die Entwickler können alle Installationen ihrer App aus der Ferne sofort patchen, ohne die Anwendung erneut im App Store einreichen und auf Genehmigung warten zu müssen.
Dafür wird üblicherweise JSPatch verwendet. Es gibt jedoch auch andere Optionen wie Siren und react-native-appstore-version-checker.
Dies ist ein gefährlicher Mechanismus, der von bösartigen Third-Party-SDKs missbraucht werden könnte; daher sollte geprüft werden, welche Methode für automatische Updates verwendet wird (falls vorhanden) und sie getestet werden. Du könntest versuchen, zu Testzwecken eine frühere Version der App herunterzuladen.

Drittanbieter

Eine große Herausforderung bei 3rd party SDKs ist die fehlende granulare Kontrolle über deren Funktionalitäten. Entwickler stehen vor der Wahl: entweder das SDK integrieren und alle seine Features akzeptieren — einschließlich möglicher Sicherheitslücken und Datenschutzprobleme — oder ganz auf dessen Vorteile verzichten. Häufig sind Entwickler nicht in der Lage, Schwachstellen in diesen SDKs selbst zu patchen. Außerdem kann es vorkommen, dass SDKs, sobald sie Vertrauen in der Community gewonnen haben, sogar Malware enthalten.

Die von Third-Party-SDKs bereitgestellten Dienste können User-Tracking, Werbung oder Verbesserungen der User Experience umfassen. Das birgt jedoch das Risiko, dass Entwickler nicht vollständig wissen, welcher Code durch diese Bibliotheken ausgeführt wird, was zu möglichen Datenschutz- und Sicherheitsproblemen führt. Es ist entscheidend, die mit Drittanbietern geteilten Informationen auf das Notwendige zu beschränken und sicherzustellen, dass keine sensiblen Daten offengelegt werden.

Die Implementierung von Drittanbieterdiensten erfolgt in der Regel in zwei Formen: als eigenständige Bibliothek oder als komplettes SDK. Zum Schutz der Privatsphäre der Nutzer sollten alle an diese Dienste übermittelten Daten anonymisiert werden, um die Offenlegung von Personal Identifiable Information (PII) zu verhindern.

Um die Bibliotheken zu identifizieren, die eine Anwendung verwendet, kann der otool-Befehl eingesetzt werden. Dieses Tool sollte gegen die Anwendung und jede gemeinsam genutzte Bibliothek ausgeführt werden, die sie nutzt, um weitere Bibliotheken zu entdecken.

otool -L <application_path>

Interessante Schwachstellen & Fallstudien

Air Keyboard Remote Input Injection

Itunesstored Bookassetd Sandbox Escape

Zero Click Messaging Image Parser Chains

Referenzen & Weitere Ressourcen

Tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks