点击上方蓝色“程序猿DD”,选择“设为星标”

回复“资源”获取独家整理的学习资料!

作者 | ale_wong@云影实验室

来源 | https://www.anquanke.com/post/id/219731

前言

迟到的Fastjson反序列化漏洞分析,按照国际惯例这次依旧没有放poc。道理还是那个道理,但利用方式多种多样。除了之前放出来用于文件读写的利用方式以外其实还可以用于SSRF。

一、漏洞概述

在之前其他大佬文章中,我们可以看到的利用方式为通过清空指定文件向指定文件写入指定内容(用到第三方库)。当gadget是继承的第一个类的子类的时候,满足攻击fastjson的条件。此时寻找到的需要gadget满足能利用期望类绕过checkAutoType。

本文分析了一种利用反序列化指向fastjson自带类进行攻击利用,可实现文件读取、SSRF攻击等。

二、调试分析

1. 漏洞调试

从更新的补丁中可以看到expectClass类新增了三个方法分别为:

java.lang.Runnable、java.lang.Readable、java.lang.AutoCloseable

首先,parseObject方法对传入的数据进行处理。通过词法解析得到类型名称,如果不是数字则开始checkAutoType检查。

if (!allDigits) {clazz = config.checkAutoType(typeName, null, lexer.getFeatures());}

当传入的数据不是数字的时候,默认设置期望类为空,进入checkAutoType进行检查传入的类。

final boolean expectClassFlag;
if (expectClass == null) {expectClassFlag = false;
} else {if (expectClass == Object.class|| expectClass == Serializable.class|| expectClass == Cloneable.class|| expectClass == Closeable.class|| expectClass == EventListener.class|| expectClass == Iterable.class|| expectClass == Collection.class) {expectClassFlag = false;} else {expectClassFlag = true;}
}

判断期望类,此时期望类为null。往下走的代码中,autoCloseable 满足不在白名单内,不在黑名单内,autoTypeSupport没有开启,expectClassFlag为false。

其中:

A.计算哈希值进行内部白名单匹配

B.计算哈希值进行内部黑名单匹配

C.非内部白名单且开启autoTypeSupport或者是期望类的,进行hash校验白名单acceptHashCodes、黑名单denyHashCodes。如果在acceptHashCodes内则进行加载( defaultClassLoader),在黑名单内则抛出 autoType is not support。

clazz = TypeUtils.getClassFromMapping(typeName);

满足条件C后来到clazz的赋值,解析来的代码中对clazz进行了各种判断

clazz = TypeUtils.getClassFromMapping(typeName);

从明文缓存中取出autoCloseable赋值给 clazz

