本文档记录了我——一名固件逆向与漏洞利用新手——的个人经验。

为了演示,我们将分析并复现 CVE-2023-27216。
为了利用任何固件,需要执行以下步骤:
gdbserver 以便进行调试。通常,固件二进制文件包含引导加载程序(uBoot)、内核文件、引导加载程序的内核头(uImage)、压缩的文件系统(通常为 SquashFS 格式)、CRC/MD5 表(用于验证文件完整性)以及其他杂项文件。
首先找一种分析固件的方法,做一些研究后,我得到了一些资源:

使用 binwalk 提取固件:binwalk -Me DSL-3782_A1_EU_1.01_07282016.bin

得到了提取出的 squashfs-root 文件夹和一些奇怪的文件。

额外提示: 如果你没有看到 squashfs-root 文件夹,可以对看到的任何 .squashfs 文件使用 unsquashfs。它们就像 zip 文件一样 😅。
检查固件的架构和字节序。可以通过检查从固件中提取的一些二进制文件来确认。检查架构和固件:file <binary>

这里我们几乎可以确认该固件运行在 MIPS 32 位 MSB 架构上。之所以说“几乎”,是因为有些固件可能运行在具有 MIPS 兼容 能力的不同架构上,例如 Lexra。
检查 squashfs-root 文件夹后发现一些有趣的文件:
usr/etc/init.d/rcS => 这是固件启动时运行的脚本usr/etc/passwd => 这是包含用户信息的文件userfs/romfile.cfg => 其中有一组凭据 admin:admin检查 rcS 文件后发现一些有趣的代码:
echo "admin:$1$$iC.dUsGpxNNJGeOm1dFio/:0:0:root:/:/bin/sh" > /usr/etc/passwd
passwd 文件Boa 是一个古老的 Web 服务器,主要用于 2000 年代的路由器等嵌入式设备。然而,boa server 早在 2005 年就停止了开发!尽管 Boa 服务器已经死掉近 20 年,但多亏了我们的厂商,它至今仍然存活。

我建议使用基于 Debian 的操作系统进行模拟,例如 Ubuntu 或 Kali。还有一个专注于固件黑客攻击的操作系统叫 AttifyOS。在本文中,我使用的是 Kali Linux。开始模拟过程,有两个工具:

让我们看看如何使用 FAT 完全模拟一个固件。首先,我们将仓库从 GitHub 克隆到你的 Kali 机器上,然后进行设置过程。你还需要修改 fat.config 文件,否则它无法正常工作。
git clone https://github.com/attify/firmware-analysis-toolkit.git
cd firmware-analysis-toolkit
./setup.sh
vi fat.config # Modify to your sudo password.
然后,我们将固件二进制文件(即从制造商处下载的那个)复制到 Kali 机器上 FAT 的文件夹中,并运行它。
./fat.py DSL-3782_A1_EU_1.01_07282016.bin
注意:在 FAT 的设置过程中,我们可能会遇到错误。它可能会提示缺少 libmagic。

只需运行
pip unistall python-magic
pip install python-magic
这应该可以解决你的问题,然后我们再次运行构建命令。现在应该会很顺利。

按 Enter 键运行。模拟过程应该会顺利工作,你可以在(Kali 机器上)浏览 http://192.168.1.1 来检查是否正常运行。

如果你有凭据,也可以登录控制台。这里是 admin:admin。

如果你决定关闭模拟的固件,只需按 Ctrl+A X。当需要再次运行时,不要再次运行 fat.py,因为固件已经被构建成镜像。你只需运行已经生成的脚本。
cd firmadyne/scratch/<Image-ID>
./run.sh

为调试目的构建 gdbserver。有很多方法可以构建 gdbserver。你也可以下载静态构建好的服务器。这个仓库 存储了一些静态构建的版本。不过,我更倾向于自己构建 gdbserver,因为 GitHub 仓库中的那些版本比较旧,可能会遇到一些兼容性问题。
可参考这篇博客文章:https://sheran.sg/blog/cross-compile-gdb-for-mips/。该博客发布于 2024 年 7 月 30 日,正好在这个项目之前,所以它完美适用。
注意:该博客是为 MIPS x32 LSB 构建的,但我们需要 MIPS x32 MSB。我们需要将 mipsel-linux-gnu 改为 mips-linux-gnu。
我们需要为 MIPS 安装工具链。幸运的是,Debian 软件包中已经包含了它。
**apt update && apt upgrade -y
apt install -y build-essential m4 gcc-mips-linux-gnu g++-mips-linux-gnu**
要为 MIPS 构建 gdbserver,我们需要构建并安装一些软件包。以下是我获取源码的地方。
获取源码
wget https://sourceware.org/pub/gdb/releases/gdb-15.1.tar.xz
wget https://gmplib.org/download/gmp/gmp-6.3.0.tar.xz
wget https://www.mpfr.org/mpfr-current/mpfr-4.2.1.tar.xz
使用工具链构建库 在构建这些库时,拥有 root 权限至关重要。我们必须先构建 GMP,因为它是构建 MPFR 时的依赖项。
tar xvf gmp-6.3.0.tar.xz && cd gmp-6.3.0
./configure --host=mips-linux-gnu
make -j$((`nproc`+1))
make install
cd ..
然后我们构建 MPFR:
tar xvf mpfr-4.2.1.tar.xz && cd mpfr-4.2.1
./configure --host=mipsel-linux-gnu --with-gmp-build=<YOUR-FOLDER>/gmp-6.3.0
make -j$((`nproc`+1))
make install
cd ..
现在我们可以最终构建 gdbserver 了:
tar xvf gdb-15.1.tar.xz && cd gdb-15.1
./configure --host=mipsel-linux-gnu --with-gmp-lib=/usr/local/lib --with-mpfr-lib=/usr/local/lib --with-gmp-include=<YOUR-FOLDER>/gmp-6.3.0 --with-mpfr-include=<YOUR-FOLDER>/mpfr-4.2.1/src
make -j$((`nproc`+1)) LDFLAGS=-static
构建出的二进制文件 gdbserver 应该位于 gdb-15.1/gdbserver 文件夹中。
模拟的固件没有 wget、nc、curl、/dev/tcp 等。我们无法托管 Python HTTP 服务器来传输文件。我们也没有 ssh。但是,我们仍然可以通过挂载镜像将 gdbserver 放入模拟的机器中。
sudo ./scripts/mount.sh 1gdbserver 复制到挂载文件夹中的任意位置。sudo ./scripts/umount.sh 1./run.sh 以确保万无一失)。

