Up-to-date guidelines for serialization-based endpoints

Issue: SPR-15317
This commit is contained in:
Juergen Hoeller 2017-03-24 11:09:57 +01:00
parent b90d3d0e88
commit 2236262fc6
7 changed files with 59 additions and 43 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2017 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.
@ -43,14 +43,15 @@ import org.springframework.util.Assert;
* @since 1.1
* @see #doExecuteRequest
*/
public abstract class AbstractHttpInvokerRequestExecutor
implements HttpInvokerRequestExecutor, BeanClassLoaderAware {
public abstract class AbstractHttpInvokerRequestExecutor implements HttpInvokerRequestExecutor, BeanClassLoaderAware {
/**
* Default content type: "application/x-java-serialized-object"
*/
public static final String CONTENT_TYPE_SERIALIZED_OBJECT = "application/x-java-serialized-object";
private static final int SERIALIZED_INVOCATION_BYTE_ARRAY_INITIAL_SIZE = 1024;
protected static final String HTTP_METHOD_POST = "POST";
@ -67,9 +68,6 @@ public abstract class AbstractHttpInvokerRequestExecutor
protected static final String ENCODING_GZIP = "gzip";
private static final int SERIALIZED_INVOCATION_BYTE_ARRAY_INITIAL_SIZE = 1024;
protected final Log logger = LogFactory.getLog(getClass());
private String contentType = CONTENT_TYPE_SERIALIZED_OBJECT;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
@ -46,14 +46,19 @@ import org.springframework.remoting.support.RemoteInvocationResult;
* a security context). Furthermore, it allows to customize request
* execution via the {@link HttpInvokerRequestExecutor} strategy.
*
* <p>Can use the JDK's {@link java.rmi.server.RMIClassLoader} to load
* classes from a given {@link #setCodebaseUrl codebase}, performing
* on-demand dynamic code download from a remote location. The codebase
* can consist of multiple URLs, separated by spaces. Note that
* RMIClassLoader requires a SecurityManager to be set, analogous to
* when using dynamic class download with standard RMI!
* <p>Can use the JDK's {@link java.rmi.server.RMIClassLoader} to load classes
* from a given {@link #setCodebaseUrl codebase}, performing on-demand dynamic
* code download from a remote location. The codebase can consist of multiple
* URLs, separated by spaces. Note that RMIClassLoader requires a SecurityManager
* to be set, analogous to when using dynamic class download with standard RMI!
* (See the RMI documentation for details.)
*
* <p><b>WARNING: Be aware of vulnerabilities due to unsafe Java deserialization:
* Manipulated input streams could lead to unwanted code execution on the server
* during the deserialization step. As a consequence, do not expose HTTP invoker
* endpoints to untrusted clients but rather just between your own services.</b>
* In general, we strongly recommend any other message format (e.g. JSON) instead.
*
* @author Juergen Hoeller
* @since 1.1
* @see #setServiceUrl

View File

@ -40,6 +40,7 @@ import org.springframework.beans.factory.FactoryBean;
* Manipulated input streams could lead to unwanted code execution on the server
* during the deserialization step. As a consequence, do not expose HTTP invoker
* endpoints to untrusted clients but rather just between your own services.</b>
* In general, we strongly recommend any other message format (e.g. JSON) instead.
*
* @author Juergen Hoeller
* @since 1.1
@ -51,8 +52,7 @@ import org.springframework.beans.factory.FactoryBean;
* @see org.springframework.remoting.rmi.RmiProxyFactoryBean
* @see org.springframework.remoting.caucho.HessianProxyFactoryBean
*/
public class HttpInvokerProxyFactoryBean extends HttpInvokerClientInterceptor
implements FactoryBean<Object> {
public class HttpInvokerProxyFactoryBean extends HttpInvokerClientInterceptor implements FactoryBean<Object> {
private Object serviceProxy;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
@ -52,6 +52,7 @@ import org.springframework.web.util.NestedServletException;
* Manipulated input streams could lead to unwanted code execution on the server
* during the deserialization step. As a consequence, do not expose HTTP invoker
* endpoints to untrusted clients but rather just between your own services.</b>
* In general, we strongly recommend any other message format (e.g. JSON) instead.
*
* @author Juergen Hoeller
* @since 1.1
@ -60,8 +61,7 @@ import org.springframework.web.util.NestedServletException;
* @see org.springframework.remoting.rmi.RmiServiceExporter
* @see org.springframework.remoting.caucho.HessianServiceExporter
*/
public class HttpInvokerServiceExporter extends RemoteInvocationSerializingExporter
implements HttpRequestHandler {
public class HttpInvokerServiceExporter extends RemoteInvocationSerializingExporter implements HttpRequestHandler {
/**
* Reads a remote invocation from the request, executes it,
@ -86,10 +86,8 @@ public class HttpInvokerServiceExporter extends RemoteInvocationSerializingExpor
/**
* Read a RemoteInvocation from the given HTTP request.
* <p>Delegates to
* {@link #readRemoteInvocation(javax.servlet.http.HttpServletRequest, java.io.InputStream)}
* with the
* {@link javax.servlet.ServletRequest#getInputStream() servlet request's input stream}.
* <p>Delegates to {@link #readRemoteInvocation(HttpServletRequest, InputStream)} with
* the {@link HttpServletRequest#getInputStream() servlet request's input stream}.
* @param request current HTTP request
* @return the RemoteInvocation object
* @throws IOException in case of I/O failure
@ -205,12 +203,10 @@ public class HttpInvokerServiceExporter extends RemoteInvocationSerializingExpor
/**
* Decorate an {@code OutputStream} to guard against {@code flush()} calls,
* which are turned into no-ops.
*
* <p>Because {@link ObjectOutputStream#close()} will in fact flush/drain
* the underlying stream twice, this {@link FilterOutputStream} will
* guard against individual flush calls. Multiple flush calls can lead
* to performance issues, since writes aren't gathered as they should be.
*
* @see <a href="https://jira.spring.io/browse/SPR-14040">SPR-14040</a>
*/
private static class FlushGuardedOutputStream extends FilterOutputStream {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
@ -45,6 +45,12 @@ import org.springframework.remoting.support.RemoteInvocationResult;
* being tied to Java. Nevertheless, it is as easy to set up as Hessian,
* which is its main advantage compared to RMI.
*
* <p><b>WARNING: Be aware of vulnerabilities due to unsafe Java deserialization:
* Manipulated input streams could lead to unwanted code execution on the server
* during the deserialization step. As a consequence, do not expose HTTP invoker
* endpoints to untrusted clients but rather just between your own services.</b>
* In general, we strongly recommend any other message format (e.g. JSON) instead.
*
* @author Juergen Hoeller
* @since 2.5.1
* @see org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor
@ -52,15 +58,14 @@ import org.springframework.remoting.support.RemoteInvocationResult;
* @see org.springframework.remoting.caucho.SimpleHessianServiceExporter
*/
@UsesSunHttpServer
public class SimpleHttpInvokerServiceExporter extends RemoteInvocationSerializingExporter
implements HttpHandler {
public class SimpleHttpInvokerServiceExporter extends RemoteInvocationSerializingExporter implements HttpHandler {
/**
* Reads a remote invocation from the request, executes it,
* and writes the remote invocation result to the response.
* @see #readRemoteInvocation(com.sun.net.httpserver.HttpExchange)
* @see #invokeAndCreateResult(org.springframework.remoting.support.RemoteInvocation, Object)
* @see #writeRemoteInvocationResult(com.sun.net.httpserver.HttpExchange, org.springframework.remoting.support.RemoteInvocationResult)
* @see #readRemoteInvocation(HttpExchange)
* @see #invokeAndCreateResult(RemoteInvocation, Object)
* @see #writeRemoteInvocationResult(HttpExchange, RemoteInvocationResult)
*/
@Override
public void handle(HttpExchange exchange) throws IOException {
@ -78,10 +83,8 @@ public class SimpleHttpInvokerServiceExporter extends RemoteInvocationSerializin
/**
* Read a RemoteInvocation from the given HTTP request.
* <p>Delegates to
* {@link #readRemoteInvocation(com.sun.net.httpserver.HttpExchange, java.io.InputStream)}
* with the
* {@link com.sun.net.httpserver.HttpExchange#getRequestBody()} request's input stream}.
* <p>Delegates to {@link #readRemoteInvocation(HttpExchange, InputStream)}
* with the {@link HttpExchange#getRequestBody()} request's input stream}.
* @param exchange current HTTP request/response
* @return the RemoteInvocation object
* @throws java.io.IOException in case of I/O failure

View File

@ -6651,13 +6651,13 @@ which consists of string aliases mapped to classes:
[WARNING]
====
By default, XStream allows for arbitrary classes to be unmarshalled, which can result in
security vulnerabilities. As such, it is __not recommended to use the
By default, XStream allows for arbitrary classes to be unmarshalled, which can lead to
unsafe Java serialization effects. As such, it is __not recommended to use the
`XStreamMarshaller` to unmarshal XML from external sources__ (i.e. the Web), as this can
result in __security vulnerabilities__. If you do use the `XStreamMarshaller` to
unmarshal XML from an external source, set the `supportedClasses` property on the
`XStreamMarshaller`, like so:
result in __security vulnerabilities__.
If you choose to use the `XStreamMarshaller` to unmarshal XML from an external source,
set the `supportedClasses` property on the `XStreamMarshaller`, like as follows:
[source,xml,indent=0]
[subs="verbatim,quotes"]

View File

@ -377,6 +377,21 @@ advanced and easier-to-use functionality. Refer to
http://hc.apache.org/httpcomponents-client-ga/[hc.apache.org/httpcomponents-client-ga/]
for more information.
[WARNING]
====
Be aware of vulnerabilities due to unsafe Java deserialization:
Manipulated input streams could lead to unwanted code execution on the server
during the deserialization step. As a consequence, do not expose HTTP invoker
endpoints to untrusted clients but rather just between your own services.
In general, we strongly recommend any other message format (e.g. JSON) instead.
If you are concerned about security vulnerabilities due to Java serialization,
consider the general-purpose serialization filter mechanism at the core JVM level,
originally developed for JDK 9 but backported to JDK 8, 7 and 6 in the meantime:
https://blogs.oracle.com/java-platform-group/entry/incoming_filter_serialization_data_a
http://openjdk.java.net/jeps/290
====
[[remoting-httpinvoker-server]]
@ -2499,7 +2514,7 @@ be obtained from JNDI instead (using `<jee:jndi-lookup>`). The Spring-based mess
listeners can then interact with the server-hosted `ResourceAdapter`, also using the
server's built-in `WorkManager`.
Please consult the JavaDoc for `JmsMessageEndpointManager`, `JmsActivationSpecConfig`,
Please consult the javadoc for `JmsMessageEndpointManager`, `JmsActivationSpecConfig`,
and `ResourceAdapterFactoryBean` for more details.
Spring also provides a generic JCA message endpoint manager which is not tied to JMS:
@ -2507,7 +2522,7 @@ Spring also provides a generic JCA message endpoint manager which is not tied to
for using any message listener type (e.g. a CCI MessageListener) and any
provider-specific ActivationSpec object. Check out your JCA provider's documentation to
find out about the actual capabilities of your connector, and consult
`GenericMessageEndpointManager`'s JavaDoc for the Spring-specific configuration details.
`GenericMessageEndpointManager`'s javadoc for the Spring-specific configuration details.
[NOTE]
====
@ -5966,7 +5981,6 @@ along with an inline image.
[WARNING]
====
Inline resources are added to the mime message using the specified `Content-ID` (
`identifier1234` in the above example). The order in which you are adding the text and
the resource are __very__ important. Be sure to __first add the text__ and after that