| Title | Netis Systems (Netcore Group) EAP930 V0.1.250905.115454 OS Command Injection (CWE-78) |
|---|
| Description | Description:
The web admin interface has a CGI script at /cgi-bin/network_tools that
handles the ping and traceroute diagnostics. It parses its own QUERY_STRING
by hand:
while [ true ]; do
param=${QUERY_STRING%%&*}
QUERY_STRING=${QUERY_STRING#*&}
val=${param#*=}
key=${param%=*}
eval "${key}='${val}'"
if [ "$param" = "$QUERY_STRING" ] || [ ${#param} -le 0 ]; then
break
fi
done
Every key=value pair from the request goes straight into eval, value
wrapped in single quotes and nothing else done to it. A single quote in the
value closes that quoting early and whatever comes after runs as shell.
Neither key nor val is escaped first - key isn't even restricted to a safe
character set, unlike two of the other CGI scripts on this same device
(telnet and hello both do key="${key//[^a-zA-Z0-9_]/_}" before their own
eval).
There's a defined-but-unused sanitizer a few lines above:
#urldecode and handle command injection
function urldecode()
{
str=$1
...
str=${str//[\"\'\`|\\<>@?*~!();,.\$\^]/}
...
}
and right before the parsing loop:
#handle query string
#QUERY_STRING=`urldecode "$QUERY_STRING"`
Commented out. Someone wrote a fix for exactly this and the line that calls
it is disabled.
The session check comes after the parsing loop, not before:
if [ ${#sid} -ne 32 ]; then
returnerrcode 6
exit
fi
access=`ubus call session access "{\"ubus_rpc_session\":\"$sid\",\"object\":\"system\",\"function\":\"upgrade\"}" | grep "true"`
if [ -z "$access" ]; then
returnerrcode 6
exit
fi
By the time this runs, eval already ran. No session id, or a garbage one,
still triggers the injection.
/etc/init.d/uhttpd has no procd_set_param user line, so uhttpd and its CGI
scripts run as root - stock OpenWrt default when nobody drops privileges.
Checked whether anything gates this one level up, at the web server itself.
Nothing does: /etc/config/uhttpd has "list httpauth" and the whole "config
httpauth prefix_user" block commented out, no .htpasswd anywhere on the
image, and cgi_prefix routes /cgi-bin/* straight to these scripts as plain
CGI. Only /cgi-bin/luci goes through LuCI's ACL system.
Firmware ships as an OpenWrt sysupgrade tarball with an overlay squashfs on
top of the base root filesystem. Checked the overlay in case it patches
this file the way it patches another one with the same eval pattern
(upgrade.cgi, sanitized in the overlay version) - network_tools isn't
touched by the overlay, so this is exactly what ships.
Proof of Concept:
Firmware from Netis's own CDN:
https://oss.netis-systems.com/file/46mQAHwr.bin
sha256 b0f6075b5e7925c8b912cf0f375eaebca918fe39a5d9d9b5b602e0ddeb269724
Extracted the squashfs rootfs and ran the unmodified network_tools file
under the device's own busybox (ARM64/musl) via qemu-user emulation.
Request (QUERY_STRING, GET or POST both work - the script reads
QUERY_STRING regardless of method):
url=x.x.x.x'; <command>; x='&count=4
Test payload:
url=x.x.x.x'; touch /tmp/PWNED; echo INJECTED-$(id) #&count=4
/tmp/PWNED got created and the id output showed up in the response, ahead
of the script's own error response for the missing session
({"jsonrpc":"2.0","id ":1,"result":[6]}, error code 6 = invalid session per
the script's own returnerrcode calls) - the command runs during eval,
before that check ever happens.
Impact:
Unauthenticated remote root command execution, single HTTP request, on a
currently sold and supported product.
Vendor contact:
Sent to Netis support ([email protected], the only address I could find
- no security contact published anywhere on netis-systems.com) on
2026-09-08. No reply as of this submission. Given Trend Micro's and
h00die-gr3y's (CVE-2024-48455/56/57) prior experience with this vendor, none
was expected.
|
|---|
| User | arpe1618 (UID 101090) |
|---|
| Submission | 09/18/2026 07:46 (24 days ago) |
|---|
| Moderation | 10/11/2026 16:33 (23 days later) |
|---|
| Status | Duplicate |
|---|
| VulDB entry | 411139 [Netcore NAP930 0.1.241010.141410 Network Tools CGI network_tools eval sid os command injection] |
|---|
| Points | 0 |
|---|