diff --git a/provider/fastbin/src/main/java/org/apache/aries/rsa/provider/fastbin/api/ObjectSerializationStrategy.java b/provider/fastbin/src/main/java/org/apache/aries/rsa/provider/fastbin/api/ObjectSerializationStrategy.java index ea23fb25..40324fef 100644 --- a/provider/fastbin/src/main/java/org/apache/aries/rsa/provider/fastbin/api/ObjectSerializationStrategy.java +++ b/provider/fastbin/src/main/java/org/apache/aries/rsa/provider/fastbin/api/ObjectSerializationStrategy.java @@ -23,6 +23,7 @@ import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -34,25 +35,31 @@ import org.fusesource.hawtbuf.DataByteArrayOutputStream; import org.osgi.framework.ServiceException; -/** - *

- *

- * - */ public class ObjectSerializationStrategy implements SerializationStrategy { public static final ObjectSerializationStrategy INSTANCE = new ObjectSerializationStrategy(); private static final ObjectSerializationStrategy V1 = INSTANCE; - private int protocolVersion = FastBinProvider.PROTOCOL_VERSION; + // private int protocolVersion = FastBinProvider.PROTOCOL_VERSION - private static final Set ALLOWEDCLASSES; + private static final Set DENIED_CLASSES; + private static final Set ALLOWED_CLASSES; private static final FilteredClassLoaderObjectInputStream.AllowlistPackagesPredicate ALLOWED_PACKAGES; + private static final String ADDITIONAL_DENIED_CLASSES = System.getProperty( "org.apache.aries.rsa.provider.fastbin.api.DESERIALIZATION_CLASS_DENY_LIST", ""); private static final String ADDITIONAL_ALLOWED_PACKAGE = System.getProperty( "org.apache.aries.rsa.provider.fastbin.api.DESERIALIZATION_PACKAGE_ALLOW_LIST", ""); private static final String ADDITIONAL_ALLOWED_CLASSES = System.getProperty( "org.apache.aries.rsa.provider.fastbin.api.DESERIALIZATION_CLASS_ALLOW_LIST", ""); static { - Set classes = new HashSet<>(); - classes.addAll(Arrays.asList( + // denied classes + Set deniedClasses = new HashSet<>(Arrays.asList("java.net.URL", "[Ljava.net.URL")); + final String[] customDeniedClasses = ADDITIONAL_DENIED_CLASSES.split(","); + if (customDeniedClasses.length > 0) + { + deniedClasses.addAll(Arrays.asList(customDeniedClasses)); + } + DENIED_CLASSES = deniedClasses; + + // allowed classes + Set allowedClasses = new HashSet<>(Arrays.asList( "B", // byte "C", // char "D", // double @@ -62,16 +69,16 @@ public class ObjectSerializationStrategy implements SerializationStrategy { "S", // short "Z", // boolean "L" // Object type (LClassName;) - )); - final String[] customClasses = ADDITIONAL_ALLOWED_CLASSES.split(","); - if (customClasses.length > 0) + )); + final String[] customAllowedClasses = ADDITIONAL_ALLOWED_CLASSES.split(","); + if (customAllowedClasses.length > 0) { - classes.addAll(Arrays.asList(customClasses)); + allowedClasses.addAll(Arrays.asList(customAllowedClasses)); } - ALLOWEDCLASSES = classes; + ALLOWED_CLASSES = allowedClasses; - List packages = new ArrayList<>(); - packages.addAll(Arrays.asList( + // allowed packages + List packages = new ArrayList<>(Arrays.asList( "java", "javax", "Ljava", @@ -100,7 +107,7 @@ public void encodeRequest(ClassLoader loader, Class[] types, Object[] args, D } public void decodeResponse(ClassLoader loader, Class type, DataByteArrayInputStream source, AsyncCallback result) throws IOException, ClassNotFoundException { - ClassLoaderObjectInputStream ois = new FilteredClassLoaderObjectInputStream(source, ALLOWEDCLASSES, ALLOWED_PACKAGES); + ClassLoaderObjectInputStream ois = new FilteredClassLoaderObjectInputStream(source, DENIED_CLASSES, ALLOWED_CLASSES, ALLOWED_PACKAGES); ois.setClassLoader(loader); Throwable error = (Throwable) ois.readObject(); Object value = ois.readObject(); @@ -112,7 +119,7 @@ public void decodeResponse(ClassLoader loader, Class type, DataByteArrayInput } public void decodeRequest(ClassLoader loader, Class[] types, DataByteArrayInputStream source, Object[] target) throws IOException, ClassNotFoundException { - ClassLoaderObjectInputStream ois = new FilteredClassLoaderObjectInputStream(source, ALLOWEDCLASSES, ALLOWED_PACKAGES); + ClassLoaderObjectInputStream ois = new FilteredClassLoaderObjectInputStream(source, DENIED_CLASSES, ALLOWED_CLASSES, ALLOWED_PACKAGES); ois.setClassLoader(loader); final Object[] args = (Object[]) ois.readObject(); if( args!=null ) { diff --git a/provider/fastbin/src/main/java/org/apache/aries/rsa/provider/fastbin/util/FilteredClassLoaderObjectInputStream.java b/provider/fastbin/src/main/java/org/apache/aries/rsa/provider/fastbin/util/FilteredClassLoaderObjectInputStream.java index 3fe1ffa9..60be7dcf 100644 --- a/provider/fastbin/src/main/java/org/apache/aries/rsa/provider/fastbin/util/FilteredClassLoaderObjectInputStream.java +++ b/provider/fastbin/src/main/java/org/apache/aries/rsa/provider/fastbin/util/FilteredClassLoaderObjectInputStream.java @@ -30,22 +30,25 @@ public class FilteredClassLoaderObjectInputStream extends ClassLoaderObjectInput static final String PROPERTY_USE_INSECURE_DESERIALIZATION = "org.apache.aries.rsa.provider.fastbin.util.useInsecureDeserialization"; static boolean useInsecureDeserialization = Boolean.getBoolean(PROPERTY_USE_INSECURE_DESERIALIZATION); + private final Set deniedClasses; private final Set allowedClasses; - private Predicate allowedPackages; + private final Predicate allowedPackages; - public FilteredClassLoaderObjectInputStream(InputStream s, Set allowedClasses) + public FilteredClassLoaderObjectInputStream(InputStream inArg, Set allowedClasses) throws IOException { - super(s); + super(inArg); if (allowedClasses == null) { throw new IllegalArgumentException("allowedClasses must not be null"); } + this.deniedClasses = null; this.allowedClasses = allowedClasses; + this.allowedPackages = null; } - public FilteredClassLoaderObjectInputStream(InputStream inArg, Set allowedClasses, Predicate allowedPackages) + public FilteredClassLoaderObjectInputStream(InputStream inArg, Set deniedClasses, Set allowedClasses, Predicate allowedPackages) throws IOException { super(inArg); @@ -55,6 +58,7 @@ public FilteredClassLoaderObjectInputStream(InputStream inArg, Set allow throw new IllegalArgumentException("allowedClasses must not be null"); } + this.deniedClasses = deniedClasses; this.allowedClasses = allowedClasses; this.allowedPackages = allowedPackages; } @@ -67,6 +71,10 @@ public FilteredClassLoaderObjectInputStream(InputStream inArg, Set allow if (!useInsecureDeserialization) { + if (deniedClasses != null && deniedClasses.contains(className)) + { + throw new InvalidClassException(className, "Invalid de-serialization data. POSSIBLE ATTACK. Invalid class=" + className); + } if (allowedClasses.contains(className)) { return super.resolveClass(clsDescriptor); @@ -75,7 +83,7 @@ public FilteredClassLoaderObjectInputStream(InputStream inArg, Set allow { return super.resolveClass(clsDescriptor); } - throw new InvalidClassException(className, "Invalid de-serialisation data. POSSIBLE ATTACK. Invalid class=" + className); + throw new InvalidClassException(className, "Invalid de-serialization data. POSSIBLE ATTACK. Invalid class=" + className); } return super.resolveClass(clsDescriptor);