XXE
环境网址:https://github.com/mcc0624/XXE
学习视频:橙子科技
XXE靶场环境搭建
1 | |

XXE前置知识——xml语言
xml引入
概述
XML是一种标记语言
XML指可扩展标记语言,把数据机构化后传输给对方让对方在结构化的数据中进行读取
类似于excle表格将各种数据归类即格式化
xml的标签没有意义,需要自定义标签
简单理解为<>为标签,中间的名称可以自定义且没有意义,但后续可以通过一些方法调用

比较xml和html
| 名称 | XML | HTML |
|---|---|---|
| 功能 | 数据读取 | 开发 |
| 标签 | 自定义,无意义 | 预定义 |
| 作用 | 传输和存储数据 | 显示数据 |
| 焦点 | 数据的内容 | 数据的外观 |
XML基本语法
所有XML标签必须闭合
在XML中,省略关闭标签是非法的。所有元素都必须有关闭标签

XML必须正确地嵌套
在XML中,所有元素都必须彼此正确地嵌套

由于<i>元素是在<b>元素内打开的,那么它必须在<b>元素内关闭
XML标签对大小写敏感
XML标签对大小写敏感,在XML中,标签<Letter>与标签<letter>是不同的。
必须同时使用相同的大小写来编写打开标签和关闭标签

XML文档必须有根元素
XML文档必须有一个元素是所有其他元素的父元素。该元素称为根元素
没有缩进要求,建议首行缩进

头声明可有可无,建议写
第一行为XML声明。定义XML版本和所使用的编码

实体引用
就是将一些有特殊含义的符号用实体引用来替换,比如:
<小于号:将它放入XML元素中会报错,因为解析器会把它当作新元素的开始
预定义实体引用
| 实体引用 | 符号 | 含义 |
|---|---|---|
| < | < | 大于 |
| > | > | 小于 |
| & | & | 和号 |
| ' | ‘ | 单引号 |
| " | “ | 双引号 |
**注释:在XML中,只有字符”<”和”&”确实是非法的。大于号是合法的。
使用php解析xml
php页面调用xml
创建一个xml文件
1 | |

可以在网页中显示
创建一个php文件
1 | |

读取出来的是一个Object对象[man]为成员属性其中包含两个数组[0][1],两个数组也分别对应一个对象,其中都包含两个成员属性:name和age
利用php读取对象的属性
1 | |
可以看到页面读取的内容是数组0对应的name:yyy

1 | |

simplexml_load_file()函数吧XML文档载入对象中
$xml是一个Object对象
使用DOMDocument读取XML文档
数据通常以POST方式吧字符串提交进去,以xml结构提交给目标网站,再通过php伪协议读取内容,进行xml解析
DOMDocument是一个类,需要先实例化为对象
load():调用文件
saveXML():读取
读取页面
这是基于目录下存在上述student.xml构造的php
1 | |

可以这样读取页面
读取成员属性
1 | |
getElementsByTagName('name')读取XML的节点名字name
item(0)指向第0个
nodeValue获取节点的值

DTD声明介绍
什么是DTD
文档类型定义,可定义合法的XML文档构建模块,使用一系列合法的元素来定义文档的结构
在XML中可以自定义标记,DTD用来定义我们自己定义的标记的含义,我们自己定义元素的相关属性的文档。它规定、约束XML规则的定义和陈述
DTD可被成行地声明于XML文档中,也可作为外部引用

!ELEMENT定义元素
!ATTLIST定义元素的属性
!NOTATION定义不被解释为元素或属性的符号
!ENTITY定义实体,这些实体可以在XML文档中被引用
DTD漏洞
外部引入DTD文件

SYSTEM读取1.dtdDTD声明
SYSTEM也可以读取其他外部文件
XML实体介绍
什么是实体
实体是对数据的引用,根据实体种类的不同,XML解析器将使用实体的替代文本或者外部文档的内容来替代实体引用
使用实体可以去掉符号的意义
实体分类
所有实体(除参数实体外)都以一个于字符(&)开始,以一个分号(;)结束
- 字符实体
- 命名实体
- 外部实体:XXE漏洞产生主要原因外部调用文件
- 参数实体:创建替换文本的可重用部分
XXE漏洞成因
XXE:XML的外部实体注入
外部实体:用来引入外部资源
DTD文档类型定义用于定义XML文档的结构
漏洞利用
1 | |
利用bp抓包,修改请求方式,更改Content-Type
1 | |

提交测试参数
1 | |
<root>为根节点
<admin>为枝节点

1 | |
源码中调用成员属性为damin,所以参数中必须是admin
增加DTD声明引起漏洞
调用外部实体,可以读取内部文件名
1 | |
DOCTYPE:定义XML的文档类型(DTD),命名为admin,内部包含实体定义<!ENTITY ben SYSTEM "file:///etc/passwd">:定义外部通用实体ENTITY:用来设置命令实体:benSYSTEM:表示引用外部资源file:///etc/passwd:本地文件协议<root><admin>&ben;</admin></root>:XML正文,通过&ben;引用上面定义的外部实体,漏洞触发后,解析器会将&ben;替换为/etc/passwd的文件内容

