Breaking into the D-Link admin with mac/ip spoofing :(

In case it ever becomes useful to anyone for any reason, the admin interface of a D-Link 655 (and likely other dlinks) uses a host’s MAC/IP address to keep authentication.

This means, if someone logs in to a D-Link router you can spoof their ip/mac address to gain access to the admin without a username/password.

I noticed the D-link admin interface wasn’t setting any form of session cookies to keep track of me being logged in, and realized they had to be keeping track of authentication this way. I tested it on two of my laptops on the local network and low and behold, easy access to the admin.

My dlink dir655 embarrasses and redeems itself

This is no review of my D-Link DIR-655. I am pretty indifferent to it as a piece of hardware. It’s a wireless router and therefore is often the subject of my hatred and loathing, but probably no more so than any other.

What I needed from my D-Link 655 was to programmatically grab the list of wireless clients.

The easiest course of action seemed to be scraping the html of the admin web interface. And of course, for any web-scraping related task we have Ruby’s Mechanize.

The Embarassment

Upon first examination of the login form to see what I needed to submit, I found two things:

1: The interface was designed in dream weaver
<!-- InstanceBegin template="/Templates/Master_No_Nav.dwt" codeOutsideHTMLIsLocked="false" -->
2: The login form was handled by the following hideous javascript
<form id="myform" action="/" onsubmit="send_login(); return false;">
  <fieldset>
    <p>
      <label class="duple" for="username">User Name :</label>
      <select id="username" name="username">
        <option value="admin">Admin</option>
        <option value="user">User</option>
      </select>
    </p>
    <p>
      <label class="duple" for="password"> Password :</label>
      <input type="password" id="password" maxlength="15" name="password" value="" tabindex="100" />
      <input class="button_submit_padleft" type="button" name="Login" value="Log In" onclick="send_login();" />
    </p>
  </fieldset>
</form>
function send_login()
{
    /*
     * Salt in hex, 8 chars long.
     */
    var salt = "99523ea3";

    var password = document.forms.myform.password.value.substr(0,16);
    document.forms.myform.password.value = "";      // Make sure password never gets sent as clear text

    /*
     * Pad the password to 16 chars.
     */
    for (var i = password.length; i < 16; i++) {
       password += String.fromCharCode(1);
    }

    /*
     * Append the password to the salt and pad the result to 63 bytes.
     */
    var input = salt + password;
    for (var i = input.length; i < 63; i++) {
       input += String.fromCharCode(1);
     }

    /*
     * Append a 'U' for user login, or a '\x01' for admin login.
     */
     input += (document.forms.myform.username.value == 'user') ? 'U' : String.fromCharCode(1);

    /*
     * MD5 hash of the salt.
     */
     var hash = hex_md5(input);

    /*
     * Append the MD5 hash to the salt.
     */
    var login_hash = salt.concat(hash);

    /*
     * Send the login hash to the server.
     */
    var xml_loader = new ajax_xmlhttp("/post_login.xml?hash=" + login_hash, xml_ready, xml_timeout);
    if (!xml_loader) {
      /*
       * Browser does not support XML DOM.
       */
        alert ("Your web browser is too old to use this web site. Please upgrade your browser.");
        return;
     }
     xml_loader.retrieve_xml();
}

The javascript code above computes a hash using my username and password and uses that to authenticate, instead of sending my username and password over as params. I avoided reimplementing the above in ruby in favor of typing my username and password into the form and grabbing the hash from my chrome developer tools console.

Sorry D-Link. Your heart may be in the right place, trying to protect my safety and whatnot, but if someone is sniffing the hash thats created from that, they have full admin access anyway.

Redemption

Once logging in and visiting the wireless clients page, I was pleasantly surprised and amused at how they handle it. The router provides the available clients as an xml file, and the interface does javascript xslt translation to format it for clients.

   var xsl_loader = new ajax_xslproc("../Status/wireless_clients.sxsl", xsl_ready);
   var xml_loader = new ajax_xmlhttp("../wifi_assoc.xml", xml_ready);

Pretty nifty way of getting around complex page generation and very nice for me to use, thanks D-Link :}.

For anyone curious, here's what the xml output of http://192.168.0.3/wifi_assoc.xml was:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<wifi_assoc>
  <radio>
    <assoc>
      <mac>001CB3B58092</mac>
      <ssid>Janus</ssid>
      <channel>1</channel>
      <rate>104</rate>
      <quality>60</quality>
      <type>802.11n (2.4GHz)</type>
      <ip_address>0.0.0.0</ip_address>
    </assoc>
    <assoc>
      <mac>0024D704F150</mac>
      <ssid>Janus</ssid>
      <channel>1</channel>
      <rate>18</rate>
      <quality>36</quality>
      <type>802.11g</type>
      <ip_address>0.0.0.0</ip_address>
    </assoc>
    <assoc>
      <mac>002100555E85</mac>
      <ssid>Janus</ssid>
      <channel>1</channel>
      <rate>13</rate>
      <quality>40</quality>
      <type>802.11n (2.4GHz)</type>
      <ip_address>0.0.0.0</ip_address>
    </assoc>
    <assoc>
      <mac>38E7D8DBBE53</mac>
      <ssid>Janus</ssid>
      <channel>1</channel>
      <rate>2</rate>
      <quality>32</quality>
      <type>802.11g</type>
      <ip_address>0.0.0.0</ip_address>
    </assoc>
    <assoc>
      <mac>00216B98F87A</mac>
      <ssid>Janus</ssid>
      <channel>1</channel>
      <rate>24</rate>
      <quality>70</quality>
      <type>802.11g</type>
      <ip_address>0.0.0.0</ip_address>
    </assoc>
    <assoc>
      <mac>002314AC6714</mac>
      <ssid>Janus</ssid>
      <channel>1</channel>
      <rate>18</rate>
      <quality>52</quality>
      <type>802.11g</type>
      <ip_address>0.0.0.0</ip_address>
    </assoc>
  </radio>
</wifi_assoc>

Science, Clarke! Do it for Science!

Things have changed since that last time I had a Presence on The Internet. Most important of which is I have now graduated and have the Time and Resources to do Things.

Some of those things people might find interesting. Some of these things people might find exciting. If you find anything I write about either exciting or interesting, you’re probably a geek. Welcome :}.