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