TALOS-2026-2432
CVE-2026-10131
An OS command injection vulnerability exists in the boa formPasswordSetup 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/formPasswordSetup page, which leads us into the formPasswordSetup() function:
0044fd5c int32_t formPasswordSetup(struct client* arg1)
0044fd88 char var_108[0x64]
0044fd88 memset(str: &var_108, c: 0, n: 0x64)
0044fd9c char* value = get_from_postbody(cli: arg1, "userName", &cgi_var_pref) // [1]
0044fdb4 char* value_1 = get_from_postbody(cli: arg1, "newPass", &cgi_var_pref) // [2]
0044fdf0 char* str1 = generate_digest_HA1(get_from_postbody(cli: arg1, "Cusername", &cgi_var_pref), // [3]
0044fdf0 get_from_postbody(cli: arg1, "Cpassword", &cgi_var_pref)) // [4]
0044fe00 char var_40[0x28]
0044fe00 apmib_get(MIB_PASSWORD, out: &var_40)
0044fe14 int32_t out
0044fe14 char* $a1_3
0044fe14
0044fe14 if (strcmp(str1, str2: &var_40) == 0) // [5]
0044fee4 free(ptr: str1)
0044fef4 int32_t $v0_4 = sx.d(*value_1)
0044fef4
0044fef0 if (sx.d(*value) == 0)
0044fef8 if ($v0_4 == 0)
0044fef8 goto label_44ff20
0044fef8
0044ff08 $a1_3 = "ERROR: userName is empty,Password should be empty."
0044fef0 else if ($v0_4 != 0)
0044ff20 label_44ff20:
0044ff20
0044ff28 if (apmib_set(MIB_USERNAME, value) != 0)
0044ff44 if (apmib_set(MIB_PASSWORD, value: value_1) != 0)
0044ff58 out = 0
0044ff5c // has to do with mesh stuff
0044ff5c apmib_get(MIB_DO_Mcli, &out) // [6]
0044ff5c
0044ff6c if (out == 1)
0044ff90 snprintf(dst: &var_108, 0x64, format: "%s %d %s &", "Mcli", 5, value_1) // [7]
0044ff98 system(string: &var_108) // [8]
As expected of a password setup function, we must first provide the desired new userName[1] and newPass[2], while also providing the current username Cusername [3] and current password Cpassword[4]. A hash is made of the currrent username and password and if they match the MIB_PASSWORD hash in flash memory then we enter our desired code flow. The new password and new user are set, but more importantly, if the system is in mesh mode (determined by the apmib_get call at [6] which we can easily set via another form), then we hit the snprintf call at [7] which takes our new password value and creates a command with it to be run by the system call at [8]. as there is no sanitization on our password field at all, this results in a classic OS command injection vulnerability.
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