web-dev-qa-db-fra.com

Empêchez les attaques XXE avec JAXB

Récemment, nous avons eu un audit de sécurité sur notre code, et l'un des problèmes est que notre application est soumise à l'attaque Xml eXternal Entity (XXE).

Fondamentalement, l'application est une calculatrice qui reçoit des entrées en XML, via un Web-Service.

Voici un exemple d'une telle attaque XXE sur notre application:

<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>

Comme vous pouvez le voir, nous pouvons nous référer à une entité qui pointe vers un fichier externe ("file:///d:/").

Concernant l'entrée XML elle-même (le <calcinput>...</calcinput> part) n'est pas compatible avec JAXB (v2.1). La partie service Web est basée sur jaxws-rt (2.1).

Que dois-je faire pour sécuriser mon service Web?

38
Romain Linsolas

[~ # ~] jaxb [~ ​​# ~]

Vous pouvez empêcher l'attaque Xml eXternal Entity (XXE) en supprimant le marshalling d'un XMLStreamReader qui a le IS_SUPPORTING_EXTERNAL_ENTITIES et/ou XMLInputFactory.SUPPORT_DTD propriétés définies sur false.

JAX-WS

Une implémentation JAX-WS devrait s'en occuper pour vous. Si ce n'est pas le cas, je recommanderais d'ouvrir un bogue contre l'implémentation spécifique.


EXEMPLE

Démo

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

Ce document XML contient une entité qui a été configurée pour obtenir la liste des fichiers que j'ai utilisés pour créer cet exemple.

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

Client

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

}

Sortie - Configuration par défaut

Par défaut, l'entité sera résolue.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customer>
    <name>Customer.Java
Demo.Java
input.xml
</name>
</customer>

Sortie lorsque XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES la propriété est définie sur false

Lorsque cette propriété est définie, l'entité n'est pas résolue.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customer>
    <name></name>
</customer>

Sortie lorsque XMLInputFactory.SUPPORT_DTD la propriété est définie sur false

Lorsque cette propriété est définie, une exception est levée en essayant de résoudre l'entité.

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
52
bdoughan