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

jbonofre pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/activemq.git


The following commit(s) were added to refs/heads/master by this push:
     new a73a85e  AMQ-7438 - Harden deserialization
     new 1f914bb  Merge pull request #502 from coheigea/AMQ-7438
a73a85e is described below

commit a73a85e6c21ac2905feb162d9132993b231f391b
Author: Colm O hEigeartaigh <cohei...@apache.org>
AuthorDate: Fri Mar 6 17:22:07 2020 +0000

    AMQ-7438 - Harden deserialization
---
 .../plugin/SubQueueSelectorCacheBroker.java        | 20 +++++++-
 .../activemq/store/kahadb/MessageDatabase.java     | 25 ++++++++--
 .../store/kahadb/disk/util/ObjectMarshaller.java   | 57 ----------------------
 3 files changed, 41 insertions(+), 61 deletions(-)

diff --git 
a/activemq-broker/src/main/java/org/apache/activemq/plugin/SubQueueSelectorCacheBroker.java
 
b/activemq-broker/src/main/java/org/apache/activemq/plugin/SubQueueSelectorCacheBroker.java
index ecea02f..6147f4c 100644
--- 
a/activemq-broker/src/main/java/org/apache/activemq/plugin/SubQueueSelectorCacheBroker.java
+++ 
b/activemq-broker/src/main/java/org/apache/activemq/plugin/SubQueueSelectorCacheBroker.java
@@ -20,8 +20,11 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.InvalidClassException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
@@ -192,7 +195,7 @@ public class SubQueueSelectorCacheBroker extends 
BrokerFilter implements Runnabl
         if (persistFile != null && persistFile.exists()) {
             try {
                 try (FileInputStream fis = new FileInputStream(persistFile);) {
-                    ObjectInputStream in = new ObjectInputStream(fis);
+                    ObjectInputStream in = new 
SubSelectorClassObjectInputStream(fis);
                     try {
                         LOG.debug("Reading selector cache....");
                         subSelectorCache = (ConcurrentHashMap<String, 
Set<String>>) in.readObject();
@@ -365,4 +368,19 @@ public class SubQueueSelectorCacheBroker extends 
BrokerFilter implements Runnabl
             return false;
         }
     }
+
+    private static class SubSelectorClassObjectInputStream extends 
ObjectInputStream {
+
+        public SubSelectorClassObjectInputStream(InputStream is) throws 
IOException {
+            super(is);
+        }
+
+        @Override
+        protected Class<?> resolveClass(ObjectStreamClass desc) throws 
IOException, ClassNotFoundException {
+            if (!(desc.getName().equals("java.lang.String") || 
desc.getName().startsWith("java.util."))) {
+                throw new InvalidClassException("Unauthorized deserialization 
attempt", desc.getName());
+            }
+            return super.resolveClass(desc);
+        }
+    }
 }
diff --git 
a/activemq-kahadb-store/src/main/java/org/apache/activemq/store/kahadb/MessageDatabase.java
 
b/activemq-kahadb-store/src/main/java/org/apache/activemq/store/kahadb/MessageDatabase.java
index d12c7d9..5c38435 100644
--- 
a/activemq-kahadb-store/src/main/java/org/apache/activemq/store/kahadb/MessageDatabase.java
+++ 
b/activemq-kahadb-store/src/main/java/org/apache/activemq/store/kahadb/MessageDatabase.java
@@ -27,8 +27,10 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InterruptedIOException;
+import java.io.InvalidClassException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
 import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -805,7 +807,7 @@ public abstract class MessageDatabase extends 
ServiceSupport implements BrokerSe
         if (metadata.producerSequenceIdTrackerLocation != null) {
             try {
                 KahaProducerAuditCommand audit = (KahaProducerAuditCommand) 
load(metadata.producerSequenceIdTrackerLocation);
-                ObjectInputStream objectIn = new 
ObjectInputStream(audit.getAudit().newInput());
+                ObjectInputStream objectIn = new 
MessageDatabaseObjectInputStream(audit.getAudit().newInput());
                 int maxNumProducers = getMaxFailoverProducersToTrack();
                 int maxAuditDepth = getFailoverProducersAuditDepth();
                 metadata.producerSequenceIdTracker = 
(ActiveMQMessageAuditNoSync) objectIn.readObject();
@@ -826,7 +828,7 @@ public abstract class MessageDatabase extends 
ServiceSupport implements BrokerSe
         if (metadata.ackMessageFileMapLocation != null) {
             try {
                 KahaAckMessageFileMapCommand audit = 
(KahaAckMessageFileMapCommand) load(metadata.ackMessageFileMapLocation);
-                ObjectInputStream objectIn = new 
ObjectInputStream(audit.getAckMessageFileMap().newInput());
+                ObjectInputStream objectIn = new 
MessageDatabaseObjectInputStream(audit.getAckMessageFileMap().newInput());
                 metadata.ackMessageFileMap = (Map<Integer, Set<Integer>>) 
objectIn.readObject();
                 metadata.ackMessageFileMapDirtyFlag.lazySet(true);
                 requiresReplay = false;
@@ -4114,7 +4116,7 @@ public abstract class MessageDatabase extends 
ServiceSupport implements BrokerSe
             byte[] data = new byte[dataLen];
             dataIn.readFully(data);
             ByteArrayInputStream bais = new ByteArrayInputStream(data);
-            ObjectInputStream oin = new ObjectInputStream(bais);
+            ObjectInputStream oin = new MessageDatabaseObjectInputStream(bais);
             try {
                 return (HashSet<String>) oin.readObject();
             } catch (ClassNotFoundException cfe) {
@@ -4227,4 +4229,21 @@ public abstract class MessageDatabase extends 
ServiceSupport implements BrokerSe
     public void setEnableSubscriptionStatistics(boolean 
enableSubscriptionStatistics) {
         this.enableSubscriptionStatistics = enableSubscriptionStatistics;
     }
+
+    private static class MessageDatabaseObjectInputStream extends 
ObjectInputStream {
+
+        public MessageDatabaseObjectInputStream(InputStream is) throws 
IOException {
+            super(is);
+        }
+
+        @Override
+        protected Class<?> resolveClass(ObjectStreamClass desc) throws 
IOException, ClassNotFoundException {
+            if (!(desc.getName().startsWith("java.lang.") || 
desc.getName().startsWith("java.util.")
+                || desc.getName().startsWith("org.apache.activemq."))) {
+                throw new InvalidClassException("Unauthorized deserialization 
attempt", desc.getName());
+            }
+            return super.resolveClass(desc);
+        }
+
+    }
 }
diff --git 
a/activemq-kahadb-store/src/main/java/org/apache/activemq/store/kahadb/disk/util/ObjectMarshaller.java
 
b/activemq-kahadb-store/src/main/java/org/apache/activemq/store/kahadb/disk/util/ObjectMarshaller.java
deleted file mode 100644
index 585ec52..0000000
--- 
a/activemq-kahadb-store/src/main/java/org/apache/activemq/store/kahadb/disk/util/ObjectMarshaller.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.activemq.store.kahadb.disk.util;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-
-/**
- * Implementation of a Marshaller for Objects
- * 
- * 
- */
-public class ObjectMarshaller extends VariableMarshaller<Object> {
-
-    public void writePayload(Object object, DataOutput dataOut) throws 
IOException {
-        ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
-        ObjectOutputStream objectOut = new ObjectOutputStream(bytesOut);
-        objectOut.writeObject(object);
-        objectOut.close();
-        byte[] data = bytesOut.toByteArray();
-        dataOut.writeInt(data.length);
-        dataOut.write(data);
-    }
-
-    public Object readPayload(DataInput dataIn) throws IOException {
-        int size = dataIn.readInt();
-        byte[] data = new byte[size];
-        dataIn.readFully(data);
-        ByteArrayInputStream bytesIn = new ByteArrayInputStream(data);
-        ObjectInputStream objectIn = new ObjectInputStream(bytesIn);
-        try {
-            return objectIn.readObject();
-        } catch (ClassNotFoundException e) {
-            throw new IOException(e.getMessage());
-        }
-    }
-    
-}

Reply via email to