Skip to content

Instantly share code, notes, and snippets.

@takawitter
Last active November 11, 2015 02:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save takawitter/20d1a88b497d596df16b to your computer and use it in GitHub Desktop.
Save takawitter/20d1a88b497d596df16b to your computer and use it in GitHub Desktop.
Limit class reference when deserializing object by using custom class loader.
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;
import org.apache.commons.collections4.map.LazyMap;
public class LimitClassReferenceWhenDeserializingObject {
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void main(String[] args) throws Throwable{
Map<String, String> map = LazyMap.lazyMap(new HashMap<>(), new ChainedTransformer(
new ConstantTransformer(Runtime.class),
new InvokerTransformer(
"getMethod",
new Class[] { String.class, Class[].class },
new Object[] { "getRuntime", new Class[0] }),
new InvokerTransformer(
"invoke",
new Class[]{ Object.class, Object[].class },
new Object[]{ null, new Object[0] }),
new InvokerTransformer(
"exec",
new Class[]{ String.class },
new Object[]{"touch hello.txt"}),
new ConstantTransformer("hello")
));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(map);
oos.flush();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())){
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException ,ClassNotFoundException {
System.out.println("resolve class: " + desc.getName());
if(desc.getName().startsWith("[")) return super.resolveClass(desc);
ClassLoader cl = new URLClassLoader(
new URL[]{Paths.get("bin/").toUri().toURL()}
, null
){
protected java.lang.Class<?> findClass(String name) throws ClassNotFoundException {
System.out.println("find class: " + name);
return super.findClass(name);
}
};
return cl.loadClass(desc.getName());
}
};
System.out.println(((Map<String, Object>)ois.readObject()).get("hello"));
}
}
resolve class: org.apache.commons.collections4.map.LazyMap
find class: org.apache.commons.collections4.map.LazyMap
resolve class: org.apache.commons.collections4.functors.ChainedTransformer
find class: org.apache.commons.collections4.functors.ChainedTransformer
resolve class: [Lorg.apache.commons.collections4.Transformer;
resolve class: org.apache.commons.collections4.functors.ConstantTransformer
find class: org.apache.commons.collections4.functors.ConstantTransformer
resolve class: java.lang.Runtime
resolve class: org.apache.commons.collections4.functors.InvokerTransformer
find class: org.apache.commons.collections4.functors.InvokerTransformer
resolve class: [Ljava.lang.Object;
resolve class: [Ljava.lang.Class;
resolve class: java.lang.String
resolve class: java.lang.Object
resolve class: java.util.HashMap
Exception in thread "main" java.lang.ClassNotFoundException: org.apache.commons.collections4.map.LazyMap
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at cpiso.LimitedClassReference$1$1.findClass(LimitedClassReference.java:53)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at cpiso.LimitedClassReference$1.resolveClass(LimitedClassReference.java:60)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1613)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
at cpiso.LimitedClassReference.main(LimitedClassReference.java:63)
@takawitter
Copy link
Author

Comment out line 48, for deserialization volnerability to work. Even you commented out 48, you can filter classes to be loaded at line 51.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment