Neutrino Security

Unauthenticated credential disclosure

CVE ID CVE-2025-65127 CVSS 7.5 (HIGH)
CWE CWE-287 AFFECTED COMPONENT get_* functions
PRODUCT WE2001 VERSION V23.09.27
EXPLOITABILITY Remote, Unauth IMPACT Information Disclosure

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.

Remediation

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)