Reverse Engineering a D-Link Backdoor

All right. It’s Saturday night, I have no date, a two-liter bottle of Shasta and my all-Rush mix-tape…let’s hack.

On a whim I downloaded firmware v1.13 for the DIR-100 revA. Binwalk quickly found and extracted a SquashFS file system, and soon I had the firmware’s web server (/bin/webs) loaded into IDA:

Strings inside /bin/webs

Based on the above strings listing, the /bin/webs binary is a modified version of thttpd which provides the administrative interface for the router. It appears to have been modified by Alphanetworks (a spin-off of D-Link). They were even thoughtful enough to prepend many of their custom function names with the string “alpha”:

Alphanetworks’ custom functions

The alpha_auth_check function sounds interesting!

This function is called from a couple different locations, most notably from alpha_httpd_parse_request:

Function call to alpha_auth_check

We can see that alpha_auth_check is passed one argument (whatever is stored in register $s2); if alpha_auth_check returns -1 (0xFFFFFFFF), the code jumps to the end of alpha_httpd_parse_request, otherwise it continues processing the request.

Some further examination of the use of register $s2 prior to the alpha_auth_check call indicates that it is a pointer to a data structure which contains char* pointers to various pieces of the received HTTP request, such as HTTP headers and the requested URL:

$s2 is a pointer to a data structure

We can now define a function prototype for alpha_auth_check and begin to enumerate elements of the data structure:

alpha_auth_check itself is a fairly simple function. It does a few strstr’s and strcmp’s against some pointers in the http_request_t structure, then calls check_login, which actually does the authentication check. If the calls to any of the strstr’s / strcmp’s or check_login succeed, it returns 1; else, it redirects the browser to the login page and returns -1:

alpha_auth_check code snippet

Those strstr’s look interesting. They take the requested URL (at offset 0xB8 into the http_request_t data structure, as previously noted) and check to see if it contains the strings “graphic/” or “public/”. These are sub-directories under the device’s web directory, and if the requested URL contains one of those strings, then the request is allowed without authentication.

It is the final strcmp however, which proves a bit more compelling:

An interesting string comparison in alpha_auth_check

This is performing a strcmp between the string pointer at offset 0xD0 inside the http_request_t structure and the string “xmlset_roodkcableoj28840ybtide”; if the strings match, the check_login function call is skipped and alpha_auth_check returns 1 (authentication OK).

A quick Google for the “xmlset_roodkcableoj28840ybtide” string turns up only a single Russian forum post from a few years ago, which notes that this is an “interesting line” inside the /bin/webs binary. I’d have to agree.

So what is this mystery string getting compared against? If we look back in the call tree, we see that the http_request_t structure pointer is passed around by a few functions:

It turns out that the pointer at offset 0xD0 in the http_request_t structure is populated by the httpd_parse_request function:

Checks for the User-Agent HTTP header

Populates http_request_t + 0xD0 with a pointer to the User-Agent header string

In other words, if your browser’s user agent string is “xmlset_roodkcableoj28840ybtide” (no quotes), you can access the web interface without any authentication and view/change the device settings (a DI-524UP is shown, as I don’t have a DIR-100 and the DI-524UP uses the same firmware):

Accessing the admin page of a DI-524UP

Based on the source code of the HTML pages and some Shodan search results, it can be reasonably concluded that the following D-Link devices are likely affected:

DIR-100

DIR-120

DI-624S

DI-524UP

DI-604S

DI-604UP

DI-604+

TM-G5240

Additionally, several Planex routers also appear to use the same firmware:

BRL-04R

BRL-04UR

BRL-04CW

You stay classy, D-Link.

UPDATE:

The ever neighborly Travis Goodspeed pointed out that this backdoor is used by the /bin/xmlsetc binary in the D-Link firmware. After some grepping, I found several binaries that appear to use xmlsetc to automatically re-configure the device’s settings (example: dynamic DNS). My guess is that the developers realized that some programs/services needed to be able to change the device’s settings automatically; realizing that the web server already had all the code to change these settings, they decided to just send requests to the web server whenever they needed to change something. The only problem was that the web server required a username and password, which the end user could change. Then, in a eureka moment, Joel jumped up and said, “Don’t worry, for I have a cunning plan!”.

Also, several people have reported in the comments that some versions of the DIR-615 are also affected, including those distributed by Virgin Mobile. I have not yet verified this, but it seems quite reasonable.

UPDATE #2:

Arbitrary code execution is also possible, thanks to the backdoor. Proof of concept.

Wow, this is insane, changing your user-agent to backdoor will gain you access.
I wonder on how many firmwares this (type of) backdoor is added.
(maybe the same string “xmlset_roodkcableoj28840ybtide” or with any other string)

“Those that are afraid of NSA should make own routers and write own firmware”

