D-Link DIR-859的RCE漏洞 CVE-2019–17621

一、模拟运行固件
二、程序调试
三、漏洞分析
四、执行exp,获取shell

一、模拟运行固件

1.环境搭建

使用attifyos 中的环境进行模拟时可能会出现各种问题,后来自己搭建环境,可以正常运行。

  1. firmadyne 环境搭建: https://github.com/firmadyne/firmadyne
  2. qemu 编译安装:https://download.qemu.org/qemu-2.5.0.tar.bz2

qemu 建议使用 qemu-2.5.0 版本进行编译安装
在安装之前,请修复 linux-user/elfload.celf_check_ehdr 函数的一个 bug:
插入 && ehdr->e_shentsize == sizeof(struct elf_shdr) 这个条件

修改之前:

/* Verify the portions of EHDR outside of E_IDENT for the target.
   This has to wait until after bswapping the header.  */
static bool elf_check_ehdr(struct elfhdr *ehdr)
{
   
    return (elf_check_arch(ehdr->e_machine)
            && ehdr->e_ehsize == sizeof(struct elfhdr)
            && ehdr->e_phentsize == sizeof(struct elf_phdr)
            && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN));
}

修改后:

static bool elf_check_ehdr(struct elfhdr *ehdr)
{
   
    return (elf_check_arch(ehdr->e_machine)
            && ehdr->e_ehsize == sizeof(struct elfhdr)
            && ehdr->e_phentsize == sizeof(struct elf_phdr)
			&& ehdr->e_shentsize == sizeof(struct elf_shdr)
            && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN));
}

编译:

./configure --target-list="mips-linux-user mipsel-linux-user arm-linux-user" --static
sudo make -j8
2.模拟运行固件
  1. 将 DIR859Ax_FW105b03.bin 固件复制到 firmadyne 目录下

  2. 在firmadyne 目录下执行以下命令:

    sudo su
    rm -rf images*
    sh ./reset.sh
    sudo -u postgres createdb -O firmadyne firmware
    sudo -u postgres psql -d firmware < ./database/schema
    ./sources/extractor/extractor.py -b Dlink -sql 127.0.0.1 -np -nk "DIR859Ax_FW105b03.bin" images
    ./scripts/getArch.sh ./images/1.tar.gz	# 获取架构信息并保存到数据库中
    ./scripts/makeImage.sh 1				# 制作镜像文件成文件系统
    ./scripts/inferNetwork.sh 1				# 自动生成配置仿真环境网卡信息
    ./scratch/1/run.sh						# 运行仿真环境
    
ip 信息:

在这里插入图片描述
配置网卡信息是,本地会生成一个与 ip 同网段的网卡:
在这里插入图片描述

运行固件:./scratch/1/run.sh

在这里插入图片描述
可以看出路由器固件 ip为: 192.168.0.1

浏览器中输入 192.168.0.1 访问仿真路由器:

在这里插入图片描述
至此,固件模拟运行成功。

二、程序调试

1. 启动 mips 系统

run-mips-sys.sh脚本信息如下:

oit@ubuntu:/home/qemu-vmsys/mips$ cat run-mips-sys.sh
sudo qemu-system-mips -M malta -kernel vmlinux-3.2.0-4-4kc-malta -hda debian_wheezy_mips_standard.qcow2 -append "root=/dev/sda1 console=ttyS0" -net nic,macaddr=00:0c:29:d4:72:11 -net tap -nographic

在这里插入图片描述
其中, msb_mips_gdbserver 是静态的 gdbserver, 之后用于 固件系统中程序的调试。信息如下:

oit@ubuntu:/home/qemu-vmsys/mips$ file ./msb_mips_gdbserver 
./msb_mips_gdbserver: ELF 32-bit MSB  executable, MIPS, MIPS-I version 1 (SYSV), statically linked, not stripped

执行脚本启动 mips 系统: run-mips-sys.sh
输入 longin:root Password:root
在这里插入图片描述

