It’s 2024 and Over 178,000 SonicWall Firewalls are Publicly Exploitable

It’s 2024 and Over 178,000 SonicWall Firewalls are Publicly Exploitable

It’s 2024 and Over 178,000 SonicWall Firewalls are Publicly Exploitable

Summary  总结

SonicWall next-generation firewall (NGFW) series 6 and 7 devices are affected by two unauthenticated denial-of-service vulnerabilities with the potential for remote code execution. SonicWall published advisories for CVE-2022-22274 and CVE-2023-0656 a year apart and reported that no exploitation had been observed in the wild; however, a proof-of-concept exploit for the latter was publicly released.
SonicWall 下一代防火墙 (NGFW) 系列 6 和 7 设备受到两个未经身份验证的拒绝服务漏洞的影响,这些漏洞可能导致远程代码执行。SonicWall 相隔一年发布了针对 CVE-2022-22274 和 CVE-2023-0656 的公告,并报告说在野外未观察到任何漏洞利用;但是,后者的概念验证漏洞已公开发布。

Our research found that the two issues are fundamentally the same but exploitable at different HTTP URI paths due to reuse of a vulnerable code pattern. In-depth analysis of the underlying bug allowed us to produce a test script that can determine whether a device is vulnerable without crashing it. Download it here.
我们的研究发现,这两个问题在根本上是相同的,但由于重用了易受攻击的 Code Pattern,因此可以在不同的 HTTP URI 路径上被利用。通过对潜在漏洞的深入分析,我们能够生成一个测试脚本,该脚本可以确定设备是否易受攻击,而不会使其崩溃。在此处下载。

Using BinaryEdge source data, we scanned SonicWall firewalls with management interfaces exposed to the internet and found that 76% (178,637 of 233,984) are vulnerable to one or both issues.
使用 BinaryEdge 源数据,我们扫描了具有暴露在互联网上的管理界面的 SonicWall 防火墙,发现 76%(233,984 个中的 178,637 个)容易受到一个或两个问题的影响。

The impact of a widespread attack could be severe. In its default configuration, SonicOS restarts after a crash, but after three crashes in a short period of time it boots into maintenance mode and requires administrative action to restore normal functionality. The latest available firmware protects against both vulnerabilities, so be sure to upgrade immediately (and make sure the management interface isn’t exposed to the internet).
大范围攻击的影响可能很严重。在其默认配置中,SonicOS 在崩溃后重新启动,但在短时间内发生三次崩溃后,它会启动到维护模式,并且需要管理操作才能恢复正常功能。最新的可用固件可防止这两个漏洞,因此请务必立即升级(并确保管理界面不会暴露在互联网上)。

Background  背景

A few months ago, Watchtowr Labs published an article detailing research that led to their discovery of nine new vulnerabilities affecting SonicWall NGFW appliances. When an emerging threat like this arises, our Cosmos team responds by quickly identifying all affected internet-facing devices and notifying our customers where they are vulnerable. This case was no different, but we also took the opportunity to review historical vulnerabilities affecting SonicWall products to see if any overlooked bugs might make for interesting research.
几个月前,Watchtowr Labs 发表了一篇文章,详细介绍了导致他们发现影响 SonicWall NGFW 设备的九个新漏洞的研究。当出现此类新出现的威胁时,我们的 Cosmos 团队会做出响应,快速识别所有受影响的面向互联网的设备,并通知我们的客户他们容易受到攻击的位置。这种情况也不例外,但我们也借此机会回顾了影响 SonicWall 产品的历史漏洞,看看是否有任何被忽视的错误可能会带来有趣的研究。

One issue in particular caught our attention: CVE-2022-22274. According to the vendor’s advisory, the vulnerability was an unauthenticated buffer overflow affecting NGFW web management interfaces. They assigned it a CVSS score of 9.4, indicating high exploitability and impact:
一个问题特别引起了我们的注意:CVE-2022-22274。根据供应商的公告,该漏洞是影响 NGFW Web 管理界面的未经身份验证的缓冲区溢出。他们给它分配了 9.4 的 CVSS 分数,表明可利用性和影响性很高:

A Stack-based buffer overflow vulnerability in the SonicOS via HTTP request allows a remote unauthenticated attacker to cause Denial of Service (DoS) or potentially results in code execution in the firewall….
SonicOS 中通过 HTTP 请求的基于堆栈的缓冲区溢出漏洞允许未经身份验证的远程攻击者造成拒绝服务 (DoS) 或可能导致在防火墙中执行代码。

