春秋杯冬季赛day2 easy_http复现
字数 1640 2025-08-22 12:23:30

Easy_HTTP漏洞分析与利用教学文档

1. 题目概述

这是一个来自春秋杯冬季赛Day2的题目"easy_http",主要特点包括:

  • 没有使用标准libc,所有libc函数都被重写且符号表被抹除
  • 采用多进程架构,调试较为复杂
  • 漏洞点本身简单但逆向难度大
  • IDA反编译结果不准确,增加了分析难度

2. 题目功能分析

2.1 HTTP请求处理

程序实现了一个简单的HTTP服务器,主要处理流程:

  1. 请求解析:通过getmessagefromheader函数解析HTTP请求头

    • 查找"POST"、"GET"、"HTTP/1.1"等关键字
    • 提取Host、Content、Content-Length字段并存入全局变量
  2. 请求格式要求

    POST / HTTP/1.1
    Host: example.com
    Content-Length: 100
    Content: AAAAA... (实际内容)
    

2.2 关键函数分析

getmessagefromheader函数

  • 通过字符串匹配查找关键字段
  • 返回是否成功找到Host、Content、Content-Length

响应生成函数

  • 生成HTTP响应头
  • 包含一个会导致进程退出的函数调用

3. 漏洞分析

3.1 漏洞位置

漏洞存在于一个关键检查函数中,涉及以下变量:

  • v10[0]: 存储从Content-Length头获取的长度值
  • v10[1]: 标志位,表示Host长度是否<=0x2f
  • v12: 通过strlen获取的实际Content长度

3.2 漏洞成因

检查逻辑错误地使用了"||"运算符:

if (v10[0] <= 0xF0 || v10[1])

本意可能是:

if (v10[0] <= 0xF0 && v10[1])

这使得攻击者可以:

  1. 伪造Content-Length头使其大于0xF0
  2. 同时保持Host长度合规(v10[1]=1)
  3. 绕过长度检查导致栈溢出

3.3 溢出机制

后续的memcpy类函数将Content内容复制到栈缓冲区:

  • 源缓冲区:Content内容
  • 目标缓冲区:栈上的v13/v14
  • 由于长度检查被绕过,可以写入超长数据导致栈溢出

4. 漏洞利用

4.1 信息泄露

利用show功能泄露canary:

  1. 发送精心构造的Content,覆盖canary最低字节的\x00
  2. 通过show功能读取被修改的canary

栈布局:

+-----------------+
| ...             |
+-----------------+
| canary          | <-- 可以被覆盖
+-----------------+
| ...             |
+-----------------+
| v14 (content)   | <-- show读取的位置
+-----------------+

4.2 ROP链构造

由于没有标准libc,需要直接使用syscall:

  1. 在.bss段写入"/bin/sh"
  2. 构造execve系统调用:
    • rax=59 (execve)
    • rdi="/bin/sh"地址
    • rsi=0
    • rdx=0

4.3 利用注意事项

  1. 路径匹配问题

    • 栈上某些地址被ROP覆盖会影响路径匹配
    • 解决方法:使用较长的pop链保持栈平衡
  2. 请求格式

    • 必须以\r\n结尾
    • 否则会导致程序异常

5. 调试技巧

5.1 多进程调试

由于set follow-fork-mode parent无效,采用以下方法:

  1. 使用ps -ax | grep attachment获取子进程PID
  2. 附加到子进程进行调试

5.2 IDA反编译问题处理

  1. 对可疑函数进行动态调试确认功能
  2. 结合上下文和寄存器变化推断函数用途
  3. 重命名函数使其意义明确

6. 完整利用步骤

  1. 泄露canary

    • 发送精心构造的请求覆盖canary最低字节
    • 通过show功能读取canary
  2. 构造ROP链

    • 计算必要gadget地址
    • 布置execve参数
  3. 触发漏洞

    • 发送超长Content触发栈溢出
    • 覆盖返回地址指向ROP链
  4. 获取shell

    • ROP链执行execve("/bin/sh", 0, 0)
    • 获取交互式shell

