Permalink
Browse files

Merge pull request #422 from JoshCunninghame/kotlin_deserialisation_g…

…adget

Kotlin deserialisation gadget
  • Loading branch information...
h3xstream committed Jul 23, 2018
2 parents ddbcb09 + 1abe926 commit f6ace14eb670a7a6c899a70fdf59e58853563920
@@ -0,0 +1,55 @@
package com.h3xstream.findsecbugs.deserialisation
import org.apache.commons.collections4.Transformer
import java.io.Serializable
import java.lang.reflect.InvocationTargetException
class InvokerTransformer<I, O> : Transformer<I, O>, Serializable {
private val iMethodName: String
private val iParamTypes: Array<Class<*>>
private val iArgs: Array<Any>
constructor(methodName: String) {
this.iMethodName = methodName
this.iParamTypes = emptyArray()
this.iArgs = emptyArray()
}
constructor(methodName: String, paramTypes: Array<Class<*>>, args: Array<Any>) {
this.iMethodName = methodName
this.iParamTypes = paramTypes.clone()
this.iArgs = args.clone()
}
override fun transform(input: I): O {
try {
val ex = (input as Any).javaClass
val method = ex.getMethod(this.iMethodName, *this.iParamTypes)
return method.invoke(input, *this.iArgs) as O
} catch (var4: NoSuchMethodException) {
throw RuntimeException("InvokerTransformer: The method \'" + this.iMethodName + "\' on \'" + (input as Any).javaClass + "\' does not exist")
} catch (var5: IllegalAccessException) {
throw RuntimeException("InvokerTransformer: The method \'" + this.iMethodName + "\' on \'" + (input as Any).javaClass + "\' cannot be accessed")
} catch (var6: InvocationTargetException) {
throw RuntimeException("InvokerTransformer: The method \'" + this.iMethodName + "\' on \'" + (input as Any).javaClass + "\' threw an exception", var6)
}
}
companion object {
private const val serialVersionUID = -8653385846894047688L
fun <I, O> invokerTransformer(methodName: String): Transformer<I, O> {
return InvokerTransformer(methodName)
}
fun <I, O> invokerTransformer(methodName: String, paramTypes: Array<Class<*>>, args: Array<Any>): Transformer<I, O> {
return if (paramTypes.size != args.size) {
throw IllegalArgumentException("The parameter types must match the arguments")
} else {
if (paramTypes.isNotEmpty()) InvokerTransformer(methodName, paramTypes, args) else InvokerTransformer(methodName)
}
}
}
}
@@ -0,0 +1,39 @@
package com.h3xstream.findsecbugs.deserialisation
import org.springframework.util.ReflectionUtils
import java.io.IOException
import java.io.ObjectInputStream
import java.lang.reflect.Method
import java.lang.reflect.Type
/**
* Inspired by the gadget : SerializableTypeWrapper.MethodInvokeTypeProvider.readObject
* Ref: org.springframework:spring-beans:4.1.4.RELEASE
*/
class MethodInvokeTypeProvider(private val provider: TypeProvider, method: Method, private val index: Int) : TypeProvider {
private val methodName: String = method.name
@Transient
private var result: Any? = null
override val type: Type
get() =
if (this.result !is Type && this.result != null) (this.result as Array<*>)[this.index] as Type else this.result as Type
override val source: Any
get() = Any()
init {
this.result = ReflectionUtils.invokeMethod(method, provider.type)
}
@Throws(IOException::class, ClassNotFoundException::class)
private fun readObject(inputStream: ObjectInputStream) {
inputStream.defaultReadObject()
val method = ReflectionUtils.findMethod(this.provider.type.javaClass, this.methodName)
this.result = ReflectionUtils.invokeMethod(method, this.provider.type)
}
}
@@ -0,0 +1,10 @@
package com.h3xstream.findsecbugs.deserialisation
import java.io.Serializable
import java.lang.reflect.Type
interface TypeProvider : Serializable {
val type: Type
val source: Any
}
@@ -1,4 +1,4 @@
package org.apache.commons.collections4.comparators;
package org.apache.commons.collections4;
public interface Transformer<I, O> {
O transform(I var1);
@@ -1,5 +1,7 @@
package org.apache.commons.collections4.comparators;
import org.apache.commons.collections4.Transformer;
import java.io.Serializable;
import java.util.Comparator;
@@ -96,7 +96,9 @@ public void detectSpringGadget() throws Exception {
public void detectCommonsCollectionAndSpringGadgetInKotlin() throws Exception {
//Locate test code
String[] files = {
getClassFilePath("bytecode_samples/kotlin_deserialisation-gadget.jar"),
getClassFilePath("com/h3xstream/findsecbugs/deserialisation/TypeProvider"),
getClassFilePath("com/h3xstream/findsecbugs/deserialisation/InvokerTransformer"),
getClassFilePath("com/h3xstream/findsecbugs/deserialisation/MethodInvokeTypeProvider")
};
//Run the analysis
@@ -1,6 +1,6 @@
package testcode.serial.commonscollections4;
import org.apache.commons.collections4.comparators.Transformer;
import org.apache.commons.collections4.Transformer;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;

0 comments on commit f6ace14

Please sign in to comment.