diff --git a/src/java/org/apache/commons/collections/functors/CloneTransformer.java b/src/java/org/apache/commons/collections/functors/CloneTransformer.java index 7200402..3df18ff 100644 --- a/src/java/org/apache/commons/collections/functors/CloneTransformer.java +++ b/src/java/org/apache/commons/collections/functors/CloneTransformer.java @@ -16,6 +16,9 @@ */ package org.apache.commons.collections.functors; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.Serializable; import org.apache.commons.collections.Transformer; @@ -24,6 +27,16 @@ import org.apache.commons.collections.Transformer; * Transformer implementation that returns a clone of the input object. *

* Clone is performed using PrototypeFactory.getInstance(input).create(). + *

+ * WARNING: This class will throw an + * {@link UnsupportedOperationException} when trying to serialize or + * de-serialize an instance to prevent potential remote code execution exploits. + *

+ * In order to re-enable serialization support for {@code CloneTransformer} + * the following system property can be used (via -Dproperty=true): + *

+ * org.apache.commons.collections.enableUnsafeSerialization
+ * 
* * @since Commons Collections 3.0 * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $ @@ -68,4 +81,21 @@ public class CloneTransformer implements Transformer, Serializable { return PrototypeFactory.getInstance(input).create(); } + /** + * Overrides the default writeObject implementation to prevent + * serialization (see COLLECTIONS-580). + */ + private void writeObject(ObjectOutputStream os) throws IOException { + FunctorUtils.checkUnsafeSerialization(CloneTransformer.class); + os.defaultWriteObject(); + } + + /** + * Overrides the default readObject implementation to prevent + * de-serialization (see COLLECTIONS-580). + */ + private void readObject(ObjectInputStream is) throws ClassNotFoundException, IOException { + FunctorUtils.checkUnsafeSerialization(CloneTransformer.class); + is.defaultReadObject(); + } } diff --git a/src/java/org/apache/commons/collections/functors/ForClosure.java b/src/java/org/apache/commons/collections/functors/ForClosure.java index f0355c4..e15475c 100644 --- a/src/java/org/apache/commons/collections/functors/ForClosure.java +++ b/src/java/org/apache/commons/collections/functors/ForClosure.java @@ -16,12 +16,25 @@ */ package org.apache.commons.collections.functors; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.Serializable; import org.apache.commons.collections.Closure; /** * Closure implementation that calls another closure n times, like a for loop. + *

+ * WARNING: This class will throw an + * {@link UnsupportedOperationException} when trying to serialize or + * de-serialize an instance to prevent potential remote code execution exploits. + *

+ * In order to re-enable serialization support for {@code ForClosure} + * the following system property can be used (via -Dproperty=true): + *

+ * org.apache.commons.collections.enableUnsafeSerialization
+ * 
* * @since Commons Collections 3.0 * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $ @@ -102,4 +115,22 @@ public class ForClosure implements Closure, Serializable { return iCount; } + /** + * Overrides the default writeObject implementation to prevent + * serialization (see COLLECTIONS-580). + */ + private void writeObject(ObjectOutputStream os) throws IOException { + FunctorUtils.checkUnsafeSerialization(ForClosure.class); + os.defaultWriteObject(); + } + + /** + * Overrides the default readObject implementation to prevent + * de-serialization (see COLLECTIONS-580). + */ + private void readObject(ObjectInputStream is) throws ClassNotFoundException, IOException { + FunctorUtils.checkUnsafeSerialization(ForClosure.class); + is.defaultReadObject(); + } + } diff --git a/src/java/org/apache/commons/collections/functors/FunctorUtils.java b/src/java/org/apache/commons/collections/functors/FunctorUtils.java index 75f8d9b..aa7bec3 100644 --- a/src/java/org/apache/commons/collections/functors/FunctorUtils.java +++ b/src/java/org/apache/commons/collections/functors/FunctorUtils.java @@ -16,6 +16,8 @@ */ package org.apache.commons.collections.functors; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.Collection; import java.util.Iterator; @@ -33,7 +35,11 @@ import org.apache.commons.collections.Transformer; * @author Matt Benson */ class FunctorUtils { - + + /** System property key to enable unsafe serialization */ + final static String UNSAFE_SERIALIZABLE_PROPERTY + = "org.apache.commons.collections.enableUnsafeSerialization"; + /** * Restricted constructor. */ @@ -152,4 +158,33 @@ class FunctorUtils { } } + /** + * Package-private helper method to check if serialization support is + * enabled for unsafe classes. + * + * @param clazz the clazz to check for serialization support + * @throws UnsupportedOperationException if unsafe serialization is disabled + */ + static void checkUnsafeSerialization(Class clazz) { + String unsafeSerializableProperty; + + try { + unsafeSerializableProperty = + (String) AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + return System.getProperty(UNSAFE_SERIALIZABLE_PROPERTY); + } + }); + } catch (SecurityException ex) { + unsafeSerializableProperty = null; + } + + if (!"true".equalsIgnoreCase(unsafeSerializableProperty)) { + throw new UnsupportedOperationException( + "Serialization support for " + clazz.getName() + " is disabled for security reasons. " + + "To enable it set system property '" + UNSAFE_SERIALIZABLE_PROPERTY + "' to 'true', " + + "but you must ensure that your application does not de-serialize objects from untrusted sources."); + } + } + } diff --git a/src/java/org/apache/commons/collections/functors/InstantiateFactory.java b/src/java/org/apache/commons/collections/functors/InstantiateFactory.java index 5d375de..938d6dc 100644 --- a/src/java/org/apache/commons/collections/functors/InstantiateFactory.java +++ b/src/java/org/apache/commons/collections/functors/InstantiateFactory.java @@ -16,6 +16,9 @@ */ package org.apache.commons.collections.functors; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -25,6 +28,16 @@ import org.apache.commons.collections.FunctorException; /** * Factory implementation that creates a new object instance by reflection. + *

+ * WARNING: This class will throw an + * {@link UnsupportedOperationException} when trying to serialize or + * de-serialize an instance to prevent potential remote code execution exploits. + *

+ * In order to re-enable serialization support for {@code InstantiateTransformer} + * the following system property can be used (via -Dproperty=true): + *

+ * org.apache.commons.collections.enableUnsafeSerialization
+ * 
* * @since Commons Collections 3.0 * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $ @@ -136,5 +149,22 @@ public class InstantiateFactory implements Factory, Serializable { throw new FunctorException("InstantiateFactory: Constructor threw an exception", ex); } } - + + /** + * Overrides the default writeObject implementation to prevent + * serialization (see COLLECTIONS-580). + */ + private void writeObject(ObjectOutputStream os) throws IOException { + FunctorUtils.checkUnsafeSerialization(InstantiateFactory.class); + os.defaultWriteObject(); + } + + /** + * Overrides the default readObject implementation to prevent + * de-serialization (see COLLECTIONS-580). + */ + private void readObject(ObjectInputStream is) throws ClassNotFoundException, IOException { + FunctorUtils.checkUnsafeSerialization(InstantiateFactory.class); + is.defaultReadObject(); + } } diff --git a/src/java/org/apache/commons/collections/functors/InstantiateTransformer.java b/src/java/org/apache/commons/collections/functors/InstantiateTransformer.java index 73d6b2f..4927f05 100644 --- a/src/java/org/apache/commons/collections/functors/InstantiateTransformer.java +++ b/src/java/org/apache/commons/collections/functors/InstantiateTransformer.java @@ -16,6 +16,9 @@ */ package org.apache.commons.collections.functors; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -25,6 +28,16 @@ import org.apache.commons.collections.Transformer; /** * Transformer implementation that creates a new object instance by reflection. + *

+ * WARNING: This class will throw an + * {@link UnsupportedOperationException} when trying to serialize or + * de-serialize an instance to prevent potential remote code execution exploits. + *

+ * In order to re-enable serialization support for {@code InstantiateTransformer} + * the following system property can be used (via -Dproperty=true): + *

+ * org.apache.commons.collections.enableUnsafeSerialization
+ * 
* * @since Commons Collections 3.0 * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $ @@ -116,4 +129,22 @@ public class InstantiateTransformer implements Transformer, Serializable { } } + /** + * Overrides the default writeObject implementation to prevent + * serialization (see COLLECTIONS-580). + */ + private void writeObject(ObjectOutputStream os) throws IOException { + FunctorUtils.checkUnsafeSerialization(InstantiateTransformer.class); + os.defaultWriteObject(); + } + + /** + * Overrides the default readObject implementation to prevent + * de-serialization (see COLLECTIONS-580). + */ + private void readObject(ObjectInputStream is) throws ClassNotFoundException, IOException { + FunctorUtils.checkUnsafeSerialization(InstantiateTransformer.class); + is.defaultReadObject(); + } + } diff --git a/src/java/org/apache/commons/collections/functors/InvokerTransformer.java b/src/java/org/apache/commons/collections/functors/InvokerTransformer.java index 6f60961..75f48af 100644 --- a/src/java/org/apache/commons/collections/functors/InvokerTransformer.java +++ b/src/java/org/apache/commons/collections/functors/InvokerTransformer.java @@ -16,6 +16,9 @@ */ package org.apache.commons.collections.functors; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -25,6 +28,16 @@ import org.apache.commons.collections.Transformer; /** * Transformer implementation that creates a new object instance by reflection. + *

+ * WARNING: This class will throw an + * {@link UnsupportedOperationException} when trying to serialize or + * de-serialize an instance to prevent potential remote code execution exploits. + *

+ * In order to re-enable serialization support for {@code InvokerTransformer} + * the following system property can be used (via -Dproperty=true): + *

+ * org.apache.commons.collections.enableUnsafeSerialization
+ * 
* * @since Commons Collections 3.0 * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $ @@ -134,4 +147,21 @@ public class InvokerTransformer implements Transformer, Serializable { } } + /** + * Overrides the default writeObject implementation to prevent + * serialization (see COLLECTIONS-580). + */ + private void writeObject(ObjectOutputStream os) throws IOException { + FunctorUtils.checkUnsafeSerialization(InvokerTransformer.class); + os.defaultWriteObject(); + } + + /** + * Overrides the default readObject implementation to prevent + * de-serialization (see COLLECTIONS-580). + */ + private void readObject(ObjectInputStream is) throws ClassNotFoundException, IOException { + FunctorUtils.checkUnsafeSerialization(InvokerTransformer.class); + is.defaultReadObject(); + } } diff --git a/src/java/org/apache/commons/collections/functors/PrototypeFactory.java b/src/java/org/apache/commons/collections/functors/PrototypeFactory.java index 4fa4150..d9908fa 100644 --- a/src/java/org/apache/commons/collections/functors/PrototypeFactory.java +++ b/src/java/org/apache/commons/collections/functors/PrototypeFactory.java @@ -49,6 +49,16 @@ public class PrototypeFactory { *
  • public copy constructor *
  • serialization clone *