Submit #1003693: D-Link DIR-868L Hardware rev B1, firmware 2.01b05 (web interface / HNAP, component /htdocs/cgibin) Command Injectioninfo

TitleD-Link DIR-868L Hardware rev B1, firmware 2.01b05 (web interface / HNAP, component /htdocs/cgibin) Command Injection
DescriptionA pre-authentication OS command injection exists in the HNAP web interface of the D-Link DIR-868L rev B1 router, firmware 2.01b05 (component /htdocs/cgibin, MD5 64a37f67c57dc25b3678dbcc8554c10e, ARM). The HNAP CGI handler authorizes requests by checking whether the SOAPACTION HTTP header *contains* the string "http://purenetworks.com/HNAP1/GetDeviceSettings" using an unanchored strstr(). Because the check is a substring match, any request whose SOAPACTION merely contains that prefix bypasses the whole authentication block (the HNAP-AUTH HMAC verification is never called). The handler then takes the "action name" as the text following the last '/' of the same header and passes it to system() without any filtering: sprintf(s, "sh /var/run/%s.sh > /dev/console", action); /* 0x1AA34 */ system(s); /* 0x1AA40 */ Shell metacharacters in the action name therefore execute arbitrary commands as root. The injected command inherits the CGI's stdout, so its output is returned in the HTTP response body when prefixed with a CGI header ("echo Content-Type: text/plain; echo;"), giving a full read-back channel. Proof of concept (GET, no credentials): GET /HNAP1/ HTTP/1.1 Host: <target> SOAPACTION: "http://purenetworks.com/HNAP1/GetDeviceSettings/; sleep 10;" The server sleeps exactly 10 seconds (measured 10.02 s; a non-spoofed unknown action returns 401, proving the auth gate is otherwise active). With output retrieval: SOAPACTION: "http://purenetworks.com/HNAP1/GetDeviceSettings/; echo Content-Type: text/plain; echo; cat /proc/self/status;" the response body contains "Uid: 0 0 0 0" (root). Payload constraints (documented from testing): the payload must follow the last '/' of the header, so it cannot contain '/' itself (runtime-construct it with e.g. s=`echo $PATH | busybox cut -c1`; cat ${s}proc${s}self${s}status); the character '(' in the header value is rejected by the web server. Verification chain (all by the reporter): 1. Static analysis of the ARM binary (IDA) - substring auth gate at sub_1A57C+0xC8, unfiltered action into system() at +0x4C4. 2. Unicorn emulation of the real firmware code - HMAC verification function never called; system() receives the attacker string verbatim. 3. qemu-arm user-mode execution - strace shows execve("/bin/sh", ["sh","-c","sh /var/run/; touch ..."]) and the injected command runs as uid=0; timing oracle exact (10.018 s). 4. FirmAE full-system emulation over HTTP - dose-dependent sleep timing (10.02 s / 5.02 s), 401 control case, command output returned, root confirmed via /proc/self/status.
Source⚠️ https://github.com/Walnut1337/Command-Injection-DIR-868L/blob/main/poc/poc_hnap_injection.py
User
 Walnut1337 (UID 100856)
Submission09/28/2026 09:43 (1 month ago)
Moderation10/14/2026 15:00 (16 days later)
StatusDuplicate
VulDB entry419825 [D-Link DIR-868L 2.01b05 HNAP CGI /htdocs/cgibin system SOAPACTION os command injection]
Points0

Are you interested in using VulDB?

Download the whitepaper to learn more about our service!