mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
81 lines
6.4 KiB
Markdown
81 lines
6.4 KiB
Markdown
# Heap Overflow
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|
||
|
||
## 基本信息
|
||
|
||
堆溢出类似于 [**栈溢出**](../stack-overflow/index.html),但发生在堆中。基本上,这意味着在堆中保留了一些空间来存储数据,而 **存储的数据大于保留的空间。**
|
||
|
||
在栈溢出中,我们知道一些寄存器,如指令指针或栈帧,将从栈中恢复,并且可能会被滥用。在堆溢出的情况下,**默认情况下堆块中没有存储任何敏感信息**,可以被溢出。然而,它可能包含敏感信息或指针,因此这种漏洞的 **严重性** **取决于** **哪些数据可能被覆盖** 以及攻击者如何利用这一点。
|
||
|
||
> [!TIP]
|
||
> 为了找到溢出偏移量,您可以使用与 [**栈溢出**](../stack-overflow/index.html#finding-stack-overflows-offsets) 相同的模式。
|
||
|
||
### 栈溢出与堆溢出
|
||
|
||
在栈溢出中,触发漏洞时栈中将存在的排列和数据是相当可靠的。这是因为栈是线性的,总是增加在冲突的内存中,在 **程序运行的特定位置,栈内存通常存储类似类型的数据**,并且它具有一些特定的结构,末尾有一些指向每个函数使用的栈部分的指针。
|
||
|
||
然而,在堆溢出的情况下,使用的内存不是线性的,而是 **分配的块通常位于内存的不同位置**(而不是一个接一个),因为 **bins 和 zones** 按大小分隔分配,并且因为 **先前释放的内存在分配新块之前被使用**。因此,**很难知道将与易受堆溢出影响的对象发生冲突的对象**。因此,当发现堆溢出时,需要找到一种 **可靠的方法使所需对象在内存中紧挨着可以被溢出的对象**。
|
||
|
||
用于此的一种技术是 **Heap Grooming**,例如在 [**这篇文章**](https://azeria-labs.com/grooming-the-ios-kernel-heap/) 中进行了说明。文章解释了当 iOS 内核中的一个区域没有足够的内存来存储内存块时,它通过一个内核页面进行扩展,并且该页面被分割成预期大小的块,这些块将按顺序使用(直到 iOS 版本 9.2,然后这些块以随机方式使用,以增加这些攻击的利用难度)。
|
||
|
||
因此,在发生堆溢出的前一篇文章中,为了强制溢出的对象与受害者对象发生冲突,多个 **`kallocs` 被多个线程强制执行,以确保所有空闲块都被填满,并且创建一个新页面**。
|
||
|
||
为了强制用特定大小的对象填充,**与 iOS mach 端口相关的离线分配**是一个理想的候选者。通过精确设置消息的大小,可以准确指定 `kalloc` 分配的大小,当相应的 mach 端口被销毁时,相应的分配将立即释放回 `kfree`。
|
||
|
||
然后,这些占位符中的一些可以被 **释放**。**`kalloc.4096` 空闲列表以后进先出顺序释放元素**,这基本上意味着如果一些占位符被释放,而利用尝试在分配易受溢出影响的对象时分配多个受害者对象,则该对象很可能会被一个受害者对象跟随。
|
||
|
||
### 示例 libc
|
||
|
||
[**在此页面**](https://guyinatuxedo.github.io/27-edit_free_chunk/heap_consolidation_explanation/index.html) 可以找到一个基本的堆溢出仿真,展示了如何通过覆盖下一个块的 prev in use 位和 prev size 的位置来 **合并一个已使用的块**(使其认为是未使用的),然后 **再次分配它**,能够覆盖在不同指针中使用的数据。
|
||
|
||
另一个来自 [**protostar heap 0**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap0/index.html) 的示例展示了一个非常基本的 CTF 示例,其中 **堆溢出** 可以被滥用以调用赢家函数以 **获取标志**。
|
||
|
||
在 [**protostar heap 1**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap1/index.html) 示例中,可以看到如何通过滥用缓冲区溢出来 **在一个临近块中覆盖一个地址**,该地址将 **写入用户的任意数据**。
|
||
|
||
### 示例 ARM64
|
||
|
||
在页面 [https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/](https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/) 中,您可以找到一个堆溢出示例,其中要执行的命令存储在溢出块的下一个块中。因此,可以通过用简单的利用覆盖它来修改执行的命令,例如:
|
||
```bash
|
||
python3 -c 'print("/"*0x400+"/bin/ls\x00")' > hax.txt
|
||
```
|
||
### 其他示例
|
||
|
||
- [**Auth-or-out. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/auth-or-out/)
|
||
- 我们利用整数溢出漏洞来获取堆溢出。
|
||
- 我们破坏指向溢出块内 `struct` 中函数的指针,以设置如 `system` 的函数并获得代码执行。
|
||
|
||
### 真实世界示例:CVE-2025-40597 – 错误使用 `__sprintf_chk`
|
||
|
||
在 SonicWall SMA100 固件 10.2.1.15 中,反向代理模块 `mod_httprp.so` 分配了一个 **0x80-byte** 的堆块,然后使用 `__sprintf_chk` 将多个字符串连接到其中:
|
||
```c
|
||
char *buf = calloc(0x80, 1);
|
||
/* … */
|
||
__sprintf_chk(buf, /* destination (0x80-byte chunk) */
|
||
-1, /* <-- size argument !!! */
|
||
0, /* flags */
|
||
"%s%s%s%s", /* format */
|
||
"/", "https://", path, host);
|
||
```
|
||
`__sprintf_chk` 是 **_FORTIFY_SOURCE** 的一部分。当它接收到一个 **正** 的 `size` 参数时,它会验证结果字符串是否适合目标缓冲区。通过传递 **`-1` (0xFFFFFFFFFFFFFFFF)**,开发人员实际上 **禁用了边界检查**,将强化调用转回经典的不安全 `sprintf`。
|
||
|
||
因此,提供一个过长的 **`Host:`** 头部允许攻击者 **溢出 0x80 字节的块并覆盖后续堆块的元数据**(根据分配器的不同,可能是 tcache / fast-bin / small-bin)。可以通过以下方式重现崩溃:
|
||
```python
|
||
import requests, warnings
|
||
warnings.filterwarnings('ignore')
|
||
requests.get(
|
||
'https://TARGET/__api__/',
|
||
headers={'Host': 'A'*750},
|
||
verify=False
|
||
)
|
||
```
|
||
实际利用需要**堆整理**以将可控对象放置在易受攻击的块之后,但根本原因强调了两个重要的要点:
|
||
|
||
1. **_FORTIFY_SOURCE 不是灵丹妙药** – 错误使用可能会使保护失效。
|
||
2. 始终将**正确的缓冲区大小**传递给`_chk`系列(或者,更好的是,使用`snprintf`)。
|
||
|
||
## 参考文献
|
||
* [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/)
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|