Reply Challenge 2020 - Thats 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 Youre 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:

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 doesnt 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