不同程序支持的协议不同
| PHP | JAVA | NET | LIBXML2 |
|---|---|---|---|
| file | file | file | file |
| http | http | http | http |
| ftp | https | https | ftp |
| php | ftp | ftp | |
| compress.Zlib | jar | ||
| compress.bzip2 | netdoc | ||
| data | mailto | ||
| glob | gopher* | ||
| phar |
XXE使用外部实体读取文件
如何判断存在XXE漏洞
查看网页源码

bp拦截抓包
查看响应包
一般是POST方法,doLogin.php文件,Content-Type是application/xml;charset=utf-8

利用XXE使用外部实体检索文件
添加DTD读取/etc/passwd
常用测试是否存在XXE漏洞payload
1 | |

参数实体
利用file协议尝试
1 | |

file协议失效,可尝试命名实体(命名实体只能在DTD文档中调用)
利用参数实体以及外部实体读取文件

搭建http服务
我利用的是云服务器搭建http服务
进入/tmp目录
1 | |
打开vim编译器
1 | |
在编译器中编辑前需先按i切换到输入模式在输入文本
1 | |
按Esc退出输入模式切换为命令模,输入:w保存:q退出编译器
查看id
1 | |

开启http服务
1 | |

触发过程

访问ip地址

构造payload
bp抓包
1 | |


使用XXE进行SSRF利用
bp抓包输入payload
调用http协议
1 | |
10.1.2.3可以通过SSRF中的知识查到

1 | |

1 | |

利用php伪协议读取文件
php伪协议
相比较file伪协议,PHP伪协议可以对读取出的额文件进行数据编码
在XXE漏洞的基础上,使用PHP伪协议对文件进行读取并编码
直接读取
执行命令可以直接读取到flag

再尝试读取index.php

发现无法读取,因为index.php会被解析掉,看不到源代码
利用php伪协议
1 | |


解码可以看到源码
利用expect扩展进行命令执行
expect协议
概念
except:// 处理交互式的流
由expect://封装协议打开的数据流PTY通过提供了对进程stdio、stdou和stderr的访问
expect://封装协议默认未开启,为了使用必须把靶机中安装有效额Expect扩展
会被拒绝的字符
以下7个字符会被拒绝,PHP的XML的解析器会出错(以编码方式也无法执行)
- 空格(可使用$IFS绕过)
- “双引号
- |管道符
- {}大括号
- \反斜杠
- <>尖括号
- :冒号
payload
1 | |

1 | |

无回显XXE带外数据
无回显XXE漏洞步骤
1、验证XXE漏洞是否存在
DNSLog查看漏洞
DNSLog原理是利用DNS协议的特性,将需要收集的信息编码成DNS查询请求,然后将请求发送到DNS服务器,最后通过DNS服务器的响应来获取信息
利用Collaborator
- 查看DNSLog信息
- 接收HTTP请求数据带外内容
构造payload
1 | |

http后的url是从Collaborator中复制出来的

利用kali监听
在kali上监听一个端口
1 | |
我这里是在云服务器上监听,在kali上命令也是一样的

payload
1 | |

2、带外数据
内部DTD嵌套调用参数实体(是错误的❌)
尝试构造payload
1 | |
定义两个参数实体
第一个参数实体%file尝试用file协议读取/etc/passwd,并把内容传给参数实体file
第二个参数实体%send,用http协议访问bp中的Collaborator模块,将%file发送
发现发送之后无法在bp中轮询查看到
原因分析:
实际上执行后响应太快且没有任何反馈信息,说明XML语句没有执行成功。内部DTD禁止调用参数实体,就是不能嵌套调用参数实体
外部DTD重复调用参数实体
外部DTD可以重复调用参数实体,允许参数实体调用其他参数实体
利用参数实体以及外部实体读取文件
工作逻辑

利用过程
在kali的1.dtd中写入
1 | |
- 参数实体file=用php伪协议把”file:///etc/passwd”的结果进行base64编码
- 参数实体send=用http伪协议把”%file;”的值get提交出去
- 参数实体int包含参数实体send
开启另一个终端监听2333端口
1 | |
在第一个端口执行命令
1 | |
在bp构造payload
1 | |
执行过程
- 调用参数实体%remote
在ip地址中下载1.dtd

- 调用参数实体%int;
执行完后

- 调用参数实体%send;
在%send;内部调用%file;(包含file:///etc/passwd的信息并GET提交给ip://2333)


xinclude
概念
xml include,类似于php include
文件包含可以使代码更干净,我们可以将定义的功能函数放在function.php中,再在需要使用功能函数的文件中使用include包含function.php,这样就可以避免重读冗长得到函数定义,同样可以增加代码的可读性
示例

功能:调用templates/目录下的文件footer.xml
与外部实体的区别
| 外部实体 | 无法成为一个成熟的独立的XML文档,因为它既不允许独立的XML声明,也不允许Doctype声明 |
|---|---|
| xinclude | 可以调用一个独立完整的XML内容 |
与PHP文件包含的区别
| php文件包含 | include直接调用函数<?php include(‘/file.php’) |
|---|---|
| xinclude | 使用时前面必须做一个前缀声明 |
利用思路
构造payload
1 | |
声明XInclude命名空间

使用SVG进行XXE漏洞利用
SVG文件
.svg一种图片格式,可缩放矢量图形,基于XML标记语言,用于描述二维的矢量图形
通过SVG文件进行XXE漏洞利用,从而读取对方文件
1 | |
定义图片的字体,大小,以及在x,y轴显示的位置
1 | |

1 | |