SonicWall PSIRT is not aware of active exploitation in the wild. No reports of a PoC have been made public and malicious use of this vulnerability has not been reported to SonicWall.
SonicWall PSIRT 不知道野外的积极利用。尚未公开任何有关 PoC 的报告,并且尚未向 SonicWall 报告恶意使用此漏洞。

Our initial research confirmed the vendor’s assertion that no exploit was available; however, once we identified the vulnerable code, we discovered it was the same issue announced a year later as CVE-2023-0656. SSD Labs had published a technical writeup of the bug with a proof of concept, noting two URI paths where the bug could be triggered. We found that CVE-2022-22274 was caused by the same vulnerable code pattern in a different place, and the exploit worked against three additional URI paths.
我们的初步研究证实了供应商的断言,即没有可用的漏洞利用;然而,一旦我们确定了易受攻击的代码,我们发现它与一年后宣布的 CVE-2023-0656 问题相同。SSD Labs 发布了该错误的技术文章,其中包含概念验证,指出了可能触发该错误的两个 URI 路径。我们发现 CVE-2022-22274 是由不同位置的相同易受攻击的 Code Pattern 引起的,并且该漏洞针对另外三个 URI 路径起作用。

Vulnerability Analysis  漏洞分析

To identify the vulnerable code underlying CVE-2022-22274, we used Ghidra and BinDiff to compare differences between vulnerable and patched versions of the sonicosv binary, which is responsible for handling HTTP requests for the web management interface. Thanks to Watchtowr Labs’ analysis (referenced above), we already had a pretty good sense of the SonicOS architecture and a guide for accessing the file system, which required extracting keys from encrypted LUKS partitions and decrypting them. Fortunately for us, during this stage of our research, Praetorian published an article providing a detailed analysis of the decryption process and released a tool to simplify key extraction, which accelerated our own efforts significantly.
为了识别 CVE-2022-22274 背后的易受攻击代码,我们使用 Ghidra 和 BinDiff 来比较 sonicosv 易受攻击的二进制文件版本和修补版本之间的差异,二进制文件负责处理 Web 管理界面的 HTTP 请求。多亏了 Watchtowr Labs 的分析(如上所述),我们已经对 SonicOS 架构有了很好的了解,并提供了访问文件系统的指南,这需要从加密的 LUKS 分区中提取密钥并对其进行解密。幸运的是,在我们研究的这个阶段,Praetorian 发表了一篇文章,对解密过程进行了详细分析,并发布了一个简化密钥提取的工具,这大大加快了我们自己的努力。

After comparing a handful of functions that were modified between NSv firmware versions 6.5.4.4-44v-21-1452 and 6.5.4.4-44v-21-1519, we found one that showed clear signs of being related to HTTP request handling, including request methods, query strings, HTML code, and messages intended for display in a web browser. The decompiled functions from the two versions revealed the following key code changes:
在比较了 NSv 固件版本 6.5.4.4-44v-21-1452 和 6.5.4.4-44v-21-1519 之间修改的一些函数后,我们发现一个函数显示出与 HTTP 请求处理相关的明显迹象,包括请求方法、查询字符串、HTML 代码和用于在 Web 浏览器中显示的消息。两个版本的反编译函数揭示了以下关键代码更改:

Vulnerable 脆弱

It’s 2024 and Over 178,000 SonicWall Firewalls are Publicly Exploitable

Patched 修补

It’s 2024 and Over 178,000 SonicWall Firewalls are Publicly Exploitable

This code block involved two sequential calls to __snprintf_chk() with the output from the first call used to determine the arguments for the second. In the patched version, the variable storing the output from the first call was changed from a signed integer to an unsigned one, a bounds check was added before feeding this value into the second function call, and additional checks were added to the input and output of the second call.
此代码块涉及两个顺序调用, __snprintf_chk() 第一个调用的输出用于确定第二个调用的参数。在修补版本中,存储第一次调用输出的变量从有符号整数更改为无符号整数,在将此值馈送到第二个函数调用之前添加了边界检查,并在第二次调用的输入和输出中添加了其他检查。

At this point, we were confident we had found the vulnerable code, but to understand the logic behind the bug and how to exploit it, we had to look at the function definition for __snprintf_chk(). According to the LSB Core Specification:
在这一点上,我们确信我们已经找到了易受攻击的代码,但要了解错误背后的逻辑以及如何利用它,我们必须查看 __snprintf_chk() 的函数定义。根据 LSB 内核规范:

