RMI-Remote Method Invocator

什么是RMI?RMI有什么用?

RMI允许用户通过数据传输,调用远程方法,在远程服务器处理数据。例如将1,3传到远程服务器的加法运算器,加法运算器处理后再把结果4传回来,从而实现远程调用。

RMI怎么使用?

  • RMI调用

p神的一个图

image

其中的流程就是开启RMI服务器--》将目标方法绑定到RMI Register上--》cli调用时,先去询问RMI regitser,找到方法对应的名字--》判断是否有目标方法--》有就进行方法调用。

  • 获取RMI所有绑定的对象
String[] list = Naming.list("rmi://127.0.0.1:1099");
  • RMI和web或者说servlet有很多相似的地方,而且支持多重绑定
private void start() throws Exception{
        RemoteHello remoteHello = new RemoteHello();
        LocateRegistry.createRegistry(1099);
        Naming.bind("rmi://127.0.0.1:1099/Hello",remoteHello);
        Naming.bind("rmi://127.0.0.1:1099/Hello1",remoteHello);
    }

用list可以得到
image

透过流量包分析rmi

window上的流量太多了,混淆太高,没办法,只能起一个虚拟机

image

很少做具体流量内容分析,有点吃力。计网的知识还需要落地

捋清了流程就是先和Register建立tcp连接--》发送查询请求--》存在即返回一个端口号,让客户端去访问--》客户端拿着返回的端口去进行RMI--》完成调用

初步了解了RMI,那怎么攻击RMI Register呢?

RMI就是一种对象后台,通过这个后台,我们可以操作绑定的对象。

那我们可不可以对Register进行绑定呢?例如远程给Register绑定一个对象。

