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:
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”:
The alpha_auth_check function sounds interesting!
This function is called from a couple different locations, most notably from alpha_httpd_parse_request:
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:
We can now define a function prototype for alpha_auth_check and begin to enumerate elements of the data structure:
struct http_request_t { char unknown[0xB8]; char *url; // At offset 0xB8 into the data structure }; int alpha_auth_check(struct http_request_t *request);
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:
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:
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:
This code is effectively:
if(strstr(header, "User-Agent:") != NULL) { http_request_t->0xD0 = header + strlen("User-Agent:") + strspn(header, " \t"); }
Knowing that offset 0xD0 in http_request_t contains a pointer to the User-Agent header, we can now re-construct the alpha_auth_check function:
#define AUTH_OK 1 #define AUTH_FAIL -1 int alpha_auth_check(struct http_request_t *request) { if(strstr(request->url, "graphic/") || strstr(request->url, "public/") || strcmp(request->user_agent, "xmlset_roodkcableoj28840ybtide") == 0) { return AUTH_OK; } else { // These arguments are probably user/pass or session info if(check_login(request->0xC, request->0xE0) != 0) { return AUTH_OK; } } return AUTH_FAIL; }
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):
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
- DI-524
- DI-524UP
- DI-604S
- DI-604UP
- DI-604+
- TM-G5240
Additionally, several Planex routers also appear to use the same firmware:
- BRL-04UR
- BRL-04CW
You stay classy, D-Link.
WOW,
really works..
tested against one of the ip listed in shodanHQ!
http://imageshack.us/photo/my-images/14/wikq.png/
Pingback: Ciekawa tylna furtka w kilku modelach ruterów D-Linka | Zaufana Trzecia Strona
It’s said in the Russian forum post:
Try to read the string backwards.
xmlset_roodkcableoj28840ybtide
Edit by 04882 joel backdoor
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)
«xmlset_roodkcableoj28840ybtide» «editby04882joelbackdoor_teslmx»
http://habrahabr.ru/post/197314/#comment_6843864
I think it is old backdoor :
http://forum.codenet.ru/q58748/%D0%BF%D0%B5%D1%80%D0%B5%D0%B1%D0%BE%D1%80+%D0%BB%D0%BE%D0%B3%D0%B8%D0%BD%D0%BE%D0%B2+-+%D0%B4%D0%B0%D0%B9%D1%82%D0%B5+%D1%81%D0%BE%D0%B2%D0%B5%D1%82
last post.
Sorry it is linked in the article
Why use this made-in-china crap at all ? I’ve stopped using more than 5 years ago after discovering the IP’s list of the DDOS network in one of the FXS devices firmware.
Because it’s cheap, easy and does the job most people need it to.
I wonder if this succeeds from outside even if outside management is disabled ?
a lot of these d-link routers are facing the web and have an “admin admin” login. you can enable telnet on em too.
Pingback: Une backdoor dans les routeurs D-Link « Korben Korben
Pingback: Une backdoor dans les routeurs D-Link- Dépannage Informatique PC à domicile Limoges haute vienne 87
Pingback: Une backdoor dans les routeurs D-Link « Mes idées HIGH TECH
Pingback: Une backdoor dans les routeurs D-Link | Blog de tout et de rien
You just seriously pissed of the NSA
Nice find!
On a sidenote, how did you go about downloading your router’s firmware? I can only seem to find articles about updating firmware when I search, nothing about downloading it.
All the more reason to start adopting openwrt/ddwrt/tomato etc. Hard to believe this slid under the radar so long.. dir100 did you say? Ha!
Nice work Craig.
And appending “public/” somewhere in the URL (like in the querystring), does that bypass the authentication too ?
No, as far as I can tell the “public/” and “graphic/” strings have to be in the URL itself, not in the query string. IIRC, the server checks for directory traversal too.
Pingback: Reverse Engineering a D-Link Backdoor | Boardmad
Pingback: Reverse Engineering a D-Link Backdoor | Enjoying The Moment
My DSL-2650U seems to be unaffected by this specific one, fortunately.
Pingback: codescaling | D-Link Backdoor badness
Well, if this was a plot by Kevin to frame Joel so he could become tech lead when the backdoor was found, he surely was playing a loooong game.
My plans for world domination !!!!
Also works on the DIR-615. Just checked.
Awesome! Any idea which hardware revision? DIR-615 has had a ton of different hardware revs.
Is there anything about this in the supplied sources?
Also find some clues at DLink’s GPL source code:
http://tsd.dlink.com.tw/downloads2008list.asp?t=1&OS=GPL&SourceType=download
For example, the GPL code of DI-524UP contains config.log,
which includes these magic strings DBACKDOOR_SIGNATURE & DXMLSET_BACKDOOR_USER_AGENT
https://gist.github.com/ccpz/6960941
couldn’t confirm this on d-link 655
This is most likely a backdoor for the installer CD, though it’s a mystery as to why they don’t use simple HTTP authentication.
That was my first thought too, but after some searching it looks like a lot of the affected devices don’t come with those “auto-setup wizard” tools.
Also the Dlink DIR-655 is conformeren to be vulnerable for this type of attack.
Sorry…. Is not.
When session is still active you can relogin with any password. This confused me.
Excellent article. Makes me want to dig into some binaries.
Holy shit!
Good job, man! That’s one heck of reverse engineering. Wondering if D-Link updates their firmware soon in response to this.
My guess is probably not. Most of the affected devices seem to be older and have been end-of-lifed, so people still using them are SOL.
Just changed the name of my neighbors router to “bigblackdix”.