int __snprintf_chk(char * str, size_t maxlen, int flag, size_t strlen, const char * format, …); 
int __snprintf_chk(char * str, size_t maxlen, int 标志, size_t strlen, const char * format, …);…


The interface __ 接口__
snprintf_chk() shall function in the same way as the interface snprintf(), except that __snprintf_chk() shall check for buffer overflow before computing a result….If an overflow is anticipated, the function shall abort and the program calling it shall exit.
snprintf_chk() 的功能应与接口 snprintf() 相同,不同之处在于 __snprintf_chk() 应在计算结果之前检查缓冲区溢出。如果预期会出现溢出,则函数将中止,调用它的程序将退出。

While it’s possible that the SonicWall developers explicitly used __snprintf_chk(), that function is usually inserted into C code at compile time as a replacement for the snprintf() function if the _FORTIFY_SOURCE flag is set to the necessary level. Regardless, the developers clearly intended to safeguard against buffer overflows, but they made one crucial oversight: they assumed that the return value from snprintf() or __snprintf_chk() would be equal to the number of characters written to the output buffer. If we look at the documentation for snprintf(), however, we see that this is not the case when the destination buffer is too small:
虽然 SonicWall 开发人员可能明确使用了 __snprintf_chk() 该函数,但如果将 _FORTIFY_SOURCE 标志设置为必要的级别,则该函数通常在编译时插入到 C 代码中作为 snprintf() 该函数的替换。无论如何,开发人员显然打算防止缓冲区溢出,但他们犯了一个关键的疏忽:他们假设 or __snprintf_chk() 的返回值等于写入输出缓冲区的 snprintf() 字符数。但是,如果我们查看 snprintf() 的文档,我们会发现当目标缓冲区太小时,情况并非如此:

The functions snprintf() and vsnprintf() do not write more than size bytes (including the terminating null byte (‘\0’)). If the output was truncated due to this limit then the return value is the number of characters (excluding the terminating null byte) which would have been written to the final string if enough space had been available. Thus, a return value of size or more means that the output was truncated.
函数 snprintf() 和 vsnprintf() 写入的字节数不超过字节(包括终止空 size 字节 (’\0’))。如果输出由于此限制而被截断,则返回值是字符数(不包括终止 null 字节),如果有足够的可用空间,这些字符数将写入最终字符串。因此,返回值大于 size 或等于表示输出被截断。

In other words, when the input string passed to snprintf() or __snprintf_chk() is larger than the number of bytes requested for printing, the return value is set to the number of characters in the input string, not the number of characters that were actually written to the output buffer.
换言之,当传递给 snprintf() __snprintf_chk() 或大于请求打印的字节数时,返回值将设置为输入字符串中的字符数,而不是实际写入输出缓冲区的字符数。

To illustrate, consider this example code:
为了说明这一点,请考虑以下示例代码:

#include <stdio.h>  
int main() {  
  char buf[20];  
  int result = __snprintf_chk(buf,6,1,20,"hello world");  
  printf("buf: %s\nresult:   %d",buf,result);
}

The output of this code is:
此代码的输出为:

buf: hello  
result: 11

Note that result holds the number of characters in the input string (11), not the number written to buf (5). 
请注意,它 result 保存的是输入字符串 (11) 中的字符数,而不是写入 buf (5) 的数字。

We believe the SonicWall developers assumed the return value would match the length of the output string, and used that to calculate both the output buffer offset and the maximum length of the string to write when calling snprintf() or __snprintf_chk() a second time. Let’s look at the impact on each of the first two arguments passed to this function call:
我们相信 SonicWall 开发人员假设返回值将与输出字符串的长度匹配,并使用它来计算输出缓冲区偏移量和调用或第二次调用 snprintf() 时 __snprintf_chk() 要写入的字符串的最大长度。让我们看一下对传递给此函数调用的前两个参数的影响:

  • The first argument to __snprintf_chk() is a pointer to the buffer where the function will write data. The value passed to the second function call is the same as the first, only the pointer is incremented by the return value from the first call. The developers clearly intended for this to cause the second function call to append data to the same buffer as the first, but if the return value from the first call is larger than the number of characters that were actually written, the second call gets a pointer to some unknown location on the stack (past the end of the buffer) as its first argument.
    的第一个 __snprintf_chk() 参数是指向函数将写入数据的缓冲区的指针。传递给第二个函数调用的值与第一个函数调用的值相同,只是指针由第一个调用的返回值递增。开发人员显然打算让第二个函数调用将数据附加到与第一个函数调用相同的缓冲区中,但是如果第一个调用的返回值大于实际写入的字符数,则第二个调用将获得指向堆栈上某个未知位置的指针(超过缓冲区的末尾)作为其第一个参数。
  • The second argument to __snprintf_chk() is the maximum size of data to be written (in bytes) to the output buffer, including the string terminator (a null byte). The value passed to the second function call is defined as 1024 minus the return value from the first call. The developers seem to have intended their code to concatenate two formatted strings together, but cap the length of the result at 1024 characters.
    的第二个参数 __snprintf_chk() 是要写入输出缓冲区的最大数据大小(以字节为单位),包括字符串终止符(null 字节)。传递给第二个函数调用的值定义为 1024 减去第一个调用的返回值。开发人员似乎打算将他们的代码连接在一起,但将结果的长度限制为 1024 个字符。

