iOS Pentesting
Tip
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
Podstawy iOS
Środowisko testowe
Na tej stronie znajdziesz informacje o iOS simulator, emulators i jailbreaking:
Wstępna analiza
Podstawowe operacje testowania iOS
Podczas testów zostanie zasugerowanych kilka operacji (połączenie z urządzeniem, odczyt/zapis/upload/download plików, użycie narzędzi…). Jeśli nie wiesz jak wykonać którąkolwiek z tych czynności, rozpocznij czytanie strony:
Tip
For the following steps the app should be installed in the device and should have already obtained the IPA file of the application.
Read the Basic iOS Testing Operations page to learn how to do this.
Podstawowa analiza statyczna
Kilka ciekawych dekompilatorów iOS - IPA files:
Zaleca się użycie narzędzia MobSF do wykonania automatycznej analizy statycznej pliku IPA.
Identyfikacja zabezpieczeń obecnych w binarnym pliku:
- PIE (Position Independent Executable): Gdy jest włączone, aplikacja ładuje się pod losowy adres pamięci przy każdym uruchomieniu, co utrudnia przewidzenie początkowego adresu pamięci.
otool -hv <app-binary> | grep PIE # It should include the PIE flag
- Stack Canaries: Aby zweryfikować integralność stosu, przed wywołaniem funkcji umieszczana jest wartość „canary”, która jest sprawdzana po zakończeniu funkcji.
otool -I -v <app-binary> | grep stack_chk # It should include the symbols: stack_chk_guard and stack_chk_fail
- ARC (Automatic Reference Counting): Aby zapobiegać typowym błędom korupcji pamięci
otool -I -v <app-binary> | grep objc_release # It should include the _objc_release symbol
- Encrypted Binary: Binar powinien być zaszyfrowany
otool -arch all -Vl <app-binary> | grep -A5 LC_ENCRYPT # The cryptid should be 1
Identyfikacja wrażliwych/niebezpiecznych funkcji
- Weak Hashing Algorithms
# On the iOS device
otool -Iv <app> | grep -w "_CC_MD5"
otool -Iv <app> | grep -w "_CC_SHA1"
# On linux
grep -iER "_CC_MD5"
grep -iER "_CC_SHA1"
- Insecure Random Functions
# On the iOS device
otool -Iv <app> | grep -w "_random"
otool -Iv <app> | grep -w "_srand"
otool -Iv <app> | grep -w "_rand"
# On linux
grep -iER "_random"
grep -iER "_srand"
grep -iER "_rand"
- Insecure ‘Malloc’ Function
# On the iOS device
otool -Iv <app> | grep -w "_malloc"
# On linux
grep -iER "_malloc"
- Insecure and Vulnerable Functions
# On the iOS device
otool -Iv <app> | grep -w "_gets"
otool -Iv <app> | grep -w "_memcpy"
otool -Iv <app> | grep -w "_strncpy"
otool -Iv <app> | grep -w "_strlen"
otool -Iv <app> | grep -w "_vsnprintf"
otool -Iv <app> | grep -w "_sscanf"
otool -Iv <app> | grep -w "_strtok"
otool -Iv <app> | grep -w "_alloca"
otool -Iv <app> | grep -w "_sprintf"
otool -Iv <app> | grep -w "_printf"
otool -Iv <app> | grep -w "_vsprintf"
# On linux
grep -R "_gets"
grep -iER "_memcpy"
grep -iER "_strncpy"
grep -iER "_strlen"
grep -iER "_vsnprintf"
grep -iER "_sscanf"
grep -iER "_strtok"
grep -iER "_alloca"
grep -iER "_sprintf"
grep -iER "_printf"
grep -iER "_vsprintf"
Typowe metody wykrywania jailbreak
- File System Checks: Sprawdzanie obecności typowych plików i katalogów jailbreak, takich jak
/Applications/Cydia.applub/Library/MobileSubstrate/MobileSubstrate.dylib. - Sandbox Violations: Próba dostępu do zastrzeżonych obszarów systemu plików, które powinny być zablokowane na urządzeniach bez jailbreak.
- API Checks: Sprawdzenie czy można użyć zabronionych wywołań takich jak
fork()do utworzenia procesu potomnego lubsystem()aby sprawdzić czy istnieje /bin/sh. - Process Checks: Monitorowanie obecności znanych procesów związanych z jailbreak, takich jak
Cydia,Substrate, lubssh. - Kernel Exploits: Sprawdzenie obecności exploitów jądra, które są często używane w jailbreakach.
- Environment Variables: Inspekcja zmiennych środowiskowych pod kątem oznak jailbreak, takich jak
DYLD_INSERT_LIBRARIES. - Libraries Check: Sprawdzenie bibliotek załadowanych do procesu aplikacji.
- Check schemes: Na przykład
canOpenURL(URL(string: "cydia://")).
Typowe metody wykrywania anti-debugging
- Check for Debugger Presence: Użycie
sysctllub innych metod do sprawdzenia, czy debugger jest podłączony. - Anti-Debugging APIs: Szukanie wywołań API anti-debugging takich jak
ptracelubSIGSTOP, np.ptrace(PT_DENY_ATTACH, 0, 0, 0). - Timing Checks: Pomiar czasu wykonania pewnych operacji i szukanie rozbieżności mogących wskazywać debugowanie.
- Memory Checks: Inspekcja pamięci pod kątem znanych artefaktów debuggera lub modyfikacji.
- Environment Variables: Sprawdzanie zmiennych środowiskowych, które mogą wskazywać sesję debugowania.
- Mach Ports: Wykrywanie czy mach exception ports są używane przez debugery.
Anti-Debugging & Anti-Tamper Techniques (Layered Checks)
Aplikacje z prawdziwego świata często nakładają kontrole pre-exec, on-attach oraz ciągłe. Typowe wzorce do zidentyfikowania (i sposoby ich neutralizacji podczas testów):
- Private API side-channel fingerprinting: prywatne launch API (np.
SBSLaunchApplicationWithIdentifierAndURLAndLaunchOptions) są nadużywane do sprawdzania zainstalowanych bundle ID (com.opa334.TrollStore,org.coolstar.SileoStore,com.tigisoftware.Filza, itd.) na podstawie kodów zwrotnych/logów. Zhakuj (hook) wywołanie i oczyszczaj argumenty/wartości zwracane, aby emulować czyste urządzenie. - Self-attestation via code-signing state:
csops()zCS_OPS_ENTITLEMENTS_BLOBodczytuje entitlements; nieoczekiwane wartości powodują zakończenie działania. Łączy się to z kontrolą integralności (CRC32/MD5 zasobów, weryfikacja certyfikatów, metadane Mach-O jakLC_ENCRYPTION_INFO_64) w celu wykrycia ponownego podpisania lub załatania. Instrumentuj te rutyny i wymuszaj “oczekiwane” wyniki podczas analizy. - Kill-on-attach:
ptrace(PT_DENY_ATTACH)w połączeniu zabort()/exit()podczas attach. Obejście przez unieszkodliwienie ścieżki zakończenia lub hookowanieptracetak, by zakończyło się sukcesem bez wymuszania odmowy. - Crash forensics sabotage: nadpisywanie rejestrów CPU przed awarią, by zniszczyć backtrace. Lepiej stosować breakpointy/hooki wcześniej w ścieżce detekcji zamiast polegać na logach awarii.
- Jetsam-based termination: celowe wywołanie presji pamięciowej by uruchomić jetsam, który nie generuje normalnego logu awarii. Szukaj dużych alokacji wokół logiki detekcji i ogranicz/skrótuj je, aby zachować logi.
- Continuous checks with delayed enforcement: timery heartbeat ponownie uruchamiają detekcję i egzekwują później. Śledź timery/dispatch sources i utrzymuj proces przy życiu, omijając opóźnioną ścieżkę zabicia.
Podstawowa analiza dynamiczna
Sprawdź analizę dynamiczną, którą wykonuje MobSF. Będziesz musiał przechodzić przez różne widoki i wchodzić z nimi w interakcję — narzędzie będzie hookować kilka klas przy realizowaniu różnych zadań i przygotuje raport po zakończeniu.
Wyświetlanie zainstalowanych aplikacji
Użyj polecenia frida-ps -Uai aby określić bundle identifier zainstalowanych aplikacji:
$ 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
Dowiedz się, jak enumerate the components of the application oraz jak łatwo hook methods and classes za pomocą objection:
Struktura IPA
Struktura pliku IPA file jest w zasadzie taka sama jak zipped package. Zmieniając jego rozszerzenie na .zip, można go dekompresować, aby odsłonić zawartość. W tej strukturze Bundle reprezentuje w pełni zapakowaną aplikację gotową do instalacji. Wewnątrz znajdziesz katalog o nazwie <NAME>.app, który kapsułkuje zasoby aplikacji.
Info.plist: Ten plik zawiera szczegółowe informacje konfiguracyjne aplikacji._CodeSignature/: Ten katalog zawiera plik plist, który zawiera podpis, zapewniający integralność wszystkich plików w bundle.Assets.car: Skompresowane archiwum przechowujące pliki zasobów, takie jak ikony.Frameworks/: Ten folder mieści natywne biblioteki aplikacji, które mogą występować w postaci plików.dyliblub.framework.PlugIns/: Ten katalog może zawierać rozszerzenia aplikacji, znane jako pliki.appex, choć nie zawsze występują. *Core Data: Służy do zapisywania trwałych danych aplikacji do użytku offline, cache’owania danych tymczasowych oraz dodawania funkcji cofania (undo) w aplikacji na pojedynczym urządzeniu. Aby synchronizować dane między wieloma urządzeniami w ramach jednego konta iCloud, Core Data automatycznie odwzorowuje schemat do kontenera CloudKit.PkgInfo: PlikPkgInfojest alternatywnym sposobem określania kodów typu i twórcy twojej aplikacji lub bundle.- en.lproj, fr.proj, Base.lproj: To pakiety językowe zawierające zasoby dla tych konkretnych języków oraz domyślne zasoby na wypadek, gdy dany język nie jest wspierany.
- Bezpieczeństwo: Katalog
_CodeSignature/odgrywa kluczową rolę w bezpieczeństwie aplikacji, weryfikując integralność wszystkich dołączonych plików za pomocą podpisów cyfrowych. - Zarządzanie zasobami: Plik
Assets.carwykorzystuje kompresję do efektywnego zarządzania zasobami graficznymi, co jest kluczowe dla optymalizacji wydajności aplikacji i zmniejszenia jej rozmiaru. - Frameworks and PlugIns: Te katalogi podkreślają modularność aplikacji iOS, pozwalając deweloperom dołączać wielokrotnego użytku biblioteki kodu (
Frameworks/) oraz rozszerzać funkcjonalność aplikacji (PlugIns/). - Lokalizacja: Struktura wspiera wiele języków, ułatwiając globalne dotarcie aplikacji poprzez dołączanie zasobów dla konkretnych pakietów językowych.
Info.plist
Plik Info.plist służy jako kamień węgielny aplikacji iOS, kapsułkując kluczowe dane konfiguracyjne w postaci par key-value. Plik ten jest wymagany nie tylko dla aplikacji, lecz także dla rozszerzeń aplikacji i frameworków dołączonych w bundle. Ma strukturę w formacie XML lub binarnym i zawiera krytyczne informacje — od uprawnień aplikacji po konfiguracje bezpieczeństwa. Aby szczegółowo zapoznać się z dostępnymi kluczami, można odwołać się do Apple Developer Documentation.
Dla tych, którzy chcą pracować z tym plikiem w bardziej dostępnym formacie, konwersję do XML można łatwo przeprowadzić za pomocą plutil na macOS (dostępnego natywnie w wersjach 10.2 i nowszych) lub plistutil na Linuxie. Polecenia do konwersji są następujące:
- Dla macOS:
$ plutil -convert xml1 Info.plist
- Dla Linuxa:
$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist
Spośród mnogości informacji, które plik Info.plist może ujawnić, godne uwagi wpisy to ciągi uprawnień aplikacji (UsageDescription), niestandardowe schematy URL (CFBundleURLTypes) oraz konfiguracje App Transport Security (NSAppTransportSecurity). Te wpisy, wraz z innymi, takimi jak eksportowane/importowane niestandardowe typy dokumentów (UTExportedTypeDeclarations / UTImportedTypeDeclarations), można z łatwością znaleźć, przeglądając plik lub używając prostego polecenia grep:
$ grep -i <keyword> Info.plist
Ścieżki danych
W środowisku iOS katalogi są przeznaczone oddzielnie dla aplikacji systemowych i aplikacji zainstalowanych przez użytkownika. Aplikacje systemowe znajdują się w katalogu /Applications, natomiast aplikacje zainstalowane przez użytkownika są umieszczone w /var/mobile/containers/Data/Application/. Każdej z tych aplikacji przypisywany jest unikatowy identyfikator znany jako 128-bit UUID, co utrudnia ręczne odnalezienie folderu aplikacji ze względu na losowość nazw katalogów.
Warning
Ponieważ aplikacje w iOS muszą być sandboxed, każda aplikacja będzie miała również folder w
$HOME/Library/Containerso nazwie będącejCFBundleIdentifieraplikacji.Jednak oba foldery (folder danych i folder kontenera) zawierają plik
.com.apple.mobile_container_manager.metadata.plist, który łączy oba foldery w kluczuMCMetadataIdentifier).
Aby ułatwić odkrycie katalogu instalacyjnego aplikacji zainstalowanej przez użytkownika, narzędzie objection udostępnia przydatne polecenie env. Polecenie to ujawnia szczegółowe informacje o katalogach dla danej aplikacji. Poniżej znajduje się przykład użycia tego polecenia:
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
Alternatywnie, nazwę aplikacji można wyszukać w katalogu /private/var/containers przy użyciu polecenia find:
find /private/var/containers -name "Progname*"
Polecenia takie jak ps i lsof można również wykorzystać odpowiednio do zidentyfikowania procesu aplikacji oraz wypisania otwartych plików, co daje wgląd w aktywne ścieżki katalogów aplikacji:
ps -ef | grep -i <app-name>
lsof -p <pid> | grep -i "/containers" | head -n 1
Bundle directory:
- AppName.app
- Jest to Application Bundle, jak wcześniej w IPA — zawiera istotne dane aplikacji, statyczne zasoby oraz skompilowany binarny plik aplikacji.
- Ten katalog jest widoczny dla użytkowników, ale użytkownicy nie mogą w nim zapisywać.
- Zawartość tego katalogu nie jest objęta kopią zapasową.
- Zawartość tego folderu jest używana do weryfikacji podpisu kodu.
Data directory:
- Documents/
- Zawiera wszystkie dane generowane przez użytkownika. Końcowy użytkownik aplikacji inicjuje tworzenie tych danych.
- Widoczne dla użytkowników i użytkownicy mogą w nim zapisywać.
- Zawartość tego katalogu jest objęta kopią zapasową.
- Aplikacja może wykluczyć ścieżki ustawiając
NSURLIsExcludedFromBackupKey. - Library/
- Zawiera wszystkie pliki, które nie są specyficzne dla użytkownika, takie jak caches, preferences, cookies, oraz pliki konfiguracyjne property list (plist).
- Aplikacje iOS zwykle używają podkatalogów
Application SupportiCaches, ale aplikacja może stworzyć własne podkatalogi. - Library/Caches/
- Zawiera półtrwałe pliki cache.
- Niewidoczne dla użytkowników i użytkownicy nie mogą w nim zapisywać.
- Zawartość tego katalogu nie jest objęta kopią zapasową.
- System może automatycznie usuwać pliki z tego katalogu, gdy aplikacja nie jest uruchomiona i przestrzeń dyskowa jest ograniczona.
- Library/Application Support/
- Zawiera trwałe pliki niezbędne do działania aplikacji.
- Niewidoczne dla użytkowników i użytkownicy nie mogą w nim zapisywać.
- Zawartość tego katalogu jest objęta kopią zapasową.
- Aplikacja może wykluczyć ścieżki ustawiając
NSURLIsExcludedFromBackupKey. - Library/Preferences/
- Służy do przechowywania właściwości, które mogą utrzymywać się nawet po ponownym uruchomieniu aplikacji.
- Informacje są zapisywane, niezaszyfrowane, wewnątrz sandboxa aplikacji w pliku plist o nazwie [BUNDLE_ID].plist.
- Wszystkie pary klucz/wartość przechowywane przy użyciu
NSUserDefaultsmożna znaleźć w tym pliku. - tmp/
- Użyj tego katalogu do zapisu plików tymczasowych, które nie muszą przetrwać między uruchomieniami aplikacji.
- Zawiera niepermanentne pliki cache.
- Niewidoczne dla użytkowników.
- Zawartość tego katalogu nie jest objęta kopią zapasową.
- System może automatycznie usuwać pliki z tego katalogu, gdy aplikacja nie jest uruchomiona i przestrzeń dyskowa jest ograniczona.
Przyjrzyjmy się bliżej katalogowi Application Bundle (.app) iGoat-Swift wewnątrz katalogu Bundle (/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app):
OWASP.iGoat-Swift on (iPhone: 11.1.2) [usb] # ls
NSFileType Perms NSFileProtection ... Name
------------ ------- ------------------ ... --------------------------------------
Regular 420 None ... rutger.html
Regular 420 None ... mansi.html
Regular 420 None ... splash.html
Regular 420 None ... about.html
Regular 420 None ... LICENSE.txt
Regular 420 None ... Sentinel.txt
Regular 420 None ... README.txt
Binary Reversing
W folderze <application-name>.app znajdziesz plik binarny o nazwie <application-name>. To jest plik, który będzie wykonywany. Możesz przeprowadzić podstawową inspekcję binarki za pomocą narzędzia 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)
[...]
Sprawdź, czy aplikacja jest zaszyfrowana
Zobacz, czy jest jakikolwiek output dla:
otool -l <app-binary> | grep -A 4 LC_ENCRYPTION_INFO
Dysasemblacja pliku binarnego
Disasembluj sekcję .text:
otool -tV DVIA-v2
DVIA-v2:
(__TEXT,__text) section
+[DDLog initialize]:
0000000100004ab8 sub sp, sp, #0x60
0000000100004abc stp x29, x30, [sp, #0x50] ; Latency: 6
0000000100004ac0 add x29, sp, #0x50
0000000100004ac4 sub x8, x29, #0x10
0000000100004ac8 mov x9, #0x0
0000000100004acc adrp x10, 1098 ; 0x10044e000
0000000100004ad0 add x10, x10, #0x268
Aby wydrukować segment Objective-C przykładowej aplikacji, można użyć:
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
Aby uzyskać bardziej kompaktowy kod Objective-C, możesz użyć 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;
};
However, the best options to disassemble the binary are: Hopper and IDA.
Przechowywanie danych
Aby dowiedzieć się, jak iOS przechowuje dane na urządzeniu, przeczytaj tę stronę:
Warning
Następujące miejsca przechowywania informacji powinny być sprawdzone bezpośrednio po zainstalowaniu aplikacji, po sprawdzeniu wszystkich funkcjonalności aplikacji oraz nawet po wylogowaniu się z jednego użytkownika i zalogowaniu do innego.
Celem jest znalezienie niechronionych poufnych informacji aplikacji (hasła, tokeny), danych bieżącego użytkownika oraz wcześniej zalogowanych użytkowników.
Plist
Pliki plist to uporządkowane pliki XML, które zawierają pary klucz-wartość. To sposób przechowywania danych trwałych, więc czasami możesz znaleźć w tych plikach poufne informacje. Zaleca się sprawdzić te pliki po zainstalowaniu aplikacji oraz po intensywnym jej używaniu, aby zobaczyć, czy zapisywane są nowe dane.
Najczęstszym sposobem utrwalania danych w plikach plist jest użycie NSUserDefaults. Ten plik plist jest zapisywany w sandboxie aplikacji w Library/Preferences/<appBundleID>.plist
Klasa NSUserDefaults zapewnia programowy interfejs do interakcji z systemem domyślnym. System domyślny pozwala aplikacji dostosować swoje zachowanie zgodnie z preferencjami użytkownika. Dane zapisane przez NSUserDefaults można przeglądać w bundle aplikacji. Ta klasa przechowuje dane w pliku plist, ale jest przeznaczona do użycia przy niewielkich ilościach danych.
Do tych danych nie można już bezpośrednio uzyskać dostępu za pomocą zaufanego komputera, ale można uzyskać do nich dostęp wykonując backup.
Możesz dump informacji zapisanych przy użyciu NSUserDefaults za pomocą objection: ios nsuserdefaults get
Aby znaleźć wszystkie pliki plist używane przez aplikację, możesz uzyskać dostęp do /private/var/mobile/Containers/Data/Application/{APPID} i uruchomić:
find ./ -name "*.plist"
Aby przekonwertować pliki z formatu XML or binary (bplist) na XML, dostępne są różne metody w zależności od systemu operacyjnego:
Dla użytkowników macOS: Użyj polecenia plutil. To narzędzie wbudowane w macOS (10.2+), przeznaczone do tego celu:
$ plutil -convert xml1 Info.plist
Dla użytkowników Linuksa: Zainstaluj najpierw libplist-utils, a następnie użyj plistutil, aby skonwertować swój plik:
$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist
Within an Objection Session: Do analizy aplikacji mobilnych, konkretna komenda pozwala bezpośrednio konwertować pliki plist:
ios plist cat /private/var/mobile/Containers/Data/Application/<Application-UUID>/Library/Preferences/com.some.package.app.plist
Core Data
Core Data to framework służący do zarządzania warstwą modelu obiektów w aplikacji. Core Data może używać SQLite jako persistent store, ale sam framework nie jest bazą danych.
CoreData nie szyfruje danych domyślnie. Można jednak dodać dodatkową warstwę szyfrowania do CoreData. Zobacz GitHub Repo po więcej informacji.
Informacje SQLite Core Data aplikacji znajdują się pod ścieżką /private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support
Jeśli możesz otworzyć SQLite i uzyskać dostęp do wrażliwych informacji, oznacza to, że wykryto nieprawidłową konfigurację.
-(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 to magazyn klucz/wartość zbudowany na SQLite.
Ponieważ bazy Yap są bazami SQLite, możesz je znaleźć używając polecenia podanego w poprzedniej sekcji.
Other SQLite Databases
Aplikacje często tworzą własne bazy danych SQLite. Mogą w nich przechowywać wrażliwe dane i pozostawiać je niezaszyfrowane. Dlatego zawsze warto sprawdzić każdą bazę danych w katalogu aplikacji. Przejdź do katalogu aplikacji, w którym zapisywane są dane (/private/var/mobile/Containers/Data/Application/{APPID})
find ./ -name "*.sqlite" -or -name "*.db"
Firebase Real-Time Databases
Programiści mogą przechowywać i synchronizować dane w NoSQL bazie danych hostowanej w chmurze za pomocą Firebase Real-Time Databases. Dane są przechowywane w formacie JSON i synchronizowane ze wszystkimi połączonymi klientami w czasie rzeczywistym.
You can find how to check for misconfigured Firebase databases here:
Realm databases
Realm Objective-C and Realm Swift oferują potężną alternatywę dla przechowywania danych, której nie zapewnia Apple. Domyślnie przechowują dane bez szyfrowania, a szyfrowanie jest dostępne po odpowiedniej konfiguracji.
Bazy danych znajdują się pod ścieżką: /private/var/mobile/Containers/Data/Application/{APPID}. Aby przeglądać te pliki, można użyć poleceń takich jak:
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*"
Do przeglądania tych plików bazy danych rekomendowane jest narzędzie Realm Studio.
Aby zaimplementować encryption w bazie danych Realm, można użyć następującego fragmentu kodu:
// 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 Bazy danych
Couchbase Lite jest opisywana jako lekki i wbudowany silnik bazy danych, który stosuje podejście zorientowane na dokumenty (NoSQL). Zaprojektowany jako natywny dla iOS i macOS, umożliwia bezproblemową synchronizację danych.
Aby zidentyfikować potencjalne bazy danych Couchbase na urządzeniu, należy sprawdzić następujący katalog:
ls /private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support/
Ciasteczka
iOS przechowuje cookies aplikacji w Library/Cookies/cookies.binarycookies w folderze każdej aplikacji. Jednak deweloperzy czasami decydują się zapisać je w keychain, ponieważ wspomniany plik cookie może być dostępny w kopiach zapasowych.
Aby przejrzeć plik cookie możesz użyć this python script lub użyć objection z poleceniem ios cookies get.\ Możesz też użyć objection, aby skonwertować te pliki do formatu JSON i przeanalizować dane.
...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"
}
]
Pamięć podręczna
Domyślnie NSURLSession przechowuje dane, takie jak żądania i odpowiedzi HTTP w Cache.db. Ta baza danych może zawierać wrażliwe dane, jeśli tokeny, nazwy użytkowników lub inne poufne informacje zostały zbuforowane. Aby znaleźć zbuforowane informacje, otwórz katalog danych aplikacji (/var/mobile/Containers/Data/Application/<UUID>) i przejdź do /Library/Caches/<Bundle Identifier>. WebKit cache jest również przechowywany w pliku Cache.db. Objection może otworzyć i operować na bazie poleceniem sqlite connect Cache.db, ponieważ jest to zwykła baza SQLite.
Zaleca się wyłączenie przechowywania w pamięci podręcznej tych danych, ponieważ mogą one zawierać poufne informacje w żądaniu lub odpowiedzi. Poniższa lista pokazuje różne sposoby osiągnięcia tego:
- Zaleca się usuwanie zbuforowanych odpowiedzi po wylogowaniu. Można to zrobić za pomocą metody udostępnionej przez Apple o nazwie
removeAllCachedResponses. Możesz wywołać tę metodę w następujący sposób:
URLCache.shared.removeAllCachedResponses()
Ta metoda usunie wszystkie zbuforowane żądania i odpowiedzi z pliku Cache.db.
- Jeśli nie potrzebujesz korzystać z zalet cookies, zaleca się użycie właściwości konfiguracyjnej .ephemeral URLSession, która wyłączy zapisywanie cookies oraz Cache.
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.
- Cache można również wyłączyć, ustawiając politykę Cache na .notAllowed. Spowoduje to wyłączenie zapisywania Cache w jakikolwiek sposób, zarówno w pamięci, jak i na dysku.
Snapshoty
Za każdym razem, gdy naciśniesz przycisk home, iOS wykonuje snapshot bieżącego ekranu, aby przejście do aplikacji było znacznie płynniejsze. Jednak jeśli na bieżącym ekranie znajdują się wrażliwe dane, zostaną one zapisane w obrazie (który utrzymuje się po ponownych uruchomieniach). To są snapshoty, do których masz dostęp także przez podwójne tapnięcie przycisku home, aby przełączać się między aplikacjami.
O ile iPhone nie jest jailbroken, atakujący musi mieć dostęp do odblokowanego urządzenia, aby zobaczyć te zrzuty ekranu. Domyślnie ostatni snapshot jest przechowywany w sandboxie aplikacji w katalogu Library/Caches/Snapshots/ lub Library/SplashBoard/Snapshots (the trusted computers can’ t access the filesystem from iOX 7.0).
Jednym ze sposobów zapobiegania temu niepożądanemu zachowaniu jest wyświetlenie pustego ekranu lub usunięcie wrażliwych danych przed wykonaniem snapshotu, używając funkcji ApplicationDidEnterBackground().
Poniżej znajduje się przykładowa metoda remediacji, która ustawi domyślny zrzut ekranu.
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];
}
To ustawia obraz tła na overlayImage.png za każdym razem, gdy aplikacja zostanie przeniesiona do tła. Zapobiega sensitive data leaks, ponieważ overlayImage.png zawsze nadpisze bieżący widok.
Keychain
Do uzyskiwania dostępu i zarządzania iOS keychain dostępne są narzędzia takie jak Keychain-Dumper, odpowiednie dla urządzeń jailbroken. Dodatkowo, Objection udostępnia komendę ios keychain dump do podobnych celów.
Przechowywanie poświadczeń
Klasa NSURLCredential jest idealna do zapisywania wrażliwych informacji bezpośrednio w keychain, omijając konieczność użycia NSUserDefaults lub innych wrapperów. Aby zapisać poświadczenia po logowaniu, używany jest następujący kod Swift:
NSURLCredential *credential;
credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistencePermanent];
[[NSURLCredentialStorage sharedCredentialStorage] setCredential:credential forProtectionSpace:self.loginProtectionSpace];
Aby wyodrębnić te przechowywane poświadczenia, używa się polecenia Objection ios nsurlcredentialstorage dump.
Klawiatury zewnętrzne i pamięć podręczna klawiatury
Od iOS 8.0 użytkownicy mogą instalować rozszerzenia klawiatur, którymi można zarządzać w Settings > General > Keyboard > Keyboards. Choć te klawiatury oferują rozszerzone funkcje, stwarzają ryzyko logowania naciśnięć klawiszy i przesyłania danych do zewnętrznych serwerów; użytkownicy są jednak informowani o klawiaturach wymagających dostępu do sieci. Aplikacje mogą — i powinny — ograniczać użycie klawiatur zewnętrznych do wprowadzania informacji wrażliwych.
Zalecenia dotyczące bezpieczeństwa:
- Zaleca się wyłączenie klawiatur firm trzecich w celu zwiększenia bezpieczeństwa.
- Zwróć uwagę na funkcje autokorekty i automatycznych sugestii domyślnej klawiatury iOS, które mogą przechowywać wrażliwe informacje w plikach cache znajdujących się w
Library/Keyboard/{locale}-dynamic-text.datlub/private/var/mobile/Library/Keyboard/dynamic-text.dat. Należy regularnie sprawdzać te pliki cache pod kątem wrażliwych danych. Zaleca się zresetowanie słownika klawiatury przez Settings > General > Reset > Reset Keyboard Dictionary w celu usunięcia danych z cache. - Przechwytywanie ruchu sieciowego może ujawnić, czy klawiatura zewnętrzna przesyła naciśnięcia klawiszy zdalnie.
Zapobieganie buforowaniu pól tekstowych
The UITextInputTraits protocol offers properties to manage autocorrection and secure text entry, essential for preventing sensitive information caching. For example, disabling autocorrection and enabling secure text entry can be achieved with:
textObject.autocorrectionType = UITextAutocorrectionTypeNo;
textObject.secureTextEntry = YES;
Ponadto deweloperzy powinni upewnić się, że pola tekstowe, szczególnie te przeznaczone do wprowadzania informacji wrażliwych, takich jak hasła i PIN-y, wyłączają buforowanie poprzez ustawienie autocorrectionType na UITextAutocorrectionTypeNo oraz secureTextEntry na YES.
UITextField *textField = [[UITextField alloc] initWithFrame:frame];
textField.autocorrectionType = UITextAutocorrectionTypeNo;
Logi
Debugowanie kodu często wymaga użycia logging. Wiąże się to z ryzykiem, ponieważ logi mogą zawierać poufne informacje. W przeszłości, w iOS 6 i wcześniejszych wersjach, logi były dostępne dla wszystkich aplikacji, co stwarzało ryzyko sensitive data leak. Obecnie aplikacje mają ograniczony dostęp tylko do własnych logów.
Pomimo tych ograniczeń, atakujący z fizycznym dostępem do odblokowanego urządzenia nadal może to wykorzystać, podłączając urządzenie do komputera i odczytując logi. Należy pamiętać, że logi pozostają na dysku nawet po odinstalowaniu aplikacji.
Aby zmniejszyć ryzyko, zaleca się dokładnie przetestować aplikację, sprawdzając wszystkie funkcjonalności i pola wejściowe, aby upewnić się, że żadne poufne informacje nie są przypadkowo logowane.
Przeglądając kod źródłowy aplikacji w poszukiwaniu potencjalnych leaków, szukaj zarówno wbudowanych, jak i niestandardowych instrukcji logowania używając słów kluczowych takich jak NSLog, NSAssert, NSCAssert, fprintf dla funkcji wbudowanych, oraz wszelkich wzmianek o Logging lub Logfile dla implementacji niestandardowych.
Monitorowanie logów systemowych
Aplikacje logują różne informacje, które mogą być poufne. Aby monitorować te logi, narzędzia i polecenia takie jak:
idevice_id --list # To find the device ID
idevicesyslog -u <id> (| grep <app>) # To capture the device logs
są przydatne. Dodatkowo, Xcode umożliwia zbieranie logów konsoli:
- Otwórz Xcode.
- Podłącz urządzenie iOS.
- Przejdź do Okno -> Urządzenia i symulatory.
- Wybierz swoje urządzenie.
- Wywołaj problem, który badasz.
- Użyj przycisku Otwórz konsolę, aby zobaczyć logi w nowym oknie.
Dla bardziej zaawansowanego logowania, połączenie z powłoką urządzenia i użycie socat umożliwia monitorowanie logów w czasie rzeczywistym:
iPhone:~ root# socat - UNIX-CONNECT:/var/run/lockdown/syslog.sock
Następują polecenia do obserwowania aktywności logów, które mogą być nieocenione przy diagnozowaniu problemów lub identyfikowaniu potencjalnego data leak w logach.
Kopie zapasowe
Funkcje automatycznych kopii zapasowych są zintegrowane z iOS, ułatwiając tworzenie kopii danych urządzenia przez iTunes (do macOS Catalina), Finder (od macOS Catalina wzwyż) lub iCloud. Te kopie zapasowe obejmują niemal wszystkie dane urządzenia, z wyłączeniem bardzo wrażliwych elementów, takich jak szczegóły Apple Pay i konfiguracje Touch ID.
Ryzyka bezpieczeństwa
Włączenie zainstalowanych aplikacji i ich danych do kopii zapasowych rodzi problem potencjalnego data leakage oraz ryzyko, że modyfikacje backupu mogą zmienić działanie aplikacji. Zaleca się nie przechowywać wrażliwych informacji w plaintext w katalogu jakiejkolwiek aplikacji ani jego podkatalogach, aby zminimalizować te ryzyka.
Wykluczanie plików z kopii zapasowych
Pliki w Documents/ i Library/Application Support/ są domyślnie uwzględniane w kopiach zapasowych. Deweloperzy mogą wykluczyć konkretne pliki lub katalogi z backupów, używając NSURL setResourceValue:forKey:error: z kluczem NSURLIsExcludedFromBackupKey. Ta praktyka jest kluczowa dla ochrony wrażliwych danych przed dołączeniem do backupu.
Testowanie podatności
Aby ocenić bezpieczeństwo backupu aplikacji, zacznij od utworzenia kopii zapasowej przy użyciu Finder, a następnie zlokalizuj ją korzystając z instrukcji w Apple’s official documentation. Przeanalizuj backup pod kątem wrażliwych danych lub konfiguracji, które mogłyby zostać zmienione w celu wpływu na działanie aplikacji.
Na wrażliwe informacje można polować używając narzędzi wiersza poleceń lub aplikacji takich jak iMazing. W przypadku zaszyfrowanych kopii zapasowych obecność szyfrowania można potwierdzić, sprawdzając klucz “IsEncrypted” w pliku “Manifest.plist” w katalogu głównym backupu.
<?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>
W radzeniu sobie z zaszyfrowanymi backupami, skrypty Python dostępne w DinoSec’s GitHub repo, takie jak backup_tool.py i backup_passwd.py, mogą być przydatne, choć mogą wymagać dostosowań, aby były kompatybilne z najnowszymi wersjami iTunes/Finder. Narzędzie iOSbackup tool to kolejna opcja umożliwiająca dostęp do plików w backupach chronionych hasłem.
Modyfikowanie zachowania aplikacji
Przykład zmiany zachowania aplikacji poprzez modyfikację backupu pokazuje Bither bitcoin wallet app, gdzie PIN blokady UI jest przechowywany w net.bither.plist pod kluczem pin_code. Usunięcie tego klucza z plist i przywrócenie backupu usuwa wymóg PIN, zapewniając nieograniczony dostęp.
Podsumowanie testowania pamięci pod kątem danych wrażliwych
Przy pracy z danymi wrażliwymi przechowywanymi w pamięci aplikacji istotne jest ograniczenie czasu ekspozycji tych danych. Istnieją dwa podstawowe podejścia do badania zawartości pamięci: creating a memory dump i analyzing the memory in real time. Obie metody mają swoje wyzwania, w tym możliwość pominięcia krytycznych danych podczas procesu dumpu lub analizy.
Retrieving and Analyzing a Memory Dump
Dla urządzeń zarówno jailbroken, jak i non-jailbroken, narzędzia takie jak objection i Fridump pozwalają na zrzut pamięci procesu aplikacji. Po zrzuceniu, analiza tych danych wymaga różnych narzędzi, w zależności od rodzaju poszukiwanych informacji.
Aby wyodrębnić ciągi znaków z memory dumpu, można użyć poleceń takich jak strings lub rabin2 -zz:
# Extracting strings using strings command
$ strings memory > strings.txt
# Extracting strings using rabin2
$ rabin2 -ZZ memory > strings.txt
Dla bardziej szczegółowej analizy, w tym wyszukiwania konkretnych typów danych lub wzorców, radare2 oferuje rozbudowane możliwości wyszukiwania:
$ r2 <name_of_your_dump_file>
[0x00000000]> /?
...
Runtime Memory Analysis
r2frida oferuje potężną alternatywę do inspekcji pamięci aplikacji w czasie rzeczywistym, bez potrzeby wykonania memory dump. To narzędzie umożliwia wykonywanie poleceń wyszukiwania bezpośrednio w pamięci uruchomionej aplikacji:
$ r2 frida://usb//<name_of_your_app>
[0x00000000]> /\ <search_command>
Słaba kryptografia
Słabe procesy zarządzania kluczami
Niektórzy deweloperzy zapisują dane wrażliwe w local storage i szyfrują je przy użyciu klucza hardcoded/predictable w code. Nie powinno się tego robić, ponieważ reversing może pozwolić atakującym na wydobycie informacji poufnych.
Użycie niebezpiecznych i/lub przestarzałych algorytmów
Deweloperzy nie powinni używać przestarzałych algorytmów do wykonywania authorisation checks, do store lub send danych. Niektóre z tych algorytmów to: RC4, MD4, MD5, SHA1… Jeśli hashes są używane do przechowywania haseł, na przykład, należy stosować hashes odporne na brute-force wraz z salt.
Sprawdzenie
Główne checks do wykonania to sprawdzenie, czy możesz znaleźć hardcoded passwords/secrets w code, czy są one predictable, oraz czy code używa jakiegoś rodzaju weak cryptography algorytmów.
Warto wiedzieć, że można automatycznie monitorować niektóre crypto libraries za pomocą objection z:
ios monitor crypt
For more information about iOS cryptographic APIs and libraries access https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06e-testing-cryptography
Uwierzytelnianie lokalne
Uwierzytelnianie lokalne odgrywa kluczową rolę, szczególnie gdy chodzi o zabezpieczanie dostępu w zdalnym punkcie końcowym za pomocą metod kryptograficznych. Istota polega na tym, że bez właściwej implementacji mechanizmy uwierzytelniania lokalnego można obejść.
Apple’s Local Authentication framework and the keychain provide robust APIs for developers to facilitate user authentication dialogs and securely handle secret data, respectively. Secure Enclave zabezpiecza identyfikator odcisku palca dla Touch ID, natomiast Face ID opiera się na rozpoznawaniu twarzy, nie narażając danych biometrycznych.
Aby zintegrować Touch ID/Face ID, deweloperzy mają do wyboru dwa interfejsy API:
LocalAuthentication.frameworkfor high-level user authentication without access to biometric data.Security.frameworkfor lower-level keychain services access, securing secret data with biometric authentication. Various open-source wrappers make keychain access simpler.
Caution
Jednak zarówno
LocalAuthentication.framework, jak iSecurity.frameworkwykazują podatności, ponieważ głównie zwracają wartości boolean bez przesyłania danych w procesach uwierzytelniania, co czyni je podatnymi na obejścia (zob. Don’t touch me that way, by David Lindner et al).
Implementacja uwierzytelniania lokalnego
Aby wywołać monit o uwierzytelnienie użytkownika, deweloperzy powinni użyć metody evaluatePolicy w klasie LAContext, wybierając pomiędzy:
deviceOwnerAuthentication: Wyświetla monit o Touch ID lub kod urządzenia, kończy się niepowodzeniem, jeśli żaden z nich nie jest włączony.deviceOwnerAuthenticationWithBiometrics: Wyświetla wyłącznie monit o Touch ID.
Pomyślne uwierzytelnienie jest sygnalizowane przez wartość boolean zwracaną przez evaluatePolicy, co wskazuje na potencjalną wadę bezpieczeństwa.
Uwierzytelnianie lokalne z użyciem keychain
Implementacja uwierzytelniania lokalnego w aplikacjach iOS obejmuje użycie keychain APIs do bezpiecznego przechowywania tajnych danych, takich jak tokeny uwierzytelniające. Proces ten zapewnia, że dane mogą być dostępne tylko dla użytkownika, przy użyciu kodu urządzenia lub uwierzytelniania biometrycznego, takiego jak Touch ID.
Keychain oferuje możliwość ustawienia elementów z atrybutem SecAccessControl, który ogranicza dostęp do elementu do momentu, aż użytkownik pomyślnie uwierzytelni się za pomocą Touch ID lub kodu urządzenia. Ta funkcja jest kluczowa dla zwiększenia bezpieczeństwa.
Poniżej znajdują się przykłady kodu w Swift i Objective-C pokazujące, jak zapisać i odczytać string do/z keychain, wykorzystując te funkcje bezpieczeństwa. Przykłady pokazują w szczególności, jak skonfigurować kontrolę dostępu wymagającą uwierzytelnienia Touch ID oraz zapewnić, że dane będą dostępne tylko na urządzeniu, na którym zostały zapisane, pod warunkiem że skonfigurowano kod urządzenia.
// 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
}
Teraz możemy zażądać zapisanego elementu z keychain. Usługi keychain wyświetlą użytkownikowi dialog uwierzytelniania i zwrócą dane lub nil w zależności od tego, czy został dostarczony odpowiedni fingerprint.
// 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
}
Wykrywanie
Użycie frameworków w aplikacji można także wykryć, analizując listę współdzielonych bibliotek dynamicznych binarki aplikacji. Można to zrobić za pomocą otool:
$ otool -L <AppName>.app/<AppName>
Jeśli LocalAuthentication.framework jest używany w aplikacji, output będzie zawierać obie z następujących linii (pamiętaj, że LocalAuthentication.framework używa Security.framework pod spodem):
/System/Library/Frameworks/LocalAuthentication.framework/LocalAuthentication
/System/Library/Frameworks/Security.framework/Security
Jeśli używany jest Security.framework, wyświetlany będzie tylko drugi.
Local Authentication Framework Bypass
Objection
Dzięki Objection Biometrics Bypass, znajdującemu się na this GitHub page, dostępna jest technika pozwalająca obejść mechanizm LocalAuthentication. Istota podejścia polega na wykorzystaniu Frida do manipulowania funkcją evaluatePolicy, tak aby zawsze zwracała wartość True, niezależnie od rzeczywistego wyniku uwierzytelniania. Jest to szczególnie przydatne do obejścia wadliwych procesów uwierzytelniania biometrycznego.
Aby aktywować ten bypass, użyj następującego polecenia:
...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
To polecenie uruchamia sekwencję, w której Objection rejestruje zadanie, które faktycznie zmienia wynik sprawdzenia evaluatePolicy na True.
Frida
Przykład użycia evaluatePolicy z 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"];
});
}
}
Aby osiągnąć bypass Local Authentication, napisano skrypt Frida. Skrypt ten celuje w sprawdzenie evaluatePolicy, przechwytując jego callback, aby upewnić się, że zwraca success=1. Poprzez zmianę zachowania callbacka, weryfikacja uwierzytelnienia jest efektywnie pominięta.
Poniższy skrypt jest wstrzykiwany, by zmodyfikować wynik metody evaluatePolicy. Zmienia wynik callbacka tak, aby zawsze wskazywał success.
// from https://securitycafe.ro/2022/09/05/mobile-pentesting-101-bypassing-biometric-authentication/
if(ObjC.available) {
console.log("Injecting...");
var hook = ObjC.classes.LAContext["- evaluatePolicy:localizedReason:reply:"];
Interceptor.attach(hook.implementation, {
onEnter: function(args) {
var block = new ObjC.Block(args[4]);
const callback = block.implementation;
block.implementation = function (error, value) {
console.log("Changing the result value to true")
const result = callback(1, null);
return result;
};
},
});
} else {
console.log("Objective-C Runtime is not available!");
}
Aby wstrzyknąć skrypt Frida i ominąć uwierzytelnianie biometryczne, używane jest następujące polecenie:
frida -U -f com.highaltitudehacks.DVIAswiftv2 --no-pause -l fingerprint-bypass-ios.js
Ujawnienie wrażliwej funkcjonalności przez IPC
Custom URI Handlers / Deeplinks / Custom Schemes
iOS Custom URI Handlers / Deeplinks / Custom Schemes
Universal Links
UIActivity Sharing
UIPasteboard
App Extensions
WebViews
Serialisation and Encoding
iOS Serialisation and Encoding
Network Communication
Ważne jest sprawdzenie, czy żadna komunikacja nie odbywa się bez szyfrowania oraz czy aplikacja poprawnie weryfikuje certyfikat TLS serwera.
Aby sprawdzić tego typu problemy możesz użyć proxy takiego jak Burp:
Hostname check
Częstym problemem przy weryfikacji certyfikatu TLS jest sprawdzenie, czy certyfikat został podpisany przez zaufane CA, ale nie sprawdzenie, czy hostname certyfikatu odpowiada odwiedzanemu hostowi.
Aby sprawdzić ten problem przy użyciu Burp, po zaufaniu Burp CA na iPhone, możesz utworzyć nowy certyfikat w Burp dla innego hostname i go użyć. Jeśli aplikacja nadal działa, to oznacza, że jest podatna.
Certificate Pinning
Jeśli aplikacja poprawnie używa SSL Pinning, aplikacja będzie działać tylko wtedy, gdy certyfikat jest tym oczekiwanym. Podczas testowania aplikacji może to być problem, ponieważ Burp będzie serwował własny certyfikat.
Aby obejść tę ochronę na urządzeniu z jailbreakiem, możesz zainstalować aplikację SSL Kill Switch lub zainstalować Burp Mobile Assistant
Możesz też użyć objection’s ios sslpinning disable
Misc
- W
/System/Librarymożesz znaleźć frameworki zainstalowane w telefonie używane przez aplikacje systemowe - Aplikacje zainstalowane przez użytkownika z App Store znajdują się w
/User/Applications - Natomiast
/User/Libraryzawiera dane zapisywane przez aplikacje na poziomie użytkownika - Możesz uzyskać dostęp do
/User/Library/Notes/notes.sqlite, aby przeczytać notatki zapisane w aplikacji. - Wewnątrz folderu zainstalowanej aplikacji (
/User/Applications/<APP ID>/) możesz znaleźć kilka ciekawych plików: iTunesArtwork: Ikona używana przez aplikacjęiTunesMetadata.plist: Informacje o aplikacji wykorzystywane w App Store/Library/*: Zawiera preferencje i cache. W/Library/Cache/Snapshots/*możesz znaleźć snapshot wykonany dla aplikacji przed wysłaniem jej w tło.
Hot Patching/Enforced Updateing
Deweloperzy mogą zdalnie załatać wszystkie instalacje swojej aplikacji natychmiast bez konieczności ponownego zgłaszania aplikacji do App Store i oczekiwania na jej zatwierdzenie.
Do tego celu zwykle używa się JSPatch. Są też inne opcje, takie jak Siren i react-native-appstore-version-checker.
Jest to niebezpieczny mechanizm, który może być nadużyty przez złośliwe SDK stron trzecich, dlatego zaleca się sprawdzenie, jaka metoda jest używana do automatycznego aktualizowania (jeśli w ogóle) i przetestowanie jej. Możesz spróbować pobrać poprzednią wersję aplikacji w tym celu.
Third Parties
Znaczącym wyzwaniem związanym z 3rd party SDKs jest brak szczegółowej kontroli nad ich funkcjonalnościami. Deweloperzy stają przed wyborem: albo zintegrować SDK i zaakceptować wszystkie jego funkcje, w tym potencjalne luki w zabezpieczeniach i zagrożenia prywatności, albo zrezygnować z jego korzyści. Często deweloperzy nie są w stanie sami załatać podatności w tych SDK. Ponadto, wraz ze wzrostem zaufania do niektórych SDK w społeczności, niektóre z nich mogą zacząć zawierać malware.
Usługi świadczone przez SDK stron trzecich mogą obejmować śledzenie zachowań użytkowników, wyświetlanie reklam lub ulepszanie doświadczenia użytkownika. Jednakże wprowadza to ryzyko, ponieważ deweloperzy mogą nie być w pełni świadomi kodu wykonywanego przez te biblioteki, co prowadzi do potencjalnych zagrożeń dla prywatności i bezpieczeństwa. Kluczowe jest ograniczenie informacji udostępnianych usługom stron trzecich do niezbędnego minimum oraz upewnienie się, że żadne dane wrażliwe nie są ujawniane.
Implementacja usług stron trzecich zwykle występuje w dwóch formach: samodzielnej biblioteki lub pełnego SDK. Aby chronić prywatność użytkowników, wszelkie dane udostępniane tym usługom powinny być anonymized, aby zapobiec ujawnieniu danych identyfikujących osobę (PII).
Aby zidentyfikować biblioteki używane przez aplikację, można użyć polecenia otool. To narzędzie powinno być uruchomione przeciwko aplikacji oraz każdej współdzielonej bibliotece, której używa, aby odkryć dodatkowe biblioteki.
otool -L <application_path>
Interesujące luki i studia przypadków
Air Keyboard Remote Input Injection
Itunesstored Bookassetd Sandbox Escape
Zero Click Messaging Image Parser Chains
Referencje i dodatkowe zasoby
- https://blog.calif.io/p/taking-apart-ios-apps-anti-debugging
- https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06b-basic-security-testing#information-gathering
- iOS & Mobile App Pentesting - INE
- https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0057/
- https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0058/
- https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0059/
- https://mas.owasp.org/MASTG/iOS/0x06d-Testing-Data-Storage
- https://coderwall.com/p/kjb3lw/storing-password-in-keychain-the-smart-way
- https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0055/
- https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0053
- https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0060/
- https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0058
- https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0060
- https://mas.owasp.org/MASTG/Android/0x05f-Testing-Local-Authentication/
- https://mas.owasp.org/MASTG/tests/ios/MASVS-AUTH/MASTG-TEST-0064
- https://medium.com/securing/bypassing-your-apps-biometric-checks-on-ios-c2555c81a2dc
- https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0054
- https://github.com/ivRodriguezCA/RE-iOS-Apps/ Bezpłatny kurs iOS(https://syrion.me/blog/ios-swift-antijailbreak-bypass-frida/)
- https://www.sans.org/reading-room/whitepapers/testing/ipwn-apps-pentesting-ios-applications-34577
- https://www.slideshare.net/RyanISI/ios-appsecurityminicourse
- https://github.com/prateek147/DVIA
- https://github.com/prateek147/DVIA-v2
- https://github.com/OWASP/MSTG-Hacking-Playground%20
- OWASP iGoat https://github.com/OWASP/igoat <<< wersja Objective-C https://github.com/OWASP/iGoat-Swift <<< wersja Swift
- https://github.com/authenticationfailure/WheresMyBrowser.iOS
- https://github.com/nabla-c0d3/ssl-kill-switch2
Tip
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.


