You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by co...@apache.org on 2020/03/18 07:50:09 UTC

[camel] branch camel-3.0.x updated: CAMEL-14711 - Disable RabbitMQ Java serialization by default (#3633)

This is an automated email from the ASF dual-hosted git repository.

coheigea pushed a commit to branch camel-3.0.x
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/camel-3.0.x by this push:
     new 26f7d74  CAMEL-14711 - Disable RabbitMQ Java serialization by default (#3633)
26f7d74 is described below

commit 26f7d74755c436513719147f6bafb6f06c655a97
Author: Colm O hEigeartaigh <co...@users.noreply.github.com>
AuthorDate: Mon Mar 16 18:50:52 2020 +0000

    CAMEL-14711 - Disable RabbitMQ Java serialization by default (#3633)
---
 .../src/main/docs/rabbitmq-component.adoc          |   3 +-
 .../camel/component/rabbitmq/RabbitMQEndpoint.java |  22 +++-
 .../rabbitmq/RabbitMQMessageConverter.java         |  10 +-
 .../rabbitmq/RabbitMQMessagePublisher.java         |   5 +-
 .../rabbitmq/reply/ReplyManagerSupport.java        |   4 +-
 .../component/rabbitmq/RabbitMQInOutIntTest.java   |  14 ++-
 .../dsl/RabbitMQEndpointBuilderFactory.java        | 120 +++++++++++++++++++++
 .../modules/ROOT/pages/rabbitmq-component.adoc     |   3 +-
 8 files changed, 161 insertions(+), 20 deletions(-)

diff --git a/components/camel-rabbitmq/src/main/docs/rabbitmq-component.adoc b/components/camel-rabbitmq/src/main/docs/rabbitmq-component.adoc
index 533b9a4..fa06b35 100644
--- a/components/camel-rabbitmq/src/main/docs/rabbitmq-component.adoc
+++ b/components/camel-rabbitmq/src/main/docs/rabbitmq-component.adoc
@@ -133,7 +133,7 @@ with the following path and query parameters:
 |===
 
 
-=== Query Parameters (59 parameters):
+=== Query Parameters (60 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
@@ -194,6 +194,7 @@ with the following path and query parameters:
 | *synchronous* (advanced) | Sets whether synchronous processing should be strictly used, or Camel is allowed to use asynchronous processing (if supported). | false | boolean
 | *topologyRecoveryEnabled* (advanced) | Enables connection topology recovery (should topology recovery be performed) |  | Boolean
 | *transferException* (advanced) | When true and an inOut Exchange failed on the consumer side send the caused Exception back in the response | false | boolean
+| *allowMessageBody Serialization* (allowMessageBodySerialization) | Whether to allow Java serialization of the message body or not. If this value is true, the message body will be serialized on the producer side using Java serialization, if no type converter can handle the message body. On the consumer side, it will deserialize the message body if this value is true and the message contains a CamelSerialize header. Setting this value to true may introduce a security vulnerability as it  [...]
 | *password* (security) | Password for authenticated access | guest | String
 | *sslProtocol* (security) | Enables SSL on connection, accepted value are true, TLS and 'SSLv3 |  | String
 | *trustManager* (security) | Configure SSL trust manager, SSL should be enabled for this option to be effective |  | TrustManager
diff --git a/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQEndpoint.java b/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQEndpoint.java
index 3f46fe2..396b496 100644
--- a/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQEndpoint.java
+++ b/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQEndpoint.java
@@ -166,7 +166,8 @@ public class RabbitMQEndpoint extends DefaultEndpoint implements AsyncEndpoint {
     private boolean guaranteedDeliveries;
     @UriParam(label = "producer")
     private boolean allowNullHeaders;
-    // camel-jms supports this setting but it is not currently configurable in camel-rabbitmq
+    @UriParam(label = "allowMessageBodySerialization", defaultValue = "false")
+    private boolean allowMessageBodySerialization;
     private boolean useMessageIDAsCorrelationID = true;
     // camel-jms supports this setting but it is not currently configurable in camel-rabbitmq
     private String replyToType = ReplyToType.Temporary.name();
@@ -191,7 +192,7 @@ public class RabbitMQEndpoint extends DefaultEndpoint implements AsyncEndpoint {
 
     public Exchange createRabbitExchange(Envelope envelope, AMQP.BasicProperties properties, byte[] body) {
         Exchange exchange = super.createExchange();
-        messageConverter.populateRabbitExchange(exchange, envelope, properties, body, false);
+        messageConverter.populateRabbitExchange(exchange, envelope, properties, body, false, allowMessageBodySerialization);
         return exchange;
     }
 
@@ -569,6 +570,23 @@ public class RabbitMQEndpoint extends DefaultEndpoint implements AsyncEndpoint {
         this.automaticRecoveryEnabled = automaticRecoveryEnabled;
     }
 
+    public boolean isAllowMessageBodySerialization() {
+        return allowMessageBodySerialization;
+    }
+
+    /**
+     * Whether to allow Java serialization of the message body or not. If this value is true, the message body
+     * will be serialized on the producer side using Java serialization, if no type converter can handle the
+     * message body. On the consumer side, it will deserialize the message body if this value is true and the
+     * message contains a CamelSerialize header.
+     *
+     * Setting this value to true may introduce a security vulnerability as it allows an attacker to attempt to
+     * deserialize to a gadget object which could result in a RCE or other security vulnerability.
+     */
+    public void setAllowMessageBodySerialization(boolean allowMessageBodySerialization) {
+        this.allowMessageBodySerialization = allowMessageBodySerialization;
+    }
+
     public Integer getNetworkRecoveryInterval() {
         return networkRecoveryInterval;
     }
diff --git a/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQMessageConverter.java b/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQMessageConverter.java
index a5ceb41..0aba71d 100644
--- a/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQMessageConverter.java
+++ b/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQMessageConverter.java
@@ -233,10 +233,11 @@ public class RabbitMQMessageConverter {
         return null;
     }
 
-    public void populateRabbitExchange(Exchange camelExchange, Envelope envelope, AMQP.BasicProperties properties, byte[] body, final boolean out) {
+    public void populateRabbitExchange(Exchange camelExchange, Envelope envelope, AMQP.BasicProperties properties, byte[] body, final boolean out,
+                                       final boolean allowMessageBodySerialization) {
         Message message = resolveMessageFrom(camelExchange, out);
         populateMessageHeaders(message, envelope, properties);
-        populateMessageBody(message, camelExchange, properties, body);
+        populateMessageBody(message, camelExchange, properties, body, allowMessageBodySerialization);
     }
 
     private Message resolveMessageFrom(final Exchange camelExchange, final boolean out) {
@@ -284,8 +285,9 @@ public class RabbitMQMessageConverter {
         }
     }
 
-    private void populateMessageBody(final Message message, final Exchange camelExchange, final AMQP.BasicProperties properties, final byte[] body) {
-        if (hasSerializeHeader(properties)) {
+    private void populateMessageBody(final Message message, final Exchange camelExchange, final AMQP.BasicProperties properties, final byte[] body,
+                                     final boolean allowMessageBodySerialization) {
+        if (allowMessageBodySerialization && hasSerializeHeader(properties)) {
             deserializeBody(camelExchange, message, body);
         } else {
             // Set the body as a byte[] and let the type converter deal with it
diff --git a/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQMessagePublisher.java b/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQMessagePublisher.java
index 02d08b1..c4cc99e 100644
--- a/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQMessagePublisher.java
+++ b/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/RabbitMQMessagePublisher.java
@@ -86,8 +86,9 @@ public class RabbitMQMessagePublisher {
 
             properties = endpoint.getMessageConverter().buildProperties(camelExchange).build();
         } catch (NoTypeConversionAvailableException | TypeConversionException e) {
-            if (message.getBody() instanceof Serializable) {
-                // Add the header so the reply processor knows to de-serialize it
+            if (message.getBody() instanceof Serializable && endpoint.isAllowMessageBodySerialization()) {
+                // Add the header so the reply processor knows to de-serialize
+                // it
                 message.getHeaders().put(RabbitMQEndpoint.SERIALIZE_HEADER, true);
                 properties = endpoint.getMessageConverter().buildProperties(camelExchange).build();
                 body = serializeBodyFrom(message);
diff --git a/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/reply/ReplyManagerSupport.java b/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/reply/ReplyManagerSupport.java
index 330c1a8..6110646 100644
--- a/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/reply/ReplyManagerSupport.java
+++ b/components/camel-rabbitmq/src/main/java/org/apache/camel/component/rabbitmq/reply/ReplyManagerSupport.java
@@ -159,8 +159,8 @@ public abstract class ReplyManagerSupport extends ServiceSupport implements Repl
                     String msg = "reply message with correlationID: " + holder.getCorrelationId() + " not received on destination: " + replyTo;
                     exchange.setException(new ExchangeTimedOutException(exchange, holder.getRequestTimeout(), msg));
                 } else {
-                    
-                    messageConverter.populateRabbitExchange(exchange, null, holder.getProperties(), holder.getMessage(), true);
+                    messageConverter.populateRabbitExchange(exchange, null, holder.getProperties(), holder.getMessage(), true,
+                                                            endpoint.isAllowMessageBodySerialization());
 
                     // restore correlation id in case the remote server messed with it
                     if (holder.getOriginalCorrelationId() != null) {
diff --git a/components/camel-rabbitmq/src/test/java/org/apache/camel/component/rabbitmq/RabbitMQInOutIntTest.java b/components/camel-rabbitmq/src/test/java/org/apache/camel/component/rabbitmq/RabbitMQInOutIntTest.java
index 113b4d8..14952f4 100644
--- a/components/camel-rabbitmq/src/test/java/org/apache/camel/component/rabbitmq/RabbitMQInOutIntTest.java
+++ b/components/camel-rabbitmq/src/test/java/org/apache/camel/component/rabbitmq/RabbitMQInOutIntTest.java
@@ -56,15 +56,13 @@ public class RabbitMQInOutIntTest extends AbstractRabbitMQIntTest {
     @Produce("direct:rabbitMQ")
     protected ProducerTemplate directProducer;
 
-    @EndpointInject("rabbitmq:localhost:5672/" + EXCHANGE + "?threadPoolSize=1&exchangeType=direct&username=cameltest&password=cameltest"
-                    + "&autoAck=true&queue=q4&routingKey=" + ROUTING_KEY
-                    + "&transferException=true&requestTimeout=" + TIMEOUT_MS)
+    @EndpointInject("rabbitmq:localhost:5672/" + EXCHANGE + "?threadPoolSize=1&exchangeType=direct&username=cameltest&password=cameltest" + "&autoAck=true&queue=q4&routingKey="
+                    + ROUTING_KEY + "&transferException=true&requestTimeout=" + TIMEOUT_MS + "&allowMessageBodySerialization=true")
     private Endpoint rabbitMQEndpoint;
 
     @EndpointInject("rabbitmq:localhost:5672/" + EXCHANGE_NO_ACK + "?threadPoolSize=1&exchangeType=direct&username=cameltest&password=cameltest"
-            + "&autoAck=false&autoDelete=false&durable=false&queue=q5&routingKey=" + ROUTING_KEY
-            + "&transferException=true&requestTimeout=" + TIMEOUT_MS
-            + "&args=#args")
+                    + "&autoAck=false&autoDelete=false&durable=false&queue=q5&routingKey=" + ROUTING_KEY + "&transferException=true&requestTimeout="
+                    + TIMEOUT_MS + "&args=#args" + "&allowMessageBodySerialization=true")
     private Endpoint noAutoAckEndpoint;
 
     @EndpointInject("mock:result")
@@ -148,7 +146,7 @@ public class RabbitMQInOutIntTest extends AbstractRabbitMQIntTest {
         testObject.setName("header");
 
         headers.put("String", "String");
-        headers.put("Boolean", new Boolean(false));
+        headers.put("Boolean", Boolean.valueOf(false));
 
         // This will blow up the connection if not removed before sending the message
         headers.put("TestObject1", testObject);
@@ -231,7 +229,7 @@ public class RabbitMQInOutIntTest extends AbstractRabbitMQIntTest {
     }
 
     @Test
-    public void inOutTimeOutTest() {
+    public void inOutTimeOutTest() throws InterruptedException {
         try {
             template.requestBodyAndHeader("direct:rabbitMQ", "TimeOut", RabbitMQConstants.EXCHANGE_NAME, EXCHANGE, String.class);
             fail("This should have thrown a timeOut exception");
diff --git a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/RabbitMQEndpointBuilderFactory.java b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/RabbitMQEndpointBuilderFactory.java
index fd5f9b3..a82f567 100644
--- a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/RabbitMQEndpointBuilderFactory.java
+++ b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/RabbitMQEndpointBuilderFactory.java
@@ -665,6 +665,46 @@ public interface RabbitMQEndpointBuilderFactory {
             return this;
         }
         /**
+         * Whether to allow Java serialization of the message body or not. If
+         * this value is true, the message body will be serialized on the
+         * producer side using Java serialization, if no type converter can
+         * handle the message body. On the consumer side, it will deserialize
+         * the message body if this value is true and the message contains a
+         * CamelSerialize header. Setting this value to true may introduce a
+         * security vulnerability as it allows an attacker to attempt to
+         * deserialize to a gadget object which could result in a RCE or other
+         * security vulnerability.
+         * 
+         * The option is a: <code>boolean</code> type.
+         * 
+         * Group: allowMessageBodySerialization
+         */
+        default RabbitMQEndpointConsumerBuilder allowMessageBodySerialization(
+                boolean allowMessageBodySerialization) {
+            doSetProperty("allowMessageBodySerialization", allowMessageBodySerialization);
+            return this;
+        }
+        /**
+         * Whether to allow Java serialization of the message body or not. If
+         * this value is true, the message body will be serialized on the
+         * producer side using Java serialization, if no type converter can
+         * handle the message body. On the consumer side, it will deserialize
+         * the message body if this value is true and the message contains a
+         * CamelSerialize header. Setting this value to true may introduce a
+         * security vulnerability as it allows an attacker to attempt to
+         * deserialize to a gadget object which could result in a RCE or other
+         * security vulnerability.
+         * 
+         * The option will be converted to a <code>boolean</code> type.
+         * 
+         * Group: allowMessageBodySerialization
+         */
+        default RabbitMQEndpointConsumerBuilder allowMessageBodySerialization(
+                String allowMessageBodySerialization) {
+            doSetProperty("allowMessageBodySerialization", allowMessageBodySerialization);
+            return this;
+        }
+        /**
          * Password for authenticated access.
          * 
          * The option is a: <code>java.lang.String</code> type.
@@ -1853,6 +1893,46 @@ public interface RabbitMQEndpointBuilderFactory {
             return this;
         }
         /**
+         * Whether to allow Java serialization of the message body or not. If
+         * this value is true, the message body will be serialized on the
+         * producer side using Java serialization, if no type converter can
+         * handle the message body. On the consumer side, it will deserialize
+         * the message body if this value is true and the message contains a
+         * CamelSerialize header. Setting this value to true may introduce a
+         * security vulnerability as it allows an attacker to attempt to
+         * deserialize to a gadget object which could result in a RCE or other
+         * security vulnerability.
+         * 
+         * The option is a: <code>boolean</code> type.
+         * 
+         * Group: allowMessageBodySerialization
+         */
+        default RabbitMQEndpointProducerBuilder allowMessageBodySerialization(
+                boolean allowMessageBodySerialization) {
+            doSetProperty("allowMessageBodySerialization", allowMessageBodySerialization);
+            return this;
+        }
+        /**
+         * Whether to allow Java serialization of the message body or not. If
+         * this value is true, the message body will be serialized on the
+         * producer side using Java serialization, if no type converter can
+         * handle the message body. On the consumer side, it will deserialize
+         * the message body if this value is true and the message contains a
+         * CamelSerialize header. Setting this value to true may introduce a
+         * security vulnerability as it allows an attacker to attempt to
+         * deserialize to a gadget object which could result in a RCE or other
+         * security vulnerability.
+         * 
+         * The option will be converted to a <code>boolean</code> type.
+         * 
+         * Group: allowMessageBodySerialization
+         */
+        default RabbitMQEndpointProducerBuilder allowMessageBodySerialization(
+                String allowMessageBodySerialization) {
+            doSetProperty("allowMessageBodySerialization", allowMessageBodySerialization);
+            return this;
+        }
+        /**
          * Password for authenticated access.
          * 
          * The option is a: <code>java.lang.String</code> type.
@@ -2670,6 +2750,46 @@ public interface RabbitMQEndpointBuilderFactory {
             return this;
         }
         /**
+         * Whether to allow Java serialization of the message body or not. If
+         * this value is true, the message body will be serialized on the
+         * producer side using Java serialization, if no type converter can
+         * handle the message body. On the consumer side, it will deserialize
+         * the message body if this value is true and the message contains a
+         * CamelSerialize header. Setting this value to true may introduce a
+         * security vulnerability as it allows an attacker to attempt to
+         * deserialize to a gadget object which could result in a RCE or other
+         * security vulnerability.
+         * 
+         * The option is a: <code>boolean</code> type.
+         * 
+         * Group: allowMessageBodySerialization
+         */
+        default RabbitMQEndpointBuilder allowMessageBodySerialization(
+                boolean allowMessageBodySerialization) {
+            doSetProperty("allowMessageBodySerialization", allowMessageBodySerialization);
+            return this;
+        }
+        /**
+         * Whether to allow Java serialization of the message body or not. If
+         * this value is true, the message body will be serialized on the
+         * producer side using Java serialization, if no type converter can
+         * handle the message body. On the consumer side, it will deserialize
+         * the message body if this value is true and the message contains a
+         * CamelSerialize header. Setting this value to true may introduce a
+         * security vulnerability as it allows an attacker to attempt to
+         * deserialize to a gadget object which could result in a RCE or other
+         * security vulnerability.
+         * 
+         * The option will be converted to a <code>boolean</code> type.
+         * 
+         * Group: allowMessageBodySerialization
+         */
+        default RabbitMQEndpointBuilder allowMessageBodySerialization(
+                String allowMessageBodySerialization) {
+            doSetProperty("allowMessageBodySerialization", allowMessageBodySerialization);
+            return this;
+        }
+        /**
          * Password for authenticated access.
          * 
          * The option is a: <code>java.lang.String</code> type.
diff --git a/docs/components/modules/ROOT/pages/rabbitmq-component.adoc b/docs/components/modules/ROOT/pages/rabbitmq-component.adoc
index 4adbfab..bd4f5e0 100644
--- a/docs/components/modules/ROOT/pages/rabbitmq-component.adoc
+++ b/docs/components/modules/ROOT/pages/rabbitmq-component.adoc
@@ -134,7 +134,7 @@ with the following path and query parameters:
 |===
 
 
-=== Query Parameters (59 parameters):
+=== Query Parameters (60 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
@@ -195,6 +195,7 @@ with the following path and query parameters:
 | *synchronous* (advanced) | Sets whether synchronous processing should be strictly used, or Camel is allowed to use asynchronous processing (if supported). | false | boolean
 | *topologyRecoveryEnabled* (advanced) | Enables connection topology recovery (should topology recovery be performed) |  | Boolean
 | *transferException* (advanced) | When true and an inOut Exchange failed on the consumer side send the caused Exception back in the response | false | boolean
+| *allowMessageBody Serialization* (allowMessageBodySerialization) | Whether to allow Java serialization of the message body or not. If this value is true, the message body will be serialized on the producer side using Java serialization, if no type converter can handle the message body. On the consumer side, it will deserialize the message body if this value is true and the message contains a CamelSerialize header. Setting this value to true may introduce a security vulnerability as it  [...]
 | *password* (security) | Password for authenticated access | guest | String
 | *sslProtocol* (security) | Enables SSL on connection, accepted value are true, TLS and 'SSLv3 |  | String
 | *trustManager* (security) | Configure SSL trust manager, SSL should be enabled for this option to be effective |  | TrustManager