一个被广泛流传的XXE漏洞错误修复方案

admin 2021年4月2日20:39:16评论118 views字数 2708阅读9分1秒阅读模式

现在百度”XXE漏洞修复”,搜索到的Java语言修复方案大部分如下:

1
2
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);

经过实际的测试发现setExpandEntityReferences(false)根本无法防御XXE漏洞!不禁思考到两个问题:

  1. setExpandEntityReferences为何无法防御XXE?
  2. 为何一个无法防御的方案,却广为流传?

上一周我们深入Java内置XML解析器中,研究XXE漏洞的深层原理。这周我们在这个基础上,进一步弄清以上两个问题。

0x01 测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import javax.xml.parsers.*;
import java.io.ByteArrayInputStream;
import java.io.InputStream;

public class DOMXXETest02 {
public static void main(String[] args) throws ParserConfigurationException,SAXException,Exception{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
DocumentBuilder db = dbf.newDocumentBuilder();
String str = " n" +
"n" +
"]>&xxe;";
InputStream is = new ByteArrayInputStream(str.getBytes());
Document doc = db.parse(is);
System.out.println(doc.getElementsByTagName("doc"));
}
}

test.dtd

1
test by c0ny1

0x02 原理分析

我们在dbf.setExpandEntityReferences(false);打断点开始分析!

setExpandEntityReferences(false)会将DocumentBuilderFactory对象中的expandEntityRef属性默认值true修改为false。

在newDocumentBuilder()会方法返回一个DocumentBuilderImpl对象前,会在DocumentBuilderImpl对象初始化时,调用setFeature()方法对DOM解析器的CREATE_ENTITY_REF_NODES_FEATURE(http://apache.org/xml/features/dom/create-entity-ref-nodes) 配置项设置为上一步的expandEntityRef变量的相反值true。

domParser.setFeature()最终会调用解析器配置对象设置目标配置项的值。

在XMLParser对象调用reset()方法重置状态时,AbstractDOMParser对象中通过解析器的配置对象获取到CREATE_ENTITY_REF_NODEShttp://apache.org/xml/features/dom/create-entity-ref-nodes) 配置项的值true,并将fCreateEntityRefNodes属性设置为true。

在XMLDocumentFragmentScannerImpl.scanDocument()进入START_ELEMENT阶段后,next()方法会对XML中的元素进行扫描。当扫描到文本中的&字符时(识别一般实体),解析器会调用scanEntityReference() 扫描实体引用。最后会调用setupCurrentEntity()创建连接并发起请求,以获取外部实体的内容,这时XXE漏洞将会触发!可以发现程序运行流程,依然会执行到XXE漏洞触发的位置。

继续跟踪,AbstractDOMParser.endGeneralEntity()在判断fCreateEntityRefNodesfalse时,实体引用&xxe将会被从DOM树删除,引用的具体内容Test by c0ny1将会在DOM树中展开,替换掉&xxe。此时为true,实体引用节点将保留在DOM树中。这是setExpandEntityReferences方法对XML解析器处理XML最终产生影响的位置。

最终调用链如下:

经过以上分析,我们大致了解了setExpandEntityReferences()方法的功能是对解析XML生成的Document文档进行设置,设置为 true则展开实体引用到生成的文档中替换掉&xxx的实体引用声明,设置为false则保留实体引用声明的DOM树在生成的文档中。

由于setExpandEntityReferences(false)对Java内置XML解析器的设置起作用前,解析器就已经发起了对外部实体的请求了,故无法防御XXE漏洞!

0x03 思考原因

为何setExpandEntityReferences明明无法防御XXE漏洞,但却很多人在使用呢?当我看了官方JDK API文档之后,发现描述过于简单,从字面上理解很容易与方法的实际功能存在偏差。

初步判断有两个原因:

  1. 官方文档的描述太过于模糊,很容易让人产生歧义。如果没有跟踪该方法底层实现很容易对它的实际功能理解错误,从而导致错误使用。

  2. 第一批修复的人应该是看了官方JDK文档来编写修复代码的,之后更多的人是直接百度到了一批人的编写的错误修复代码,直接复制粘贴。导致这个错误的修复方案进一步蔓延。

0x04 参考文章

文章来源于gv7.me:一个被广泛流传的XXE漏洞错误修复方案

相关推荐: 从代码层面理解java的00截断漏洞深入篇

4个月前写了一篇文章叫《从代码层面理解java的00截断漏洞》,由于当时出差新疆没时间深入,便在文末立了个有空继续深入的flag。今天我们通过跟踪jdk代码, 彻底搞清楚java中00截断的原理,以及它之后版本是如何修复的? 一、漏洞测试代码改进 看了一些ja…

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年4月2日20:39:16
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   一个被广泛流传的XXE漏洞错误修复方案https://cn-sec.com/archives/318107.html

发表评论

匿名网友 填写信息