ASUSTOR ADM vpnupload.cgi Format String / Stack Buffer Overflow RCE — CVE-2026-6643
by mlgzackfly · 2026-07-05
- Severity
- Critical
- CVE
- CVE-2026-6643
- Category
- binary
- Affected product
- ASUSTOR ADM (ASUSTOR Data Master), /portal/apis/settings/vpnupload.cgi (upload_wireguard action)
- Affected versions
- ADM 5.1.2.REO1 (X64_G3, build 2026-02-25); per source repository for other versions
- Disclosed
- 2026-07-05
- Patch status
- unpatched
References
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-05 |
| Last Updated | 2026-04 |
| Author / Researcher | mlgzackfly |
| CVE / Advisory | CVE-2026-6643 |
| Category | binary |
| Severity | Critical |
| CVSS Score | Not specified in source (source lists qualitative severity “High”) |
| Status | PoC |
| Tags | asustor, adm, nas, format-string, stack-buffer-overflow, cwe-134, cwe-121, rce, wireguard |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | ASUSTOR ADM (ASUSTOR Data Master), /portal/apis/settings/vpnupload.cgi (upload_wireguard action) |
| Versions Affected | ADM 5.1.2.REO1 (X64_G3, build 2026-02-25); per source repository for other versions |
| Language / Platform | Native C binary (CGI), x86-64 Linux firmware; PoC written in Python 3 |
| Authentication Required | Yes — a valid Revive_Session cookie is required |
| Network Access Required | Yes |
Summary
The ASUSTOR ADM NAS operating system’s WireGuard config upload handler (vpnupload.cgi, upload_wireguard action) contains two chained memory-safety bugs. First, it JSON-encodes the parsed config and passes the result directly as the format string to printf(), giving an authenticated attacker control over a printf format string (CWE-134) — allowing stack memory disclosure via %x/%p and arbitrary memory writes via %n. Second, it copies config fields into fixed 300-byte stack buffers using unbounded sscanf("%s") while accepting up to 32,768 bytes per line via fgets (CWE-121), enabling a classic stack buffer overflow. The repository’s PoC and analysis chain these two bugs — using the format string leak to recover a libc base address, then overflowing the Endpoint field (closest 300-byte buffer to the saved return address) to redirect execution to system() or a one-gadget, achieving remote code execution as the web server user.
Vulnerability Details
Root Cause
In the upload_wireguard handler, the parsed WireGuard config is serialized to JSON and then executed as printf(pcVar2) instead of printf("%s", pcVar2), so any format specifiers embedded in config field values (e.g. PrivateKey) are interpreted by printf. Separately, eight config fields (PrivateKey, Address, PublicKey, ListenPort, PresharedKey, AllowedIPs, PersistentKeepalive, Endpoint) are each copied into 300-byte stack buffers via sscanf(__s, "Field = %s", buf) with no length limit, while only the DNS field has a bound applied. The binary was compiled without stack canaries, without PIE, and with only partial RELRO (GOT writable), and FORTIFY_SOURCE protection is absent (plain printf rather than __printf_chk), which together make both the info leak and the overwrite reliable.
Attack Vector
- Authenticate to obtain a valid
Revive_Sessioncookie. - Upload a crafted WireGuard config (via a two-part multipart POST to
vpnupload.cgi?act=upload_wireguard) with format specifiers (e.g.%08x) embedded in thePrivateKeyfield to leak stack values, including a libc pointer, in the response. - Compute the libc base address from the leaked pointer using a known symbol offset (e.g.
__libc_start_main), and usereadelf/one_gadgetagainst the extractedlibc.so.6to computesystem(),/bin/sh, and gadget offsets. - Overflow the
Endpointfield (local_164, 300 bytes, 364 bytes from the saved return address) with a value exceeding 300 bytes to overwrite the saved RIP — a libc address’s trailing null bytes align naturally with the already-zero upper bytes of a typical return address, avoiding early truncation bysscanf("%s"). - Redirect execution to a one-gadget or a
pop rdi; ret→system("/bin/sh")ROP chain built entirely from libc addresses (to avoid embedded NUL bytes) to obtain a shell as the web server user; the includedexploit.pyautomates offset detection, leak, and RCE stages, plus arbitrary command execution once the GOT/return-address overwrite is established.
Impact
An authenticated attacker (any user able to reach the VPN config upload endpoint) can achieve remote code execution as the ADM web server process, leading to full compromise of the NAS device, including access to all stored data and any connected network segments.
Environment / Lab Setup
Target: ASUSTOR ADM 5.1.2.REO1 (X64_G3) vpnupload.cgi, extracted/run from firmware image X64_G3_5.1.2.REO1.img; local test setup uses a single-byte auth-bypass patch (je -> jmp at offset 0x1224) for authenticated testing only
Attacker: Python 3 with `requests`, `readelf`, `strings`, and `one_gadget` (Ruby gem) for computing exploitation offsets
Proof of Concept
PoC Script
See
exploit.pyin this folder.
| |
The script runs in stages: offset detects the format-string argument offset, leak dumps stack values to recover a libc pointer, rce/rce-rop overwrites the return address using either a one-gadget or a pop rdi+system() ROP chain, and shell executes an arbitrary command once code execution is established. Constants (LIBC_SYSTEM, LIBC_BINSH, LIBC_POP_RDI_RET, LIBC_ONE_GADGETS) must be updated per the target’s extracted libc.so.6.
Detection & Indicators of Compromise
Example crafted request:
POST /portal/apis/settings/vpnupload.cgi?act=upload_wireguard HTTP/1.1
Cookie: <session>
Content-Type: multipart/form-data; boundary=BOUND
PrivateKey = AAAA_%08x_%08x_%08x_%08x
Signs of compromise:
- WireGuard config uploads to
vpnupload.cgicontaining%x,%p,%n, or other printf conversion specifiers in field values. - Unusually large field values (thousands of bytes) for
PrivateKey/Endpoint/other WireGuard fields in upload requests. - CGI process crashes (SIGSEGV, exit code 139) correlating with VPN config uploads.
- Outbound shell/command execution originating from the ADM web server process shortly after a VPN config upload.
Remediation
| Action | Detail |
|---|---|
| Primary fix | No vendor patch confirmed as of 2026-07-05; source recommends replacing printf(pcVar2) with printf("%s", pcVar2) or fputs(pcVar2, stdout), and adding explicit length limits to all sscanf format strings (e.g. %299s for 300-byte buffers). |
| Interim mitigation | Restrict network access to the ADM management/VPN upload interface to trusted hosts, and disable WireGuard config upload functionality for untrusted accounts until patched. |
References
Notes
Mirrored from https://github.com/mlgzackfly/CVE-2026-6643 on 2026-07-05.
| |