TALOS-2026-2391
CVE-2026-33568
A OS command injection vulnerability exists in the boa formMapDelDevice macstr 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.
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)
X2000R - https://www.totolink.net/home/menu/newstpl/menu_newstpl/products/id/242.html
9.1 - CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H
CWE-78 - Improper Neutralization of Special Elements used in an OS Command (‘OS Command Injection’)
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/formMapDelDevice page, which leads us into the formMapDelDevice() function:
0045de48 int32_t formMapDelDevice(struct client* arg1)
0045de78 char* macstr = get_from_postbody(cli: arg1, "macstr", &cgi_var_pref) // [1]
0045de90 char* $v0 = get_from_postbody(cli: arg1, "bandstr", &cgi_var_pref)
0045dea8 char* clientoff = get_from_postbody(cli: arg1, "clientoff", &cgi_var_pref) // [2]
0045dec0 char* hostnameAdd = get_from_postbody(cli: arg1, "hostnameAdd", &cgi_var_pref)
0045ded0 int32_t hnameadd_val
0045ded0
0045ded0 if (sx.d(*clientoff) == 0)
0045ded4 hnameadd_val = sx.d(*hostnameAdd)
0045ded0 else // [3]
0045dedc char* var_d0_1 = $v0
0045deec p2_vfork_execve("/bin/map_del_device", 2, 0, macstr) // [4]
0045def4 hnameadd_val = sx.d(*hostnameAdd)
0045def4
Without going too far in, we examine the potential case in which we’ve provided HTTP POST parameters macstr[1] and clientoff[2], such that we hit the branch at [3] and enter into the /bin/map_del_device with our macstr argument passed in via execve // [4]. Looking at the /bin/map_del_device binary’s main() function we see the following:
004005e0 int32_t main(int32_t argc, char** argv, char** envp)
00400608 int32_t var_44 = 0
00400604 void str_3
00400604 memset(str: &str_3, c: 0, n: 0x2f)
0040061c int32_t var_78 = 0
00400618 void str_2
00400618 memset(str: &str_2, c: 0, n: 0x2f)
00400630 int32_t string_1 = 0
0040062c void str_1
0040062c memset(str: &str_1, c: 0, n: 0x60)
00400644 int32_t string = 0
00400640 void str
00400640 memset(&str, c: 0, n: 0x60)
00400650 uint32_t $v0 = zx.d(var_78.b)
00400650
0040064c if (argc s>= 2) // [5]
00400658 strcpy(dest: &var_44, src: argv[1]) // [6]
00400668 $v0 = zx.d(var_78.b)
00400668
00400664 if (argc != 2)
00400670 strcpy(dest: &var_78, src: argv[2])
00400678 $v0 = zx.d(var_78.b)
Since we know from the execve call above that our argc parameter is 0x2, we hit the branch at [5] and our macstr parameter is copied via strcpy to the stack. Continuing on into how this macstr parameter is then used:
00400680 if ($v0 != 0x35)
004006d4 system(string: "iwpriv wlan1 set_mib aclmode=2")
004006e8 sprintf(&string, "iwpriv wlan1 add_acl_table %s", &mac) // [6]
004006f0 system(&string) // [7]
004006f8 sleep(3)
00400704 system(string: "iwpriv wlan1 set_mib aclmode=0")
00400710 $a0_8 = &sysstr
00400714 $a1_2 = "iwpriv wlan1 clear_acl_table %s"
00400680 else
// [...]
Our mac string is copied via an unfiltered and unsanitized sprintf at [6] to the stack, followed by running our input via the system call at [7]. This code setup is a classic command injection and leads to arbitrary OS commands being run on the target machine.
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
Lilith Wyatt of Cisco Talos