介绍
-
XXE就是XML外部实体注入。当允许引用外部实体 时,通过构造恶意内容,就可能导致任意文件读取、系统命令执 行、内网端口探测、攻击内网网站等危害。
-
XXE支持sun.net.www.protocol 里的所有协议:http,https, file,ftp,mailto,jar,netdoc。一般利用file协议读取文件,利用 http协议探测内网,没有回显时可组合利用file协议和ftp协议来读取文件。
XML常见接口
DocumentBuilder
- 以此产生的XXE是存在回显的。javax.xml.parsers包中的DocumentBuilderFactory用于创建DOM模式的解析器对象,DocumentBuilderFactory是一个抽象工厂类,它不能直接实例化,但该类提供了一个newInstance()方法,这个方法会根据本地平台默认安装的解析器,自动创建一个工厂的对象并返回。
// 有回显@RequestMapping(value = "/DocumentBuilder/vuln01", method = RequestMethod.POST)public String DocumentBuilderVuln01(HttpServletRequest request) {try {String body = WebUtils.getRequestBody(request);logger.info(body);DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();DocumentBuilder db = dbf.newDocumentBuilder();StringReader sr = new StringReader(body);InputSource is = new InputSource(sr);Document document = db.parse(is); // parse xml// 遍历xml节点name和valueStringBuilder 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;}}
XMLReader
- XMLReader接口是一种通过回调读取XML文档的接口,其存在于公共区域中。XMLReader接口是XML解析器实现SAX2驱动程序所必需的接口,其允许应用程序设置和查询解析器中的功能和属性、注册文档处理的事件处理程序,以及开始文档解析。当XMLReader使用默认的解析方法并且未对XML进行过滤时,会出现XXE漏洞
@PostMapping("/XMLReader/vuln")public String XMLReaderVuln(HttpServletRequest request) {try {String body = WebUtils.getRequestBody(request);logger.info(body);SAXParserFactory spf = SAXParserFactory.newInstance();SAXParser saxParser = spf.newSAXParser();XMLReader xmlReader = saxParser.getXMLReader();xmlReader.parse(new InputSource(new StringReader(body)));} catch (Exception e) {logger.error(e.toString());return EXCEPT;}return "XMLReader xxe vuln code";}
SAXBuilder
- SAXBuilder是一个JDOM解析器,其能够将路径中的XML文件解析为Document对象。SAXBuilder使用第三方SAX解析器来处理解析任务,并使用SAXHandler的实例侦听SAX事件。当SAXBuilder使用默认的解析方法并且未对XML进行过滤时,会出现XXE漏洞
@RequestMapping(value = "/SAXBuilder/vuln", method = RequestMethod.POST)public String SAXBuilderVuln(HttpServletRequest request) {try {String body = WebUtils.getRequestBody(request);logger.info(body);SAXBuilder builder = new SAXBuilder();// org.jdom2.Document documentbuilder.build(new InputSource(new StringReader(body))); // cause xxereturn "SAXBuilder xxe vuln code";} catch (Exception e) {logger.error(e.toString());return EXCEPT;}}
SAXReader
- saxReader是第三方的库,该类是无回显的。DOM4J是dom4j.org出品的一个开源XML解析包,使用起来非常简单,只要了解基本的XML-DOM模型,就能使用。DOM4J读/写XML文档主要依赖于org.dom4j.io包,它有DOMReader和SAXReader两种方式。因为使用了同一个接口,所以这两种方式的调用方法是完全一致的。同样的,在使用默认解析方法并且未对XML进行过滤时,其也会出现XXE漏洞。
saxReader是第三方的库,该类是无回显的@RequestMapping(value = "/SAXReader/vuln", method = RequestMethod.POST)public String SAXReaderVuln(HttpServletRequest request) {try {String body = WebUtils.getRequestBody(request);logger.info(body);SAXReader reader = new SAXReader();// org.dom4j.Document documentreader.read(new InputSource(new StringReader(body))); // cause xxe} catch (Exception e) {logger.error(e.toString());return EXCEPT;}return "SAXReader xxe vuln code";}
SAXParserFactory
- SAXParserFactory使应用程序能够配置和获取基于SAX的解析器以解析XML文档。其受保护的构造方法,可以强制使用newInstance()。跟上面介绍的一样,在使用默认解析方法且未对XML进行过滤时,其也会出现XXE漏洞。
//该类也是JDK内置的类,但他不可回显内容,可借助dnslog平台@RequestMapping(value = "/SAXParser/vuln", method = RequestMethod.POST)public String SAXParserVuln(HttpServletRequest request) {try {String body = WebUtils.getRequestBody(request);logger.info(body);SAXParserFactory spf = SAXParserFactory.newInstance();SAXParser parser = spf.newSAXParser();parser.parse(new InputSource(new StringReader(body)), new DefaultHandler()); // parse xmlreturn "SAXParser xxe vuln code";} catch (Exception e) {logger.error(e.toString());return EXCEPT;}}
Digester
- Digester类用来将XML映射成Java类,以简化XML的处理。它是Apache Commons库中的一个jar包:common-digester包。一样的在默认配置下会出现XXE漏洞。其触发的XXE漏洞是没有回显的,我们一般需通过Blind XXE的方法来利用
@RequestMapping(value = "/Digester/vuln", method = RequestMethod.POST)public String DigesterVuln(HttpServletRequest request) {try {String body = WebUtils.getRequestBody(request);logger.info(body);Digester digester = new Digester();digester.parse(new StringReader(body)); // parse xml} catch (Exception e) {logger.error(e.toString());return EXCEPT;}return "Digester xxe vuln code";}
修复方法
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);.setFeature("http://xml.org/sax/features/external-general-entities",false).setFeature("http://xml.org/sax/features/external-parameter-entities",false);
Java中的XXE关键词
-
其实不仅是Java,其他语言依旧是一样的思路,XML解析一般在导入配置、数据传输接口等场景可能会用到,涉及到XML文件处理的场景可查看XML解析器是否禁用外部实体,从而判断是否存在XXE。审计时首先需要定位危险函数,在Java中有如下的几个函数支持XML解析
javax.xml.parsers.DocumentBuilder javax.xml.parsers.DocumentBuilderFactory javax.xml.parsers.SAXParser javax.xml.parsers.SAXParserFactory 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
XML介绍
- XML是一种非常流行的标记语言,XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。
- DTD实体的引用有内部声明实体和外部引用实体的区别。按类型分则分为:内置实体,字符实体,通用实体,参数实体。而在XXE中最常见的就是通用实体和参数实体
内部实体
<!DOCTYPE 文件名 [
<!ENTITY 实体名 "实体内容">
]>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE aaa[
<!ENTITY name "Zh1z3ven">
]>
<root>
<name>&name;</name>
外部实体
- 外部的DTD实体则需要通过URL来远程调用一个.dtd文件,也或者可以利用file协议引用一个本地的文件;
通用实体
-
在DTD 中定义,在XML中以 &实体名; 引用
-
file协议
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE aaa [ <!ENTITY name SYSTEM "file:///c:/windows/win.ini" > ]> <name>&name;</name>
-
http协议
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE aaa [ <!ENTITY name SYSTEM "http://127.0.0.1/123.txt" > ]> <name>&name;</name>
参数实体
-
使用 % 实体名 在 DTD 中定义,并且只能在 DTD 中使用 %实体名; 引用
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE a [<!ENTITY % name SYSTEM "http://127.0.0.1/test.dtd">%name; ]> <d>&test;</d>
Test.dtd<!ENTITY test SYSTEM "http://127.0.0.1/123.txt" >
语言与协议
- XXE不仅是file和http,也支持其他的协议,不过不同的语言支持的协议不一样,可以参考下图。
LIBXML2 | PHP | JAVA | .NET |
---|---|---|---|
file | file | http | file |
http | http | https | http |
ftp | ftp | ftp | https |
php | file | ftp | |
compress.zlib | jar | ||
compress.bzip2 | netdoc | ||
data | mailto | ||
glob | gopher * | ||
phar |
dnsLog介绍
- 什么是DNS:DNS的全称是Domain Name System(网络名称系统),它作为将域名和IP地址相互映射,使人更方便地访问互联网。当用户输入某一网址如www.baidu.com,网络上的DNS Server会将该域名解析,并找到对应的真实IP如127.0.0.1,使用户可以访问这台服务器上相应的服务。
- 什么是DNSlog:DNSlog就是存储在DNS Server上的域名信息,它记录着用户对域名www.baidu.com等的访问信息,类似日志文件。
- 在某些无法直接利用漏洞获得回显的情况下,但是目标可以发起DNS请求,这个时候就可以通过这种方式把想获得的数据外带出来。
- 原理:我注册了一个为a.com的域名,我将他a记录泛解析到10.0.0.0上,这样就实现了无论我记录值填什么他都有解析,并且都指向10.0.0.0,当我向dns服务器发起test.a.com的解析请求时,DNSlog中会记录下他给test.a.com解析,解析值为10.0.0.0。(通俗来讲就是我们申请一个dnslog的平台,当我们盲注的时候把想要的数据和平台给的地址拼接起来,dnslog平台就会把请求的记录显示出来。)