使用JAXB防止XXE攻击

时间:2012-10-19 15:14:46

标签: java security jaxb ws-security xxe

最近,我们对我们的代码进行了安全审核,其中一个问题是我们的应用程序受到 Xml eXternal Entity (XXE)攻击。

基本上,应用程序是一个通过Web服务以XML形式接收输入的计算器。

以下是对我们的应用程序的此类XXE攻击的示例:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header/>
   <soapenv:Body>
      <foo:calculateStuff>
         <!--Optional:-->
         <xmlInput><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE currency [  
   <!ENTITY include SYSTEM "file:///d:/" >]>
<calcinput>...</calcinput>
]]></xmlInput>
      </foo:calculateStuff>
   </soapenv:Body>
</soapenv:Envelope>

如您所见,我们可以引用指向外部文件("file:///d:/")的实体。

关于XML输入本身(<calcinput>...</calcinput>部分)是使用JAXB(v2.1)解组的。 Web服务部分基于jaxws-rt(2.1)。

我需要做些什么来保护我的网络服务?

1 个答案:

答案 0 :(得分:50)

<强> JAXB

您可以通过从XMLStreamReader和/或IS_SUPPORTING_EXTERNAL_ENTITIES属性设置为XMLInputFactory.SUPPORT_DTD的{​​{1}}进行解组来阻止Xml外部实体(XXE)攻击。

<强> JAX-WS

JAX-WS实现应该为您解决这个问题。如果不是,我会建议针对特定的implmententation打开一个错误。


示例

演示

false

input.xml中

此XML文档包含一个实体,该实体已设置为获取我用于创建此示例的文件列表。

package xxe;

import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.transform.stream.StreamSource;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Customer.class);

        XMLInputFactory xif = XMLInputFactory.newFactory();
        xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
        xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
        XMLStreamReader xsr = xif.createXMLStreamReader(new StreamSource("src/xxe/input.xml"));

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Customer customer = (Customer) unmarshaller.unmarshal(xsr);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(customer, System.out);
    }

}

<强>客户

<?xml version="1.0"?>
<!DOCTYPE customer
[
<!ENTITY name SYSTEM "/Users/bdoughan/Examples/src/xxe/">
]
>
<customer>
  <name>&name;</name>
</customer>

输出 - 默认配置

默认情况下,实体将被解析。

package xxe;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Customer {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <customer> <name>Customer.java Demo.java input.xml </name> </customer> 属性设置为XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES时的输出

设置此属性后,实体未解析。

false

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <customer> <name></name> </customer> 属性设置为XMLInputFactory.SUPPORT_DTD时的输出

设置此属性时,会尝试解析实体时抛出异常。

false