The first problem with this approach is that maxlen uses type size_t, which is equivalent to an unsigned 64-bit integer in this case. If the return value from the first call is larger than 1024, when the second call subtracts this value from 1024, the result wraps around to the maximum integer value instead of becoming negative (see this discussion of integer overflow for more details). In other words, the second function call specifies an extremely large amount of data to write into the relatively tiny 1024-byte buffer.
这种方法的第一个问题是 maxlen 使用 type size_t ,在这种情况下,它等效于无符号的 64 位整数。如果第一次调用的返回值大于 1024,则当第二次调用从 1024 中减去此值时,结果将换行到最大整数值,而不是变为负数(有关详细信息,请参阅此整数溢出讨论)。换言之,第二个函数调用指定要写入相对较小的 1024 字节缓冲区的大量数据。

One might assume that the buffer overflow protection described in the documentation for __snprintf_chk() would prevent that overflow from actually occurring. However, that protection depends on the strlen parameter being set to a value smaller than the maxlen parameter. In the second function call strlen is set to the maximum value of a 64-bit unsigned integer (0xffffffffffffffff), so maxlen can never be larger than strlen and the overflow protection becomes useless. This suggests to us that the developers wrote their code using snprintf() instead of __snprintf_chk(), then enabled buffer overflow protections at compile time, causing the compiler to replace snprintf() with __snprintf_chk() and set the value of strlen to match the size of the output buffer. Since the output buffer size is dynamic in the second function call, and strlen must be declared as a constant, the compiler set strlen to the maximum possible value instead of a reasonable size (like 1024).
有人可能会认为,文档中描述的缓冲区溢出保护 __snprintf_chk() 将防止该溢出实际发生。但是,该保护取决于 strlen 将参数设置为小于参数 maxlen 的值。在第二个函数中,调用 strlen 被设置为 64 位无符号整数 ( 0xffffffffffffffff ) 的最大值,因此 maxlen 永远不能大于 strlen ,并且溢出保护变得无用。这向我们表明,开发人员使用 snprintf() 而不是 __snprintf_chk() 编写代码,然后在编译时启用缓冲区溢出保护,导致编译器替换 snprintf() with __snprintf_chk() 并将值 strlen 设置为与输出缓冲区的大小相匹配。由于输出缓冲区大小在第二个函数调用中是动态的,并且 strlen 必须声明为常量,因此编译器设置为 strlen 最大可能值,而不是合理的大小(如 1024)。

To illustrate, consider that the developers probably wrote code like this:
为了说明这一点,请考虑开发人员可能编写了如下代码:

n = snprintf(buf, 0x400, "%s", user_input);  
snprintf(&buf[n], 0x400-n, "%s", user_input);

Then, at compile time, the compiler changed the code to this:
然后,在编译时,编译器将代码更改为:

n=__snprintf_chk(buf, 0x400, 1, 0x400, "%s", user_input);  // strlen=0x400  
__snprintf_chk(&buf[n], 0x400-n, 1, 0xffffffffffffffff, "%s", user_input);  // sizeof(&buf[n]) can only be determined at runtime, so strlen=(size_t) -1

To fix this error in the patched version of the firmware, the developers added a check between the two snprintf() or __snprintf_chk() calls to ensure that the return value from the first call is less than 1024. If the check fails, the second function call is skipped and handling of the request is terminated. The patch effectively restores buffer overflow protection without modifying the actual calls to snprintf() or __snprintf_chk().
为了在固件的修补版本中修复此错误,开发人员在两个 snprintf() or __snprintf_chk() 调用之间添加了检查,以确保第一次调用的返回值小于 1024。如果检查失败,则跳过第二个函数调用并终止对请求的处理。此修补程序可有效恢复缓冲区溢出保护,而无需修改对 snprintf() 或 __snprintf_chk() 的实际调用。

