这篇文章比较详细的分享了环境搭建以及漏洞原理,具体复现还在进行中,后续完成了会更新的 orz
参考了 swing师傅博客文章 同时感谢xsh师傅的答疑解惑 orz
配置fortigate-vm
导入forigate-vm
将网络适配器都改为 net,登录账号admin 密码初始为空 登录后自己设置密码,然后配置ip
查看网卡配置
1 | show system interface |
网卡ip配置:
为了后续方便调试,这里的ip设置为自己另一台ubuntu同段的ip
注意要设置在vm的dhcp设置范围内
1 | config system interface |
配置网卡
1 | config router static |
然后就可以在unbuntu中去访问对应网页了
配置 sslvpn
因为漏洞出现在sslvpn中
先添加三个网段 SSLVPN_address | subnet_addres | ubuntu22
然后添加一个用户
再添加一个用户组,并把之前注册的用户添加进新的用户组
修改 vpn 门户,并进入 full-access 修改界面
VPN —–> SSL-VPN-Portals—-> full-access
选择 ok 后,进入 vpn 设置
更改防火墙策略,新建一个防火墙策略
然后就可以用创建的用户账号访问4433端口了
注意:
- fortigate 是低版本的 tls 协议,所以很多浏览器都无法访问 4433 sslvpn 服务端口,最后换成低版本的chrome浏览器,才成功访问,而且需要注意,是 https 协议访问,不能用 http
——xshhc师傅
能打开即配置好sslvpn服务了
这里可以备份一下设置后续也可以用备份文件快速搭建
GDB环境配置
利用gdb+gdbserver方式来调试,复用22、23端口(ssh、telnet的默认端口、前面配置fgt时开启了)
提取固件
找到虚拟机文件目录,将fgt的硬盘挂到ubuntu上
打开并将里面的rootfs.gz 复制出来解压
赋权、解压
1 | cd ~/Dekstop/fortios |
gdb
准备一个busybox 提供完成的sh指令,fgt自带的sh缺少很多指令
busybox的下载、配置、编译、安装一条龙服务_static linking against glibc, can’t use –gc-secti-CSDN博客
1 | wget https://busybox.net/downloads/busybox-1.31.0.tar.bz2 |
替换原来的sh
1 | sudo cp ../busybox ./bin |
在命令行中执行 diagnose hardware smartctl
系统会执行 /bin/smartctl 程序;
可以自己重新写个smartctl放进去、复用22端口为sh
1 |
|
gcc编译,替换原来的smartctl
1 | gcc smartctl.c -static -o smartctl |
下载个gdbserver,也放入/bin下
1 | #https://github.com/hugsy/gdb-static |
逆向分析就不详细说了,flatkc 是系统内核文件、内核的命令行参数位于 extlinux.conf 文件中;可以用vmlinux-to-elf将内核文件转为elf文件拖入ida分析
/bin/init 程序 main 函数中首先会有几处校验,如果校验失败就会调用 do_halt 重启系统,把call do_halt的部分都nop掉
然后替换掉原来的init,再重新打包,替换掉原来的rootfs.gz
1 | #压缩/bin文件 |
绕过校验
在vm目录下的.vmx文件中添加下列信息
1 | debugStub.listen.guest64="TRUE" |
试运行gdb
先在ubuntu准备好gdb,然后开启foritage,在如下booting the kernel界面出来1~2秒后,target链接target remote 192.168.201.1:12345
然后定位到fgt_veritf检测这里,手动修改返回值为0
然后就可以正常执行到init、然后就可以在fortigate中登录
运行提前准备好的smartctl
1 |
|
1 | diagnose hardware smartctl |
会显示执行的ls、id,证明smartctl执行成功、将sh挂在了22端口
然后就可以通过kali去连(ubuntu会将未激活的fgt认定为危险、不过我用ubuntu还是连上了)
启动gdbserver,并将其附加到 sslvpnd
进程上
1 | # 给gdbserver运行权限 |
可能会报错、多试几次
然后就可以gdb连23端口正常调试了
漏洞原理分析
当我们向 fortigate sslvpn 发送一个 enc 的 HTTP 参数的时候, 会进到一个parse_enc_data (自命名) 函数中,可以通过图中这串字符串快速定位
进入改函数之后会对enc数据长度、奇偶性判断,需要长度大于11且为偶数,然后会进行md5初始化以及je_malloc申请size/2+1大小,来存放数据
数据存放形式:0x61616161---》/x61/x61/x61/x61
注意,这里会在处理完实际enc数据后加 \x00截断
数据处理完就进入漏洞点这里了,这里网上文章的说法都迷迷糊糊的,我的理解是这里判断条件是 实际传入的enc数据长度 与enc参数中定义的size比较,而je_malloc申请的大小实际是 实际长度/2 + 1
并且后续解密时循环次数使用的是定义长度,所以当我们实际长度 > 定义长度 > 实际长度/2 + 1时,我们就可以实现堆溢出
不过这里堆溢出的数据会是md5异或后的数据,要控制为我们想要的值还是有点困难的
这里原作者提供了一个非常巧妙的技巧,利用\x00以及异或的性质,向将目标位置用\x00覆盖掉,第二次找到特定seed来将改位置的值覆盖为想到的值,又因为 x ^ y = z ; z ^ y = x ,我们可以将其他数据还原回来,也就是可以实现不改变其他数据的情况下改变一个字节
漏洞利用
iot设备堆溢出,根据网上其他师傅文章、可以溢出覆盖 SSL 结构中的 handshake_func
指针从而劫持程序流
根据网上poc可以控制偏移覆盖,修改一下就可以达到溢出任意写
现在问题是怎么问题控制到ssl结构体、是如何劫持程序流的
- 本文作者: 1uckyc
- 本文链接: https://1uckyc.github.io/2024/04/22/CVE-2023-27997环境搭建以及堆溢出复现/