XML External Entity (XXE) Injection

Overview

XML external entity injection (XXE) is a vulnerability that allows an attacker to interfere with an application's processing of XML data. XXE vulnerabilities arise because the XML specification contains various potentially dangerous features, and standard parsers support these features even if they are not normally used by an application.

For example, if an application is vulnerable to XXE, an attacker can retrieve the /etc/passwd file by submitting the following XXE payload:

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

This XXE payload defines an external entity &xxe; whose value is the contents of the /etc/passwd file and uses the entity within the productId value. This causes the application's response to include the contents of the /etc/passwd file.

You can find more details at PortSwigger Web Security Academy: XML external entity (XXE) injection.

This page contains recommendations for the implementation of protection against XML External Entity (XXE) injection attacks.

General

  • Disable DTDs (external entities) completely.

  • If it is not possible to disable DTDs (external entities) completely, disable external entities and external document type declarations.

  • Use up-to-date XML parsers that are actively maintained by a community or its authors.

Disabling DTDs (external entities)

Disabling DTDs (external entities) depends on the XML parser being used. You can find prevention guidance for many languages and commonly used XML parsers in those languages at the following link OWASP Cheat Sheet Series: XML External Entity Prevention Cheat Sheet.

Use the encoding/xml package to work with XML in Go. Go's XML decoder does not process XML DTDs (external entities), therefore, it is protected against XXE by default.

import (
    "encoding/xml"
)

func handler(w http.ResponseWriter, r *http.Request) {
    decoder := xml.NewDecoder(r.Body)
    for {
        token, err := decoder.Token()
    // ...
    }
}

References

Last updated