try {
            Naming.bind("rmi://10.1.1.1:1099/Hello3", (Remote) new RemoteTest());
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (RemoteException | AlreadyBoundException e) {
            e.printStackTrace();
        }

image

可以看到当以上述的方式继续绑定一个对象时,是可以实现的。那我不经思考--》如果在我调用前,先绑定一个恶意的对象上去,再去调用岂不是很nice??

但后面发现,似乎会对请求方进行检测,必须为本地绑定才行。。。

对RMI的重思考~~~

RMI Server就是一个服务,可以进行路径或者叫名称绑定,和web类似。操作上没啥高级的

那怎么攻击RMI呢?
按照上面的说法,似乎如果想攻击RMI Register,必须服务器端自带可控对象,不然正常情况下就不可能被攻击。

RMI利用CodeBase进行RCE(简单介绍下)
就是最开始java能在浏览器中运行,类不可能都在本地,所以避免不了远程加载。此时codeBase就是用于指明类的路径,不仅支持类似ClassPath这种本地的,更主要的是可以加载远程的。既然可以加载远程的,那不就gg了。但由于现在基本不可能被利用。所以目前就简要分析下。

从原理分析codebase如何传递到被利用

分析上面抓到的数据包
image

0xACED 是java反序列化数据

使用NickstaDB / SerializationDumper来分析java的反序列化数据

java -jar SerializationDumper.jar "aced0005770f014183be440000017d6eb0a0238009737d00000002000f6a6176612e726d692e52656d6f74650016524d49536572766572244952656d6f746548656c6c6f70787200176a6176612e6c616e672e7265666c6563742e50726f7879e127da20cc1043cb0200014c0001687400254c6a6176612f6c616e672f7265666c6563742f496e766f636174696f6e48616e646c65723b7078707372002d6a6176612e726d692e7365727665722e52656d6f74654f626a656374496e766f636174696f6e48616e646c65720000000000000002020000707872001c6a6176612e726d692e7365727665722e52656d6f74654f626a656374d361b4910c61331e0300007078707732000a556e696361737452656600093132372e302e312e3100008fc704b70c39403fd45e4183be440000017d6eb0a02380010178"

协议格式如下,根据java官方序列化协议的文档进行对照。

STREAM_MAGIC - 0xac ed
STREAM_VERSION - 0x00 05
Contents
  TC_BLOCKDATA - 0x77
    Length - 15 - 0x0f
    Contents - 0x014183be440000017d6eb0a0238009
  TC_OBJECT - 0x73
    TC_PROXYCLASSDESC - 0x7d
      newHandle 0x00 7e 00 00
      Interface count - 2 - 0x00 00 00 02
      proxyInterfaceNames
        0:
          Length - 15 - 0x00 0f
          Value - java.rmi.Remote - 0x6a6176612e726d692e52656d6f7465
        1:
          Length - 22 - 0x00 16
          Value - RMIServer$IRemoteHello - 0x524d49536572766572244952656d6f746548656c6c6f
      classAnnotations
        TC_NULL - 0x70
        TC_ENDBLOCKDATA - 0x78
      superClassDesc
        TC_CLASSDESC - 0x72
          className
            Length - 23 - 0x00 17
            Value - java.lang.reflect.Proxy - 0x6a6176612e6c616e672e7265666c6563742e50726f7879
          serialVersionUID - 0xe1 27 da 20 cc 10 43 cb
          newHandle 0x00 7e 00 01
          classDescFlags - 0x02 - SC_SERIALIZABLE
          fieldCount - 1 - 0x00 01
          Fields
            0:
              Object - L - 0x4c
              fieldName
                Length - 1 - 0x00 01
                Value - h - 0x68
              className1
                TC_STRING - 0x74
                  newHandle 0x00 7e 00 02
                  Length - 37 - 0x00 25
                  Value - Ljava/lang/reflect/InvocationHandler; - 0x4c6a6176612f6c616e672f7265666c6563742f496e766f636174696f6e48616e646c65723b
          classAnnotations
            TC_NULL - 0x70
            TC_ENDBLOCKDATA - 0x78
          superClassDesc
            TC_NULL - 0x70
    newHandle 0x00 7e 00 03
    classdata
      java.lang.reflect.Proxy
        values
          h
            (object)
              TC_OBJECT - 0x73
                TC_CLASSDESC - 0x72
                  className
                    Length - 45 - 0x00 2d
                    Value - java.rmi.server.RemoteObjectInvocationHandler - 0x6a6176612e726d692e7365727665722e52656d6f74654f626a656374496e766f636174696f6e48616e646c6572
                  serialVersionUID - 0x00 00 00 00 00 00 00 02
                  newHandle 0x00 7e 00 04
                  classDescFlags - 0x02 - SC_SERIALIZABLE
                  fieldCount - 0 - 0x00 00
                  classAnnotations
                    TC_NULL - 0x70
                    TC_ENDBLOCKDATA - 0x78
                  superClassDesc
                    TC_CLASSDESC - 0x72
                      className
                        Length - 28 - 0x00 1c
                        Value - java.rmi.server.RemoteObject - 0x6a6176612e726d692e7365727665722e52656d6f74654f626a656374
                      serialVersionUID - 0xd3 61 b4 91 0c 61 33 1e
                      newHandle 0x00 7e 00 05
                      classDescFlags - 0x03 - SC_WRITE_METHOD | SC_SERIALIZABLE
                      fieldCount - 0 - 0x00 00
                      classAnnotations
                        TC_NULL - 0x70
                        TC_ENDBLOCKDATA - 0x78
                      superClassDesc
                        TC_NULL - 0x70
                newHandle 0x00 7e 00 06
                classdata
                  java.rmi.server.RemoteObject
                    values
                    objectAnnotation
                      TC_BLOCKDATA - 0x77
                        Length - 50 - 0x32
                        Contents - 0x000a556e696361737452656600093132372e302e312e3100008fc704b70c39403fd45e4183be440000017d6eb0a023800101
                      TC_ENDBLOCKDATA - 0x78
                  java.rmi.server.RemoteObjectInvocationHandler
                    values
      <Dynamic Proxy Class>

后面的知识区有些模糊,就先不讨论。想了解可以看p神的java安全漫谈

更多文章请关注《万象专栏》