High severityNVD Advisory· Published Dec 15, 2019· Updated Aug 6, 2024
CVE-2014-3643
CVE-2014-3643
Description
jersey: XXE via parameter entities not disabled by the jersey SAX parser
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
com.sun.jersey:jersey-coreMaven | < 1.13 | 1.13 |
Affected products
1Patches
149f1e5a6ac60Improved handling of external XML entities.
10 files changed · +702 −109
changes.txt+1 −0 modified@@ -1,4 +1,5 @@ release 1.13 +- Improved handling of external XML entities - Fixed issue 1198 http://java.net/jira/browse/JERSEY-1198 UriTemplates containing characters that had special meaning (for regex expressions) did not work correctly.
jersey-core/src/main/java/com/sun/jersey/core/impl/provider/entity/SourceProvider.java+35 −31 modified@@ -40,12 +40,12 @@ package com.sun.jersey.core.impl.provider.entity; -import com.sun.jersey.spi.inject.Injectable; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.annotation.Annotation; import java.lang.reflect.Type; + import javax.ws.rs.Consumes; import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; @@ -55,6 +55,7 @@ import javax.ws.rs.core.Response.Status; import javax.ws.rs.ext.MessageBodyReader; import javax.ws.rs.ext.MessageBodyWriter; + import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParserFactory; @@ -65,39 +66,42 @@ import javax.xml.transform.sax.SAXSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; + import org.w3c.dom.Document; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; +import com.sun.jersey.spi.inject.Injectable; + /** * - * @author Paul.Sandoz@Sun.Com + * @author Paul Sandoz (paul.sandoz at oracle.com) */ public final class SourceProvider { - + @Produces({"application/xml", "text/xml", "*/*"}) @Consumes({"application/xml", "text/xml", "*/*"}) - public static final class StreamSourceReader implements + public static final class StreamSourceReader implements MessageBodyReader<StreamSource> { public boolean isReadable(Class<?> t, Type gt, Annotation[] as, MediaType mediaType) { return StreamSource.class == t; } public StreamSource readFrom( - Class<StreamSource> t, - Type gt, - Annotation[] as, - MediaType mediaType, + Class<StreamSource> t, + Type gt, + Annotation[] as, + MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException { return new StreamSource(entityStream); } } - + @Produces({"application/xml", "text/xml", "*/*"}) @Consumes({"application/xml", "text/xml", "*/*"}) - public static final class SAXSourceReader implements + public static final class SAXSourceReader implements MessageBodyReader<SAXSource> { // Delay construction of factory private final Injectable<SAXParserFactory> spf; @@ -111,10 +115,10 @@ public boolean isReadable(Class<?> t, Type gt, Annotation[] as, MediaType mediaT } public SAXSource readFrom( - Class<SAXSource> t, - Type gt, - Annotation[] as, - MediaType mediaType, + Class<SAXSource> t, + Type gt, + Annotation[] as, + MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException { try { @@ -129,27 +133,27 @@ public SAXSource readFrom( } } } - + @Produces({"application/xml", "text/xml", "*/*"}) @Consumes({"application/xml", "text/xml", "*/*"}) - public static final class DOMSourceReader implements + public static final class DOMSourceReader implements MessageBodyReader<DOMSource> { // Delay construction of factory private final Injectable<DocumentBuilderFactory> dbf; - + public DOMSourceReader(@Context Injectable<DocumentBuilderFactory> dbf) { this.dbf = dbf; } - + public boolean isReadable(Class<?> t, Type gt, Annotation[] as, MediaType mediaType) { return DOMSource.class == t; } public DOMSource readFrom( - Class<DOMSource> t, - Type gt, - Annotation[] as, - MediaType mediaType, + Class<DOMSource> t, + Type gt, + Annotation[] as, + MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException { try { @@ -164,24 +168,24 @@ public DOMSource readFrom( } } } - + @Produces({"application/xml", "text/xml", "*/*"}) @Consumes({"application/xml", "text/xml", "*/*"}) - public static final class SourceWriter implements + public static final class SourceWriter implements MessageBodyWriter<Source> { // Delay construction of factory private final Injectable<SAXParserFactory> spf; - + // Delay construction of factory private final Injectable<TransformerFactory> tf; - + public SourceWriter(@Context Injectable<SAXParserFactory> spf, @Context Injectable<TransformerFactory> tf) { this.spf = spf; this.tf = tf; } - + public boolean isWriteable(Class<?> t, Type gt, Annotation[] as, MediaType mediaType) { return Source.class.isAssignableFrom(t); } @@ -190,8 +194,8 @@ public long getSize(Source o, Class<?> type, Type genericType, Annotation[] anno return -1; } - public void writeTo(Source o, Class<?> t, Type gt, Annotation[] as, - MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, + public void writeTo(Source o, Class<?> t, Type gt, Annotation[] as, + MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException { try { @@ -209,6 +213,6 @@ public void writeTo(Source o, Class<?> t, Type gt, Annotation[] as, } catch (TransformerException ex) { throw new WebApplicationException(ex, Status.INTERNAL_SERVER_ERROR); } - } + } } -} \ No newline at end of file +}
jersey-core/src/main/java/com/sun/jersey/core/impl/provider/xml/SAXParserContextProvider.java+9 −30 modified@@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright (c) 2010-2011 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010-2012 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development @@ -40,53 +40,32 @@ package com.sun.jersey.core.impl.provider.xml; -import com.sun.jersey.core.util.FeaturesAndProperties; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.ws.rs.core.Context; -import javax.xml.XMLConstants; + import javax.xml.parsers.SAXParserFactory; +import com.sun.jersey.core.util.FeaturesAndProperties; + /** * - * @author Paul.Sandoz@Sun.Com + * @author Paul Sandoz (paul.sandoz at oracle.com) + * @author Martin Matula (martin.matula at oracle.com) */ public class SAXParserContextProvider extends ThreadLocalSingletonContextProvider<SAXParserFactory> { - private static final Logger LOGGER = Logger.getLogger( - SAXParserContextProvider.class.getName()); - private final boolean disableXmlSecurity; - + public SAXParserContextProvider(@Context FeaturesAndProperties fps) { super(SAXParserFactory.class); - disableXmlSecurity = fps.getFeature(FeaturesAndProperties.FEATURE_DISABLE_XML_SECURITY); } @Override protected SAXParserFactory getInstance() { SAXParserFactory f = SAXParserFactory.newInstance(); - f.setNamespaceAware(true); - if (!disableXmlSecurity) { - try { - f.setFeature("http://xml.org/sax/features/external-general-entities", Boolean.FALSE); - } catch (Exception ex) { - throw new RuntimeException("Security features for the SAX parser could not be enabled", ex); - } - - try { - f.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE); - } catch (Exception ex) { - LOGGER.log(Level.WARNING, - "JAXP feature XMLConstants.FEATURE_SECURE_PROCESSING cannot be set on a SAXParserFactory. " + - "External general entity processing is disabled but other potential security related" + - " features will not be enabled.", - ex); - } + f = new SecureSAXParserFactory(f); } - return f; } -} \ No newline at end of file +}
jersey-core/src/main/java/com/sun/jersey/core/impl/provider/xml/SecureSAXParserFactory.java+262 −0 added@@ -0,0 +1,262 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * http://glassfish.java.net/public/CDDL+GPL_1_1.html + * or packager/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at packager/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * Oracle designates this particular file as subject to the "Classpath" + * exception as provided by Oracle in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ + +/* + * Portions contributed by Joseph Walton (Atlassian) + */ + +package com.sun.jersey.core.impl.provider.xml; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.xml.XMLConstants; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.validation.Schema; + +import org.xml.sax.EntityResolver; +import org.xml.sax.HandlerBase; +import org.xml.sax.InputSource; +import org.xml.sax.Parser; +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.DefaultHandler; + +/** +* @author Martin Matula (martin.matula at oracle.com) +*/ +final class SecureSAXParserFactory extends SAXParserFactory { + private static final Logger LOGGER = Logger.getLogger(SecureSAXParserFactory.class.getName()); + private static final EntityResolver EMPTY_ENTITY_RESOLVER = new EntityResolver() { + public InputSource resolveEntity(String publicId, String systemId) { + return new InputSource(new ByteArrayInputStream(new byte[0])); + } + }; + + private final SAXParserFactory spf; + + SecureSAXParserFactory(SAXParserFactory spf) { + this.spf = spf; + try { + spf.setFeature("http://xml.org/sax/features/external-general-entities", Boolean.FALSE); + spf.setFeature("http://xml.org/sax/features/external-parameter-entities", Boolean.FALSE); + } catch (Exception ex) { + throw new RuntimeException("Security features for the SAX parser could not be enabled", ex); + } + + try { + spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE); + } catch (Exception ex) { + LOGGER.log(Level.WARNING, + "JAXP feature XMLConstants.FEATURE_SECURE_PROCESSING cannot be set on a SAXParserFactory. " + + "External general entity processing is disabled but other potential security related" + + " features will not be enabled.", + ex); + } + } + + @Override + public void setNamespaceAware(boolean b) { + spf.setNamespaceAware(b); + } + + @Override + public void setValidating(boolean b) { + spf.setValidating(b); + } + + @Override + public boolean isNamespaceAware() { + return spf.isNamespaceAware(); + } + + @Override + public boolean isValidating() { + return spf.isValidating(); + } + + @Override + public Schema getSchema() { + return spf.getSchema(); + } + + @Override + public void setSchema(Schema schema) { + spf.setSchema(schema); + } + + @Override + public void setXIncludeAware(boolean b) { + spf.setXIncludeAware(b); + } + + @Override + public boolean isXIncludeAware() { + return spf.isXIncludeAware(); + } + + @Override + public SAXParser newSAXParser() throws ParserConfigurationException, SAXException { + return new WrappingSAXParser(spf.newSAXParser()); + } + + @Override + public void setFeature(String s, boolean b) throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException { + spf.setFeature(s, b); + } + + @Override + public boolean getFeature(String s) throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException { + return spf.getFeature(s); + } + + private static final class WrappingSAXParser extends SAXParser { + private final SAXParser sp; + + protected WrappingSAXParser(SAXParser sp) { + this.sp = sp; + } + + @Override + public void reset() { + sp.reset(); + } + + @Override + public void parse(InputStream inputStream, HandlerBase handlerBase) throws SAXException, IOException { + sp.parse(inputStream, handlerBase); + } + + @Override + public void parse(InputStream inputStream, HandlerBase handlerBase, String s) throws SAXException, IOException { + sp.parse(inputStream, handlerBase, s); + } + + @Override + public void parse(InputStream inputStream, DefaultHandler defaultHandler) throws SAXException, IOException { + sp.parse(inputStream, defaultHandler); + } + + @Override + public void parse(InputStream inputStream, DefaultHandler defaultHandler, String s) throws SAXException, IOException { + sp.parse(inputStream, defaultHandler, s); + } + + @Override + public void parse(String s, HandlerBase handlerBase) throws SAXException, IOException { + sp.parse(s, handlerBase); + } + + @Override + public void parse(String s, DefaultHandler defaultHandler) throws SAXException, IOException { + sp.parse(s, defaultHandler); + } + + @Override + public void parse(File file, HandlerBase handlerBase) throws SAXException, IOException { + sp.parse(file, handlerBase); + } + + @Override + public void parse(File file, DefaultHandler defaultHandler) throws SAXException, IOException { + sp.parse(file, defaultHandler); + } + + @Override + public void parse(InputSource inputSource, HandlerBase handlerBase) throws SAXException, IOException { + sp.parse(inputSource, handlerBase); + } + + @Override + public void parse(InputSource inputSource, DefaultHandler defaultHandler) throws SAXException, IOException { + sp.parse(inputSource, defaultHandler); + } + + @Override + public Parser getParser() throws SAXException { + return sp.getParser(); + } + + @Override + public XMLReader getXMLReader() throws SAXException { + XMLReader r = sp.getXMLReader(); + r.setEntityResolver(EMPTY_ENTITY_RESOLVER); + return r; + } + + @Override + public boolean isNamespaceAware() { + return sp.isNamespaceAware(); + } + + @Override + public boolean isValidating() { + return sp.isValidating(); + } + + @Override + public void setProperty(String s, Object o) throws SAXNotRecognizedException, SAXNotSupportedException { + sp.setProperty(s, o); + } + + @Override + public Object getProperty(String s) throws SAXNotRecognizedException, SAXNotSupportedException { + return sp.getProperty(s); + } + + @Override + public Schema getSchema() { + return sp.getSchema(); + } + + @Override + public boolean isXIncludeAware() { + return sp.isXIncludeAware(); + } + } +}
jersey-core/src/main/java/com/sun/jersey/core/provider/jaxb/AbstractJAXBProvider.java+39 −36 modified@@ -40,63 +40,66 @@ package com.sun.jersey.core.provider.jaxb; -import com.sun.jersey.api.provider.jaxb.XmlHeader; -import com.sun.jersey.core.provider.AbstractMessageReaderWriterProvider; -import com.sun.jersey.core.util.FeaturesAndProperties; -import javax.xml.bind.PropertyException; +import java.io.InputStream; +import java.lang.annotation.Annotation; +import java.util.Map; +import java.util.WeakHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; + import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.ext.ContextResolver; import javax.ws.rs.ext.Providers; + import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; +import javax.xml.bind.PropertyException; import javax.xml.bind.Unmarshaller; import javax.xml.parsers.SAXParserFactory; import javax.xml.transform.sax.SAXSource; -import java.io.InputStream; -import java.lang.annotation.Annotation; -import java.util.Map; -import java.util.WeakHashMap; -import java.util.logging.Level; -import java.util.logging.Logger; + import org.xml.sax.InputSource; +import com.sun.jersey.api.provider.jaxb.XmlHeader; +import com.sun.jersey.core.provider.AbstractMessageReaderWriterProvider; +import com.sun.jersey.core.util.FeaturesAndProperties; + /** * A base class for implementing JAXB-based readers and writers. - * - * @author Paul.Sandoz@Sun.Com + * + * @author Paul Sandoz (paul.sandoz at oracle.com) */ -public abstract class AbstractJAXBProvider<T> extends AbstractMessageReaderWriterProvider<T> { - private static final Map<Class, JAXBContext> jaxbContexts = +public abstract class AbstractJAXBProvider<T> extends AbstractMessageReaderWriterProvider<T> { + private static final Map<Class, JAXBContext> jaxbContexts = new WeakHashMap<Class, JAXBContext>(); private final Providers ps; - + private final boolean fixedMediaType; - + private final ContextResolver<JAXBContext> mtContext; private final ContextResolver<Unmarshaller> mtUnmarshaller; - + private final ContextResolver<Marshaller> mtMarshaller; private boolean formattedOutput = false; - private boolean xmlRootElementProcessing = false; public AbstractJAXBProvider(Providers ps) { this(ps, null); } - + public AbstractJAXBProvider(Providers ps, MediaType mt) { this.ps = ps; - + fixedMediaType = mt != null; if (fixedMediaType) { this.mtContext = ps.getContextResolver(JAXBContext.class, mt); this.mtUnmarshaller = ps.getContextResolver(Unmarshaller.class, mt); - this.mtMarshaller = ps.getContextResolver(Marshaller.class, mt); + this.mtMarshaller = ps.getContextResolver(Marshaller.class, mt); } else { this.mtContext = null; this.mtUnmarshaller = null; @@ -113,34 +116,34 @@ public void setConfiguration(FeaturesAndProperties fp) { protected boolean isSupported(MediaType m) { return true; } - + protected final Unmarshaller getUnmarshaller(Class type, MediaType mt) throws JAXBException { if (fixedMediaType) return getUnmarshaller(type); - - final ContextResolver<Unmarshaller> uncr = ps.getContextResolver(Unmarshaller.class, mt); + + final ContextResolver<Unmarshaller> uncr = ps.getContextResolver(Unmarshaller.class, mt); if (uncr != null) { Unmarshaller u = uncr.getContext(type); if (u != null) return u; } return getJAXBContext(type, mt).createUnmarshaller(); } - + private Unmarshaller getUnmarshaller(Class type) throws JAXBException { if (mtUnmarshaller != null) { Unmarshaller u = mtUnmarshaller.getContext(type); if (u != null) return u; } - + return getJAXBContext(type).createUnmarshaller(); } - + protected final Marshaller getMarshaller(Class type, MediaType mt) throws JAXBException { if (fixedMediaType) return getMarshaller(type); - - final ContextResolver<Marshaller> mcr = ps.getContextResolver(Marshaller.class, mt); + + final ContextResolver<Marshaller> mcr = ps.getContextResolver(Marshaller.class, mt); if (mcr != null) { Marshaller m = mcr.getContext(type); if (m != null) return m; @@ -152,7 +155,7 @@ protected final Marshaller getMarshaller(Class type, MediaType mt) throws JAXBEx return m; } - + private Marshaller getMarshaller(Class type) throws JAXBException { if (mtMarshaller != null) { Marshaller u = mtMarshaller.getContext(type); @@ -164,7 +167,7 @@ private Marshaller getMarshaller(Class type) throws JAXBException { m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, formattedOutput); return m; } - + private JAXBContext getJAXBContext(Class type, MediaType mt) throws JAXBException { final ContextResolver<JAXBContext> cr = ps.getContextResolver(JAXBContext.class, mt); if (cr != null) { @@ -180,10 +183,10 @@ private JAXBContext getJAXBContext(Class type) throws JAXBException { JAXBContext c = mtContext.getContext(type); if (c != null) return c; } - + return getStoredJAXBContext(type); } - + protected JAXBContext getStoredJAXBContext(Class type) throws JAXBException { synchronized (jaxbContexts) { JAXBContext c = jaxbContexts.get(type); @@ -192,9 +195,9 @@ protected JAXBContext getStoredJAXBContext(Class type) throws JAXBException { jaxbContexts.put(type, c); } return c; - } + } } - + protected static SAXSource getSAXSource(SAXParserFactory spf, InputStream entityStream) throws JAXBException { try { @@ -234,4 +237,4 @@ protected void setHeader(Marshaller m, Annotation[] annotations) throws Property } } } -} \ No newline at end of file +}
jersey-core/src/test/java/com/sun/jersey/core/impl/provider/entity/SourceProviderTest.java+76 −0 added@@ -0,0 +1,76 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * http://glassfish.java.net/public/CDDL+GPL_1_1.html + * or packager/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at packager/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * Oracle designates this particular file as subject to the "Classpath" + * exception as provided by Oracle in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ + +/* + * Portions contributed by Joseph Walton (Atlassian) + */ + +package com.sun.jersey.core.impl.provider.entity; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; + +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXSource; +import javax.xml.transform.stream.StreamResult; + +import org.junit.Test; + +import com.sun.jersey.core.impl.provider.xml.SAXParserContextProviderTest; +import com.sun.jersey.spi.inject.Injectable; + +public class SourceProviderTest { + @Test + public void saxSourceReaderDoesNotReadExternalDtds() throws Exception { + Injectable<SAXParserFactory> spf = new Injectable<SAXParserFactory>() { + @Override + public SAXParserFactory getValue() { + return SAXParserContextProviderTest.createSAXParserFactory(); + } + }; + SourceProvider.SAXSourceReader reader = new SourceProvider.SAXSourceReader(spf); + InputStream entityStream = new ByteArrayInputStream("<!DOCTYPE x SYSTEM 'file:///no-such-file'> <rootObject/>".getBytes("us-ascii")); + SAXSource ss = reader.readFrom(null, null, null, null, null, entityStream); + + TransformerFactory.newInstance().newTransformer().transform(ss, new StreamResult(new ByteArrayOutputStream())); + } +}
jersey-core/src/test/java/com/sun/jersey/core/impl/provider/xml/SAXParserContextProviderTest.java+98 −0 added@@ -0,0 +1,98 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * http://glassfish.java.net/public/CDDL+GPL_1_1.html + * or packager/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at packager/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * Oracle designates this particular file as subject to the "Classpath" + * exception as provided by Oracle in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ + +/* + * Portions contributed by Joseph Walton (Atlassian) + */ + +package com.sun.jersey.core.impl.provider.xml; + +import java.io.ByteArrayInputStream; +import java.util.Collections; +import java.util.Map; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.junit.Test; +import org.xml.sax.InputSource; + +import com.sun.jersey.core.util.FeaturesAndProperties; + +public class SAXParserContextProviderTest { + private static final FeaturesAndProperties EMPTY_FEATURES_AND_PROPERTIES = new FeaturesAndProperties() { + @Override + public Object getProperty(String propertyName) { + return null; + } + + @Override + public Map<String, Object> getProperties() { + return Collections.emptyMap(); + } + + @Override + public Map<String, Boolean> getFeatures() { + return Collections.emptyMap(); + } + + @Override + public boolean getFeature(String featureName) { + return false; + } + }; + + public static SAXParserFactory createSAXParserFactory() { + SAXParserContextProvider provider = new SAXParserContextProvider(EMPTY_FEATURES_AND_PROPERTIES); + return provider.getInstance(); + } + + @Test + public void xmlReaderDoesNotResolveExternalParameterEntities() throws Exception { + + SAXParser sp = createSAXParserFactory().newSAXParser(); + + String url = "file:///no-such-file"; + + String content = "<!DOCTYPE x [<!ENTITY % pe SYSTEM '" + url + "'> %pe;]><x/>"; + + sp.getXMLReader().parse(new InputSource(new ByteArrayInputStream(content.getBytes("us-ascii")))); + } +}
jersey-core/src/test/java/com/sun/jersey/core/provider/jaxb/AbstractJAXBProviderTest.java+70 −0 added@@ -0,0 +1,70 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * http://glassfish.java.net/public/CDDL+GPL_1_1.html + * or packager/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at packager/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * Oracle designates this particular file as subject to the "Classpath" + * exception as provided by Oracle in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ + +/* + * Portions contributed by Joseph Walton (Atlassian) + */ + +package com.sun.jersey.core.provider.jaxb; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXSource; +import javax.xml.transform.stream.StreamResult; + +import org.junit.Test; + +import com.sun.jersey.core.impl.provider.xml.SAXParserContextProviderTest; + +public class AbstractJAXBProviderTest { + @Test + public void abstractJaxbProviderDoesNotReadExternalDtds() throws Exception { + SAXParserFactory spf = SAXParserContextProviderTest.createSAXParserFactory(); + + String url = "file:///no-such-file"; + String s = "<!DOCTYPE x SYSTEM '" + url + "'><x/>"; + SAXSource saxSource = AbstractJAXBProvider.getSAXSource(spf, new ByteArrayInputStream(s.getBytes("us-ascii"))); + + TransformerFactory.newInstance().newTransformer().transform(saxSource, new StreamResult(new ByteArrayOutputStream())); + } +}
jersey-server/src/main/java/com/sun/jersey/server/impl/model/parameter/multivalued/JAXBStringReaderProviders.java+11 −12 modified@@ -39,18 +39,15 @@ */ package com.sun.jersey.server.impl.model.parameter.multivalued; -import com.sun.jersey.api.container.ContainerException; -import com.sun.jersey.impl.ImplMessages; -import com.sun.jersey.spi.StringReader; -import com.sun.jersey.spi.StringReaderProvider; -import com.sun.jersey.spi.inject.Injectable; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.Map; import java.util.WeakHashMap; + import javax.ws.rs.core.Context; import javax.ws.rs.ext.ContextResolver; import javax.ws.rs.ext.Providers; + import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.UnmarshalException; @@ -59,27 +56,29 @@ import javax.xml.bind.annotation.XmlType; import javax.xml.parsers.SAXParserFactory; import javax.xml.transform.sax.SAXSource; -import javax.xml.transform.stream.StreamSource; + import org.xml.sax.InputSource; +import com.sun.jersey.api.container.ContainerException; +import com.sun.jersey.impl.ImplMessages; +import com.sun.jersey.spi.StringReader; +import com.sun.jersey.spi.StringReaderProvider; +import com.sun.jersey.spi.inject.Injectable; + /** * - * @author Paul.Sandoz@Sun.Com + * @author Paul Sandoz (paul.sandoz at oracle.com) */ public class JAXBStringReaderProviders { private static final Map<Class, JAXBContext> jaxbContexts = new WeakHashMap<Class, JAXBContext>(); - private final Providers ps; - private final ContextResolver<JAXBContext> context; private final ContextResolver<Unmarshaller> unmarshaller; public JAXBStringReaderProviders(Providers ps) { - this.ps = ps; - this.context = ps.getContextResolver(JAXBContext.class, null); this.unmarshaller = ps.getContextResolver(Unmarshaller.class, null); } @@ -158,4 +157,4 @@ public Object fromString(String value) { }; } } -} \ No newline at end of file +}
jersey-server/src/test/java/com/sun/jersey/server/impl/model/parameter/multivalued/JAXBStringReaderProvidersTest.java+101 −0 added@@ -0,0 +1,101 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * http://glassfish.java.net/public/CDDL+GPL_1_1.html + * or packager/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at packager/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * Oracle designates this particular file as subject to the "Classpath" + * exception as provided by Oracle in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ + +/* + * Portions contributed by Joseph Walton (Atlassian) + */ + +package com.sun.jersey.server.impl.model.parameter.multivalued; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.ext.ContextResolver; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.MessageBodyReader; +import javax.ws.rs.ext.MessageBodyWriter; +import javax.ws.rs.ext.Providers; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.parsers.SAXParserFactory; + +import org.junit.Test; + +import com.sun.jersey.api.core.DefaultResourceConfig; +import com.sun.jersey.core.impl.provider.xml.SAXParserContextProvider; +import com.sun.jersey.spi.inject.Injectable; + +public class JAXBStringReaderProvidersTest { + @Test + public void stringReaderDoesNotReadExternalDtds() { + Injectable<SAXParserFactory> spf = new SAXParserContextProvider(new DefaultResourceConfig()).getInjectable(null, null, SAXParserFactory.class); + + JAXBStringReaderProviders.RootElementProvider provider = new JAXBStringReaderProviders.RootElementProvider(spf, new Providers() { + @Override + public <T> MessageBodyReader<T> getMessageBodyReader(Class<T> type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return null; + } + + @Override + public <T> MessageBodyWriter<T> getMessageBodyWriter(Class<T> type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return null; + } + + @Override + public <T extends Throwable> ExceptionMapper<T> getExceptionMapper(Class<T> type) { + return null; + } + + @Override + public <T> ContextResolver<T> getContextResolver(Class<T> contextType, MediaType mediaType) { + return null; + } + }); + + String content = "<!DOCTYPE x SYSTEM 'file:///no-such-file'> <rootObject/>"; + + provider.getStringReader(RootObject.class, null, null).fromString(content); + } + + @XmlRootElement + static class RootObject { + } +}
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
7- access.redhat.com/security/cve/cve-2014-3643ghsavendor-advisoryx_refsource_REDHATWEB
- github.com/advisories/GHSA-5m48-vr54-vmh3ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2014-3643ghsaADVISORY
- bugzilla.redhat.com/show_bug.cgighsax_refsource_MISCWEB
- github.com/javaee/jersey-1.x/commit/49f1e5a6ac608ccb51939205e4739f328f2223e6ghsaWEB
- www.oracle.com/security-alerts/cpujul2022.htmlghsax_refsource_MISCWEB
- www.sourceclear.com/vulnerability-database/security/xml-external-entity-xxe/java/sid-22175ghsaWEB
News mentions
0No linked articles in our index yet.