Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

订阅源联系隐私© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2026-76071 — 针对 Netis NC63 ipFilterList 处理程序中通过无界 sscanf 扫描集触发的预认证栈缓冲区溢出漏洞的原创研究与 PoC | Kitploit
工具/GitHubGitHub/ozcanpng/cve-2026-76071
物联网安全漏洞分析漏洞利用逆向工程二进制分析固件分析
GitHubozcanpng/cve-2026-76071

CVE-2026-76071

针对 Netis NC63 ipFilterList 处理程序中通过无界 sscanf 扫描集触发的预认证栈缓冲区溢出漏洞的原创研究与 PoC

查看仓库
1281个月前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2026-76071:Netis NC63 中 skk_set.cgi 的 ipFilterList 处理程序通过 sscanf %[^,] 导致的未认证预认证栈缓冲区溢出

研究员: Özcan Ersan (@ozcanpng)

披露状态

  • CVE: CVE-2026-76071
  • 厂商: Netis Systems Co., Ltd.
  • 产品: Netis NC63 AC1200 无线双频千兆 MU-MIMO 路由器
  • 测试固件: NC63_V3.0.0.3327
  • 受影响组件: /bin/netis.cgi
  • 端点: POST /cgi-bin/skk_set.cgi
  • 触发条件: ipFilterList=mod
  • 动态确认的参数: destHost
  • 静态可达同一解析器的参数: srcHost
  • 认证: 在已验证路径中未观察到也不需要认证
  • 架构: MIPS32r2 小端序,o32 ABI,uClibc
  • 漏洞类别: 基于栈的缓冲区溢出,可控制保存的返回地址
  • 验证: 在隔离的 QEMU 用户模式运行时中对原始哈希的生产 CGI 进行验证
  • 准备时的 CVE 记录状态: 已分配;CNA 记录详情待补充

执行摘要

Netis NC63 固件 V3.0.0.3327 中的通用 MIB/值解析器使用两个 %[^,] 扫描集解析 ipFilterList 的 destHost 字段,但没有最大字段宽度限制。每次转换都会写入一个 16 字节的本地栈缓冲区。因此,直接使用 HTTP 客户端即可提交一个不含逗号的长组件,并覆盖该函数保存的控制数据。

对于动态测试的第二个 destHost 组件,保存的 ra 距离本地缓冲区恰好 112 字节。针对原始哈希 CGI 的 QEMU 跟踪确认,攻击者选择的第三项位于 0x0040f7f4。另一项仅观察测试将返回地址重定向到原始 system() PLT 路径 0x00423ab0,同时将攻击者控制的请求数据保留为精确的 MIPS a0 参数。一个受保护的 /bin/sh 记录了标记,但未执行任何命令。

公开 PoC 有意仅包含超长的 B 模式。它不包含私有的控制转移值或命令边界构造。单独维护的 RCE 脚本位于 poc/exploit-db/,已准备提交至 Exploit-DB,仅用于对受影响系统进行授权测试。

受影响工件完整性

193f6a5e2ce65972b1805bf076f8d3521379a8441c8aaeb5ad0ba174bbee0792  netis_NC63_V3.0.0.3327.bin
eb298774c27070dc595fefcabb4e8c12a46cb5f4fd08f91c3ca92282c3a289a2  squashfs-root/bin/netis.cgi
23faa747b7d2f067aa5431bcc227ceca97a7977cf3e7c372f715cbba57f9209b  squashfs-root/bin/boa
e3fd0ee3013014d59b14a409fb4ee5bb546e7d32413758ab3ad4fb0f0d3dcc47  squashfs-root/lib/libapmib.so

原始生产环境哈希

攻击面与认证状态

厂商前端将 srcHost 和 destHost 构建为三个以逗号分隔的 组件,并将它们与 ipFilterList 一起提交到 /cgi-bin/skk_set.cgi:

param.destHost = $("#dest_host").val();
param.destHost += "," + $("#dest_ip_1").val();
param.destHost += "," + $("#dest_ip_2").val();
param.ipFilterList = $("#ip_action").val();

request({
    url: "/cgi-bin/skk_set.cgi",
    data: param
});

Vendor 前端请求构造

经过验证的 HTTP 形式 CGI 请求不包含 Cookie 或 Authorization 头。/tmp/boa_auth 不存在,但执行仍继续进入 ipFilterList=mod 和 destHost 解析路径。内存破坏缺陷是 FUN_0040f7f4 中无宽度限制的扫描集;更广泛的 CGI 授权失败是使该特权处理程序在认证前暴露的条件。

未认证的 root CGI 边界

从源到汇的追踪

Unauthenticated HTTP client
  |
  | POST /cgi-bin/skk_set.cgi
  | ipFilterList=mod
  | destHost=1,0.0.0.0,<long comma-free component>
  v
FUN_004138a0
  v
FUN_004134c8 (ipFilterList trigger row)
  v
FUN_00410898(request, "ipFilterList")
  v
FUN_0040f7f4(request, trigger, mib_table, pMib)
  |
  | get_request_param("destHost")
  v
sscanf(value, "%d,%[^,],%[^,]", ...)
  |
  | second destination: char[16]
  | no maximum scanset width
  v
saved fp overwrite -> saved ra overwrite -> controlled PC

原始 libapmib.so 元数据将 srcHost 和 destHost 都映射到类型 0x0c,从而选中此解析器分支。动态验证使用 destHost 进行;srcHost 作为同一解析器的静态覆盖纳入,而非单独的动态验证声明。

处理程序路由与原始 MIB 元数据