Exploit Development 漏洞利用开发

Having identified the vulnerable code underlying CVE-2022-22274, we proceeded to back trace through the decompiled source to understand how to craft an HTTP request that could reach it. The request handler function contained if statements that performed a series of string comparisons against a buffer of unknown origin. Examining each of these comparisons revealed strings that appeared to be URI paths, so it wasn’t a stretch for us to assume that sending an HTTP request beginning with the URI path in a particular if statement would lead us down its corresponding code path, e.g.:
在确定了 CVE-2022-22274 的漏洞代码后,我们继续通过反编译的源进行回溯跟踪,以了解如何构建可以到达它的 HTTP 请求。请求处理程序函数包含 if 针对未知来源的缓冲区执行一系列字符串比较的语句。检查这些比较中的每一个都揭示了似乎是 URI 路径的字符串,因此我们假设在特定 if 语句中以 URI 路径开头的 HTTP 请求将导致我们沿着其相应的代码路径向下移动,这并不夸张,例如:

It’s 2024 and Over 178,000 SonicWall Firewalls are Publicly Exploitable

We found two such URI paths leading to the vulnerable code block: /resources/ and /%s/. The latter was a format string (not the one pictured above) related to the Advanced Threat Protection (ATP) feature. When enabled, this feature is accessible at /atp/; when disabled, it can be reached at //.
我们发现了两个这样的 URI 路径,这些路径指向易受攻击的代码块: /resources/ 和 /%s/ 。后者是与高级威胁防护 (ATP) 功能相关的格式字符串(不是上图所示的字符串)。启用后,可在以下位置 /atp/ 访问此功能;禁用后,可以通过 访问它 // 。

At that point, we knew where to send an HTTP request to trigger the bug, but still needed to come up with a payload. Based on our analysis of the vulnerable code, we knew that the URI path in the HTTP request needed to be longer than 1024 bytes in order to create the conditions for a buffer overflow, but we also had to provide a long enough input string for the second call to __snprintf_chk(). Fortunately, the second call also took its input string from the HTTP request, but instead of reading the URI path, it read the HTTP version string. It became clear, then, that the two functions were used to build a request like so:
在这一点上,我们知道在哪里发送 HTTP 请求来触发错误,但仍然需要提出有效负载。根据我们对易受攻击代码的分析,我们知道 HTTP 请求中的 URI 路径需要超过 1024 字节才能为缓冲区溢出创建条件,但我们还必须为第二次调用提供足够长的 __snprintf_chk() 输入字符串。幸运的是,第二次调用也从 HTTP 请求中获取了其输入字符串,但它没有读取 URI 路径,而是读取 HTTP 版本字符串。很明显,这两个函数用于构建如下请求:

  • First call to __snprintf_chk(): write request method (e.g. GET) and URI path
    第一次调用 __snprintf_chk() :写入请求方法(例如 GET)和 URI 路径
  • Second call to __snprintf_chk(): append HTTP version
    第二次调用 __snprintf_chk() :append HTTP version

The second requirement for exploitation, then, was an exceedingly long HTTP version string. Using this knowledge together with dynamic analysis to test some of our assumptions, we ended up writing the following proof of concept in Python:
因此,利用的第二个要求是极长的 HTTP 版本字符串。利用这些知识与动态分析来测试我们的一些假设,我们最终用 Python 编写了以下概念证明:

import socket, ssl 
ctx=ssl.SSLContext() 
ctx.verify_mode=ssl.CERT_NONE 
s=socket.create_connection(("192.168.250.152",443)) 
ss=ctx.wrap_socket(s) 
data=b'GET /resources/' +b'A'*0x700 + b' HTTP/1.'+b'0'*0x4000+b'\r\n\r\n' 
ss.send(data)

We tested the exploit against our vulnerable NSv instance and observed it crash with a segmentation fault:
我们针对易受攻击的 NSv 实例测试了该漏洞,并观察到它崩溃并出现分段错误:

It’s 2024 and Over 178,000 SonicWall Firewalls are Publicly Exploitable

With a bit more testing, we discovered the application used stack canaries and a smaller payload could produce a more reliable crash by overwriting them with non-zero values:
通过更多的测试,我们发现应用程序使用了堆栈金丝雀,较小的有效负载可以通过用非零值覆盖它们来产生更可靠的崩溃:

