Summary
CVE-2025-49113 is a Post-Authentication Remote Code Execution (RCE) vulnerability in Roundcube Webmail, one of the most widely used open-source webmail clients written in PHP. The vulnerability arises due to unsafe PHP object deserialization, allowing an authenticated attacker to execute arbitrary code on the server.
Assigned a CVSSv3 base score of 8.8 (High), this vulnerability impacts Roundcube versions prior to 1.6.5 and 1.5.6, and poses a significant threat in environments where authenticated access is attainable — such as multi-user or shared hosting scenarios.
Technical Details
Roundcube is a web-based email client that supports a modular plugin architecture. This plugin system allows developers to enhance or modify the behavior of Roundcube by hooking into events, modifying views, or storing custom data.
To preserve the state and context of these plugins across user sessions (i.e., from one request to another), Roundcube often needs to store complex PHP objects temporarily, especially when:
- Storing plugin-specific user preferences
- Managing session state
- Passing plugin context between components
To store these objects efficiently, PHP serialization is used — converting PHP objects into a string format that can be saved and later restored using serialize() and unserialize() functions.
What Is PHP Object Deserialization?
Serialization is a way of converting complex objects (like arrays or custom classes) into a string so they can be stored in sessions or files. Deserialization is the reverse process — taking that string and converting it back into a live PHP object.
If an attacker can supply their own serialized string, and that string gets unserialized without proper validation, it can be exploited to perform dangerous actions, especially if the application has classes with magic methods like:
- __wakeup()
- __destruct()
- __call()
These methods automatically execute when the object is deserialized or destroyed — making them "gadgets" in exploitation chains.
What Went wrong in RoundCube?
Roundcube allows users to upload files, such as avatars or signature images, through the settings interface. When handling these uploads, Roundcube expects a GET parameter called _from, which identifies the upload context (e.g., add-avatar, edit-signature).
Here’s a simplified snippet of how Roundcube processes the uploaded file:
- The _from value is directly used to construct session keys such as avatar.files.
- The resulting $type (e.g., avatar) becomes part of the session variable key.
- These session variables are serialized and stored server-side.
The problem arises when the _from parameter is manipulated in a specific way to inject malicious serialized payloads into the session, which are later unconditionally deserialized upon reloading the session — enabling exploitation.
PHP uses serialize() and unserialize() functions to manage complex session data, such as objects and arrays. Roundcube internally stores user session data using a custom serializer that formats session keys and values like this:
This format is then parsed using PHP’s session_decode() during login or request initialization. If an attacker can insert a forged session variable string like:
…then unserialize() will instantiate an object of type EvilClass and assign prop = "touch /tmp/RCE". If EvilClass implements __destruct() or __wakeup() methods, PHP will automatically execute them — without any validation.
This becomes dangerous when a built-in or bundled class contains a destructor that executes system commands, such as with proc_open().
Exploitation
Roundcube includes the PEAR library Crypt_GPG, whose internal class Crypt_GPG_Engine has a destructor that calls proc_open() using the private property $_gpgconf.
An attacker can instantiate this class via deserialization with a custom $_gpgconf value pointing to any executable shell command.
Serialized payload:
This payload creates an object where the private member _gpgconf is set to "touch /tmp/pwned". When the object is destroyed (e.g., at the end of a request), the proc_open() is triggered, resulting in command execution.
To abuse this, the attacker:
- Needs to have a valid set of credentials to log in to Roundcube.
- Uploads a file via the settings page using a crafted _from parameter containing malicious session key injections.
- The session stores the serialized payload, and it’s later deserialized in future requests.
Example HTTP POST Request to upload file:
This injects a session key like:
On the next page load or settings refresh:
- Roundcube restores session state via session_decode().
- The malicious object is deserialized.
- The destructor is automatically invoked.
proc_open() is executed with attacker-supplied command → RCE achieved.
A working exploit for CVE-2025-49113 has been released publicly by the Fearsoff team and can be found on GitHub:
PoC URL:
https://raw.githubusercontent.com/fearsoff-org/CVE-2025-49113/refs/heads/main/CVE-2025-49113.php
You can run the exploit using PHP CLI with the following syntax:
Mitigation
- The Roundcube development team has released patches addressing this vulnerability:
Fixed in versions:- 1.6.11
- 1.5.10
- Use a hardened deserialization handler that checks object types before allowing them to be unserialized.