关于xxe,我们首先要了解什么是xxe?XXE(XML External Entity Injection)XML外部实体注入攻击。下面就详细介绍XXE。
那DTD又是什么呢。DTD(Document Type Definition)即文档类型定义,是一种XML约束模式语言,属于XML文件组成的一部分。下面是我们的一个常见的XML文档,最上面第一行是文档声明,中间的部分就是文档类型定义也就是我们的DTD,最下面的部分就是XML的主体各种文档元素了。DTD主要就起到了告诉解释器该怎么样解释这个XML文档的作用。
DTD文档有三种应用形式:
1.内部DTD文档
<!DOCTYPE 根元素[定义内容]>
2.外部DTD文档
<!DOCTYPE 根元素 SYSTEM "DTD文件路径">
3.内外部DTD文档结合
<!DOCTYPE 根元素 SYSTEM "DTD文档路径"[定义内容]>
其中第二三种类型中的SYSTEM是一种标识符,可以理解为:根据DTD文件路径,加载这个文件的内容,并赋值给前面的根元素,该标识符意味着该实体将从外部来源获取内容。
既然XML可以从外部读取DTD文件,那我们就自然地想到了如果将路径换成另一个文件的路径,那么服务器在解析这个XML的时候就会把那个文件的内容赋值给SYSTEM前面的根元素中,只要我们在XML中让前面的根元素的内容显示出来,不就可以读取那个文件的内容了。这就造成了一个任意文件读取的漏洞。
那如果我们指向的是一个内网主机的端口呢?是否会给出错误信息,我们是不是可以从错误信息上来判断内网主机这个端口是否开放,这就造成了一个内部端口被探测的问题。
另外,一般来说,服务器解析XML有两种方式,一种是一次性将整个XML加载进内存中,进行解析;另一种是一部分一部分的、“流式”地加载、解析。如果我们递归地调用XML定义,一次性调用巨量的定义,那么服务器的内存就会被消耗完,造成了拒绝服务攻击。
(环境:win 10,apache 2.4.9,php 5.5.12)
我们先来把环境模拟一下,写一个客户端(client.html)、一个服务端(server.php),并且在根目录下创建一个文件(D:/testXXE),随便写点东西来模拟任意文件。
首先是客户端的模拟表单
然后是一个将form表单转化为xml的函数
最后是ajax发送xml请求
下面是处理XML请求的服务端,这里我说明一下。由于libXML 在2.9.1版本以后解析XML就默认不解析外部实体了,所以我们需要自己开启解析外部实体的功能。
至此环境搭建完毕,接下来打开Burp Suite,打开代理监听,在我们的客户端里发送请求
然后在Burp Suite里已经截获到了我们的请求,将请求如下修改后发送
可以看到testXXE这个文件的内容已经被读取出来,显示在了页面上。
从根源上说,这个漏洞就是由于XML解析器对外部实体的解析不当造成的,所以我们只需禁止XML解析器解析外部实体或者只解析特定的可信的公用外部实体即可从根源上解决问题。对于PHP来说,若使用simpleXML或者DOM解析实体的,目前libXML 2.9.1版本之后是默认不解析外部实体了,对于之前的版本,可以在加载实体之前加上
libxml_disable_entity_loader(true)
这句话来手动禁止解析实体。若使用XMLreader来解析实体的,可以在加载实体前加上下面这段来禁止解析实体。
<?php
// with the XMLReader functionality:
$doc = XMLReader::xml($badXml,'UTF-8',LIBXML_NONET);
?>
XXE攻击
http://www.cnblogs.com/tongwen/p/5194483.html
XXE漏洞的简单理解和测试
https://b1ngz.github.io/XXE-learning-note