TALOS-2026-2428
CVE-2026-9814
An OS command injection vulnerability exists in the boa formWizard newPass 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/formWizard page, which leads us into the formWizard() function:
0044e3dc size_t formWizard(struct client* cli)
// [...]
0044e474 char* opmode_wizard = get_from_postbody(cli, "opmode_wizard", &cgi_var_pref) // [1]
0044e484 int32_t* $a1_2 = &var_12c
0044e480 int32_t MIB_DO_Mcli
0044e480
0044e480 if (sx.d(*opmode_wizard) != 0) ... // [2]
0044e480
0044e5cc int32_t $a2 = 1
0044e5cc
0044e5c8 // useless, just need wispWanId post param
0044e5c8 if (handle_wispWanId(cli, $a1_2) s>= 0) // [3]
0044e5d4 int32_t $v0_3
0044e5d4 $v0_3, $a2 = get_ntp_servernames(cli, &var_12c, 1) // [4]
0044e5d4
0044e5dc if ($v0_3 s>= 0)
0044e5e4 set_timeZone()
0044e5f8 char* $v0_4 = get_from_postbody(cli, "newPass", &cgi_var_pref) // [5]
0044e60c char* $a1_15 = &var_12c
0044e60c
0044e608 if (sx.d(*$v0_4) != 0)
0044e614 apmib_set(MIB_PASSWORD, $v0_4)
0044e628 MIB_DO_Mcli = 0
0044e624 apmib_get(MIB_DO_Mcli, out: &MIB_DO_Mcli) // [6]
0044e638 $a1_15 = &var_12c
0044e638
0044e634 if (MIB_DO_Mcli == 1)
0044e654 sprintf(dst: &var_190, fmt: "%s %d %s &", "Mcli", 5, $v0_4) // [7]
0044e65c system(string: &var_190) // [8]
0044e664 $a1_15 = &var_12c
To reach our desired vulnerable code path we first have to make sure to have an opmode_wizard HTTP POST parameter [1] that is equal to 0x0, such that we skip the large branch at [2]. The handle_wispWanId() function at [3] can likewise be easily be passed by if we set our wispWanId HTTP POST parameter to 0x1. The get_ntp_servernames function [4] can also be ignored most simply if we set our timeZone parameter to something valid. We finally hit the read of our input payload at [5] inside of the newPass HTTP POST parameter, but before we can utilize it, we must note that actually hitting this vulnerability requires a specific router configuration to be set (the MIB_DO_Mcli [6] parameter, which determines if the router is in Mesh mode), but this can easily be done via the web portal. Assuming this has been done, we reach the sprintf call at [7], which builds a command that is run with system at [8], a command that includes our unsantized newPass input, resulting in arbitrary command injection.
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