Web Attacks Assessment
HTB Academy web attacks assessment walkthrough.
The ask: Try to escalate your privileges and exploit different vulnerabilities to read the flag at '/flag.php'.
Initial Access
After logging in here is the page we are presented with:

Theres a settings.php
page as well:

Testing and Identifying Vulnerabilities
There is an option to change your password on settings.php
and capturing the Request:

also, capturing the request when clicking on the profile gives us the following request:

We can see the response gives us details of the user:

IDOR Vulnerability
Can we modify the /usr/74
path to see if we can get other users?
Looks like we can by modify the number after /usr/
:


This looks like an Indirect Object Reference vulnerability, that is covered in the IDOR Insecure APIs section
Cycling through it looks like there are no entries after 100, so I wrote up a quick file of numbers from 1 to 100:
seq 1 100 > nums.txt
With this Ill use burp's Intruder to Brute force the api endpoint for the users and see if any specific account catches my attention:

With this we can see that we are able to pull details of the users:
{
"uid":"4",
"username":"r.trainor",
"full_name":"Riggs Trainor",
"company":"Beer, Daugherty and Lang"
}
Not much else can be seen just from this, so going back to the password reset option we have with the current user. When attempting to reset the password we see the following Requests:

When forwarding the request through we see the POST request to /reset.php
:
POST /reset.php HTTP/1.1
Host: 94.237.56.224:38726
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://94.237.56.224:38726/settings.php
Content-Type: application/x-www-form-urlencoded
Content-Length: 62
Origin: http://94.237.56.224:38726
DNT: 1
Connection: keep-alive
Cookie: PHPSESSID=8bfrvm93coop8ai87ejs4ldt1q; uid=74
Priority: u=4
uid=74&token=e51a8ea6-17ac-11ec-8e81-e7ed2e0a2951&password=123

There we can see that a parameter is the uid
and token
and password
. Maybe I can change the password for a different uid
. As a test I will use uid
5, for Jakari Bigelow:

Modifying the POST
to /reset.php
with the uid=5
and a password=123
:

it looks like the response with this is Access Denied
:

Trying to attack uid
in Intruder to see if its like this for all 100 accounts. This doesnt change the "Access Denied". Instead I fed the parameters directly to the URL:
94.237.56.224:38726/reset.php?uid=5&token=e51a8ea6-17ac-11ec-8e81-e7ed2e0a2951&password=123
This returns something different, this now returns Invalid Token
:

Capturing Tokens
Trying this GET
request through Intruder for this path: /api.php/token/5
to see if we can get a token for uid
5:

# UID 5
{"token":"e51a7e48-17ac-11ec-8e22-af3c03bc0d85"}
It looks like I can get tokens for users by supplying the uid
, so im throwing this in Intruder and we see that we get different token corresponding to the uid:

Im goin got try capturing these tokens and writing them to a file and throwing them in Intruder, ill try using cURL to capture these requests. Im thinking that iterating over the uids combined with the tokens will allow us to modify the password of a user that we can then sign in as.
Testing to see if I can pull the token with cURL:
# curl "http://94.237.56.224:38726/api.php/token/5"
{"token":"e51a7e48-17ac-11ec-8e22-af3c03bc0d85"}
so we get the response, now to write a script for this:
#!/bin/bash
echo "Capturing tokens now..."
for i in {0..100}; do
response=$(curl -s "http://94.237.56.224:43710/api.php/token/$i" | jq -r '.token' )
echo "$i:$response"
echo $response >> tokens.txt
done
jq
: is a JSON processor that can be used to extract the token value from the response like.token
in this case as it is the key in the key:value pair-r
flag in jq stands for "raw output." Without it, jq outputs the result as a JSON-formatted string, including quotes. When you use-r
, jq prints the actual unquoted value
The results print out and append to tokens.txt
:

With this we have a list of 100 tokens that we can iterate through along with the 100 uids.
Finding the Admin
Revisiting the users in the company I decided to grep on some keywords to see if anyone jumps out, and sure enough i had missed the following user:
{"uid":"52","username":"a.corrales","full_name":"Amor Corrales","company":"Administrator"}
It looks like this person is listed as an administrator, and all that work for the tokens was for nothing 😭. Anyways, lets abuse the /api.php/token/
path and pull Amor's token:
{"token":"e51a85fa-17ac-11ec-8e51-e78234eb7b0c"}

This is most likely the best path to continue down, event though it didnt come from the script.

So with Amor's uid of 52 and token: e51a85fa-17ac-11ec-8e51-e78234eb7b0c
lets try resetting her password:

Verb Tampering Vulnerability
Still getting access denied. I feel like we've exhausted the IDOR vulnerability and got a lot so far, time to switch it up. Since this is a POST request let me change it to a GET:

And with that change we actually get a successful password change:

and to verify we log out and log back in with the username a.corrales
and the password I set 123
and voila:

We are in.
The flag should be at /flag.php
so trying that:

And nothing. Continuing with the dig, the Admin has a bit different functionality, they are able to "Add Events" :

This gives us the ability to create new events at /event.php
:

XXE Vulnerability
When creating an event here is our response:


Capturing this POST request and testing it in Repeater we can add the XML header:

It looks as if the response displays what's in the name field, and that can be tested by changing it:

Looks like it does. So now we can work on the XXE Injections. To test this we can set an entity to see if we can call it, by inserting:
<!DOCTYPE email [
<!ENTITY company "Inlane Freight">
]>
then in the name
field we call the entity we set, company
with &company;
:

We can now test for a local file disclosure vulnerability by calling sensitive files with that entity, I try /etc/passwd
, and we get results:

Trying for the /flag.php
, and no dice:

Next I try php wrappers, specifically this one, that will encode the file in base64, and send it back in a response upon reading the entity:
<!DOCTYPE email [
<!ENTITY company SYSTEM "php://filter/convert.base64-encode/resource=index.php">
]>
And we get some base64
:

Feeding the base64
encoded string through printf
:
$ printf '<BASE64 HERE>' | base64 -d
We get the flag:

Last updated