Talos Vulnerability Report

TALOS-2026-2393

Totolink X2000R boa formParentControl deviceName stack-based buffer overflow vulnerability

October 20, 2026

CVE Number

CVE-2026-40615

Summary

A stack-based buffer overflow vulnerability exists in the boa formParentControl deviceName functionality of X2000R (version(s): TOTOLINK-X2000R-Gh-V1.0.0-B20250421.1327). A specially crafted HTTP request can lead to arbitrary code execution. An attacker can make an authenticated HTTP request to trigger this vulnerability.

Confirmed Vulnerable Versions

The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.

X2000R (version(s): TOTOLINK-X2000R-Gh-V1.0.0-B20250421.1327)

Product URLs

X2000R - https://www.totolink.net/home/menu/newstpl/menu_newstpl/products/id/242.html

CVSSv3 Score

9.1 - CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H

CWE

CWE-121 - Stack-based Buffer Overflow

Details

The Totolink X2000R is a popular budget gigabit home router primarly found in eastern markets. Supporting IPV6, WPA3, mesh capabilities among other features, the Totolink X2000R is a solid choice for the price point.

The Totolink X2000R mainly relies on the standalone boa binary for all web administration and subsequent configuration. While normally a security risk in itself due to the age, it appears that the version running on the X2000R has been patched. Regardless, for the current set of vulnerabilities we only pay attention to the Totolink-specific issues, so we start from the point where authentication has already occurred via the /boafrm/formLogin webpage, and then we can successfully interact with another /boafrm/form* page, each of which have a corresponding callback. For the current vulnerability we examine the /boafrm/formParentControl page, which leads us into the formParentControl() function:

00419abc    size_t formParentControl(struct client* arg1)

00419aec        struct client* cli = arg1
00419afc        void _days_of_week
00419afc        memcpy(dest: &_days_of_week, src: &days_of_week, n: 0x1c)
00419b2c        uint32_t _addPCRule = get_from_postbody(cli, "addPCRule", &cgi_var_pref)
00419b44        char* _delPCRule = get_from_postbody(cli, "delPCRule", &cgi_var_pref)
00419b5c        char* _modPCRule = get_from_postbody(cli, "modPCRule", &cgi_var_pref) // [1]
00419b64        char* _addPCUrl = get_from_postbody(cli, "addPCUrl", &cgi_var_pref)   // [2]
00419b8c        char* _delPCUrl = get_from_postbody(cli, "delPCUrl", &cgi_var_pref)
00419ba4        char* _urlnum = get_from_postbody(cli, "modRuleStatus", &cgi_var_pref)
00419ba0        char* _enabled = get_from_postbody(cli, "enabled", &cgi_var_pref)
// [...]
00419e44        if (__addPCRule == 0 && sx.d(*_modPCRule) == 0)
00419e4c            mod_rule = sx.d(*_urlnum)
00419e44        else
00419d60            memset(str: &overflow_0x190, c: 0, n: 0x98)
00419d70            memset(str: &var_458, c: 0, n: 0x130)
00419d84            char* $v0_17 = get_from_postbody(cli, "deviceName", &cgi_var_pref) // [3]
00419d84            
00419d90            if (sx.d(*$v0_17) != 0)
00419d9c                strcpy(dest: &overflow_0x190, src: $v0_17)    // [4]

To start, assuming either of our HTTP POST modPCRule[1] or addPCUrl[2] variables are non-zero, we hit the branch containing the line at [3], at which point the program also pulls out our deviceName HTTP POST parameter if it exists. Assuming it’s non-zero, we hit the unrestricted strcpy at [4], and copy our deviceName into a stack-based buffer overflow, resulting in code execution.

Crash Information

Breakpoint 1, 0x00419d9c in ?? ()

[o.o]> !ls
***********************************************************************************
***********************************************************************************
v0[H]      : 0x0049a9a8                         | s3[H]      : 0x0049a958
v1         : 0x00000041                         | s4[X]      : 0x0046496c
a0[S]      : 0x7f8f7ed0                         | s5[X]      : 0x004780c0
a1[X]      : 0x00470000                         | s6[H]      : 0x0049a978
a2[L]      : 0x774622d0                         | s7[X]      : 0x004780c0
a3         : 0x00000001                         | t8[X]      : 0x0048c0dc
t0         : 0x77468628                         | t9[L]      : 0x779338bc
t1         : 0x77468628                         | k0         : 0x00000000
t2[H]      : 0x0049a3b8                         | k1         : 0x00000000
t3         : 0xfffffffc                         | gp[L]      : 0x7794f020
t4         : 0x00000020                         | sp[S]      : 0x7f8f7be8
t5         : 0x00000001                         | ra[X]      : 0x00419d8c
t6         : 0x000006d8                         | status     : 0x0000f413
t7[H]      : 0x00490000                         | badvaddr   : 0x77376159
s0[H]      : 0x0049c998                         | pc[X]      : 0x00419d9c
s1         : 0x00480000                         | fcsr       : 0x00000000
s2[X]      : 0x004780c0                         | restart    : 0x00000000
***********************************************************************************
   0x419d90:    beqz    v1,0x419da8
   0x419d94:    lui     a1,0x47
   0x419d98:    addiu   a0,sp,744
=> 0x419d9c:    jal     0x47bf60
   0x419da0:    move    a1,v0
   0x419da4:    lui     a1,0x47
   0x419da8:    addiu   a2,s1,-32576
   0x419dac:    addiu   a1,a1,-24980
***********************************************************************************
#0  0x00419d9c in (0x400000 0x47c000 0x7c000 0x0 r-xp /bin/boa)(+0x19d9c)
***********************************************************************************

[>_>]> c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()

[^_^] SIGSEGV

***********************************************************************************
***********************************************************************************
v0         : 0x00000083                         | s3         : 0x41414141
v1[H]      : 0x00490000                         | s4         : 0x41414141
a0[H]      : 0x004aa4af                         | s5         : 0x41414141
a1[S]      : 0x7f8f744b                         | s6         : 0x41414141
a2         : 0x00000003                         | s7         : 0x41414141
a3[S]      : 0x7f8f744b                         | t8[X]      : 0x0048c074
t0         : 0x0000003e                         | t9[L]      : 0x7741a6d0
t1         : 0x3e6d726f                         | k0         : 0x00000000
t2         : 0x6c622f3c                         | k1         : 0x00000000
t3         : 0x716b636f                         | gp[L]      : 0x7746a400
t4         : 0x65746f75                         | sp[S]      : 0x7f8f8060
t5         : 0x622f3c3e                         | ra         : 0x41414141
t6         : 0x3e79646f                         | status     : 0x0000f413
t7         : 0x74682f3c                         | badvaddr   : 0x41414140
s0         : 0x41414141                         | pc         : 0x41414141
s1         : 0x41414141                         | fcsr       : 0x00000000
s2         : 0x41414141                         | restart    : 0x00000000
***********************************************************************************
Invalid $pc @ 0x41414141
#0  0x41414141 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
***********************************************************************************

Timeline

2026-06-16 - vulndev@cisco.com - Initial Vendor Notification
2026-06-23 - vulndiscovery@external.cisco.com - Follow-up sent
2026-06-25 - fae_hardware@zioncom.net - Vendor Acknowledged
2026-06-25 - vulndiscovery@external.cisco.com - Resent all notifications
2026-07-16 - vulndiscovery@external.cisco.com - Follow-up sent
2026-09-15 - vulndiscovery@external.cisco.com - Follow-up sent

Credit

Lilith Wyatt of Cisco Talos