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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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 * @since 1.1
* @see #doExecuteRequest * @see #doExecuteRequest
*/ */
public abstract class AbstractHttpInvokerRequestExecutor public abstract class AbstractHttpInvokerRequestExecutor implements HttpInvokerRequestExecutor, BeanClassLoaderAware {
implements HttpInvokerRequestExecutor, BeanClassLoaderAware {
/** /**
* Default content type: "application/x-java-serialized-object" * Default content type: "application/x-java-serialized-object"
*/ */
public static final String CONTENT_TYPE_SERIALIZED_OBJECT = "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"; protected static final String HTTP_METHOD_POST = "POST";
@ -67,9 +68,6 @@ public abstract class AbstractHttpInvokerRequestExecutor
protected static final String ENCODING_GZIP = "gzip"; 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()); protected final Log logger = LogFactory.getLog(getClass());
private String contentType = CONTENT_TYPE_SERIALIZED_OBJECT; 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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 * a security context). Furthermore, it allows to customize request
* execution via the {@link HttpInvokerRequestExecutor} strategy. * execution via the {@link HttpInvokerRequestExecutor} strategy.
* *
* <p>Can use the JDK's {@link java.rmi.server.RMIClassLoader} to load * <p>Can use the JDK's {@link java.rmi.server.RMIClassLoader} to load classes
* classes from a given {@link #setCodebaseUrl codebase}, performing * from a given {@link #setCodebaseUrl codebase}, performing on-demand dynamic
* on-demand dynamic code download from a remote location. The codebase * code download from a remote location. The codebase can consist of multiple
* can consist of multiple URLs, separated by spaces. Note that * URLs, separated by spaces. Note that RMIClassLoader requires a SecurityManager
* RMIClassLoader requires a SecurityManager to be set, analogous to * to be set, analogous to when using dynamic class download with standard RMI!
* when using dynamic class download with standard RMI!
* (See the RMI documentation for details.) * (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 * @author Juergen Hoeller
* @since 1.1 * @since 1.1
* @see #setServiceUrl * @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 * Manipulated input streams could lead to unwanted code execution on the server
* during the deserialization step. As a consequence, do not expose HTTP invoker * during the deserialization step. As a consequence, do not expose HTTP invoker
* endpoints to untrusted clients but rather just between your own services.</b> * 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 * @author Juergen Hoeller
* @since 1.1 * @since 1.1
@ -51,8 +52,7 @@ import org.springframework.beans.factory.FactoryBean;
* @see org.springframework.remoting.rmi.RmiProxyFactoryBean * @see org.springframework.remoting.rmi.RmiProxyFactoryBean
* @see org.springframework.remoting.caucho.HessianProxyFactoryBean * @see org.springframework.remoting.caucho.HessianProxyFactoryBean
*/ */
public class HttpInvokerProxyFactoryBean extends HttpInvokerClientInterceptor public class HttpInvokerProxyFactoryBean extends HttpInvokerClientInterceptor implements FactoryBean<Object> {
implements FactoryBean<Object> {
private Object serviceProxy; 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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 * Manipulated input streams could lead to unwanted code execution on the server
* during the deserialization step. As a consequence, do not expose HTTP invoker * during the deserialization step. As a consequence, do not expose HTTP invoker
* endpoints to untrusted clients but rather just between your own services.</b> * 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 * @author Juergen Hoeller
* @since 1.1 * @since 1.1
@ -60,8 +61,7 @@ import org.springframework.web.util.NestedServletException;
* @see org.springframework.remoting.rmi.RmiServiceExporter * @see org.springframework.remoting.rmi.RmiServiceExporter
* @see org.springframework.remoting.caucho.HessianServiceExporter * @see org.springframework.remoting.caucho.HessianServiceExporter
*/ */
public class HttpInvokerServiceExporter extends RemoteInvocationSerializingExporter public class HttpInvokerServiceExporter extends RemoteInvocationSerializingExporter implements HttpRequestHandler {
implements HttpRequestHandler {
/** /**
* Reads a remote invocation from the request, executes it, * 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. * Read a RemoteInvocation from the given HTTP request.
* <p>Delegates to * <p>Delegates to {@link #readRemoteInvocation(HttpServletRequest, InputStream)} with
* {@link #readRemoteInvocation(javax.servlet.http.HttpServletRequest, java.io.InputStream)} * the {@link HttpServletRequest#getInputStream() servlet request's input stream}.
* with the
* {@link javax.servlet.ServletRequest#getInputStream() servlet request's input stream}.
* @param request current HTTP request * @param request current HTTP request
* @return the RemoteInvocation object * @return the RemoteInvocation object
* @throws IOException in case of I/O failure * @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, * Decorate an {@code OutputStream} to guard against {@code flush()} calls,
* which are turned into no-ops. * which are turned into no-ops.
*
* <p>Because {@link ObjectOutputStream#close()} will in fact flush/drain * <p>Because {@link ObjectOutputStream#close()} will in fact flush/drain
* the underlying stream twice, this {@link FilterOutputStream} will * the underlying stream twice, this {@link FilterOutputStream} will
* guard against individual flush calls. Multiple flush calls can lead * guard against individual flush calls. Multiple flush calls can lead
* to performance issues, since writes aren't gathered as they should be. * 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> * @see <a href="https://jira.spring.io/browse/SPR-14040">SPR-14040</a>
*/ */
private static class FlushGuardedOutputStream extends FilterOutputStream { 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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, * being tied to Java. Nevertheless, it is as easy to set up as Hessian,
* which is its main advantage compared to RMI. * 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 * @author Juergen Hoeller
* @since 2.5.1 * @since 2.5.1
* @see org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor * @see org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor
@ -52,15 +58,14 @@ import org.springframework.remoting.support.RemoteInvocationResult;
* @see org.springframework.remoting.caucho.SimpleHessianServiceExporter * @see org.springframework.remoting.caucho.SimpleHessianServiceExporter
*/ */
@UsesSunHttpServer @UsesSunHttpServer
public class SimpleHttpInvokerServiceExporter extends RemoteInvocationSerializingExporter public class SimpleHttpInvokerServiceExporter extends RemoteInvocationSerializingExporter implements HttpHandler {
implements HttpHandler {
/** /**
* Reads a remote invocation from the request, executes it, * Reads a remote invocation from the request, executes it,
* and writes the remote invocation result to the response. * and writes the remote invocation result to the response.
* @see #readRemoteInvocation(com.sun.net.httpserver.HttpExchange) * @see #readRemoteInvocation(HttpExchange)
* @see #invokeAndCreateResult(org.springframework.remoting.support.RemoteInvocation, Object) * @see #invokeAndCreateResult(RemoteInvocation, Object)
* @see #writeRemoteInvocationResult(com.sun.net.httpserver.HttpExchange, org.springframework.remoting.support.RemoteInvocationResult) * @see #writeRemoteInvocationResult(HttpExchange, RemoteInvocationResult)
*/ */
@Override @Override
public void handle(HttpExchange exchange) throws IOException { public void handle(HttpExchange exchange) throws IOException {
@ -78,10 +83,8 @@ public class SimpleHttpInvokerServiceExporter extends RemoteInvocationSerializin
/** /**
* Read a RemoteInvocation from the given HTTP request. * Read a RemoteInvocation from the given HTTP request.
* <p>Delegates to * <p>Delegates to {@link #readRemoteInvocation(HttpExchange, InputStream)}
* {@link #readRemoteInvocation(com.sun.net.httpserver.HttpExchange, java.io.InputStream)} * with the {@link HttpExchange#getRequestBody()} request's input stream}.
* with the
* {@link com.sun.net.httpserver.HttpExchange#getRequestBody()} request's input stream}.
* @param exchange current HTTP request/response * @param exchange current HTTP request/response
* @return the RemoteInvocation object * @return the RemoteInvocation object
* @throws java.io.IOException in case of I/O failure * @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] [WARNING]
==== ====
By default, XStream allows for arbitrary classes to be unmarshalled, which can lead to
By default, XStream allows for arbitrary classes to be unmarshalled, which can result in unsafe Java serialization effects. As such, it is __not recommended to use the
security vulnerabilities. As such, it is __not recommended to use the
`XStreamMarshaller` to unmarshal XML from external sources__ (i.e. the Web), as this can `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 result in __security vulnerabilities__.
unmarshal XML from an external source, set the `supportedClasses` property on the
`XStreamMarshaller`, like so: 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] [source,xml,indent=0]
[subs="verbatim,quotes"] [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/] http://hc.apache.org/httpcomponents-client-ga/[hc.apache.org/httpcomponents-client-ga/]
for more information. 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]] [[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 listeners can then interact with the server-hosted `ResourceAdapter`, also using the
server's built-in `WorkManager`. server's built-in `WorkManager`.
Please consult the JavaDoc for `JmsMessageEndpointManager`, `JmsActivationSpecConfig`, Please consult the javadoc for `JmsMessageEndpointManager`, `JmsActivationSpecConfig`,
and `ResourceAdapterFactoryBean` for more details. and `ResourceAdapterFactoryBean` for more details.
Spring also provides a generic JCA message endpoint manager which is not tied to JMS: 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 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 provider-specific ActivationSpec object. Check out your JCA provider's documentation to
find out about the actual capabilities of your connector, and consult 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] [NOTE]
==== ====
@ -5966,7 +5981,6 @@ along with an inline image.
[WARNING] [WARNING]
==== ====
Inline resources are added to the mime message using the specified `Content-ID` ( 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 `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 the resource are __very__ important. Be sure to __first add the text__ and after that