إرسال #850500: WAVLINK WL-NU516U1 2026-05-15 (build 708c073-mt7628) Command Injectionالمعلومات

عنوانWAVLINK WL-NU516U1 2026-05-15 (build 708c073-mt7628) Command Injection
الوصف# WAVLINK NU516U1: Stack Buffer Overflow via CONTENT_LENGTH in nas.cgi Leading to Remote Code Execution ## Summary WAVLINK NU516U1 has a critical stack-based buffer overflow vulnerability in the `nas.cgi` binary. The `main()` function reads the HTTP `CONTENT_LENGTH` header without upper-bound validation and uses it as the size argument to `fgets()`, writing attacker-controlled data into a fixed 516-byte stack buffer. An authenticated attacker (or unauthenticated via MeshMode=2 auth bypass) can overflow the buffer to overwrite the saved return address on the MIPS32 stack and achieve arbitrary code execution as root. The binary has no stack canary, no ASLR for the main executable, and no NX — a single HTTP POST request is sufficient for full RCE. A one-gadget within the binary's own code (`jal system@PLT; move a0, s0` at 0x0040536c) avoids PIC/$gp issues entirely. ## Affected Versions WAVLINK NU516U1 firmware version 2026-05-15 (build 708c073-mt7628) ## Vulnerability Details ### Root Cause: Unbounded fgets() with attacker-controlled size `nas.cgi` → `main()` (`nas.c` lines 26-54): ```c char acStack_210[516]; // 516-byte stack buffer (line 26) pcVar2 = getenv("CONTENT_LENGTH"); // attacker-controlled (line 44) lVar3 = strtol(pcVar2, NULL, 10); // no upper bound check (line 48) memset(acStack_210, 0, 0x200); fgets(acStack_210, lVar3 + 1, stdin); // reads up to CONTENT_LENGTH+1 bytes (line 54) ``` When `CONTENT_LENGTH > 515`, the `fgets()` call writes past the end of `acStack_210`, corrupting the saved `$s0`–`$s2` registers and the return address `$ra` on the MIPS32 stack frame. ### Exploitation: One-Gadget RCE The MIPS32 stack frame layout for `main()`: | Offset from buffer | Content | |---|---| | 0–515 | `acStack_210` (buffer) | | 516 | saved `$s0` | | 520 | saved `$s1` | | 524 | saved `$ra` (return address) | The exploit overwrites: - `$s0` → pointer to a command string placed at offset 528 (after `$ra`) - `$ra` → `0x0040536c` (one-gadget: `move $a0, $s0; jal system@PLT`) The `system()` PLT stub at `0x00406c80` uses absolute addressing (`lui $t7, 0x41; lw $t9, 28712($t7)`), so no `$gp`/`$t9` setup is needed. ### Attack Chain - Attacker sends a single HTTP POST to `/cgi-bin/nas.cgi` with `CONTENT_LENGTH` set to a value larger than 516 - The POST body overflows the stack buffer, setting `$s0` to the command string address and `$ra` to the one-gadget - `main()` returns, jumping to the one-gadget which calls `system()` with the attacker's command - Command executes as `uid=0(root)` ## Proof of Concept ```bash # Sends 2048 bytes into a 516-byte buffer — triggers SIGSEGV # lighttpd returns HTTP 500 when the CGI process crashes curl -X POST http://192.168.10.1/cgi-bin/nas.cgi \ -H "Referer: http://192.168.10.1/" \ -H "Cookie: session=VALID_SESSION" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "$(python3 -c 'print("page=nas&" + "A"*2048)')" # Expected: HTTP 500 (Internal Server Error) — CGI process killed by SIGSEGV ``` ### Reproduction Result ``` Normal request (8 bytes): HTTP 200, normal response Overflow request (2048 bytes): HTTP 500 (CGI process SIGSEGV, exit code 139) ``` The saved `$ra` is at offset 524 from the buffer. With no stack canary, no ASLR for the main binary, and no NX, the attacker controls `$ra` and can redirect execution to the one-gadget at `0x0040536c` (`move $a0, $s0; jal system@PLT`) to call `system()` with an arbitrary command string. ## Impact An attacker on the local network (or remote via CSRF) can: - Execute arbitrary commands as `root` on the router with a single HTTP request - Install persistent backdoors, modify DNS settings, intercept traffic - Pivot to other devices on the LAN - Combine with MeshMode=2 auth bypass to exploit without valid credentials - Combine with CSRF referer bypass (`strstr` substring match) for drive-by exploitation from a malicious web page ## Suggested Remediation ```c // nas.c main() — clamp fgets size to buffer capacity pcVar2 = getenv("CONTENT_LENGTH"); lVar3 = strtol(pcVar2, NULL, 10); if (lVar3 + 1 > sizeof(acStack_210)) { lVar3 = sizeof(acStack_210) - 1; // clamp to buffer size } fgets(acStack_210, lVar3 + 1, stdin); ``` Additionally, enable stack canaries (`-fstack-protector-strong`) and ASLR for all CGI binaries to raise the exploitation bar for residual memory corruption issues.
المصدر⚠️ https://github.com/oduoke567/WAVLINK-NU516U1-2026-05-1/blob/main/report2.md
المستخدم
 oduoke (UID 98772)
ارسال06/06/2026 12:16 PM (2 أشهر منذ)
الاعتدال02/08/2026 10:33 PM (2 months later)
الحالةتمت الموافقة
إدخال VulDB385416 [Wavlink WL-NU516U1 708c073-mt7628 nas.cgi fgets CONTENT_LENGTH تلف الذاكرة]
النقاط20

Want to know what is going to be exploited?

We predict KEV entries!