1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
|
From: Miguel Landaeta <nomadium@debian.org>
Date: Mon, 24 Mar 2014 16:57:19 -0300
Subject: CVE-2014-0054
Bug: http://bugs.debian.org/741604
diff --git a/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/castor/CastorMarshaller.java b/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/castor/CastorMarshaller.java
index 871075f..fea0519 100644
--- a/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/castor/CastorMarshaller.java
+++ b/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/castor/CastorMarshaller.java
@@ -120,6 +120,11 @@ public class CastorMarshaller extends AbstractMarshaller implements Initializing
this.encoding = encoding;
}
+ @Override
+ protected String getDefaultEncoding() {
+ return this.encoding;
+ }
+
/**
* Set the locations of the Castor XML Mapping files.
*/
diff --git a/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java b/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java
index 1b3412d..37d7937 100644
--- a/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java
+++ b/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java
@@ -317,6 +317,13 @@ public class Jaxb2Marshaller
this.processExternalEntities = processExternalEntities;
}
+ /**
+ * @return the configured value for whether XML external entities are allowed.
+ */
+ public boolean isProcessExternalEntities() {
+ return this.processExternalEntities;
+ }
+
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
}
diff --git a/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/jibx/JibxMarshaller.java b/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/jibx/JibxMarshaller.java
index 5d6a053..0de00b2 100644
--- a/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/jibx/JibxMarshaller.java
+++ b/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/jibx/JibxMarshaller.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2010 the original author or authors.
+ * Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@ import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
@@ -133,6 +134,11 @@ public class JibxMarshaller extends AbstractMarshaller implements InitializingBe
this.encoding = encoding;
}
+ @Override
+ protected String getDefaultEncoding() {
+ return this.encoding;
+ }
+
/**
* Set the document standalone flag for marshalling. By default, this flag is not present.
*/
@@ -301,7 +307,7 @@ public class JibxMarshaller extends AbstractMarshaller implements InitializingBe
}
catch (TransformerException ex) {
throw new MarshallingFailureException(
- "Could not transform to [" + ClassUtils.getShortName(result.getClass()) + "]");
+ "Could not transform to [" + ClassUtils.getShortName(result.getClass()) + "]", ex);
}
}
@@ -367,7 +373,7 @@ public class JibxMarshaller extends AbstractMarshaller implements InitializingBe
@Override
protected Object unmarshalDomNode(Node node) throws XmlMappingException {
try {
- return transformAndUnmarshal(new DOMSource(node));
+ return transformAndUnmarshal(new DOMSource(node), null);
}
catch (IOException ex) {
throw new UnmarshallingFailureException("JiBX unmarshalling exception", ex);
@@ -377,12 +383,15 @@ public class JibxMarshaller extends AbstractMarshaller implements InitializingBe
@Override
protected Object unmarshalSaxReader(XMLReader xmlReader, InputSource inputSource)
throws XmlMappingException, IOException {
- return transformAndUnmarshal(new SAXSource(xmlReader, inputSource));
+ return transformAndUnmarshal(new SAXSource(xmlReader, inputSource), inputSource.getEncoding());
}
- private Object transformAndUnmarshal(Source source) throws IOException {
+ private Object transformAndUnmarshal(Source source, String encoding) throws IOException {
try {
Transformer transformer = transformerFactory.newTransformer();
+ if (encoding != null) {
+ transformer.setOutputProperty(OutputKeys.ENCODING, encoding);
+ }
ByteArrayOutputStream os = new ByteArrayOutputStream();
transformer.transform(source, new StreamResult(os));
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
@@ -390,7 +399,7 @@ public class JibxMarshaller extends AbstractMarshaller implements InitializingBe
}
catch (TransformerException ex) {
throw new MarshallingFailureException(
- "Could not transform from [" + ClassUtils.getShortName(source.getClass()) + "]");
+ "Could not transform from [" + ClassUtils.getShortName(source.getClass()) + "]", ex);
}
}
diff --git a/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/support/AbstractMarshaller.java b/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/support/AbstractMarshaller.java
index cee37bb..09bc006 100644
--- a/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/support/AbstractMarshaller.java
+++ b/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/support/AbstractMarshaller.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2010 the original author or authors.
+ * Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -73,6 +73,34 @@ public abstract class AbstractMarshaller implements Marshaller, Unmarshaller {
private final Object documentBuilderFactoryMonitor = new Object();
+ private boolean processExternalEntities = false;
+
+
+ /**
+ * Indicates whether external XML entities are processed when unmarshalling.
+ * <p>Default is {@code false}, meaning that external entities are not resolved.
+ * Note that processing of external entities will only be enabled/disabled when the
+ * {@code Source} passed to {@link #unmarshal(Source)} is a {@link SAXSource} or
+ * {@link StreamSource}. It has no effect for {@link DOMSource} or {@link StAXSource}
+ * instances.
+ */
+ public void setProcessExternalEntities(boolean processExternalEntities) {
+ this.processExternalEntities = processExternalEntities;
+ }
+
+ /**
+ * @return the configured value for whether XML external entities are allowed.
+ */
+ public boolean isProcessExternalEntities() {
+ return this.processExternalEntities;
+ }
+
+ /**
+ * @return the default encoding to use for marshalling or unmarshalling from
+ * a byte stream, or {@code null}.
+ */
+ abstract protected String getDefaultEncoding();
+
/**
* Marshals the object graph with the given root into the provided <code>javax.xml.transform.Result</code>.
@@ -131,7 +159,7 @@ public abstract class AbstractMarshaller implements Marshaller, Unmarshaller {
return unmarshalSaxSource((SAXSource) source);
}
else if (source instanceof StreamSource) {
- return unmarshalStreamSource((StreamSource) source);
+ return unmarshalStreamSourceNoExternalEntitities((StreamSource) source);
}
else {
throw new IllegalArgumentException("Unknown Source type: " + source.getClass());
@@ -173,7 +201,9 @@ public abstract class AbstractMarshaller implements Marshaller, Unmarshaller {
* @throws SAXException if thrown by JAXP methods
*/
protected XMLReader createXmlReader() throws SAXException {
- return XMLReaderFactory.createXMLReader();
+ XMLReader xmlReader = XMLReaderFactory.createXMLReader();
+ xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", isProcessExternalEntities());
+ return xmlReader;
}
@@ -356,8 +386,42 @@ public abstract class AbstractMarshaller implements Marshaller, Unmarshaller {
}
/**
+ * Template method for handling {@code StreamSource}s with protection against
+ * the XML External Entity (XXE) processing vulnerability taking into account
+ * the value of the {@link #setProcessExternalEntities(boolean)} property.
+ * <p>
+ * The default implementation wraps the StreamSource as a SAXSource and delegates
+ * to {@link #unmarshalSaxSource(javax.xml.transform.sax.SAXSource)}.
+ *
+ * @param streamSource the {@code StreamSource}
+ * @return the object graph
+ * @throws IOException if an I/O exception occurs
+ * @throws XmlMappingException if the given source cannot be mapped to an object
+ *
+ * @see <a href="https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing">XML_External_Entity_(XXE)_Processing</a>
+ */
+ protected Object unmarshalStreamSourceNoExternalEntitities(StreamSource streamSource) throws XmlMappingException, IOException {
+ InputSource inputSource;
+ if (streamSource.getInputStream() != null) {
+ inputSource = new InputSource(streamSource.getInputStream());
+ inputSource.setEncoding(getDefaultEncoding());
+ }
+ else if (streamSource.getReader() != null) {
+ inputSource = new InputSource(streamSource.getReader());
+ }
+ else {
+ inputSource = new InputSource(streamSource.getSystemId());
+ }
+ return unmarshalSaxSource(new SAXSource(inputSource));
+ }
+
+ /**
* Template method for handling <code>StreamSource</code>s.
* <p>This implementation defers to <code>unmarshalInputStream</code> or <code>unmarshalReader</code>.
+ * <p>As of 3.2.8 and 4.0.2 this method is no longer invoked from
+ * {@link #unmarshal(javax.xml.transform.Source)}. The method invoked instead is
+ * {@link #unmarshalStreamSourceNoExternalEntitities(javax.xml.transform.stream.StreamSource)}.
+ *
* @param streamSource the <code>StreamSource</code>
* @return the object graph
* @throws IOException if an I/O exception occurs
diff --git a/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/xmlbeans/XmlBeansMarshaller.java b/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/xmlbeans/XmlBeansMarshaller.java
index eb5a6e6..9f06b35 100644
--- a/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/xmlbeans/XmlBeansMarshaller.java
+++ b/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/xmlbeans/XmlBeansMarshaller.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2009 the original author or authors.
+ * Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -116,6 +116,10 @@ public class XmlBeansMarshaller extends AbstractMarshaller {
return this.validating;
}
+ @Override
+ protected String getDefaultEncoding() {
+ return null;
+ }
/**
* This implementation returns true if the given class is an implementation of {@link XmlObject}.
diff --git a/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/xstream/XStreamMarshaller.java b/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/xstream/XStreamMarshaller.java
index d6521ff..efa9403 100644
--- a/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/xstream/XStreamMarshaller.java
+++ b/projects/org.springframework.oxm/src/main/java/org/springframework/oxm/xstream/XStreamMarshaller.java
@@ -26,11 +26,9 @@ import java.io.Writer;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import javax.xml.stream.XMLEventReader;
-import javax.xml.stream.XMLEventWriter;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamReader;
-import javax.xml.stream.XMLStreamWriter;
+import javax.xml.stream.*;
+import javax.xml.transform.stax.StAXSource;
+import javax.xml.transform.stream.StreamSource;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.ConversionException;
@@ -349,6 +347,11 @@ public class XStreamMarshaller extends AbstractMarshaller implements Initializin
this.encoding = encoding;
}
+ @Override
+ protected String getDefaultEncoding() {
+ return this.encoding;
+ }
+
/**
* Set the classes supported by this marshaller.
* <p>If this property is empty (the default), all classes are supported.
@@ -470,6 +473,13 @@ public class XStreamMarshaller extends AbstractMarshaller implements Initializin
// Unmarshalling
@Override
+ protected Object unmarshalStreamSourceNoExternalEntitities(StreamSource streamSource)
+ throws XmlMappingException, IOException {
+
+ return super.unmarshalStreamSource(streamSource);
+ }
+
+ @Override
protected Object unmarshalDomNode(Node node) throws XmlMappingException {
HierarchicalStreamReader streamReader;
if (node instanceof Document) {
diff --git a/projects/org.springframework.web/src/main/java/org/springframework/http/converter/xml/SourceHttpMessageConverter.java b/projects/org.springframework.web/src/main/java/org/springframework/http/converter/xml/SourceHttpMessageConverter.java
index 15b7d8e..3126ca4 100644
--- a/projects/org.springframework.web/src/main/java/org/springframework/http/converter/xml/SourceHttpMessageConverter.java
+++ b/projects/org.springframework.web/src/main/java/org/springframework/http/converter/xml/SourceHttpMessageConverter.java
@@ -85,6 +85,13 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
this.processExternalEntities = processExternalEntities;
}
+ /**
+ * @return the configured value for whether XML external entities are allowed.
+ */
+ public boolean isProcessExternalEntities() {
+ return this.processExternalEntities;
+ }
+
@Override
public boolean supports(Class<?> clazz) {
return DOMSource.class.equals(clazz) || SAXSource.class.equals(clazz)
@@ -146,7 +153,7 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
private Source readStAXSource(InputStream body) {
try {
XMLInputFactory inputFactory = XMLInputFactory.newFactory();
- inputFactory.setProperty("javax.xml.stream.isSupportingExternalEntities", processExternalEntities);
+ inputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, this.processExternalEntities);
XMLStreamReader streamReader = inputFactory.createXMLStreamReader(body);
return StaxUtils.createStaxSource(streamReader);
}
|