Introduction 介绍
Our last blog post on the FortiClient EMS SQL injection vulnerability, CVE-2023-48788, as it turns out only worked on 7.0.x versions. This article will discuss the differences in exploitation between FortiClient EMS’s two mainline versions: 7.0.x and 7.2.x.
我们上一篇关于 FortiClient EMS SQL 注入漏洞 CVE-2023-48788 的博文,原来仅适用于 7.0.x 版本。本文将讨论 FortiClient EMS 的两个主线版本(7.0.x 和 7.2.x)之间的利用差异。
When writing exploits for different versions of vulnerable software, the differences in the exploit are usually small, such as different offsets, renamed parameters, or changed endpoints. Exploitation of the 7.2.x attack path for CVE-2023-48788 was an interesting challenge, because the core vulnerability and endpoint being attacked were the same, but the code path traversed was largely different.
在为不同版本的易受攻击软件编写漏洞利用时,漏洞利用的差异通常很小,例如不同的偏移量、重命名的参数或更改的端点。利用 CVE-2023-48788 的 7.2.x 攻击路径是一个有趣的挑战,因为被攻击的核心漏洞和端点是相同的,但遍历的代码路径却大不相同。
A quick review of the previous article shows that this vulnerability affects ‘binary components’ of this software suite. Rather than this being a web application based SQL injection, this SQL injection is performed against an endpoint written in C++ and Golang and compiled for a 64 bit x86 Windows target. It also uses a custom linefeed based protocol.
快速查看上一篇文章表明,此漏洞会影响此软件套件的“二进制组件”。这不是基于 Web 应用程序的 SQL 注入,而是针对用 C++ 和 Golang 编写的端点执行的,并为 64 位 x86 Windows 目标编译。它还使用基于自定义换行符的协议。
Windows and SQL injection? Sounds like XP_CMDSHELL. Delicious.
Windows 和 SQL 注入?听起来像XP_CMDSHELL。美味。
XP_CMDSHELL is a type of SQL stored procedure used to evaluate custom commands on input or output data. A trivial example would be to use the XP_CMDSHELL procedure to hash a user password before storing its digest in a registered users table.
XP_CMDSHELL 是一种 SQL 存储过程,用于评估输入或输出数据上的自定义命令。一个简单的示例是,在将用户密码摘要存储在注册用户表中之前,使用 XP_CMDSHELL 过程对用户密码进行哈希处理。
Attackers, however, frequently abuse this capability to turn SQL Injection into Remote Code Execution. That is how the exploit we designed for NodeZero gains access to vulnerable EMS servers.
但是,攻击者经常滥用此功能将 SQL 注入转换为远程代码执行。这就是我们为 NodeZero 设计的漏洞利用如何访问易受攻击的 EMS 服务器。
Mitigations exist to prevent damage caused by this feature of MSSQL. For example, by default, XP_CMDSHELL is disabled and must be re-enabled by the attacker to execute commands. The privilege needed to re-enable XP_CMDSHELL is also a removable privilege, so the account in use can be prevented from enabling this functionality. In practice, this is rarely done, so SQLi against an MSSQL server is almost always a path to RCE.
存在缓解措施,以防止 MSSQL 的此功能造成的损害。例如,默认情况下,XP_CMDSHELL处于禁用状态,攻击者必须重新启用才能执行命令。重新启用XP_CMDSHELL所需的权限也是可移动权限,因此可以阻止正在使用的帐户启用此功能。在实践中,这种情况很少发生,因此针对MSSQL服务器的SQLi几乎总是通往RCE的途径。
New Exploitation Challenges
新的开发挑战
The original 7.0.x weaponization utilized MSSQL’s CONVERT
on a hex encoded payload to bypass a behavior of FortiClient that would always uppercase the entire SQL query. This behavior causes many arbitrary Windows commands to fail as most utilities are case sensitive.
最初的 7.0.x 武器化利用十六进制编码有效负载 CONVERT
上的 MSSQL 来绕过 FortiClient 的行为,该行为始终将整个 SQL 查询大写。此行为会导致许多任意 Windows 命令失败,因为大多数实用程序区分大小写。
Figure 1. Original 7.0.x payload
图 1.原始 7.0.x 有效负载
Running the 7.0.x variant of the exploit against a vulnerable 7.2.x target immediately shows an issue.
对易受攻击的 7.2.x 目标运行该漏洞的 7.0.x 变体会立即显示问题。
Figure 2. Errors on 7.2.x
图2.7.2.x 上的错误
The target returns an extremely opaque error message. From here, it seems prudent to observe the logs of a real client, and put the server in a debug logging state so we can observe any changes in the message type being sent to the server.
目标返回极其不透明的错误消息。从这里开始,观察真实客户端的日志,并将服务器置于调试日志记录状态,以便我们可以观察发送到服务器的消息类型的任何更改。
From this we can see that the format of the arguments for the registration message has changed (the SYSINFO field is now between the pipe characters). Further inspection of the base64 encoded system information parameter shows several required fields have been added to the message format.
从中我们可以看到注册消息的参数格式已更改(SYSINFO 字段现在位于管道字符之间)。对 base64 编码系统信息参数的进一步检查显示,消息格式中添加了几个必填字段。
Figure 3. Differences in agent registration
图3.代理注册的差异
Compensating for these changes is easy enough, and we can use copy and pasted data from the sample registration we observed. This, however, requires performing version detection to determine the correct message format for the exploit. Fortunately, there is a request that provides us with this information.
补偿这些变化很容易,我们可以使用从我们观察到的样本配准中复制和粘贴的数据。但是,这需要执行版本检测以确定漏洞利用的正确消息格式。幸运的是,有一个请求为我们提供了此信息。
Figure 4. Detecting FortiClient versions remotely
图4.远程检测 FortiClient 版本
The new version of this output is as follows:
此输出的新版本如下所示:
Figure 5. Updating to detect 7.2.x versions
图5.更新以检测 7.2.x 版本
Let’s look at what is going on. Now that we have a valid message, let’s attempt to reuse our previous exploit payload.
让我们看看发生了什么。现在我们有了一条有效的消息,让我们尝试重用我们之前的漏洞利用有效负载。
Figure 6. Errors after updating
图6.更新后出错
A similarly opaque error message like before. That’s unfortunate. Let’s dig into what is going on here.
与以前一样,类似的不透明错误消息。这是不幸的。让我们深入了解这里发生了什么。
Figure 7. Detailed error showing SQL ending before equal sign
图7.显示 SQL 在等号之前结束的详细错误
Interesting. 7.2.x appears to be using = as a delimiter on the input being provided to the vulnerable function. Another thing to note is that our input is being converted to upper case in the code path leading to the vulnerable function. This disqualifies base64 as an encoding method.
有趣。7.2.x 似乎使用 = 作为提供给易受攻击函数的输入的分隔符。另一件需要注意的事情是,我们的输入在导致易受攻击函数的代码路径中被转换为大写。这会使 base64 失去作为编码方法的资格。
Extending The Exploit 扩展漏洞利用
At this point, to diverge from the cool and dispassionate tone of most exploit deep dives, I’ll provide a glimpse into the reality of exploit development for people interested in this field, and encouragement for fellow exploit development professionals. We ran into three simple issues that coalesced into a difficult upgrade process. This set of issues disguised our success for over a week, in which we hammered this target with everything we could think of to get around the equals sign delimiter issue. The core issues follow:
在这一点上,为了与大多数漏洞利用深入研究的冷静和冷静的语气不同,我将为对这个领域感兴趣的人提供对漏洞利用开发的现实的一瞥,并为其他漏洞利用开发专业人士提供鼓励。我们遇到了三个简单的问题,这些问题合并成一个困难的升级过程。这一系列问题掩盖了我们一个多星期的成功,在这个星期里,我们用我们能想到的一切来解决这个问题,以解决等号分隔符问题。核心问题如下:
- calc.exe is no longer a valid test payload for command execution
calc.exe不再是命令执行的有效测试负载
- calc.exe is no longer an executable in system32, executing it from cmd.exe now executes an application called Calculator.exe
calc.exe 不再是 system32 中的可执行文件,从cmd.exe执行它现在执行名为 Calculator.exe
- SQL does not guarantee the order of execution of sub-statements, only that execution of statements occurs in a valid order.
SQL 不保证子语句的执行顺序,只保证语句的执行顺序有效。
- All input is converted to upper case for case insensitive comparisons.
所有输入都转换为大写,以便进行不区分大小写的比较。
- The equals sign delimiter makes the design of useful payloads very challenging.
等号分隔符使得有用有效载荷的设计非常具有挑战性。
- Individual EXEs and commands with no arguments can be executed with ease, but complex statements require encoding, which again is complicated by issue 3.
可以轻松执行没有参数的单个 EXE 和命令,但复杂的语句需要编码,这再次因问题 3 而变得复杂。
The confluence of these issues was being unable to detect successful exploitation until we looked into the audit logs of the SQL server itself. At that point, we saw invocations of XP_CMDSHELL going back to the day after we began this project. Changing the test payload from calc.exe to notepad.exe demonstrated successful exploitation.
这些问题的汇合点是,在我们查看 SQL Server 本身的审核日志之前,无法检测到成功的利用。在这一点上,我们看到XP_CMDSHELL的调用可以追溯到我们开始这个项目后的第二天。将测试有效载荷从 calc.exe 更改为 notepad.exe 证明了成功利用。
To quote Vonnegut: “So it goes.”
引用冯内古特的话:“就这样吧。
We mitigated the equals delimiter and upper case issues by using a mix of PowerShell and url encoding.
我们通过混合使用 PowerShell 和 url 编码来缓解等号分隔符和大写问题。
The basic algorithm of the payload looks like this:
有效负载的基本算法如下所示:
EXEC xp_cmdshell ‘Powershell.exe -command “cmd.exe /c “UrlDecode( “<url encoded attacker command>” ) “‘
It relies on powershell to decode the arguments passed to cmd.exe. `start /b` was not needed here, due to the fact that MSSQL spawns commands in it’s own session, which is not attached to a window.
它依赖于 powershell 来解码传递给cmd.exe的参数。这里不需要’start /b’,因为MSSQL在其自己的会话中生成命令,该会话未附加到窗口。
Figure 8. 7.2.x payload utilizing case insensitive powershell decoding
图8.7.2.x 有效负载使用不区分大小写的 PowerShell 解码
And the post-ex process tree for our lovely defender siblings.
还有我们可爱的后卫兄弟姐妹的后前任流程树。
Figure 9. Successful arbitrary command execution
图 9.成功的任意命令执行
NodeZero 节点零
NodeZero Attack Path utilizing CVE-2023-48788 to load a remote access tool and dump LSASS
利用 CVE-2023-48788 加载远程访问工具并转储 LSASS 的 NodeZero 攻击路径
Horizon3.ai clients and free-trial users alike can run a NodeZero operation to determine the exposure and exploitability of this issue.
Horizon3.ai 客户端和免费试用用户都可以运行 NodeZero 操作来确定此问题的暴露和可利用性