Remove DOCTYPE and its containing tags from xml using XmlOptions

Viewed 1020

I have below request and i want to remove DOCTYPE and its contaning ENTITY tag(s) . i dont have parser access but in class i can pass XMlOptions so is there any way that i can remove DOCTYPE using XMLOptions , so XMl enity expansion vunerbility will removed

request i am using to send

<!DOCTYPE foo [
<!ENTITY xeebri2n0 "o16ja">
<!ENTITY xeebri2n1 "&xeebri2n0;&xeebri2n0;">
<!ENTITY xeebri2n2 "&xeebri2n1;&xeebri2n1;">
<!ENTITY xeebri2n3 "&xeebri2n2;&xeebri2n2;">]>
<SubmitPaymentRequest xmlns="http://www.qwest.com/XMLSchema" xmlns:bim="http://www.qwest.com/XMLSchema/BIM">
    <EPWFHeaderInfo>
        <RequestId>IR1BCSRDQBSIRW7745 &xeebri2n3;<RequestId>
        <SendTimeStamp>2019-12-23T14:23:01.183-05:00<SendTimeStamp>
        <MessageSrcSystem>IPS<MessageSrcSystem>
    </EPWFHeaderInfo>
</SubmitPaymentRequest>

EPWFSubmitPaymentEventHandler.java class where i am using above class to parse

EPWFSubmitPaymentEventHandler{
public String handleEventMessage(String inXml, XmlObject xmlBean, Map<String, String> metaInfo) {


SubmitPaymentRequestWrapper request = new SubmitPaymentRequestWrapper(inXml);

}
}

class where i am parsing the xml.

  SubmitPaymentRequestWrapper {

    public SubmitPaymentRequestWrapper(String reqXml, XmlOptions options) throws XmlException {
            this(SubmitPaymentRequestDocument.Factory.parse(reqXml, options));
        }
}

in Above SubmitPaymentRequestWrapper.java class i can not access SubmitPaymentRequestDocument.java So, is there any way that i can disbale or remove the DOCTYPE using passing XMLOptions ?

1 Answers

We usually don't remove the doctype elements manually, but parametrise the the parser to ignore it. How you can do that depends unfortunately strong on which parser it is. In JAXB you can do it like this:

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

The line with XMLInputFactory.SUPPORT_DTD will disable the doctype completely. If I recall it correctly all entities defined will be replaced with empty strings then (don't take my word - test it).

The line with XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES is there, because I have found out, that XML parsers in Java's default configuration are not vulnerable to XML bomb attacks (like the one you have in the XML). The attack will stop after 60k iterations quite fast (remember - don't take my word). So after a lot of testing I decided to stop only external entities, which are a nuisance and an insecure default in Java.

If you don't use JAXB but JDOM, then external entity prevention will look differently:

SAXBuilder builder = new SAXBuilder();
File xmlFile = new File("test.xml");
builder.setExpandEntities(false);
Document document = builder.build(xmlFile);

It's different in Dom4J too:

SAXReader reader = new SAXReader();
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
Document document = reader.read("test.xml");
Related