XXE: The Complete Practical Guide to XML External Entity Injection

XXE via File Upload (SVG, DOCX, XLSX)

How to exploit XXE through uploads: SVG and Office files are XML under the hood, and injecting a DOCTYPE into an SVG or word/document.xml.

Published

File upload is one of the richest XXE surfaces, because the formats people upload are XML underneath. An SVG avatar is an XML document. A .docx or .xlsx is a ZIP of XML parts. If the server parses any of that to render, thumbnail, or extract text, an entity you inject into the file becomes XXE, often on an endpoint nobody thinks of as an XML parser.

SVG and Office files are XML under the hood

The key realization is that these are not opaque binaries:

  • An SVG is plain XML. You can open it, add a DOCTYPE, and it is still a valid image.
  • A .docx / .xlsx is a ZIP archive. Unzip it and you find XML parts like word/document.xml or xl/workbook.xml that the server reads.

Wherever that XML is parsed, the external-entity machinery applies.

Injecting a DOCTYPE into an SVG upload

The simplest case is an avatar or image feature that accepts SVG. Upload an SVG that declares an entity and references it in a visible element:

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

If the server rasterizes the SVG to a PNG preview, the file's contents get drawn into the image as text, and you read them straight off the rendered output.

Tampering word/document.xml inside a .docx

For Office files, the payload goes inside the archive. The workflow:

  1. Unzip the .docx.
  2. Edit word/document.xml (or xl/workbook.xml for .xlsx) to add a DOCTYPE with your external entity and reference it in a text node.
  3. Re-zip the archive back into a .docx.
  4. Upload it to a feature that parses or previews the document.

When the server reads the document's XML, your entity resolves. Keep the rest of the document structure intact so the file still opens as a valid Office document.

Where the server parses the embedded XML

Not every upload is parsed, so look for features that read the file's contents:

  • A preview or thumbnail generator that renders the image or document.
  • A text-extraction step (search indexing, "convert to PDF", metadata extraction).
  • A server-side validator that opens the XML to check it.

If the upload is just stored and served back verbatim, there may be no parser to attack. The finding is wherever the server opens the XML.

Getting the result back

Match the exfiltration to what the server does with your file:

  • Rendered image or extracted text: the entity's value appears in the output you can view (in-band).
  • Nothing visible: switch to the out-of-band DTD technique from blind XXE, so the parser calls back to your server with the data even though the upload result is never shown.
  • An error: a verbose parse error may leak the contents or confirm the entity resolved.

Upload-based XXE is also why "images only" uploads are not safe, a theme shared with file-upload attacks generally. When you cannot inject a full DOCTYPE because you only control a fragment, see XInclude attacks. Practice an SVG XXE on a free live target.

← Back to XXE: The Complete Practical Guide to XML External Entity Injection