01Summary

XML Injection occurs when user-supplied input is inserted into XML documents without proper sanitization or encoding. An attacker can inject malicious XML tags, entities, or structural elements to alter the document's meaning, bypass validation, or trigger unintended application behavior. This weakness is particularly dangerous in systems that parse XML for configuration, data exchange, or authentication.

02How It Happens

Applications often construct XML documents by concatenating user input directly into XML strings or by inserting untrusted data into XML nodes without escaping special characters. XML has reserved characters (<, >, &, ", ') and entity syntax that carry structural meaning. When these characters appear in user input and are not escaped, the XML parser interprets them as markup rather than data, allowing an attacker to inject new elements, close existing ones prematurely, or define malicious entities. The vulnerability is compounded when the application then parses or processes the resulting XML without validating its structure.

03Real-World Impact

An attacker exploiting XML Injection can modify XML-based authentication tokens, inject false data into configuration files, bypass access controls embedded in XML schemas, or trigger XML External Entity (XXE) attacks if the parser is vulnerable. In systems using XML for SOAP messages, API requests, or data serialization, injection can lead to privilege escalation, data tampering, or information disclosure. The impact depends on how the application uses the XML—a malicious injection in a user profile XML might alter permissions, while injection in a payment XML might change transaction amounts.

04Vulnerable & Fixed Patterns

Vulnerable pattern
import xml.etree.ElementTree as ET

user_name = request.args.get('name')
user_comment = request.args.get('comment')

# Directly concatenating user input into XML string
xml_string = f"""<user>
  <name>{user_name}</name>
  <comment>{user_comment}</comment>
</user>"""

root = ET.fromstring(xml_string)

Why it's vulnerable:
User input is inserted directly into the XML string without escaping. An attacker can inject tags like </name><admin>true</admin><name> to alter the document structure.

Fixed pattern
import xml.etree.ElementTree as ET

user_name = request.args.get('name')
user_comment = request.args.get('comment')

# Build XML using element creation, not string concatenation
root = ET.Element('user')
name_elem = ET.SubElement(root, 'name')
name_elem.text = user_name
comment_elem = ET.SubElement(root, 'comment')
comment_elem.text = user_comment

xml_string = ET.tostring(root, encoding='unicode')
Vulnerable pattern
<?php
$user_name = $_GET['name'];
$user_comment = $_GET['comment'];

// Directly concatenating user input into XML string
$xml = <<<XML
<user>
  <name>$user_name</name>
  <comment>$user_comment</comment>
</user>
XML;

$dom = new DOMDocument();
$dom->loadXML($xml);
?>

Why it's vulnerable:
User input is embedded directly in the XML string without escaping. An attacker can break out of the current element and inject new ones.

Fixed pattern
<?php
$user_name = $_GET['name'];
$user_comment = $_GET['comment'];

// Build XML using DOM methods, not string concatenation
$dom = new DOMDocument();
$root = $dom->createElement('user');
$dom->appendChild($root);

$name_elem = $dom->createElement('name');
$name_elem->appendChild($dom->createTextNode($user_name));
$root->appendChild($name_elem);

$comment_elem = $dom->createElement('comment');
$comment_elem->appendChild($dom->createTextNode($user_comment));
$root->appendChild($comment_elem);

$xml = $dom->saveXML();
?>

05Prevention Checklist

Use DOM or XML libraries to construct XML
, never string concatenation. Let the library handle escaping.
Validate XML structure
against a schema (XSD) after parsing to ensure it matches expected format.
Disable external entity processing
in XML parsers to prevent XXE attacks that often accompany injection.
Escape user input if you must build XML strings
: replace & with &amp;, < with &lt;, > with &gt;, " with &quot;, and ' with &apos;.
Use allowlists for XML element and attribute names
if user input influences structure; reject anything not on the list.
Log and monitor XML parsing errors
— unexpected parse failures may indicate injection attempts.

06Signs You May Already Be Affected

Look for unexpected XML elements or attributes in logs, configuration files, or data exports that you did not create. Check for malformed XML error messages in application logs, which may indicate failed injection attempts. Review any XML-based authentication tokens or session data for structural anomalies or extra elements that shouldn't be present.

07Related Recent Vulnerabilities