javaxmljaxbxxe

How to fix this Unmarshal Exception with JAXB that arose on fixing XXE vulnerabilites?


The format of the XML Message we supposed to process is so:

<?xml version="1.0" encoding="UTF-8"?>
<ns0:MessageType xmlns:ns0="http://www.path.to/some/schema.xsd">
    <ns0:NonRelevantBody>
        ....
    </ns0:NonRelevantBody>
</ns0:MessageType>

Exception recieved:

javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"ns0:MessageType"). Expected elements are <{http://www.path.to/some/schema.xsd}MessageType>

The above exception occurs in com.xmlprocessor.MessageParser class. The code in the said class used to be so (and had been working for ages):

StringReader stringReader = new StringReader(xmlMessageAsString);

JAXBContext context = new JAXBContext.newInstance(MessageObjectFactory.class);
Unmarshaller unmarshalr = context.createUnmarshaller();
this.messageTypeContent = (MessageTypeContent) unmarshalr.unmarshal(stringReader);

Turns out this can give you a bad case of XXE. So we tried a number of very similar things DocumentBuilder, SAXParser etc. for disabling External Entities, Doctype Declaration and such things. All gave us the very same exception stated above. Anyways, here's the change with SAXParser:

StringReader stringReader = new StringReader(xmlMessageAsString);

SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

Source xmlSource = new SAXSource(spf.newSAXParser().getXMLReader(), new InputSource(stringReader));

JAXBContext context = new JAXBContext.newInstance(MessageObjectFactory.class);
Unmarshaller unmarshalr = context.createUnmarshaller();
this.messageTypeContent = (MessageTypeContent) unmarshalr.unmarshal(xmlSource);

The code for com.xmlprocessor.MessageTypeContent class is as such unchanged:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "messageType",
    "messageApprovalType"
})
@XmlRootElement(name = "MessageType")
public class MessageTypeContent {
    // Likely irrelevant unless you say so.
}

I have tried a number of things including adding namespace="ns0" or namespace="http://www.path.to/some/schema.xsd" to the @XmlRootElement annotation, it leads to similar versions of the same exception in runtime.

Please mind that there are no syntax errors in the code. Any that my have come about was in the process turning it into a question. It is entirely possible that I am a git missing out on something exteremly basic. I would really appreciate if you could point it out. Thanks.


Solution

  • Making the sax parser namespace aware fixed the issue:

    spf.setNamespaceAware(true);
    

    In the end, too much ado about nothing.