Suppose we can define new entities and have them displayed on the web page. In that case, we should also be able to define external entities and make them reference a local file, which, when displayed, should show us the content of that file on the back-end server.
Identify
e.g Contact Form Web Application
If we fill the contact form and click on Send Data
, then intercept the request with Burp, we can see that the request is being sent in XML.
Once we send the request without any modification, we have a message saying Check your email email@xxe.htb for further instruction.
.
This means the email
element is being displayed so this would be our possible injection point. For now, we know that whatever value we place in the <email></email>
element gets displayed in the HTTP response.
Let’s try defining a new entity and then use it as a variable in the email element.
To define a new XML entity, we will add the following line after the first line in the XML input:
Note: In our example, the XML input in the HTTP request had no DTD being declared within the XML data itself, or being referenced externally, so we added a new DTD before defining our entity. If the
DOCTYPE
was already declared in the XML request, we would just add theENTITY
element to it.
Now that we have created a XML entity called company
, let’s inject &compay
inside email
element and we will see the value we defined (Inlane Freight
) is getting displayed.
This confirms that we are dealing with a web application vulnerable to XXE
.
Note: Some web applications may default to a JSON format in HTTP request, but may still accept other formats, including XML. So, even if a web app sends requests in a JSON format, we can try changing the
Content-Type
header toapplication/xml
, and then convert the JSON data to XML with an online tool. If the web application does accept the request with XML data, then we may also test it against XXE vulnerabilities, which may reveal an unanticipated XXE vulnerability.
Reading Sensitive Files
By adding SYSTEM
keyword to the payload, we can read local files as such:
Reading Source Code
If we can read the source code, it is Whitebox Pentesting from that point.
Let’s try the following entity:
However, above won’t work out somehow.
This is because the file we are referencing is not in proper XML format, so it fails to be referenced as an external XML entity.
PHP provides wrapper filters that allows base64 encoding which will output with no break in XML format.
To do this, we can use php://filter/
wrapper:
Above will correctly return index.php
.
However, above will only work with PHP web apps.
RCE with XXE
If we can read local files, we can read files such as ssh
keys, or attempt to utilize a hash stealing trick in Windows-based web apps by making a call to our server.
On PHP-based web application, we can execute commands through PHP://expect
filter. But this requires expect
module is installed and enabled.
expect://whoami
Most efficient method to turn XXE into RCE is by fetching a web shell from our server and writing to the web app, and then we can interact with it.
We can write a basic PHP web shell and start a Python web server:
Now, we can use the following XML code to execute a curl
command that downloads our web shell into the remote server:
Note: We replaced all spaces in the above XML code with
$IFS
, to avoid breaking the XML syntax. Furthermore, many other characters like|
,>
, and{
may break the code, so we should avoid using them.
Note: The expect module is not enabled/installed by default on modern PHP servers, so this attack may not always work. This is why XXE is usually used to disclose sensitive local files and source code, which may reveal additional vulnerabilities or ways to gain code execution.
Other XXE Attacks
DOS