oh I see, so it’s okay to trust NSA since it’s an american agency, but not country X? fuck u, u stupid american twat, fuck your usa internet backbone and fuck your nsa prism. no country should spy on anyone, got that retard.

And a quick search also digs up a “Joel Liu” and a “Joel Lee”, who seem somewhat affiliated with alphanetworks. But that’s probably fake, because it is well known that Chinese parents always pick a Chinese name for their children.

Not necessarily fake. These days, many chinese people adopt a western name (usually american) that they use when talking to foreigners. I guess foreigners’s pronunciation of chinese name is so bad that chinese people can barely notice you’re referring to them (happened to me when in china). That, or the guy think John’s a cool name.

Stop thinking that English/Christian names are only for people in Europe, America or Australia. Christanity exists in all parts of the world, including China and India and hence the first names of some people from many countries are not what you want them to sound like.

So to block this backdoor, we need to patch the firmware binary to set that string (in two places) to some other random string, and patch it to pass bootup checksum (or just disable checksum checking).
I’m good with the first part, but the second part I don’t have yet. Anyone?

On my phone in any browser, double-clicking images scales them, but does not scale them to useful sizes. Most of the images on this page (for example) are shown in a choice of 1/4 screen width or full screen width. The screen is 2.25 inches wide.

I don’t think this will work. The ‘graphic/’ and/or ‘public/’ strings need to be in the requested URL (not the query string), and the server checks for directory traversal elsewhere in the http request parser. I did some preliminary (but not complete) testing without any luck.

These are all Phased Out routers, accept for the DIR-100 in EU and is not sold in the USA, that are no longer in development nor marketed and may not see any fixes for this. I notice also that there are no newer gen routers listed or tested for this hack either. IF your concerned about this, I recommend that you phone contact your regional D-Link support office and inquire to check to see if your model router is actually effected by this.

Yes, the affected routers all appear to be older models. Probably no longer supported, so they won’t be getting firmware updates.

I guess you could try contacting D-Link. I doubt they will know what devices are affected though. They don’t write the firmware anyway, and based on my previous interactions they have no way of tracking which devices use the same, or similar, firmware.

I’m trying to duplicate your work found that the SquashFS filesystem is compressed with LZMA (not LZMA2/XZ), which is no longer supported. I cannot find a way to decompress it. How did you do mount it?

Yes, this is why there’s the concept of Bind. Say for example you have a FTP server on a machine with 2 network adapters (say, a router…). You just bind it to 192.168.0.1 and prevent the WAN from accessing. Or you can specify localhost (127.0.0.1) in most applications, and it’ll only accept loopback connections.

Technically, you can have more than one IP address per physical Ethernet connector, so even the 2nd adapter is optional. As an example, VMWare and the like have features like that.

I’m extremely impressed with your writing skills as well as with the layout on your weblog. Is this a paid theme or did you modify it yourself? Anyway keep up the excellent quality writing, it is rare to see a nice blog like this one today.

I also can’t confirm for DI-524 Rev B (firmware version: V2.07DE, Tue, March 18 2008) with deactivated remote management when accessing the device from internal LAN using the given user agent string. I only get the normal login popup.

The article contains a link to a codenet.ru forum post which mentions the backdoor string, if that’s what you are talking about.

However, unless Google translate is failing me, they were just looking at strings in /bin/webs (as well as other files) in an effort to discover a telnet login on a DI-524UP. The forum contains no further analysis of /bin/webs and no mention of how to use the backdoor string.

Interesting, as I have an DIR-857 with Hardware Version A1 with Firmware version 1.03.
The Python script with the Proof of Concept, seems to return HTTP404. I imagine that should be translated to the attempt of Ping has failed.
Am I right ?

Got a Linksys router and think you’re safe? Even changed the default user name and password? Or perhaps you turned off remote sign-in in order to be safer?

Type in 192.168.1.1 or even your remote IP address (the one your ISP has assigned you), since that is what anyone else would use to reach you…..

user name: root
password: admin

or

user name: root
password: root

Your user name and password doesn’t mean anything. Depending on your model, you just logged in as root, by passing whatever user name and password you had before (and on some models even if you had remote log-in turned off).

According to Chinese website, D-Link’s management ordered a security review of their products in April 2013 and assure customers that their products are secure. So why there is still a backdoor in Octoberr 2013? It is hard to trust such products in future.

I do consider all the ideas you’ve presented on your post. They’re really convincing and can certainly work. Still, the posts are very brief for novices. May just you please extend them a little from next time? Thanks for the post. cfcdcdcgabca

How did you get this running in an emulator? I have been playing around with a whole collection of router firmwares and running them in qemu but this particular one has some finicky and proprietary code that prevents it from running.

Could you reverse-engineer AMD’s firmware for their R9 270X card? I’m trying to only use GNU software but my old CRT monitor is making my eyes hurt because there’s no proprietary firmware loaded and it thus it reaches only 60 Hz.