java审计-XXE

介绍

  • 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和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();
         return buf.toString();
     } catch (Exception e) {
         logger.error(e.toString());
         return EXCEPT;
     }
 }

java审计-XXE_第1张图片

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";
 }

java审计-XXE_第2张图片

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 document
         builder.build(new InputSource(new StringReader(body)));  // cause xxe
         return "SAXBuilder xxe vuln code";
     } catch (Exception e) {
         logger.error(e.toString());
         return EXCEPT;
     }
 }

java审计-XXE_第3张图片

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 document
         reader.read(new InputSource(new StringReader(body))); // cause xxe

     } catch (Exception e) {
         logger.error(e.toString());
         return EXCEPT;
     }

     return "SAXReader xxe vuln code";
 }

java审计-XXE_第4张图片

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 xml

         return "SAXParser xxe vuln code";
     } catch (Exception e) {
         logger.error(e.toString());
         return EXCEPT;
     }
 }

java审计-XXE_第5张图片

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";
 }

java审计-XXE_第6张图片

修复方法

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平台就会把请求的记录显示出来。)
    java审计-XXE_第7张图片

你可能感兴趣的:(java,开发语言,系统安全,代码复审)