Blind XXE with out-of-band interaction

4 min read Medium PortSwigger
XXE
Contents

On this page

The lab

here is how portswigger describes it

This lab has a "Check stock" feature that parses XML input but does not display the result.

You can detect the blind XXE vulnerability by triggering out-of-band interactions with an external domain.

To solve the lab, use an external entity to make the XML parser issue a DNS lookup and HTTP request to Burp Collaborator.

this follows the file retrieval and ssrf xxe labs. both of those handed us our answer in the response, the file contents or the metadata came straight back where our value went. this one is blind, the parser reads our xml but never shows the result, so we need a different way to prove the entity resolved at all.

The idea#

blind means no output. the server still parses our xml and still expands our entities, it just does not echo anything we can read, so pointing an entity at a file gets us nowhere because we would never see the file. the trick for the blind case is to stop trying to read data back and instead watch for the parser reaching out. if we point an external entity at a domain we control, resolving that entity makes the server perform a dns lookup for the domain and then an http request to it and both of those land on our server as a visible hit. we do not learn any secret from it but the contact itself proves the entity resolved, which is what confirms the vulnerability is there.

Step 1 - Find the xml being parsed#

as in the earlier labs, opening a product and clicking check stock sends an xml body that the server parses.

111
XML
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck><productId>1</productId><storeId>1</storeId></stockCheck>

the difference this time is that whatever the parser makes of our input, none of it comes back in the response, so we cannot read a file or a metadata value out of it. we need the out of band approach.

Step 2 - Point an external entity at collaborator#

in burp we open the collaborator tab and copy the unique subdomain it gives us, then we declare an external entity whose SYSTEM value is an http url on that subdomain.

XML
<!DOCTYPE stockCheck [ <!ENTITY xxe SYSTEM "http://your-collaborator-subdomain"> ]>

this is the same shape of entity as the previous labs, it declares an entity named xxe and the SYSTEM keyword with an http url makes it an external entity. the difference is only where it points, at our collaborator subdomain rather than a file or the metadata endpoint. resolving it forces the server to look up that subdomain in dns and then send it an http request. we drop it into the body and reference &xxe; in the product id so the parser is made to resolve it

XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE stockCheck [ <!ENTITY xxe SYSTEM "http://your-collaborator-subdomain"> ]>
<stockCheck><productId>&xxe;</productId><storeId>1</storeId></stockCheck>
222

Step 3 - Watch the interactions in collaborator#

we send the request and the response tells us nothing useful which is exactly what blind means. the proof is over in the collaborator tab, where after polling we see interactions arrive from the lab server, first a dns lookup for our subdomain and then an http request to it.

333

with this, the lab is solved!