Reply Challenge 2020 - That’s what server says
This is the Writeup for the 300 points Web challenge for Reply Challenge CTF. During the CTF I and my team achieved first blood on this challenge. The challenge consists of finding a service endpoint on a web page, with a login API. Then you have to exploit an XXE (XML External Entities) Injection to get an LFI (Local File Inclusion) to get the sysadmin credentials to login on the service and get the flag.
Service discovery
Fist we land on a page with just a <h1>
title and an <img>
. The title talks
about robots and in the image there are some blackberries. So as they
hinted we navigate to the /robots.txt
files to find if there are some
disallowed entries. We are greeted by the character Michael from The Office
saying “You’re not my friend Barry”.
User Agent
Since the roots.txt
file is blocked and there is anything else on the main
page, we have to circumvent the check on this file. They hinted to us something
about berries or blackberries. So we can try to access the robots.txt
as a
BlackBerry phone. This can be done by changing the User-Agent
header of your
HTTP request. We can find a list of valid User-Agent
string on
this website.
After we changed the User-agent
we revisit the page and now we can see a
disallowed entry /file_upload.php
.
File Upload
The file_upload.php
API permits us to upload a [png, jpg, jpeg, gif]
file
to the machine and will return where the file was uploaded.
Spoiler: we never use the uploaded file (rev shell or other) probably was a rabbit hole.
There are two curious facts about this API. The first is that the POST
request has sent three values:
- fileToUpload: The file to upload and its filename
- req: A string that represents an endpoint on the server
- submit: A request method (POST)
The second one is when you send the request without uploading a file, you get a
message to contact the sysadmin to use the API /services
and set the
authorized.xml
file.
Exploitation
We can not access the /services
from our machine, so we can try to use
file_upload.php
to communicate with this API. First, we can try to change the
req
value to /services
and check what we get back. Sending an image we get
that the page doesn’t support this method. Then we change the submit
value to
GET
. The page responds with an HTML/XML body. This is XML WSDL a standard
for Web Services Description Language, it is used to describe web services.
We can see that the services have an endpoint at /services/perform_login
requires as input a user
and a pwd
that is probably the one in the
authorized.xml
referenced before.
XXE Injection
We can now try to send the file to the login API. If we send an image the
endpoint returns XML Format Error
, so we know that the page requires an XML
file. Unfortunately, file_upload.php
only accepts certain extension, we need
to craft or XML payload and rename the file to a valid extension like .jpg
.
From the XML WSDL, we know the arguments that are required, and with a bit of trial and error, we can find the right format of the payload.
<user>test</user>
When we send the post we get an error saying:
test is not a register user
Now we have a value user
that can output on the response. This means we can
make an XXE Injection to get the authorized.xml
file as the user value and
make the response print it as an error for profit. We can guess the position of
the file because the response includes where our image was uploaded, or we
could try and get the entire directory, or a known file like /etc/passwd
.
The final payload is the following.
<!DOCTYPE root [!ENTITY test SYSTEM 'file:///var/chall300_web/authorized.xml'>]>
<user>&test;</user>
If you want to read more about XXE here PayloadAllTheThings/XXE Injection