2. 挂载固件跟文件系统
  • 解包固件:binwalk -Me DIR859Ax_FW105b03.bin

    oit@ubuntu:~/tools/Template/dir_859$ binwalk -Me ./DIR859Ax_FW105b03.bin
    oit@ubuntu:~/tools/Template/dir_859$ cd _DIR859Ax_FW105b03.bin.extracted/在这里插入图片描述

  • 将跟文件系统 squashfs-root 和 msb_mips_gdbserver 传到 debian-mips系统中:
    在这里插入图片描述

  • 将 msb_mips_gdbserver 复制到 squashfs-root 目录下:
    cp ./msb_mips_gdbserver ./squashfs-root

  • 挂载跟文件系统并启动
    root@debian-mips:~#mount -o bind /dev/ ./squashfs-root/dev/
    root@debian-mips:~#mount -t proc /proc/ ./squashfs-root/proc/
    root@debian-mips:~#chroot ./squashfs-root sh
    查看文件系统中运行的进程:

     chroot ./squashfs-root shroot@debian-mips:~# chroot ./squashfs-root/ sh
     BusyBox v1.14.1 (2016-06-28 10:53:08 CST) built-in shell (msh)
     Enter 'help' for a list of built-in commands.
     
     # ps
       PID USER       VSZ STAT COMMAND
         1 0         2660 S    init [2]   
         2 0            0 SW   [kthreadd]
         3 0            0 SW   [ksoftirqd/0]
         6 0            0 SW   [watchdog/0]
         7 0            0 SW<  [cpuset]
         8 0            0 SW<  [khelper]
         9 0            0 SW   [kdevtmpfs]
        10 0            0 SW<  [netns]
        11 0            0 SW   [sync_supers]
        12 0            0 SW   [bdi-default]
        13 0            0 SW<  [kintegrityd]
        14 0            0 SW<  [kblockd]
        15 0            0 SW<  [ata_sff]
        16 0            0 SW<  [rpciod]
        18 0            0 SW   [khungtaskd]
        19 0            0 SW   [kswapd0]
        20 0            0 SWN  [ksmd]
        21 0            0 SW   [fsnotify_mark]
        22 0            0 SW<  [nfsiod]
        23 0            0 SW<  [crypto]
        26 0            0 SW   [scsi_eh_0]
        27 0            0 SW   [scsi_eh_1]
        28 0            0 SW   [kworker/u:1]
        31 0            0 SW   [kworker/u:3]
        32 0            0 SW   [jbd2/sda1-8]
        33 0            0 SW<  [ext4-dio-unwrit]
       157 0         3408 S    udevd --daemon 
       221 0            0 SW<  [kpsmoused]
       222 0            0 SW   [khubd]
       636 0         3344 S    udevd --daemon 
       637 0         3344 S    udevd --daemon 
      1631 0         5160 S    dhclient -v -pf /run/dhclient.eth0.pid -lf /var/lib/d
      1633 0         3012 S    /sbin/rpcbind -w 
      1677 102       3400 S    /sbin/rpc.statd 
      1689 0         3412 S    /usr/sbin/rpc.idmapd 
      1960 0        29752 S    /usr/sbin/rsyslogd -c5 
      2009 1         2800 S    /usr/sbin/atd 
      2021 0         4536 S    /usr/sbin/cron 
      2167 0         7664 S    /usr/sbin/sshd 
      2345 101       8924 S    /usr/sbin/exim4 -bd -q30m 
      2372 0         2812 S    /sbin/getty 38400 tty1 
      2373 0         2812 S    /sbin/getty 38400 tty2 
      2374 0         2812 S    /sbin/getty 38400 tty3 
      2375 0         2812 S    /sbin/getty 38400 tty4 
      2376 0         2812 S    /sbin/getty 38400 tty5 
      2377 0         2812 S    /sbin/getty 38400 tty6 
      2378 0         4520 S    /bin/login --      
      2379 0         6120 S    -bash 
      2389 0        11144 S    sshd: root@pts/0  
      2391 0         6108 S    -bash 
      2399 0         2588 S    /usr/lib/openssh/sftp-server 
      2583 0            0 SW   [kworker/0:1]
      2896 0        11012 S    sshd: root@notty  
      2898 0         2588 S    /usr/lib/openssh/sftp-server 
      2937 0            0 SW   [kworker/0:0]
      3036 0            0 SW   [flush-8:0]
      3052 0            0 SW   [kworker/0:2]
      3057 0          856 S    sh 
      3058 0          748 R    ps 
      # 
    

    查看网络:
    在这里插入图片描述
    由此可知,跟文件系统在mips系统中成功挂载并运行。

