Skip to content

Instantly share code, notes, and snippets.

@takawitter
Last active November 11, 2015 02:51
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Embed
What would you like to do?
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