7. 防御建议

  1. 修复漏洞

    • 将"||"改为"&&"进行严格检查
    • 使用strlen获取的实际长度进行验证
  2. 增强防护

    • 启用栈保护(虽然本题已使用canary)
    • 限制单个请求的最大长度
  3. 代码审计

    • 对关键安全检查进行重点审计
    • 确保长度验证逻辑正确

8. 总结

本题展示了以下安全知识点:

  1. HTTP协议实现中的安全问题
  2. 长度验证不严谨导致的栈溢出
  3. 无libc环境下的ROP利用技巧
  4. 多进程应用的调试方法
  5. 对抗反编译不准确的逆向技巧
Easy_ HTTP漏洞分析与利用教学文档 1. 题目概述 这是一个来自春秋杯冬季赛Day2的题目"easy_ http",主要特点包括: 没有使用标准libc,所有libc函数都被重写且符号表被抹除 采用多进程架构,调试较为复杂 漏洞点本身简单但逆向难度大 IDA反编译结果不准确,增加了分析难度 2. 题目功能分析 2.1 HTTP请求处理 程序实现了一个简单的HTTP服务器,主要处理流程: 请求解析 :通过 getmessagefromheader 函数解析HTTP请求头 查找"POST"、"GET"、"HTTP/1.1"等关键字 提取Host、Content、Content-Length字段并存入全局变量 请求格式要求 : 2.2 关键函数分析 getmessagefromheader 函数 通过字符串匹配查找关键字段 返回是否成功找到Host、Content、Content-Length 响应生成函数 生成HTTP响应头 包含一个会导致进程退出的函数调用 3. 漏洞分析 3.1 漏洞位置 漏洞存在于一个关键检查函数中,涉及以下变量: v10[0] : 存储从Content-Length头获取的长度值 v10[1] : 标志位,表示Host长度是否 <=0x2f v12 : 通过strlen获取的实际Content长度 3.2 漏洞成因 检查逻辑错误地使用了"||"运算符: 本意可能是: 这使得攻击者可以: 伪造Content-Length头使其大于0xF0 同时保持Host长度合规(v10[ 1 ]=1) 绕过长度检查导致栈溢出 3.3 溢出机制 后续的 memcpy 类函数将Content内容复制到栈缓冲区: 源缓冲区:Content内容 目标缓冲区:栈上的v13/v14 由于长度检查被绕过,可以写入超长数据导致栈溢出 4. 漏洞利用 4.1 信息泄露 利用show功能泄露canary: 发送精心构造的Content,覆盖canary最低字节的\x00 通过show功能读取被修改的canary 栈布局: 4.2 ROP链构造 由于没有标准libc,需要直接使用syscall: 在.bss段写入"/bin/sh" 构造execve系统调用: rax=59 (execve) rdi="/bin/sh"地址 rsi=0 rdx=0 4.3 利用注意事项 路径匹配问题 : 栈上某些地址被ROP覆盖会影响路径匹配 解决方法:使用较长的pop链保持栈平衡 请求格式 : 必须以 \r\n 结尾 否则会导致程序异常 5. 调试技巧 5.1 多进程调试 由于 set follow-fork-mode parent 无效,采用以下方法: 使用 ps -ax | grep attachment 获取子进程PID 附加到子进程进行调试 5.2 IDA反编译问题处理 对可疑函数进行动态调试确认功能 结合上下文和寄存器变化推断函数用途 重命名函数使其意义明确 6. 完整利用步骤 泄露canary : 发送精心构造的请求覆盖canary最低字节 通过show功能读取canary 构造ROP链 : 计算必要gadget地址 布置execve参数 触发漏洞 : 发送超长Content触发栈溢出 覆盖返回地址指向ROP链 获取shell : ROP链执行execve("/bin/sh", 0, 0) 获取交互式shell 7. 防御建议 修复漏洞 : 将"||"改为"&&"进行严格检查 使用strlen获取的实际长度进行验证 增强防护 : 启用栈保护(虽然本题已使用canary) 限制单个请求的最大长度 代码审计 : 对关键安全检查进行重点审计 确保长度验证逻辑正确 8. 总结 本题展示了以下安全知识点: HTTP协议实现中的安全问题 长度验证不严谨导致的栈溢出 无libc环境下的ROP利用技巧 多进程应用的调试方法 对抗反编译不准确的逆向技巧