0x01 setFeature小谈

setFeature()

当我们使用DOM document builder或者SAX parser来解析XML格式的内容时,我们可以使用setFeature()来把一个特性设置为true或者false,从而打开或者关闭这个特性。而对于XXE的防御,正是设置相关feature的开关来实现的。

OWASP推荐的XXE防御

以DocumentBuilder的XXE为例,具体代码可看《XML注入之DocumentBuilder与XXE攻击防御>,这里只看下之前示例的XXE防御的setFeature()是设置了哪些特性:

1
2
3
4
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

以上设置的4个特性源自OWASP的建议,参考自《XML_External_Entity_Prevention_Cheat_Sheet》,原文解释如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// This is the PRIMARY defense. If DTDs (doctypes) are disallowed, almost all 
// XML entity attacks are prevented
// Xerces 2 only - http://xerces.apache.org/xerces2-j/features.html#disallow-doctype-decl
FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
dbf.setFeature(FEATURE, true);

// If you can't completely disable DTDs, then at least do the following:
// Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-general-entities
// Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-general-entities
// JDK7+ - http://xml.org/sax/features/external-general-entities
FEATURE = "http://xml.org/sax/features/external-general-entities";
dbf.setFeature(FEATURE, false);

// Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-parameter-entities
// Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-parameter-entities
// JDK7+ - http://xml.org/sax/features/external-parameter-entities
FEATURE = "http://xml.org/sax/features/external-parameter-entities";
dbf.setFeature(FEATURE, false);

// Disable external DTDs as well
FEATURE = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
dbf.setFeature(FEATURE, false);

下面细看下以上几个特性。

几个重要的feature

disallow-doctype-decl

防御XXE的最重要的特性,将该特性设置成true后,几乎所有的XML实体攻击都会被成功防御。

http://apache.org/xml/features/disallow-doctype-decl

True: A fatal error is thrown if the incoming document contains a DOCTYPE declaration.
False: DOCTYPE declaration is allowed.
Default: false
Since: Xerces-J 2.3.0

我们可以以之前DocumentBuilder的Demo为例,只调用setFeature()将该特性设置为true,然后会发现,只要在XML中尝试定义DOCTYPE的都会报错,因此便不支持解析DTD了,更不用谈后续的利用:

external-general-entities

该特性指定是否包含外部生成的实体,当设置为false时,不支持解析外部实体。

如果你不能完全禁用DTD,建议开启该特性。

http://xml.org/sax/features/external-general-entities

True: Include external general entities.
False: Do not include external general entities.
Default: true
Access: (parsing) read-only; (not parsing) read-write;
See: http://xml.org/sax/features/external-parameter-entities

还是之前的例子,只调用setFeature()将该特性设置为false,先尝试解析内部实体,是OK的:

再尝试解析外部实体时,虽然会发送外部请求,但是在SYSTEM解析时就会报错了:

external-parameter-entities

该特性指定是否包含外部的参数,包括外部DTD子集。当设置为false时,不支持外部参数实体及外部DTD子集。

http://xml.org/sax/features/external-parameter-entities

True: Include external parameter entities and the external DTD subset.
False: Do not include external parameter entities or the external DTD subset.
Default: true
Access: (parsing) read-only; (not parsing) read-write;
See: http://xml.org/sax/features/external-general-entities

接上一小节的示例,解析外部普通实体时,是可以成功利用的,不存在报错:

但是换种形式,当解析外部参数实体时,就会报错了:

load-external-dtd

当设置为false时,禁用外部DTD。

http://apache.org/xml/features/nonvalidating/load-external-dtd

True: Load the external DTD.
False: Ignore the external DTD completely.
Default: true
Note: This feature is always on when validation is on.
See: http://xml.org/sax/features/validation
See: http://apache.org/xml/features/nonvalidating/load-dtd-grammar

接着上一小节的示例,尝试解析外部参数实体,是ok的:

但是换成解析外部普通实体时,就报错了:

Bypass小结

配置补全或出错,如disallow-doctype-decl设置为false等,相当于没防御,看情况而定。

下面就单一的几种设置看看,具体几种的组合的Bypass自行考虑即可:

  • 如果disallow-doctype-decl设置为true,无法Bypass;
  • 如果external-general-entities设置为false,则只能解析内部实体而无法解析外部实体,此时能利用的只有XXE DoS攻击,但要看具体的JDK版本;
  • 如果external-parameter-entities设置为false,则解析内部实体、外部普通实体而无法解析外部参数实体,此时可以进行外部普通实体的形式来攻击或者XXE DoS;
  • 如果load-external-dtd设置为false,则解析内部实体、外部参数实体而无法解析外部普通实体,此时可以进行外部参数实体的形式来攻击或者XXE DoS;

0x02 参考

Feature

XML_External_Entity_Prevention_Cheat_Sheet