data=b'GET /resources/' +b'A'*0x400 + b' HTTP/1.1'+b'A'*0x4000+b'\r\n\r\n'
It’s 2024 and Over 178,000 SonicWall Firewalls are Publicly Exploitable

We tested the DoS exploit successfully against vulnerable series 6 and 7 virtual appliances, and we confirmed that it failed against patched firmware versions in both series.
我们针对易受攻击的系列 6 和 7 虚拟设备成功测试了 DoS 漏洞,并确认它针对两个系列中已修补的固件版本都失败了。

(Re-)Discovery of CVE-2023-0656
(重新-)发现 CVE-2023-0656

During our review of the sequential __snprintf_chk() function calls, we noticed that the same code pattern was reused in other places within the web handler function. By repeating our previous attack path analysis, we discovered additional exploitable URI paths:
在回顾顺序 __snprintf_chk() 函数调用时,我们注意到在 Web 处理程序函数的其他位置重用了相同的 Code Pattern。通过重复之前的攻击路径分析,我们发现了其他可利用的 URI 路径:

  • /stats/
  • /Security_Services
  • /prefsProcessing.html (although this path had other conditions that we were unable to satisfy)
    /prefsProcessing.html (尽管这条路径还有其他我们无法满足的条件)

We were excited at first to find that exploiting the first two of these paths was successful not only against the NSv appliances that were vulnerable to CVE-2022-22274, but also against the ones that had been patched! Not long after, however, we discovered that instead of finding 0-days, we had independently validated CVE-2023-0656. SSD Labs had published a writeup of this vulnerability in April 2023 and released a proof-of-concept exploit nearly identical to our own.
起初,我们很兴奋地发现,利用其中前两条路径不仅可以成功应对易受 CVE-2022-22274 攻击的 NSv 设备,还可以成功应对已修补的 NSv 设备!然而,不久之后,我们发现我们没有找到 0 天,而是独立验证了 CVE-2023-0656。SSD Labs 在 2023 年 4 月发布了该漏洞的文章,并发布了与我们几乎相同的概念验证漏洞。

To our knowledge, no previous research has been published establishing a link between CVE-2022-22274 and CVE-2023-0656. Clearly, both vulnerabilities share the same underlying bug, but the initial patch only fixed the vulnerable code in one place, leaving the other instances to be found and reported a year later.
据我们所知,之前没有发表任何研究在 CVE-2022-22274 和 CVE-2023-0656 之间建立联系。显然,这两个漏洞都具有相同的潜在错误,但最初的补丁只在一个地方修复了易受攻击的代码,而其他实例则在一年后被发现和报告。

Development of a Safe Vulnerability Check
开发安全漏洞检查

Being able to crash a target is all well and good, but what about identifying vulnerable devices without knocking them offline? Based on our analysis of the bug, we tried to come up with a test that could reliably tell whether a specific target was affected or unaffected. It proved to be rather simple – if you recall, we had to satisfy two conditions to trigger the crash using an HTTP request:
能够使目标崩溃固然很好,但是在不使易受攻击的设备离线的情况下识别它们呢?根据我们对该错误的分析,我们试图提出一个测试,可以可靠地判断特定目标是否受到影响。事实证明,这相当简单——如果你还记得,我们必须满足两个条件才能使用 HTTP 请求触发崩溃:

  1. URI path must be longer than 1024 bytes
    URI 路径必须超过 1024 字节
  2. HTTP version string must be long enough to cause a stack canary overwrite
    HTTP 版本字符串必须足够长,才能导致堆栈金丝雀覆盖

By satisfying the first condition, but not the second, it turns out we can reliably elicit different responses from the target, because the buffer overflow check in patched versions causes the connection to be dropped without a response. Here is our modified proof of concept:
通过满足第一个条件,而不是第二个条件,事实证明,我们可以可靠地从目标引出不同的响应,因为修补版本中的缓冲区溢出检查会导致连接断开而没有响应。以下是我们修改后的概念验证:

import socket, ssl 
ctx = ssl.SSLContext() 
ctx.verify_mode = ssl.CERT_NONE 
s = socket.create_connection(("192.168.250.152", 443)) 
ss = ctx.wrap_socket(s) 
data = b"GET /resources/" + b"A" * 0x400 + b" HTTP/1.1\r\n\r\n" 
ss.send(data) 
print(ss.recv(1048))

And here are the responses we get from our test targets:
以下是我们从测试目标中得到的响应:

  • Vulnerable: b'HTTP/1.1 302 Found\r\nLocation: https:// 192.168.250.152/auth.html\r\n\r\n'  脆弱: b'HTTP/1.1 302 Found\r\nLocation: https:// 192.168.250.152/auth.html\r\n\r\n'
  • Patched: b''  修补: b''

In cases where a device is unaffected, i.e., a required component is not accessible because it is disabled, blocked, or simply not available (as in series 5 devices), the response is a different HTTP status code (usually 404). Therefore, we can reduce the vulnerability check to the following outcomes:
在设备不受影响的情况下,即由于所需组件被禁用、阻止或根本不可用而无法访问(如系列 5 设备),则响应是不同的 HTTP 状态代码(通常为 404)。因此,我们可以将漏洞检查减少到以下结果:

  • HTTP 302: vulnerable  HTTP 302:易受攻击
  • empty (connection dropped): patched
    空(连接断开):已修补
  • any other HTTP status code: unaffected
    任何其他 HTTP 状态代码:不受影响

We tested this against all five URI paths and found the vulnerability check was reliable across a wide variety of SonicOS versions, so we put together a user-friendly Python tool for easily testing (and exploiting, if desired) any target: download it here.
我们针对所有五个 URI 路径对此进行了测试,发现漏洞检查在各种 SonicOS 版本中都是可靠的,因此我们整理了一个用户友好的 Python 工具,用于轻松测试(如果需要,还可以利用)任何目标:在此处下载。

Scan Methodology  扫描方法

Having discovered a crash-safe vulnerability check, we found ourselves wondering, “How many SonicWall devices on the internet are vulnerable?” To answer this question, we first turned to BinaryEdge to assemble a target list. Since the HTTP response header “Server: SonicWALL” is hard-coded into all SonicWall NGFW devices, they are easily identifiable on the internet:
在发现崩溃安全漏洞检查后,我们发现自己想知道,“互联网上有多少 SonicWall 设备容易受到攻击?为了回答这个问题,我们首先求助于BinaryEdge来组装一个目标列表。由于 HTTP 响应标头“服务器:SonicWALL”被硬编码到所有 SonicWall NGFW 设备中,因此它们很容易在互联网上识别:

It’s 2024 and Over 178,000 SonicWall Firewalls are Publicly Exploitable

A quick search returned approximately 1.5 million results, but some filtering was needed to ensure we were only getting NGFW devices and, specifically, the web management interface. Fortunately for us, this was as simple as ensuring the “Server” response header was just “SonicWALL” and not, e.g., “SonicWALL SSL-VPN Web Server,” as well as making sure the connection used TLS encapsulation. On all series 6 and 7 devices, the web management interface only allows access via HTTPS (although you can enable HTTP redirection).
快速搜索返回了大约 150 万条结果,但需要进行一些过滤,以确保我们只获得 NGFW 设备,特别是 Web 管理界面。幸运的是,这很简单,只需确保“服务器”响应标头只是“SonicWALL”而不是“SonicWALL SSL-VPN Web 服务器”,以及确保连接使用 TLS 封装即可。在所有系列 6 和 7 设备上,Web 管理界面仅允许通过 HTTPS 访问(尽管您可以启用 HTTP 重定向)。

We exported the entire data set from BinaryEdge, extracted HTTPS URLs, filtered the list to IPv4 (for simplicity – it was a negligible difference), and removed duplicate entries. We then wrote a simple script to test reachability and check the response headers. After filtering our results in this manner, we ended up with a target set of 234,720 devices.
我们从BinaryEdge导出了整个数据集,提取了HTTPS URL,将列表过滤为IPv4(为了简单起见,这是一个可以忽略不计的差异),并删除了重复的条目。然后,我们编写了一个简单的脚本来测试可访问性并检查响应标头。以这种方式过滤结果后,我们最终得到了 234,720 台设备的目标集。

We then wrote a threaded version of our vulnerability check to quickly scan all five potentially vulnerable paths on all the targets. By including some optimizations (like minimizing the number of test paths for each CVE), we were able to gather the results within a few hours. Here’s a sample of our result set:
然后,我们编写了一个线程版本的漏洞检查,以快速扫描所有目标上的所有五个潜在易受攻击的路径。通过包括一些优化(例如最小化每个 CVE 的测试路径数量),我们能够在几个小时内收集结果。下面是我们的结果集的示例:

{"https://65.144.219.82:443": {"CVE-2022-22274": true, "CVE-2023-0656": true}} 
{"https://65.141.205.218:8443": {"CVE-2022-22274": false, "CVE-2023-0656": false}} 
{"https://65.144.97.218:443": {"CVE-2022-22274": true, "CVE-2023-0656": true}} 
{"https://65.141.191.90:443": {"CVE-2022-22274": false, "CVE-2023-0656": true}}

In some cases, the results included different ports on the same target, so we consolidated those (resulting in 233,984 unique devices) and were left with the following results:
在某些情况下,结果包括同一目标上的不同端口,因此我们合并了这些端口(产生了 233,984 个独特的设备),并留下了以下结果:

Devices Vulnerable To: 易受以下影响的设备:

Count 计数

Percent of Total  占总数的百分比

CVE-2022-22274  CVE-2022-22274 漏洞

146,116

62%

CVE-2023-0656  CVE-2023-0656 漏洞

178,608

76%

Both CVEs  两个 CVE

146,087

62%

At least one CVE  至少一个 CVE

178,637

76%

Perhaps most astonishing was the discovery that over 146,000 publicly-accessible devices are vulnerable to a bug that was published almost two years ago!
也许最令人惊讶的是,发现超过 146,000 台可公开访问的设备容易受到近两年前发布的漏洞的攻击!

Conclusion  结论

CVE-2022-22274 and CVE-2023-0656 represent the same vulnerability on different URI paths, an issue which is easily exploited to crash vulnerable devices. Now that we know how to perform a safe vulnerability check, be sure to test any SonicWall NGFW devices you have deployed on your network! If you have a vulnerable device, there are two steps you should take immediately:
CVE-2022-22274 和 CVE-2023-0656 在不同的 URI 路径上表示相同的漏洞,这个问题很容易被利用导致易受攻击的设备崩溃。现在我们知道了如何执行安全的漏洞检查,请务必测试您在网络上部署的任何 SonicWall NGFW 设备!如果您的设备易受攻击,则应立即采取两个步骤:

  1. Remove the web management interface from public access.
    从公共访问中删除 Web 管理界面。
  2. Upgrade the firmware to the latest available version.
    将固件升级到最新的可用版本。

At this point in time, an attacker can easily cause a denial of service using this exploit, but as SonicWall noted in its advisories, a potential for remote code execution exists. While it may be possible to devise an exploit that can execute arbitrary commands, additional research is needed to overcome several challenges, including PIE, ASLR, and stack canaries. Perhaps a bigger challenge for an attacker is determining in advance what firmware and hardware versions a particular target is using, as the exploit must be tailored to these parameters. Since no technique is currently known for remotely fingerprinting SonicWall firewalls, the likelihood of attackers leveraging RCE is, in our estimation, still low. Regardless, taking the appropriate precautions to secure your devices will ensure they don’t fall victim to a potentially painful DoS attack.
此时,攻击者可以使用此漏洞轻松造成拒绝服务,但正如 SonicWall 在其公告中指出的那样,存在远程代码执行的可能性。虽然有可能设计出可以执行任意命令的漏洞利用,但需要额外的研究来克服一些挑战,包括 PIE、ASLR 和堆栈金丝雀。对于攻击者来说,更大的挑战可能是提前确定特定目标正在使用的固件和硬件版本,因为漏洞必须根据这些参数进行定制。由于目前尚无已知的远程指纹识别 SonicWall 防火墙的技术,因此据我们估计,攻击者利用 RCE 的可能性仍然很低。无论如何,采取适当的预防措施来保护您的设备将确保它们不会成为潜在痛苦的 DoS 攻击的受害者。

As always, our Cosmos customers were the first to benefit from this research. As soon as we developed a vulnerability check, we scanned our customers and notified each one of the affected (and unaffected) devices on their attack surface. As a result, these issues have been remediated for all those under our watch as of the time of this writing. We remain committed to our mission and will continue seeking out new opportunities to keep our subscribers safe from harm!
与往常一样,我们的Cosmos客户是第一个从这项研究中受益的客户。一旦我们开发了漏洞检查,我们就会扫描客户,并在其攻击面上通知每个受影响(和未受影响)的设备。因此,截至撰写本文时,这些问题已针对我们关注的所有人员进行了补救。我们仍然致力于我们的使命,并将继续寻找新的机会来保护我们的订阅者免受伤害!

原文始发于Carlos Vieira:It’s 2024 and Over 178,000 SonicWall Firewalls are Publicly Exploitable

版权声明:admin 发表于 2024年1月24日 下午9:31。
转载请注明:It’s 2024 and Over 178,000 SonicWall Firewalls are Publicly Exploitable | CTF导航

相关文章