【问题标题】:Prevent XXE Attack with JAXB使用 JAXB 防止 XXE 攻击
【发布时间】:2012-10-10 05:57:13
【问题描述】:

最近,我们对代码进行了安全审计,其中一个问题是我们的应用程序受到了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 输入本身(&lt;calcinput&gt;...&lt;/calcinput&gt; 部分)使用 JAXB (v2.1) 解组。 Web 服务部分基于 jaxws-rt (2.1)。

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

【问题讨论】:

    标签: java security jaxb ws-security xxe


    【解决方案1】:

    JAXB

    您可以通过从 XMLStreamReader 中解组来防止 Xml 外部实体 (XXE) 攻击,该 XMLStreamReader 属性设置为 IS_SUPPORTING_EXTERNAL_ENTITIES 和/或 XMLInputFactory.SUPPORT_DTD 属性设置为 false

    JAX-WS

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


    示例

    演示

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

    input.xml

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

    <?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 时的输出

    当设置此属性时,尝试解析实体时会引发异常。

    Exception in thread "main" javax.xml.bind.UnmarshalException
     - with linked exception:
    [javax.xml.stream.XMLStreamException: ParseError at [row,col]:[8,15]
    Message: The entity "name" was referenced, but not declared.]
        at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException(UnmarshallerImpl.java:436)
        at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:372)
        at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:342)
        at xxe.Demo.main(Demo.java:18)
    Caused by: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[8,15]
    Message: The entity "name" was referenced, but not declared.
        at com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next(XMLStreamReaderImpl.java:598)
        at com.sun.xml.bind.v2.runtime.unmarshaller.StAXStreamConnector.bridge(StAXStreamConnector.java:196)
        at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:370)
        ... 2 more
    

    【讨论】:

    • 感谢您非常详细的回答!我还有一个小问题:当我设置xif.setProperty(XMLInputFactory.SUPPORT_DTD, false); 时,我得到以下ParseError实体“include”被引用,但未声明。但是,如果我删除此属性(但保留第一个属性),则 XML 被正确解析。有什么想法吗?
    • @BlaiseDoughan 有没有办法启用实体,但将它们限制为 5 或 10 的值?我们收到在用户输入的某些字段中带有“&”的请求。
    • @asgs - 您可以指定 VM 级别的实体扩展限制。见:blog.bdoughan.com/2011/03/…
    • @BlaiseDoughan,创建一个安全配置的 XMLInputFactory 然后为每个实例文档创建一个新的 XMLStreamReader 是否安全/线程安全?
    • 我有一个 Spring MVC Web 服务,我在其中配置了如上所述的编组和解组,但我仍然在 Acunetix 工具中获得 XML 外部实体注入。请帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-31
    • 2015-10-10
    • 2015-04-03
    • 2012-12-23
    • 2014-10-02
    • 1970-01-01
    • 2018-01-19
    相关资源
    最近更新 更多