clazz = TypeUtils.getClassFromMapping(typeName);if (clazz == null) {clazz = deserializers.findClass(typeName);
}if (clazz == null) {clazz = typeMapping.get(typeName);
}if (internalWhite) {clazz = TypeUtils.loadClass(typeName, defaultClassLoader, true);
}if (clazz != null) {if (expectClass != null&& clazz != java.util.HashMap.class&& !expectClass.isAssignableFrom(clazz)) {throw new JSONException("type not match. " + typeName + " -> " + expectClass.getName());}return clazz;

当clazz不为空时,expectClassFlag为空不满足条件,返回clazz,至此,第一次的checkAutoType检查完毕。

ObjectDeserializer deserializer = config.getDeserializer(clazz);
Class deserClass = deserializer.getClass();
if (JavaBeanDeserializer.class.isAssignableFrom(deserClass)&& deserClass != JavaBeanDeserializer.class&& deserClass != ThrowableDeserializer.class) {this.setResolveStatus(NONE);
} else if (deserializer instanceof MapDeserializer) {this.setResolveStatus(NONE);
}
Object obj = deserializer.deserialze(this, clazz, fieldName);
return obj;

将检查完毕的autoCloseable进行反序列化,该类使用的是JavaBeanDeserializer反序列化器,从MapDeserializer中继承

public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {return deserialze(parser, type, fieldName, 0);
}public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName, int features) {return deserialze(parser, type, fieldName, null, features, null);
}//进入后代码如下
if ((typeKey != null && typeKey.equals(key))|| JSON.DEFAULT_TYPE_KEY == key) {lexer.nextTokenWithColon(JSONToken.LITERAL_STRING);if (lexer.token() == JSONToken.LITERAL_STRING) {String typeName = lexer.stringVal();lexer.nextToken(JSONToken.COMMA);if (typeName.equals(beanInfo.typeName)|| parser.isEnabled(Feature.IgnoreAutoType)) {// beanInfo.typeName是autoCloseable ,但IgnoreAutoType没有开启   if (lexer.token() == JSONToken.RBRACE) {lexer.nextToken();break;}continue;}//不满足条件所以这块代码被跳过了

JSON.DEFAULT_TYPE_KEY 为@type ,并给它赋值传入的key @type ,将第二个类也就是这次 的gadget传入

if (deserializer == null) {Class<?> expectClass = TypeUtils.getClass(type);userType = config.checkAutoType(typeName, expectClass, lexer.getFeatures());deserializer = parser.getConfig().getDeserializer(userType);
}

期望类在这里发生了变化,expectClass的值变为java.lang.AutoCloseable,typeName为gadget,

boolean jsonType = false;InputStream is = null;try {String resource = typeName.replace('.', '/') + ".class";if (defaultClassLoader != null) {is = defaultClassLoader.getResourceAsStream(resource);} else {is = ParserConfig.class.getClassLoader().getResourceAsStream(resource);//开了一个class文件的输入流}if (is != null) {ClassReader classReader = new ClassReader(is, true);//new reader工具TypeCollector visitor = new TypeCollector("<clinit>", new Class[0]);classReader.accept(visitor);jsonType = visitor.hasJsonType();}} catch (Exception e) {// skip} finally {IOUtils.close(is);//关闭流 JarURLConnection$JarURLInputStream}

来到JSONType注解,取typename gadget转换变为路径,resource通过将 “.” 替换为”/“得到路径 。其实已经开始读取gadget了,它本意应该是加载AutoCloseable。

public ClassReader(InputStream is, boolean readAnnotations) throws IOException {this.readAnnotations = readAnnotations;{ByteArrayOutputStream out = new ByteArrayOutputStream();byte[] buf = new byte[1024];for (; ; ) {int len = is.read(buf);if (len == -1) {break;}if (len > 0) {out.write(buf, 0, len);}}is.close();this.b = out.toByteArray();}

可以看到这里有读取文件的功能。所以之前网传的POC可能是利用这里这个特性(?)留意一下以后研究…

if (autoTypeSupport || jsonType || expectClassFlag) {boolean cacheClass = autoTypeSupport || jsonType;clazz = TypeUtils.loadClass(typeName, defaultClassLoader, cacheClass);//开始加载gadget
}
if (expectClass != null) {if (expectClass.isAssignableFrom(clazz)) {//判断里面的类是否为继承类TypeUtils.addMapping(typeName, clazz);return clazz;} else {throw new JSONException("type not match. " + typeName + " -> " + expectClass.getName());}
}

isAssignableFrom()这个方法用于判断里面的类是否为继承类,当利用了java.lang.AutoCloseable这个方法去攻击fastjson,那么后续反序列化的链路需要是继承于该类的子类。

TypeUtils.addMapping(typeName, clazz)这一步成功把gadget加入缓存中并返回被赋值gadget的clazz.

checkAutoType正式检查完毕,此时用deserializer = parser.getConfig().getDeserializer(userType); userType既gadget进行反序列化。

private void xxTryOnly(boolean isXXXXeconnect, Properties mergedProps) throws XXXException {Exception connectionNotEstablishedBecause = null;try {coreConnect(mergedProps);this.connectionId = this.io.getThreadId();this.isClosed = false;

进入coreConnect()

在这里进行连接。至此漏洞利用完结。

2. 总结

在本次反序列化漏洞中,笔者认为关键点在于找到合适并且可利用的常用jar包中的gadget。gadget在被反序列化后即可执行类里的恶意的功能(不仅限于RCE还包括任意文件读取/创建,SSRF等)。也可以使本漏洞得到最大化的利用。

三、参考考链接

  • https://b1ue.cn/archives/348.html

  • https://daybr4ak.github.io/2020/07/20/fastjson%201.6.68%20autotype%20bypass/

往期推荐

音效摸鱼还不够爽?试试IDE里打几盘魂斗罗?

3折购书优惠码限时抢,第二波书单来了!

面试:知道 CopyOnWriteArrayList 吗?

居然还有人在用 System.out.println打日志的吗?

不错的秒杀系统架构分析与实战!

一个让你敲代码的同时,找回童年乐趣的 IntelliJ 插件

扫一扫,关注我

一起学习,一起进步

每周赠书,福利不断

深度内容

推荐加入

最近热门内容回顾   #技术人系列

Fastjson 1.2.68版本反序列化漏洞分析篇相关推荐

  1. Fastjson 1.2.22-24 反序列化漏洞分析

    目录 0x00 废话 0x01 简单介绍 FastJson的简单使用 0x02 原理分析 分析POC 调试分析 0x03 复现过程 0x04 参考文章 0x00 废话 balabala 开始 0x01 ...

  2. MySQLJDBC反序列化漏洞分析

    JDBC反序列化漏洞 Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数 ...

  3. tomcat源码分析_CVE-2020-9484 tomcat session反序列化漏洞分析

    作者:N1gh5合天智汇 title: CVE-2020-9484 tomcat session反序列化漏洞分析 tags: CVE,Tomcat,反序列化 grammar_cjkRuby: true ...

  4. commons-collections反序列化漏洞分析——远程代码执行

    commons-collections反序列化漏洞分析--远程代码执行 命令执行以及通过反射进行命令执行 这里先说说java里面的命令执行.其实java的命令执行和PHP类似,PHP一般通过eval和 ...

  5. XStream反序列化漏洞分析

    XStream反序列化漏洞分析 XStream反序列化漏洞分析 代理模式 EventHandler XStream 生成payload XStream流程分析 写在最后 XStream反序列化漏洞分析 ...

  6. ECSHOP全版本注入漏洞分析

    ECSHOP全版本注入漏洞分析 2014-04-03 10:34:52|  分类: Pentest-skills |举报 |字号 订阅 下载LOFTER 我的照片书  | 初学PHP,看了两天语法,找 ...

  7. thinkphp5.0.24反序列化漏洞分析

    thinkphp5.0.24反序列化漏洞分析 文章目录 thinkphp5.0.24反序列化漏洞分析 具体分析 反序列化起点 toArray getRelationData分析 $modelRelat ...

  8. fastjson反序列化map_最新fastjson反序列化漏洞分析

    前言 写的有点多,可能对师傅们来说比较啰嗦,不过这么写完感觉自己也就明白了 poc newPoc.javaimport com.alibaba.fastjson.JSON; public class ...

  9. fastjson 序列化 不包括转义字符_CVE-2020-14644 weblogic iiop反序列化漏洞分析

    报告编号:B6-2020-081101 报告来源:360CERT 报告作者:ph4nt0mer 更新日期:2020-08-11 0x01 weblogic 受影响版本 Oracle WebLogic ...

最新文章

  1. Serverless 时代 DevOps 的最佳打开方式
  2. 我python写的闭包为什么效率很低_GitHub - llzhi001/interview_python_practice: interview 面试题 CS-Notes之ME-技术总结...
  3. IOI 2007 Sail (线段树+贪心)
  4. docker 报错 Container is not running
  5. NG Updata(升级)
  6. preprocessor预处理器
  7. Python网络编程之socket
  8. 32位微型计算机原理接口,32位微机原理与接口实验箱
  9. python 构建来源gis_Python语言在ArcGIS环境中的应用.pptx
  10. python2000个5除以84的余数_python中负数除法的求商和取余的问题
  11. 面对传统ie工时分析工具痛点,Vioovi的ECRS霸气出手了!
  12. linux下java的日志在哪里,Linux下的系统日志管理
  13. 微信小程序-输入框输入文字后,将光标移到文字中间,接着输入文字后光标又自动跳到最后...
  14. 论一个优秀的小牛论坛管理员(转:五只鹳狸猿进笼观猴,各留一只爪)
  15. Socket的超时时间
  16. bash通配符(wildcard)和特殊符号
  17. Python+大数据-数据处理与分析-pandas快速入门
  18. 5分绩点转4分_4分绩点与百分制转换方法
  19. Vmware ESXi安装群晖Synology DSM 5.x
  20. 移动端SEO优化需要怎么做排名?

热门文章

  1. spring MVC之返回JSON数据(Spring3.0 MVC+Jackson+AJAX)
  2. pycharm 添加数据库驱动
  3. 漏洞高危 中危 低危的划分标准
  4. 重载内核全程分析笔记
  5. 修正后的SYSTEM_THREADS与SYSTEM_PROCESSES结构体
  6. MFC中CArray类原理及其应用
  7. TCP/IP详解--学习笔记(10)-TCP连接的建立与中止
  8. TCP/IP详解--学习笔记(4)-ICMP协议,ping和Traceroute
  9. openstack-Mitaka Glance上传镜像报错
  10. javabean反射改字段内容_BAT程序员编写:深入理解 Java 反射和动态代理源码分析...