最近ctf比赛使用java作为web开发语言的题目越来越多,Fastjson的漏洞是一个很重要的rce。学会审计Fastjson漏洞,更有机会挖出高质量的漏洞,所以还是得多学习学习的。
Fastjson简介
Fastjson是一个Java库,可以用来将Java对象转换成它们的JSON表示。它还可以用于将JSON字符串转换为等效的Java对象。Fastjson可以处理任意Java对象,包括您没有源代码的现有对象。
Fastjson相对其他JSON库的特点是快速且简洁,但是却被屡屡爆出漏洞。
Fastjson可通过这个链接获取 https://github.com/alibaba/fastjson
漏洞分析
以下代码作为一个测试用例
package serialize;
import java.io.IOException;
import com.alibaba.fastjson.JSON;
class T1{
public T1() throws IOException{
Runtime.getRuntime().exec("calc");
}
}
public class Test {
public static void main(String[] args) {
Object object = JSON.parseObject("{\"@type\": \"serialize.T1\"}");
System.out.println(object);
}
}
实际环境中,一般不会有这样的代码可以直接供我们去触发,下面尝试使用TemplatesImpl类实现远程代码执行。
public static void main(String[] args) {
// Open calc in mac
String payload =
"{
\"@type\":
\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\",
\"_bytecodes\": [\"这里写入payload,需要进行Base64编码\"],
\"_name\": \"lightless\",
\"_tfactory\":{
},
\"_outputProperties\":{ }}";
JSON.parseObject(payload, Feature.SupportNonPublicField);
}
这里作为测试命令执行的main方法。
这里分析一下,使用TemplatesImpl的利用链。知道了利用链,我们就知道为什么上面的payload是这样构造了。
在TypeUtils.class下打断点,发现加载了TemplatesImpl类
我们可以从payload大致看出要调用的方法
在com\alibaba\fastjson\parser\deserializer\JavaBeanDeserializer.class下,有一个帮我们去掉payload中下划线的操作
这里先处理的就是_bytecodes,这里会进入com\alibaba\fastjson\serializer\ObjectArrayCodec.class下的deserialize方法
继续跟进,这里有base解码的操作
下面摘抄一段关于_tfactory的说明
fastjson只会反序列化公开的属性和域,而com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
中_bytecodes
却是私有属性,_name
也是私有域,所以在parseObject的时候需要设置Feature.SupportNonPublicField,这样_bytecode
s字段才会被反序列化。_tfactory
这个字段在TemplatesImpl既没有get方法也没有set方法,这没关系,我们设置_tfactory为{ }
,fastjson会调用其无参构造函数得tfactory对象,这样就解决了某些版本中在defineTransletClasses()用到会引用_tfactory属性导致异常退出。
现在我们回过头来看TemplatesImpl类中有关对象初始化的那个部分。
transformer = new TransformerImpl(getTransletInstance(), _outputProperties,_indentNumber, _tfactory);
由于这里调用了getTransletInstance()函数,在该函数处打下断点观察。
这里的_class对象已经成为了我们传入的对象,同时使用用newInstance生成一个java实例
可以看到,如果我们进入下一条语句,此时计算器就会弹出。