From 07275eecb26710fc3d78624884bb7e811d3f0afe Mon Sep 17 00:00:00 2001 From: Gursev Singh Kalra Date: Fri, 1 Jul 2016 18:19:59 -0700 Subject: [PATCH] Adds XXE fixes to JAXBDecoder and SAXDecoder classes (#415) fixes #411 --- .../src/main/java/feign/jaxb/JAXBDecoder.java | 22 ++++++++++++++++++- sax/src/main/java/feign/sax/SAXDecoder.java | 5 +++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/jaxb/src/main/java/feign/jaxb/JAXBDecoder.java b/jaxb/src/main/java/feign/jaxb/JAXBDecoder.java index 3a97db27..5c9a11b6 100644 --- a/jaxb/src/main/java/feign/jaxb/JAXBDecoder.java +++ b/jaxb/src/main/java/feign/jaxb/JAXBDecoder.java @@ -20,11 +20,17 @@ import java.lang.reflect.Type; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.Source; +import javax.xml.transform.sax.SAXSource; import feign.Response; import feign.Util; import feign.codec.DecodeException; import feign.codec.Decoder; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; /** * Decodes responses using JAXB.

Basic example with with Feign.Builder:

@@ -57,11 +63,25 @@ public class JAXBDecoder implements Decoder { throw new UnsupportedOperationException( "JAXB only supports decoding raw types. Found " + type); } + + try { + SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); + /* Explicitly control sax configuration to prevent XXE attacks */ + saxParserFactory.setFeature("http://xml.org/sax/features/external-general-entities", false); + saxParserFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + saxParserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false); + saxParserFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + + Source source = new SAXSource(saxParserFactory.newSAXParser().getXMLReader(), new InputSource(response.body().asInputStream())); Unmarshaller unmarshaller = jaxbContextFactory.createUnmarshaller((Class) type); - return unmarshaller.unmarshal(response.body().asInputStream()); + return unmarshaller.unmarshal(source); } catch (JAXBException e) { throw new DecodeException(e.toString(), e); + } catch (ParserConfigurationException e) { + throw new DecodeException(e.toString(), e); + } catch (SAXException e) { + throw new DecodeException(e.toString(), e); } finally { if (response.body() != null) { response.body().close(); diff --git a/sax/src/main/java/feign/sax/SAXDecoder.java b/sax/src/main/java/feign/sax/SAXDecoder.java index 0da7d40f..b0081705 100644 --- a/sax/src/main/java/feign/sax/SAXDecoder.java +++ b/sax/src/main/java/feign/sax/SAXDecoder.java @@ -74,6 +74,11 @@ public class SAXDecoder implements Decoder { XMLReader xmlReader = XMLReaderFactory.createXMLReader(); xmlReader.setFeature("http://xml.org/sax/features/namespaces", false); xmlReader.setFeature("http://xml.org/sax/features/validation", false); + /* Explicitly control sax configuration to prevent XXE attacks */ + xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", false); + xmlReader.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + xmlReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false); + xmlReader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); xmlReader.setContentHandler(handler); InputStream inputStream = response.body().asInputStream(); try {