BOOK THIS SPACE FOR AD
ARTICLE ADIf you’ve ever worked with secure XML parsing in Java (to prevent XXE Injections), you probably have come across an XML parser flag named SecureProcessing and thought “Huh, that sounds useful”. But soon after, you were wondering what this flag actually does and, most importantly, if it actually secures your XML parser against XXE.
So does it? Well, unfortunately not.
To play around with this, we create a simple Spring Boot app that has an endpoint that accepts an inputXML, parses the XML, converts it back to a string, and returns it. Say the endpoint looks something like this:
@RequestMapping(method=RequestMethod.POST, value="/process-xml")public String processXml(String inputXml) {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(inputXml)));
return xmlToString(doc);
}
xmlToString() may look something like this:
public static String xmlToString(Document doc) {StringWriter sw = new StringWriter();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.transform(new DOMSource(doc), new StreamResult(sw));
return sw.toString();
}
Note that for simplicity, we omitted things like exception handling and input validation.
The above functionality is of course vulnerable to XXE, and can be exploited by e.g. sending the following XML:
This renders the /etc/passwd file in the response:
Now, it’s time to implement SecureProcessing because that’s kinda why we’re here, right?
For this, we adjust our /process-xml endpoint slightly and get the following:
@RequestMapping(method=RequestMethod.POST, value="/process-xml")public String processXml(String inputXml) {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// enables secure processing
String feature = "http://javax.xml.XMLConstants/feature/secure-processing"
dbf.setFeature(feature, true);
DocumentBuilder builder = dbf.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(inputXml)));
return xmlToString(doc);
}
Now we send our previous XXE payload again and… it still works! The app is still vulnerable to XXE and the payload still extracts the /etc/passwd file. Wait what?
Yes, you read that right. SecureProcessing does not make the XML parser secure at all.
If you want to play around with this code example yourself, check out my GitHub repo: https://github.com/dub-flow/Secure-Processing-XXE-Tests-Java.
At this point, you might be feeling slightly confused so let me explain. SecureProcessing is a can of worms because different XML parsers may treat the flag differently.
I wouldn’t be surprised if there even was an XML parser out there that was secure solely by implementing SecureProcessing, but it’s fair to say that you should generally not trust this feature to secure you. Instead, just follow the remediation guidance from the OWASP XXE cheat sheet: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html.
And, for what it’s worth, the XML parser we used in the example, DocumentBuilderFactory, is safe from the Billion Laughs attack if SecureProcessing is enabled.
To test for the Billion Laughs attack, we can send a payload like this:
Without SecureProcessing enabled, the app hangs and we can successfully DoS it.
With SecureProcessing implemented, the attack fails and the app quickly throws an error:
The SecureProcessing feature serves as a reminder that just because it says “secure” doesn’t mean it actually is secure.
If you have any questions on the matter or wanna share your own experiences, please feel free to reach out to me on LinkedIn: https://www.linkedin.com/in/florian-ethical-hacker/.
Also, if you like my content, feel free to follow me for more 😃.