漏洞代码

规范化后的 Ghidra 派生伪代码:

case 0x0c:
    value = get_request_param(request, metadata_name);
    sscanf(value,
           "%d,%[^,],%[^,]",
           &selector,
           first_ip_component,   /* char[16] */
           second_ip_component); /* char[16] */

    *(char *)(destination + field_offset) = selector;
    inet_aton(first_ip_component, destination + field_offset + 1);
    inet_aton(second_ip_component, destination + field_offset + 5);
    break;

无界扫描集转换

sscanf() 本身并不是漏洞所在。缺陷在于 %[^,] 没有最大字段宽度,因此 sscanf 并不知道每个目标缓冲区只有 16 字节。一个具备容量感知的格式会使用诸如 %15[^,] 的宽度,验证恰好三次转换成功,然后校验解析出的地址值。这是一个缓解措施示例,并非厂商补丁。

栈破坏分析

FUN_0040f7f4 起始于 0x0040f7f4,并创建一个 0x1d0 字节的栈帧:

0040f7f4  addiu sp,sp,-0x1d0
0040f7f8  sw    ra,0x1cc(sp)
0040f7fc  sw    fp,0x1c8(sp)
0040f800  sw    s0,0x1c4(sp)

类型为 0x0c 的目标位于 fp+0x14c 和 fp+0x15c。保存的 ra 位于 fp+0x1cc,因此与第二个缓冲区的精确距离为:

0x1cc - 0x15c = 0x70 = 112 bytes

栈布局与保存的 ra 偏移

动态验证

程序计数器控制

隔离的 PC 证明使用了 112 个填充字节,后跟 0x0040f7f4 的三个低位小端字节;sscanf 终止符提供了第四个零字节。QEMU 观察到两个普通解析器条目,随后是由被覆盖的返回地址引起的第三个条目:

parser_entry_hit=3 pc=0x0040f7f4
GPR28: ... s8 41414141 ra 0040f7f4
total_parser_entry_hits=3
PASS: third parser entry is the overwritten saved RA.

受控的第三方解析器入口

仅观察的命令边界

一个单独的私有验证形成了已保存的 ra=0x00423ab0,即原始二进制文件的 system() PLT 路径。一个受控的请求键后缀在返回时保留在 MIPS 的 a0 中。一次性运行时将 /bin/sh 替换为一个静态记录器:

argv[0]=</bin/sh>
argv[1]=<-c>
argv[2]=<NC63_IPFILTER_RCE_PROOF>
CONTROLLED_MARKER_PREFIX_REACHED
PASS: attacker-controlled request data reached system() as exact a0.
PASS: guarded /bin/sh recorded argv and executed no command.

这在隔离的生产代码路径中建立了一个 RCE 原语。物理路由器的确切利用可靠性、内核随机化行为以及默认 WAN 暴露情况均未测试。

运行时适配与证据边界

所测试的 netis.cgi 与生产制品逐字节一致。由于 qemu-user 中无法获得由 flash 支持的 MIB 状态,一次性 rootfs 使用了一个已披露的、仅限实验室的 libapmib.so 适配方案,该方案分配了清零的 MIB 状态并调整了一个打包字段的对齐方式。它没有改变 CGI、请求解析器、存在漏洞的 sscanf、栈帧、保存的返回地址偏移、尾声或 system() 路径。静态元数据来自原始厂商的 libapmib.so。

原始可执行文件为固定基址,缺少栈金丝雀和 RELRO,并具有可执行栈和 RWX 段。这些属性支持可利用性分析,但不能替代动态 PC 和受保护边界测试。

二进制加固状态

安全的公开 PoC

URL 编码请求体的试运行生成:

python3 poc/poc.py

显式传输至授权的可丢弃目标:

python3 poc/poc.py --target http://192.168.1.1 --send

Exploit-DB RCE 脚本

poc/exploit-db/CVE-2026-76071.py 是为 Exploit-DB 准备的 RCE 脚本。 它针对已记录的未认证 ipFilterList 漏洞,并 接受一个命令参数,用于对已授权的受影响测试目标进行测试:

python3 poc/exploit-db/CVE-2026-76071.py <target> "id"

公开脚本使用一个 115 字节的 B 组件来演示溢出条件。发送该组件可能导致 CGI 进程崩溃。它不包含命令字符串、shellcode、返回 system 的地址、反向 shell 或持久化机制。

影响

成功利用可在路由器管理上下文中执行攻击者选定的命令。原始 Boa 配置以 root 身份运行 CGI。潜在后果包括路由器配置和机密信息泄露、DNS/防火墙/路由操纵、流量重定向、服务中断以及设备完全被攻陷。

修复建议

  1. 对每个 16 字节目标使用 %15[^,],并要求三次成功转换。
  2. 在解析前拒绝过大的序列化主机值。
  3. 在存储前对两个 IP 值进行服务端验证。
  4. 在特权 CGI 分发前强制执行管理员授权。
  5. 审计每个元数据解析器分支,检查是否存在无宽度限制的 %s 和 %[...]。
  6. 使用栈保护、PIE、NX 和 RELRO 重新构建。

证据索引

参见 evidence/README.md。规范化伪代码和指令证据位于 attachments/decompiled-functions/ 下。

披露时间线

  • 2026-08-16: 完成发现和隔离的生产二进制验证。
  • 2026 年 8 月: 报告至 VulnCheck。
  • 2026-08-20: VulnCheck 分配 CVE-2026-76071 并授权公开披露。
  • 2026-08-20: 发布公开披露包。

参考资料

下载工具