Skip to main content

Wolfcore Cyber Security

How XML external entity (XXE) attacks work and how to stop them

Written by Ruben Selby, founder and penetration tester at Wolfcore. Last reviewed 12 November 2026.

In one sentence: An XXE attack tricks software that reads XML files into fetching a local file or a web address the attacker chooses, because the software was set up to follow instructions hidden inside the file.

What it is

XML is a text format that programs use to exchange data: invoices, configuration files, single sign-on messages, document uploads. An XML file can start with a “document type definition” (DTD). A DTD can declare an “entity”, which works like a shortcut. An external entity is a shortcut that points to something outside the file, such as a file on disk or a URL.

OWASP describes the weakness (CWE-611) as XML input containing a reference to an external entity being processed by a weakly configured parser. The result, per OWASP, may be disclosure of confidential data, denial of service, server-side request forgery, or port scanning from the point of view of the server running the parser.

This page explains the mechanism at concept level. It does not include working payloads.

How it works

  1. The application accepts XML from outside. This might be an upload, an API request, an imported configuration or a login message.
  2. The attacker adds a DTD that declares an external entity. The “system identifier” of that entity points to a file path or URL the attacker wants read.
  3. The parser resolves it. OWASP explains that the processor dereferences the identifier and replaces the entity with whatever it finds. So a file the application can read becomes part of the document.
  4. The data leaves. Sometimes the content is reflected in the response. OWASP notes the application does not need to return the response for the attack to work: an attacker can use DNS lookups carrying data to a server they control.
  5. The server is used as a stepping stone. Because the request comes from the server, it can reach internal web services that the outside world cannot, which is the SSRF effect (see how-ssrf-works).

Risk factors listed by OWASP: the application parses XML, untrusted data reaches the DTD, and the parser is set to process the DTD and resolve external entities.

A generic illustration (not an exploit)

The vulnerable pattern is a parser used with its defaults on untrusted input. The fixed pattern, from OWASP’s Java guidance, rejects any DOCTYPE outright.

// Risky: relies on parser defaults, which vary by provider and version
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
Document doc = dbf.newDocumentBuilder().parse(untrustedStream);

// Safer: reject DTDs before parsing
DocumentBuilderFactory dbf = DocumentBuilderFactory.newDefaultInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
Document doc = dbf.newDocumentBuilder().parse(untrustedStream);

OWASP adds that if a setting is not supported, you should treat that as a configuration failure and stop, not continue with partial hardening.

Who it affects and how badly

Anything that parses XML from outside the business: web applications and APIs, document converters, SSO (SAML) and SOAP services, and management software. Parser defaults vary by language and version, so each one needs checking.

  • Sole trader to 10 staff: you are most exposed through bought-in software such as portals, plugins and appliances you cannot patch yourself. Worst case: a file with passwords or keys is read and used to log in.
  • 10 to 50 and 50 to 250 staff, SaaS start-ups and MSPs: the risk is in your own code and in tools you run. Worst case: an attacker pivots from one XML endpoint to internal services and client data.
  • Regulated (fintech, insurance, healthcare) and 250 plus: XXE in a customer-facing API can expose personal data and trigger breach reporting. Worst case: regulator involvement and lost clients.

Real examples

  • N-able N-central, November 2026. The Hacker News reports that an independent researcher published flaws in this remote management platform, including XML external entity injection, with chains described as using “XXE/NCI trust abuse”. N-able’s hotfix 2026.4 HF2 lists CVE-2026-125883, “Multiple XXE Vulnerabilities”. Huntress confirms the same CVE list and says N-able had not seen successful exploitation in customer environments at the time. Sources: The Hacker News, Huntress.
  • PostgreSQL, CVE-2012-3489. OWASP lists this XXE vulnerability in its references, showing the weakness has long affected mainstream products. Source: OWASP_Processing).

What we check on a test

During a web or application test, a Wolfcore penetration tester looks at:

  • Every place the application accepts XML, including less obvious ones: file imports, document uploads, SOAP and SAML messages, and API endpoints that may also accept XML.
  • Whether the parser accepts a DOCTYPE at all, using harmless test input agreed in scope, and whether outbound requests from the server are possible.
  • Whether the server can reach internal services that XXE could be used to probe.
  • Which parser libraries and versions are in use, since defaults differ by language.
  • Whether the fix is applied everywhere or only on one endpoint.

How to detect it

  1. Search your code for XML parsers and check each one is configured to reject or ignore DTDs. OWASP’s cheat sheet lists Semgrep rules that flag unsafe Java parser set-up.
  2. Check web server and application logs for XML requests containing a DOCTYPE declaration where you do not expect one.
  3. Watch for unexpected outbound connections or DNS lookups from application servers, which can indicate data leaving through an external entity.
  4. Review a dependency list for old XML libraries and appliances. For software you buy, check the vendor’s security advisories for XXE entries.
  5. Ask a tester to include XML endpoints in scope. A scanner may not find them.

How to fix or prevent it

  1. Disable DTD processing entirely. OWASP says to disable DTDs whenever possible and reject DOCTYPE declarations if the parser supports it.
  2. If you must allow DTDs, disable external entity resolution and external DTD loading, and limit entity expansion.
  3. Keep XInclude disabled, and restrict external access during schema validation and style sheet processing too.
  4. Pass streams, not untrusted file names or URLs, to the parser.
  5. Use current parser versions. For example, OWASP notes libxml2 version 2.9 and later disables XXE by default, and PHP 8.0 and later does too.
  6. Block outbound traffic from application servers except where needed, so a successful attack has nowhere to send data.
  7. Patch vendor software promptly when XXE advisories appear.

Related terms

how-ssrf-works, sql-injection, owasp-top-10, how-xss-works, remote-monitoring-and-management-tool-abuse, data-exfiltration

Browse the Hacking techniques category.

FAQ

Is XXE still a real risk? Yes. A remote management platform received XXE fixes this month, as reported by The Hacker News and Huntress.

Does blocking external entities stop every XML attack? No. OWASP notes that preventing XXE does not prevent every XML denial-of-service attack, such as entity expansion.

What is the single best fix? Turn off DTD processing for untrusted XML, as OWASP recommends.

How Wolfcore helps

A Wolfcore penetration test finds this the way an attacker would, by hand, not with a scanner. Start with the free web vulnerability scan at free web vulnerability scan and see our web application penetration testing service.