Summary Executive Summary An unauthenticated denial of service is triggered by an oversized POST body. The router web stack forwards attacker-controlled request bodies into a CGILua parser before authentication gates matter, and that parser still exposes an eager body-processing path that can be stressed from the first HTTP transaction even when the body stays below the visible default maxinput ceiling. Root Cause The vulnerability is not a simple missing size check. It is a pre-auth architectural flaw: the router eagerly reads and parses application/x-www-form-urlencoded input inside the allowed parser budget before authentication gates matter. Exploit Path Oversized POST body Pre-auth parser accepts request Body is read and parsed within the configured max-input budget Router web UI becomes unavailable Key Takeaway Authentication is not the relevant barrier here because POST parsing happens before login enforcement, and the expensive body-processing path is still reachable below the configured size ceiling. Trigger Request Evidence Preview POST / HTTP/1.1 Host: 192.168.1.1 Content-Type: application/x-www-form-urlencoded Content-Length: 1000000 Array.from({ length: 100000 }, () => String.fromCharCode(65 + Math.floor(Math.random() * 26))).join(''); The browser-console generator shown here uses a 100,000-character body. In some models, a 1,000,000-character body was required, which can be sent using Python. Devices At time of report this issue was affecting 140K+ devices worldwide across 17+ models . The 140K+ number is the original 2024 exposure estimate. Based on direct testing, almost any version prior to 2022 is affected across this H-series surface. H8102E H168N H167A H199A H288A H198A H267A H267N H268A H388X H196A H369A H268N H208N H367N H181A H196Q Lab Validation Footage Two clips from my 2024 lab set: one shows the denial-of-service path, the other shows a model that did not reproduce. 2024 Lab Set Live Validation H-Series Primary Validation Denial-of-service path Main clip from my original 2024 validation set showing the denial-of-service path. 0:58 Primary clip Supplementary Clip Not vulnerable model This clip shows a model from the same test set that did not reproduce the denial-of-service condition. 0:18 Supplementary clip Impact and Limits Impact Web management interface becomes unavailable. No login is required to reach the request path. The trigger lives in request-body handling before authentication logic matters. Recovery required a manual router reboot; the interface did not recover on its own during testing. Limits The 140K+ exposure figure is historical, based on the 2024 Shodan workset. The vendor stated that the issue had been resolved in March 2021. Root Cause Analysis The extracted firmware exposes a custom httpd and a Lua web application under home/httpd . The request parser is implemented in compiled Lua chunks, including cgilua.lua and cgilua/post.lua . Those chunks were decompiled back into readable Lua source and then checked against the live validation path from the original report. This conclusion is not based on reverse engineering alone. The issue was reported to ZTE PSIRT in May 2024 with live validation evidence, ZTE acknowledged receipt, and the later firmware analysis explains the request-body path that matches the reported behavior. cgilua.lua runs post.parsedata() for every POST before the later login and page-action flow, so the body hits parser code before authentication matters. The caller passes a visible default maxinput of 2097152 bytes into the parser. parsedata() only rejects input when inputsize > maxinput , so any body below that threshold continues into content-type dispatch. The exact dangerous branch is the x-www-form-urlencoded path: urlcode.parsequery(read(inputsize), defs.args) . That is where the bug occurs: an unauthenticated attacker-controlled body is fully read and immediately parsed into Lua structures, which is enough to stall the web UI in the validated firmware set. The vulnerability is not a simple missing size check. It is a fundamental logic flaw: the router eagerly reads and parses the entire POST body before authentication takes place, as long as the payload stays within the visible parser budget. In practice, that means a large urlencoded body can still reach a full read(inputsize) plus parsequery(...) operation on the unauthenticated request path. Before/After Code Comparison The H168N firmware provides a definitive look at the vulnerable parser logic. It is the clearest same-surface code comparison in the current workspace, and the decompiled source maps directly to the live exploitation path. What The Comparison Shows The H168N parser file cgilua/post.lua decompiles cleanly from both firmware artifacts compared here. The decompiled Lua source is identical in the request-body path that matters for this issue. cgilua.lua is also materially unchanged in the caller path that sets _default_maxinput = 2097152 and invokes post.parsedata() . Open Research Challenges Capturing the final vendor remediation diff remains an active objective, and it still requires a later same-model web-code artifact that can be extracted and compared directly. Extracting the encrypted remediation firmware for the target line remains an open community challenge ; H288A and H267A provide useful firmware-era spread, and I invite the community to collaborate on decrypting these later artifacts. Tools Used The working set combined live validation, firmware extraction, Lua decompilation, and parser comparison. The main tools used across that path were: Chrome DevTools for live request validation against the H-series test set. UnluacNET for clean decompilation of the router's Lua 5.1 bytecode into readable source. LuaDecompy and LuaPytecode for chunk parsing, structural checks, and disassembly support. 7-Zip for extracting firmware payloads and carved filesystem regions. Where The Bug Happens in Code Only two files matter here. cgilua.lua is the caller that sends every POST body into the parser. cgilua/post.lua is the parser file where the urlencoded body is actually read and parsed. cgilua.lua Reconstructed logic, not vendor source Caller-side POST setup and visible max-input default Copy local _default_maxinput = 2097152 local _maxinput = _default_maxinput POST_DESC = {isExceedMaxInput = false, maxFileSize = _maxfilesize} if requestmethod == "POST" then post.parsedata({ read = sapi.Request.getpostdata, discardinput = ap and ap.discard_request_body, content_type = servervariable("CONTENT_TYPE"), content_length = servervariable("CONTENT_LENGTH"), maxinput = _maxinput, maxfilesize = _maxfilesize, args = POST, POST_DESC = POST_DESC }) end cgilua/post.lua Reconstructed logic, not vendor source Exact branch where the bug happens Copy function parsedata(defs) assert(type(defs.args) == "table", "field `args' must be a table") init(defs) local inputsize = tonumber(defs.content_length) or 0 if inputsize > maxinput then _G.g_logger:warn("inputsize(" .. inputsize .. ") > maxinput(" .. maxinput .. ")") defs.POST_DESC.isExceedMaxInput = true inputsize = 0 return end if not content_type then error("Undefined Media Type") end if string.find(content_type, "x-www-form-urlencoded", 1, true) then urlcode.parsequery(read(inputsize), defs.args) elseif string.find(content_type, "multipart/form-data", 1, true) then if inputsize > 0 then Main(inputsize, defs.args, defs.POST_DESC) end elseif string.find(content_type, "application/xml", 1, true) or string.find(content_type, "text/xml", 1, true) or string.find(content_type, "text/plain", 1, true) then tinsert(defs.args, read(inputsize)) else error("Unsupported Media Type: " .. content_type) end end The bug is the combination of those two snippets: every POST reaches post.parsedata() , and if the body is still under maxinput , the urlencoded branch performs a full read(inputsize) followed by urlcode.parsequery(...) before authentication gates matter. Vendor Position ZTE responded in February 2026 that the issue had been resolved on 2021-03-23 and declined vendor-side CVE assignment. The public record still matters because the issue was reported in 2024, acknowledged by the vendor, escalated through MITRE, and ultimately published as CVE-2026-34473 . Sources CVE Record Official ID and publication record CGILua Manual Framework behavior reference
CVE-2026-34473 (CVSS 7.5) is a pre-authentication denial-of-service vulnerability affecting multiple ZTE H-series router models, where an unauthenticated attacker can render the web management interface unavailable by sending an oversized POST request with an `application/x-www-form-urlencoded` body. The router's web stack eagerly parses the request body before applying authentication checks, consuming resources and causing a crash that requires a manual reboot. The article indicates widespread historical exposure for firmware versions prior to 2022 but does not provide specific patched version numbers from the vendor or NVD.