从现在起,你可以在 Kali 机器内进行调试和黑客攻击。不过,我们还可以更进一步,将模拟机器端口转发到宿主机(Windows 或 Mac)。
首先让我们使用 ifconfig 检查网络。

结果告诉我们有 2 个接口:eth0 和 tap1_0。据我们所知,eth0 是宿主机共享网络的接口,而 tap1_0 是模拟固件机器的接口。
为了更容易理解,eth0 的网络就像公共网络,我们可以从宿主机访问 Kali 机器。tap1_0 则像私有网络,只能从 Kali 机器访问。我们需要将来自 eth0 的连接转发到 tap1_0 接口上的 192.168.1.1:80 端口。
有很多工具可以帮助我们实现这一点。不过,iptables 似乎效果最好——当然,前提是你知道如何配置。
我们必须先允许端口转发。运行以下命令:
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
这仅在一次会话中有效。如果你想永久生效,请修改 /etc/sysctl.conf 的内容。
net.ipv4.ip_forward=1 # Find this line, uncomment it.
完成后保存并关闭文件。
然后应用此文件中的设置。运行以下命令:
sudo sysctl -p
sudo sysctl --system
通常,我们可以运行一堆 iptables 命令。但这太繁琐了 😵💫。我们可以安装一个工具 iptables-persistent。它允许你编写配置文件、加载到文件或提取链到文件。所有这些都可以快速完成。
apt install iptables-persistent
我们要修改的配置文件是 /etc/iptables/rules.v4。我们将文件内容改为下面的内容。
*filter
:INPUT ACCEPT [37:22880]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [35:2330]
# Forward HTTP Port
-A FORWARD -i eth0 -o tap1_0 -p tcp --dport 80 -d 192.168.1.1 -j ACCEPT
-A FORWARD -i tap1_0 -o eth0 -p tcp --sport 80 -s 192.168.1.1 -j ACCEPT
# Forward Debugger port
-A FORWARD -i eth0 -o tap1_0 -p tcp --dport 31337 -d 192.168.1.1 -j ACCEPT
-A FORWARD -i tap1_0 -o eth0 -p tcp --sport 31337 -s 192.168.1.1 -j ACCEPT
COMMIT
# Completed on Wed Aug 7 09:32:11 2024
# Generated by iptables-save v1.8.10 (nf_tables) on Wed Aug 7 09:32:11 2024
*nat
:PREROUTING ACCEPT [60:5405]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [1096:50947]
-A PREROUTING -i eth0 -p tcp -j DNAT --to-destination 192.168.1.1
-A POSTROUTING -o tap1_0 -p tcp -d 192.168.1.1 -j MASQUERADE
注意: 允许所有端口会产生大量安全问题。建议
DROP所有端口,然后只按你的需要FORWARD少量端口。
保存并刷新 iptables 链。
service netfilter-persistent reload
现在你可以从宿主机外部访问它了。

有多个可攻击的端点。其中 2 个位于 cfg_manager 二进制文件中。我只演示其中一个,另一个留给你自己去弄清楚。
将二进制文件扔进你最喜欢的反编译器中,检查所有 system 命令,你可能会看到这个。该命令运行一个名为 /etc/lanconfig.sh 的文件。

检查其他可能使用这个文件的地方时,我找到了一个我们可以写入该文件的位置。

解释一下它的作用:
/etc/lanconfig.shmxmlElementGetAttr,我猜测它是从某个对象中查找属性,可能是直接或间接来自 HTTP 请求,也可能是 XML。sprintf 根据 mxmlElementGetAttr 获取的属性来构造字符串。fputs 将内容写入文件。我立即在 Web 文件夹 boaroot 中搜索与 IP、netmask 相关的内容,然后发现了这个。boa webserver 的文档极其有限,我只能猜测它是将 POST 参数 lan_ip1 放入某个 XML 中的 IP 参数,而这个 XML 会被二进制文件调用。

在界面上,我们可以找到触发该漏洞的请求。它位于 设置 > 网络

当我们按下 Save 时,用 Burpsuite 拦截该请求。

这个载荷 192.168.1.1;utelnetd -p 8090 -l /bin/sh; 是一个反向 shell。我们可以执行连接它。

类似的工具,可能比 FAT 更好(我还没试过)-> FirmAE。
如果你有学生身份,Binary Ninja 只需 74 美元。许可证可以分享给任何人。
与该 CVE 相关的其他漏洞:

这同样可能导致 RCE,我把它留给你自己去完成。那个位置 data_4c0160 的内存可以在某处被注入 🫡。

