Some notes before we start#

For this walkthrough, I tried to showcase my findings as I would in a penetration testing report. This is my first time writing one 😃, so some aspects may not be perfect.

Also, note that I’ll use TARGET_IP instead of the actual IP because the value is not constant - it changes on every room refresh.

Also also, make sure you are connected to the VPN! You can run ifconfig | grep 192 and you should see two IPs, one assigned by your router and one for the VPN.


Scope#

Target machine: TARGET_IP, with no additional machines.

Find a way to read the information stored in user.txt and root.txt, information known as flags. Each flag has the following format: thm{<some-value>}.


Enumeration#

Starting with nmap -sV -sC -p- TARGET_IP, the server exposes two ports:

  • port 22 via TCP, exposing an OpenSSH 7.6p1 server
  • port 80 via TCP, exposing a HTTP server (possibly written in Go) This step took about 5 minutes to run.

The underlying operating system is Linux Ubuntu.

HTTP Webserver#

The main page displays content related to the room’s story. One hint is “to follow the rabbit”.

Using dirsearch -u http://TARGET_IP, all tested paths appear to be redirects (HTTP status code 301). However, there are two routes that stands out.

The first one is /img -> img/. Upon investigating http://TARGET_IP/img/, I listed images on this folder. These files do not contain any metadata of interest. Trying a path traversal using OWASP techniques yields nothing of use - the HTTP server correctly stripts ../ from the URL and does not allow accessing files outside the server’s scope.

The second one is /r -> r/. This one reveals another webpage, similar to the main one, containing additional passages from “Alice in Wonderland”. Using curl & brute forcing possible paths from http://TARGET_IP/r/, we find another webpage at http://TARGET_IP/r/a/. This one contains yet another passage from “Alice in Wonderland”.

The curl command
for letter in {a..z}; do 
    curl -s -I "http://TARGET_IP/$letter/" | grep 200; 
    [ $? -eq 0 ] && echo $letter; 
done

Following the same logic, we find the other webpages:

  • http://TARGET_IP/r/
  • http://TARGET_IP/r/a/
  • http://TARGET_IP/r/a/a/
  • http://TARGET_IP/r/a/a/b/
  • http://TARGET_IP/r/a/a/b/i/
  • http://TARGET_IP/r/a/a/b/i/t/

The last page contains a hidden paragraph with the following user credentials:

<p style="display: none;">alice:HowDothTheLittleCrocodileImproveHisShiningTail</p>

Privilege escalation#

User alice#

Username: alice
Password: HowDothTheLittleCrocodileImproveHisShiningTail

Checking the user’s home directory, we find the following:

  • a file owned and readable only by root, called root.txt
  • a Python script called walrus.py

Running sudo -l reveals an important aspect: this user can run a command as user rabbit.

(rabbit) /usr/bin/python3.6 /home/alice/walrus.py

The Python script simply imports the random library and prints random lines from a selected list. As user alice, we cannot edit this file. However, we can exploit the way Python libraries work: by creating a new file called random.py that will get imported instead of the actual random library!

import os
os.system("/bin/bash -i")

Running the command now as sudo -u rabbit /usr/bin/python3.6 /home/alice/walrus.py gives us a shell as user rabbit.

User rabbit#

Username: rabbit
Password: <unknown>

In the home directory for this user, we find a SUID binary called teaParty. It is an ELF binary owned by root (so it cannot be modified), and with the help of Ghidra, we can decompile it to the following code:

teaParty decompiled code
void main(void)
{
    setuid(0x3eb);
    setgid(0x3eb);
    puts("Welcome to the tea party!\nThe Mad Hatter will be here soon.");
    system("/bin/echo -n \'Probably by \' && date --date=\'next hour\' -R");
    puts("Ask very nicely, and I will give you some tea while you wait for him");
    getchar();
    puts("Segmentation fault (core dumped)");
    return;
}

There are two interesting aspects here. First, the system() call is vulnerable, because in this case, the date binary is found via PATH resolution (because it’s not provided via an absolute path like /bin/echo, so the shell will look in the paths pointed to by the PATH variable to find the actual binary). By manipulating the PATH before running the teaParty binary, we can get a shell.

However, even if a shell is spawned, it will run under user with UID=1003 and GID=1003 (0x3eb in hex evaluates to 1003 decimal). Later, we’ll see that this user is hatter.

Returning to the date binary, we can create the following script in /home/rabbit:

#!/bin/bash

/bin/bash -i

This will ignore the other arguments --date and -R and will give us a shell. To run the compromised program, we modify the PATH variable as follows:

$ PATH=/home/rabbit:$PATH ; ./teaParty

User hatter#

Username: hatter
Password: WhyIsARavenLikeAWritingDesk?

In the home directory for this user, we find password.txt, reabable by user hatter. Using linPEAS.sh, I’ve found some vulnerabilities that could be exploited:

  • pkexec could be vulerable to CVE-2021-4034 (after testing, confirmed as not vulnerable)
  • the kernel version was old, possible vulnerable to CVE-2018-18955 (after testing, confirmed as not vulnerable)
  • current open ports do not indicate a possible next step
  • no SUID binaries found, besides teaParty
  • no sudo privileges for this user
  • /usr/bin/perl has cap_setuid+ep set

The last finding is crucial - perl is a scripting language, which means it can spawn shells. Having the cap_setuid+ep set means it can spawn root shells. Using the following Perl command (inspired by GTFOBins), we are now root:

perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/bash"'

User root#

Username: root
Password: <unknown>

As root, we can read /home/alice/root.txt for the flag.

Upon inspection of the /root directory, we find the user.txt flag too. However, if the file itself was place somewhere else on the system, we could run a discovery step:

find / -name "*.txt" -size -3KB -readable -exec cat {} \+ | grep thm\{

This command work with some assumptions:

  • each flag is in a .txt file
  • each file is below 3KB in size (to avoid large files where thm{ could be present, but not an actual flag)

MITRE ATT&CK mapping#