3. 程序调试测试:msb_mips_gdbserver、IDA

这里测试 /htdocs/cgibin 文件的远程调试( /htdocs/cgibin 后面会用到)

  • 执行 ./msb_mips_gdbserver 192.168.126.150:1234 /htdocs/cgibin
    远程ip: 192.168.126.150
    监听端口:1234
    /htdocs/cgibin:调试程序
    在这里插入图片描述
  • 将 /htdocs/cgibin 复制到 pc下,用ida打开
    在main 函数处下断点,按 F9运行->选择Remote GDB debuger
    在这里插入图片描述
    点击OK,输入Hostname 和 Port:(启动gdbserver 时设置的 )
    Hostname: 192.168.126.150
    Port:1234
    在这里插入图片描述
    点击OK,出现调试界面
    在这里插入图片描述
    F9 运行,执行到刚才main 函数断点处
    在这里插入图片描述
    由此可以看到,一切正常,说明环境配置及远程调试没有问题。

三、漏洞分析

对于漏洞分析,参考原文:
https://blog.csdn.net/NOSEC2019/article/details/103823845
根据纰漏,可知远程代码执行漏洞在UPnP请求的代码中

1. UPnP协议栈

UPnP是实现智能设备端到端网络连接的结构。它也是一种架构在TCP/IP和HTTP技术之上的,分布式、开放的网络结构,以使得在联网的设备间传递控制和数据。UPnP 技术实现了 控制点、 设备和 服务之间通讯的支持,并且设备和相关服务的也使用XML定义并且公布出来。使用UPnP,设备可以动态加入网络,自动获得一个IP地址,向其他设备公布它的能力或者获知其他设备的存在和服务,所有这些过程都是自动完成的,此后设备能够彼此直接通讯。
UPnP不需要设备驱动程序,因此使用UPnP建立的网络是介质无关的。同时UPnP使用标准的TCP/IP和网络协议,使它能够无缝的融入现有网络。构造UPnP应用程序时可以使用任何语言,并在任何操作系统平台上编译运行。对于设备的描述,使用HTML表单表述设备控制界面。它既允许设备供应商提供基于浏览器的用户界面和编程控制接口,也允许开发人员定制自己的设备界面。

2. 漏洞所在位置

在满足一定前置条件情况下,二进制可执行文件/htdocs/cgibin中的genacgi_main()函数包含了可远程执行代码的漏洞。

使用 ghidra 查看 genacgi_main() 函数的反编译代码:

undefined4 genacgi_main(void)

{
   
  char *pcVar1;
  char *env_http_callback;
  char *__s1;
  char *env_http_nt;
  char *env_REMOTE_ADDR;
  size_t sVar2;
  __pid_t pid;
  __pid_t _Var3;
  char *pcVar4;
  undefined4 uVar5;
  int iVar6;
  int iVar7;
  int iVar8;
  char buf8 [8];
  char acStack528 [500];
  undefined *local_18;
  
  local_18 = &_gp;
  pcVar4 = getenv("REQUEST_METHOD");
  if (pcVar4 == (char *)0x0) {
   
    return 0xffffffff;
  }
                    /* getenv */
  uVar5 = (**(code **)(local_18 + -0x7c90))("REQUEST_URI");
                    /* strchr */
  iVar6 = (**(code **)(local_18 + -0x7f78))(uVar5,0x3f);
  if (iVar6 == 0) {
   
    return 0xffffffff;
  }
                    /* strncmp */
  iVar7 = (**(code **)(local_18 + -0x7d44))(iVar6,"?service=",9);
  if (iVar7 != 0) {
   
    return 0xffffffff;
  }
                    /* strcasecmp */
  iVar7 = (**(code **)(local_18 + -0x7d30))(pcVar4,"SUBSCRIBE");
  uri_service <
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值