下载了D-link无线路由器(型号:DIR-100 revA)的[固件程序 v1.13](ftp://ftp.dlink.eu/Products/dir/dir-100/driver_software/DIR-100_fw_reva_113_ALL_en_20110915.zip)。使用工具Binwalk,很快的就从中发现并提取出一个只读SquashFS文件系统,没用多大功夫我就将这个固件程序的web server(/bin/webs)加载到了IDA中:
![](https://images.seebug.org/1452156660242)
基于上面的字符信息可以看出,这个/bin/webs二进制程序是一个修改版的thttpd,提供路由器管理员界面操作功能。看起来是经过了台湾明泰科技(D-Link的一个[子公司](http://www.alphanetworks.com/chinese/06_about/00_overview.php))的修改。他们甚至很有心计的将他们很多自定义的函数名都辅以“alpha”前缀:
![](https://images.seebug.org/1452156690006)
这个 **alpha_auth_check** 函数看起来很有意思!
这个函数被很多地方调用,最明显的一个是来自 **alpha_httpd_parse_request** 函数:
![](https://images.seebug.org/1452156694868)
我们可以看到alpha_auth_check函数接收一个参数(是存放在寄存器 $s2 里);如果alpha_auth_check返回-1(0xFFFFFFFF),程序将会跳到 alpha_httpd_parse_request 的结尾处,否则,它将继续处理请求。
寄存器$s2在被alpha_auth_check函数使用前的一些操作代码显示,它是一个指向一个数据结构体的指针,里面有一个char*指针,会指向从HTTP请求里接收到的各种数据;比如HTTP头信息和请求地址URL:
![](https://images.seebug.org/1452156729502)
我们现在可以模拟出alpha_auth_check函数和数据结构体的大概样子:
```
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本身是一个非常简单的函数。它会针对http_request_t结构体里的一些指针进行字符串strcmp比较操作,然后调用check_login函数,实际上就是身份验证检查。如果一旦有字符串比较成功或check_login成功,它会返回1;否者,它会重定向浏览器到登录页,返回-1;
![](https://images.seebug.org/1452156749318)
这些字符串比较过程看起来非常有趣。它们提取请求的URL地址(在http_request_t数据结构体的偏移量0xB8处),检查它们是否含有字符串“graphic/” 或 “public/”。这些都是位于路由器的Web目录下的公开子目录,如果请求地址包含这样的字符串,这些请求就可以不经身份认证就能执行。
然而,这最后一个strcmp却是相当的吸引眼球:
![](https://images.seebug.org/1452156781077)
这个操作是将http_request_t结构体中偏移量0xD0的字符串指针和字符串“xmlset_roodkcableoj28840ybtide”比较,如果字符匹配,就会跳过check_login函数,alpha_auth_check操作返回1(认证通过)。
我在谷歌上搜索了一下“xmlset_roodkcableoj28840ybtide”字符串,只发现在一个俄罗斯论坛里提到过它,说这是一个在/bin/webs里一个“非常有趣”的一行。我非常同意。
那么,这个神秘的字符串究竟是和什么东西进行比较?如果回顾一下调用路径,我们会发现http_request_t结构体被传进了好几个函数:
![](https://images.seebug.org/1452156786981)
事实证明,http_request_t结构体中处在偏移量 0xD0处的指针是由httpd_parse_request函数赋值的:
![](https://images.seebug.org/1452156791980)
![](https://images.seebug.org/1452156796740)
这代码实际上就是:
```
if(strstr(header, "User-Agent:") != NULL)
{
http_request_t->0xD0 = header + strlen("User-Agent:") + strspn(header, " \t");
}
```
知道了http_request_t偏移量0xD0处的指针指向User-Agent头信息,我们可以推测出alpha_auth_check函数的结构:
```
#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;
}
```
换句话说,如果浏览器的User-Agent值是“xmlset_roodkcableoj28840ybtide”(不带引号),你就可以不经任何认证而能访问web控制界面,能够查看/修改路由器的设置(下面是D-Link路由器(DI-524UP)的截图,我没有 DIR-100型号的,但DI-524UP型号使用的是相同的固件):
![](https://images.seebug.org/1452156806724)
> 万能的网友指出,字符串“xmlset_roodkcableoj28840ybtide”是一个倒序文,反过来读就是“editby04882joelbackdoor_teslmx”——edit by 04882joel backdoor _teslmx,这个后门的作者真是位天才!
知道创宇安全研究团队,利用 ZoomEye.org 大数据扫描分析,绘制了全球范围内D-Link的部署地图。截图如下:
![](https://images.seebug.org/1452156810909)
公网上可访问的D-Link设备有 62460个。
受影响的型号分布
![](https://images.seebug.org/1452156814581)
根据报道受影响的版本,在公网可访问数量占公网上可访问的全部D-Link数量比例为
![](https://images.seebug.org/1452156819356)
#### 参考:
关于后门的原始分析信息参考:http://www.devttys0.com/2013/10/reverse-engineering-a-d-link-backdoor/
中文翻译:http://blog.jobbole.com/49959/
ZoomEye 影响报告: https://www.zoomeye.org/lab/report/dlink
D-Link 路由后门漏洞曝光 可允许完全访问
http://news.itxinwen.com/2013/1014/536611.shtml
暂无评论