XML常见解析方式及XXE防御

发布于:2024-05-07 ⋅ 阅读:(30) ⋅ 点赞:(0)

1.PHP
1.1 SimpleXML
SimpleXML是PHP5后提供的一套简单易用的xml工具集,可以把xml转换成方便处理的对象,也可以组织生成xml数据。不过它不适用于包含namespace的xml,而且要保证xml格式完整(well-formed)。它提供了三个方法:simplexml_import_dom、simplexml_load_file、simplexml_load_string,函数名很直观地说明了函数的作用。三个函数都返回SimpleXMLElement对象,数据的读取/添加都是通过SimpleXMLElement操作.

simplexml_load_file:直接解析xml文件,如下例子:

<?php
if (file_exists('test.xml'))
  {
   
  $xml = simplexml_load_file('test.xml');
  var_dump($xml);
  }
else
  {
   
  exit('Error.');
  }
?>

simplexml_load_string:解析xml数据,如下例子:

<?php
$xmlstring = <<<XML
<?xml version="1.0" encoding="ISO-8859-1"?>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
XML;
$xml = simplexml_load_string($xmlstring);
var_dump($xml);
?>

以上两种方法对xml的解析都是存在xxe漏洞的风险,如果要防御xxe漏洞,php提供了禁止导入外部实体的方法。
libxml_disable_entity_loader:打开或关闭外部实体导入功能,如关闭需要在解析xml之前调用该函数并将参数置为:true,如下例子:

<?php
$xmlstring = <<<XML
<?xml version="1.0" encoding="ISO-8859-1"?>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
XML;
Libxml_disable_entity_loader(true);//禁止外部实体注入
$xml = simplexml_load_string($xmlstring);
var_dump($xml);
?>

2.java
2.1 DOM
DOM的全称是Document Object Model,也即文档对象模型。在应用程序中,基于DOM的XML分析器将一个XML文档转换成一个对象模型的集合(通常称DOM树),应用程序正是通过对这个对象模型的操作,来实现对XML文档数据的操作,如下:

import javax.xml.parsers.DocumentBuilder;  
import javax.xml.parsers.DocumentBuilderFactory;  
...
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();  
        System.out.println("class name: " + dbf.getClass().getName());  
        // step 2:获得具体的dom解析器  
        DocumentBuilder db = dbf.newDocumentBuilder(); 
        // step3: 解析一个xml文档,获得Document对象(根结点)  
        Document document = db.parse(new File("candidate.xml"));  
        NodeList list = document.getElementsByTagName("PERSON");

防御建议1:完全禁止DTDs,这样几乎可以完全阻止所有的xml实体攻击,如下例子:

import javax.xml.parsers.DocumentBuilder;  
import javax.xml.parsers.DocumentBuilderFactory;  
...
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
        Try{
    
       // 这是优先选择. 如果不允许DTDs (doctypes) ,几乎可以阻止所有的XML实体攻击
       String FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
       dbf.setFeature(FEATURE, true);  //设置该特征如上传xml文件包含DTDs将提示报错。
        System.out.println("class name: " + dbf.getClass().getName());  
        // step 2:获得具体的dom解析器  
        DocumentBuilder db = dbf.newDocumentBuilder(); 
        // step3: 解析一个xml文档,获得Document对象(根结点)  
        Document document = db.parse(new File("candidate.xml"));  
        NodeList list = document.getElementsByTagName("PERSON");
        }
        catch (ParserConfigurationException e) {
   
            // This should catch a failed setFeature feature
            logger.info("ParserConfigurationException was thrown. The feature '" +
                        FEATURE +
                        "' is probably not supported by your XML processor.");
            ...
        }
	...

防御建议2:如不完全禁止DTDs,可单独禁止外部实体导入,如下例子:

import javax.xml.parsers.DocumentBuilder;  
import javax.xml.parsers.DocumentBuilderFactory;  
...
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();  
	Try{
   
      	// 如果不能完全禁用DTDs,最少采取以下措施
       FEATURE = "http://xml.org/sax/features/external-general-entities";
       dbf.setFeature(FEATURE, false);
       FEATURE = "http://xml.org/sax/features/external-parameter-entities";
       dbf.setFeature(FEATURE, false);
       // and these as well, per Timothy Morgan's 2014 paper: "XML Schema, DTD, and