JAVA安全—SpringBoot框架MyBatis注入Thymeleaf模板注入
前言
之前我们讲了JAVA的一些组件安全,比如Log4j,fastjson。今天讲一下框架安全,就是这个也是比较常见的SpringBoot框架。
SpringBoot框架
Spring Boot是由Pivotal团队提供的一套开源框架,可以简化spring应用的创建及部署。它提供了丰富的Spring模块化支持,可以帮助开发者更轻松快捷地构建出企业级应用。Spring Boot通过自动配置功能,降低了复杂性,同时支持基于JVM的多种开源框架,可以缩短开发时间,使开发更加简单和高效。
先来了解一下这个框架里面常见的东西
路由映射
@RequestMapping, @GetMapping, 和 @PostMapping 注解用于定义HTTP请求的映射路径。
@RequestMapping 是通用注解,而 @GetMapping 和 @PostMapping 是其简化形式,分别用于处理GET和POST请求。
参数传递
@RequestParam 注解用于从HTTP请求中提取参数,使得控制器方法可以访问并使用这些参数。
数据响应
@RestController 注解用于标识一个类是RESTful风格的控制器,它包含了 @ResponseBody 和 @Controller 的功能。
@ResponseBody 表示方法的返回值将直接作为HTTP响应体返回给客户端。
@Controller 通常用于标识传统的MVC控制器,而 @RestController 更适用于RESTful风格的控制器。
项目构建
新建一个项目。

这个服务器URL是默认从官网获取架构,如果说你觉得网络卡的话,你可以改为https://start.aliyun.com,去从阿里云获取架构。

版本的话目前最新的就是3.4.0了。

如果你前面用的是阿里云的架构网址,那么就会只显示2.x的版本,就是说阿里云认为这几个版本比较稳定,所以只提供这几个。

我这里网速慢,就用阿里云的2.3.16版本,依赖选择Spring Web。

创建成功之后可以看到这个框架自带了很多外部库,什么Log4j啊啥的,就不需要我们自己去下载了,比较方便。

新建一个类叫controller.IndexController。

我们写入以下代码。
package com.sf.maven.springboot.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class IndexController {@RequestMapping("/wlw")public String index(){return "wlw";}}
接着回到Application.java这里运行起来。

此时便可以在控制台这里看到启动了8080端口也就是Tomcat服务,这是它自带的我并没有去配置它。

如果端口被占用的话,你可以在resources目录下的application.properties配置文件进行修改。

访问8080端口,返回的确是我们写入的东西。

我们稍微修改一下,添加POST请求和GET请求。
package com.sf.maven.springboot.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class IndexController {@RequestMapping(value = "/wlwget",method = RequestMethod.GET) //get请求public String getmethod(){return "wlwget";}@RequestMapping(value = "/wlwpost",method = RequestMethod.POST) //post请求public String postmethod(){return "wlwpost";}}
我们运行起来再访问一下,可以看大此时我们再访问wlw的话会报错,这个就是典型的SpringBoot报错页面。

get提交wlwget,则是正常返回。

我们用postman这个工具去请求wlwpost,也是正常返回信息。

现在我们修改代码添加参数来试一下,稍微修改一下代码,传递参数name。

get请求。
post请求。

MyBatis注入
MyBatis是SpringBoot中用的较多的一个数据库驱动,它存在的一个安全问题就是,使用MyBatis的时候遇到了#{}和${}可能导致sql注入的问题。
先创建一个项目重新来吧,命名为MyBatis-demo。

依赖项就选择Spring web,MyBatis Framework,MySQL Driver。

数据库的话我这里是用phpstudy,简单方便,我是在user库里面新建一个user表来进行测试。

在pom文件这里可以看到,外部包都被导入了。

接着再来配置一下数据库连接,把src/main/resources/ 目录下的 application.properties文件改为application.yml

清空里面的内容。写入以下的内容。
spring:datasource:url: jdbc:mysql://localhost:3306/userusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driver

新建一个类叫entity.User。

接着我们先写入以下代码,要和数据库的字段对应。

然后右键选择生成,选择Setter和Getter,把显示的三个东西都选上确定即可。

自动生成了方法代码。

同理选择toStron()方法自动生成。

再新建一个类叫mapper.Usermapper。

写入以下的代码,创建sql查询的接口。
package com.sf.maven.mybatisdemo.mapper;import com.sf.maven.mybatisdemo.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;import java.util.List;@Mapper
public interface Usermapper {// ${id} 是拼接写法,#{id} 是预编译写法@Select("select * from name")//通过ID查询public List<User> findAll();@Select("select * from name where ID=1")public List<User> findID();
}
同理再创建一个constroller类去调用我们的sql查询,新建一个类叫constroller.Getnamecontroller,
这个和上面的那个 web 应用访问一样,就是返回数据为从数据库获取信息。
package com.sf.maven.mybatisdemo.constroller;
import com.sf.maven.mybatisdemo.entity.User;
import com.sf.maven.mybatisdemo.mapper.Usermapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;@RestController
public class Getnamecontroller {@Autowiredprivate Usermapper Usermapper;@GetMapping("/Getpasswd")//定义请求路径public List<User> getpasswd(@RequestParam Integer id) {List<User> all = Usermapper.findAll();//调用sql查询接口return all;}@GetMapping("/GetID")public List<User> getID() {List<User> all = Usermapper.findID();return all;}}
把搞好的项目运行起来,访问路径可以查看到表的内容,说明是执行了我们设定好的sql语句。


接下来就讲一下产生的安全问题,改一下刚才的代码。


运行起来访问一下,这次要加上参数才可以进行查询。

我们设置的sql语句是 select * from name where id like '%${id}%',此时我们只要把 id=1 的查询改为 id=1%' or 1=1# 即可产生sql注入,这是因为当参数拼接上去之后sql语句就变成这样子了
select * from name where id like '%1%' or 1=1#' 。
只是不知道为啥我这里会报错,sql语句没问题呀。

我索性去到数据库那里试一下,发现是可以执行没有报错,你妹的。

关于为啥会产生sql注入,可以看一下这篇文章,在Java中呢,sql注入是非常少的,但是不代表没有。
Mybatis 框架下 SQL 注入攻击的 3 种方式,真是防不胜防! - 知乎
【安全】mybatis中#{}和${}导致sql注入问题及解决办法_${}sql注入-CSDN博客
Thymeleaf模板注入
我们在浏览一些网站时,会发现有些网站的页面十分的精美,这是由于网站开发引用了一些模板。而在SpringBoot中,Thymeleaf是个不安全的模版,日常开发中语言切换页面,主题更换等传参导致的 SSTI 注入安全问题。
新建一个项目叫Thymeleaf demo。

依赖项选择Thymeleaf和Spring web。

新建一个类叫controller.thymeleafcontroller。

我们写入个比较简单的代码,什么意思呢,就是访问index,由于我没有使用模板渲染那么就会返回个Hello World。

运行起来访问index,确实返回了Hello World,我这里就比较简陋的测试一下,实际情况中一般都是十分精美的页面。

那么现在我们使用一下模板渲染,在配置文件中可以看到模板的路径为templates/。

我们在resources目录下新建一个templates目录。

写一个index.html文件当作模板。

修改一下调用文件,调用我们的index模板并输出hello wlw。

运行代码访问index,然而却并没有返回hello wlw,而是返回了index。

这是为啥呢,原来是@RestController包含了 @ResponseBody 和 @Controller 的功能。@ResponseBody index当做字符串显示操作,所以我们更换为@Controller 没有ResponseBody index那么就会当做资源文件去渲染。

改了之后再访问返回了hello wlw,说明成功调用了模板。

查看页面源码,发现和我们写的index.html文件差不多。

OK那么我们现在来看一下安全问题,上面我们说过安全问题就是由于模板的调用,我们可以看到当前的lang=ZH_CN就是调用了中文页面的模板。

当我们把lang的值换为en那么就会调用英文的模板,思考一下我们把lang的值换位Java代码是否能实现rce。

注入漏洞存在与3.0.0—3.0.11版本,2.x版本的应该也会存在漏洞,但是我们的这个包是从阿里云拉取的。阿里云的东西一般都比较稳定没啥漏洞,我们替换一下pom文件。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.springframework</groupId><artifactId>java-spring-thymeleaf</artifactId><version>1.0</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><!--latest--><version>2.2.0.RELEASE</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency></dependencies><properties><java.version>1.8</java.version></properties><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>
替换了之后我们可以看到版本变为了2.2.0release。

稍微修改一下调用文件,使其可以传递参数lang。

我们再新建一个index-en.html模板文件,啥也不用写。

运行代码访问啥也没有,因为我们模板啥也没写。

把index-en换成下面的Java代码,成功弹出计算机。
__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22calc%22).getInputStream()).next()%7d__::.x

至于poc怎么构造的后面有机会再说了,或者看一下以下文章。
thymeleaf模板注入学习与研究--查找与防御
Thymeleaf模板生成过程以及注入原因分析 - 先知社区
总结
本次从开发的方面讲了两个SpringBoot框架常见的安全问题,感觉有点强度了,哎。
最后,以上仅为个人的拙见,如何有不对的地方,欢迎各位师傅指正与补充,有兴趣的师傅可以一起交流学习。
相关文章:
JAVA安全—SpringBoot框架MyBatis注入Thymeleaf模板注入
前言 之前我们讲了JAVA的一些组件安全,比如Log4j,fastjson。今天讲一下框架安全,就是这个也是比较常见的SpringBoot框架。 SpringBoot框架 Spring Boot是由Pivotal团队提供的一套开源框架,可以简化spring应用的创建及部署。它提…...
【STM32系列】提升ADC采样精度的方法
资料地址 兆易创新GigaDevice-资料下载兆易创新GD32 MCU ADC简介 ADC转换包括采样、保持、量化、编码四个步骤。的采样电容上,即在采样开关 SW 关闭的过程中,外部输入信号通过外部的输入电阻 RAIN 和以及 ADC 采样电阻 RADC 对采样电容 CADC 充电。采样…...
前端面试如何出彩
1、原型链和作用域链说不太清,主要表现在寄生组合继承和extends继承的区别和new做了什么。2、推荐我的两篇文章:若川:面试官问:能否模拟实现JS的new操作符、若川:面试官问:JS的继承 3、数组构造函数上有哪些…...
Linux 切换用户的两种方法
sudo -su user1 与 su - user1 都可以让当前用户切换到 user1 的身份执行命令或进入该用户的交互式 Shell。但它们在权限认证方式、环境变量继承和 Shell 初始化过程等方面存在一些差异。 权限认证方式 su - user1 su 是 “switch user” 的缩写,默认情况下需要你输…...
Spring Boot 3 中Bean的配置和实例化详解
一、引言 在Java企业级开发领域,Spring Boot凭借其简洁、快速、高效的特点,迅速成为了众多开发者的首选框架。Spring Boot通过自动配置、起步依赖等特性,极大地简化了Spring应用的搭建和开发过程。而在Spring Boot的众多核心特性中ÿ…...
Vue实现留言板(实现增删改查)注意:自己引入Vue.js哦
代码: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><scri…...
IDEA创建Spring Boot项目配置阿里云Spring Initializr Server URL【详细教程-轻松学会】
1.首先打开idea选择新建项目 2.选择Spring Boot框架(就是选择Spring Initializr这个) 3.点击中间界面Server URL后面的三个点更换为阿里云的Server URL Idea中默认的Server URL地址:https://start.spring.io/ 修改为阿里云Server URL地址:https://star…...
读取电视剧MP4视频的每一帧,检测出现的每一个人脸并保存
检测效果还不错,就是追踪有点难做 import cv2 import mediapipe as mp import os from collections import defaultdict# pip install msvc-runtime# 初始化OpenCV的MultiTracker # multi_tracker = cv2.MultiTracker_create() # multi_tracker = cv2.legacy.MultiTracker_cre…...
HTML前端开发-- Iconfont 矢量图库使用简介
一、SVG 简介及基础语法 1. SVG 简介 SVG(Scalable Vector Graphics)是一种基于 XML 的矢量图形格式,用于在网页上显示二维图形。SVG 图形可以无限缩放而不会失真,非常适合用于图标、图表和复杂图形。SVG 文件是文本文件&#x…...
使用Allure作为测试报告生成器(Java+Selenium)
背景 JAVA项目中原先用Jenkinsseleniumselenium grid来日常测试UI并记录。 问题 当某一个testSuite失败时,当需要确认UI regression issue还是selenium test case自身的问题,需要去jenkins中查log,一般得到的是“Can not find element xxx…...
RocketMQ面试题合集
消费者获取消息是从Master Broker还是Slave Broker获取? Master Broker宕机,Slave Broker会自动切换为Master Broker吗? 这种Master-Slave模式不是彻底的高可用模式,他没法实现自动把Slave切换为Master。在RocketMQ 4.5之后&…...
Qt初识_对象树
个人主页:C忠实粉丝 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C忠实粉丝 原创 Qt初识_对象树 收录于专栏【Qt开发】 本专栏旨在分享学习Qt的一点学习笔记,欢迎大家在评论区交流讨论💌 目录 什么是对象树 为什么要引…...
axios的get和post请求,关于携带参数相关的讲解一下
在使用 Axios 发送 HTTP 请求时,GET 和 POST 请求携带参数的方式有所不同。以下是关于这两种请求方法携带参数的详细讲解: GET 请求携带参数 对于 GET 请求,参数通常附加在 URL 之后,以查询字符串的形式传递。 直接在 URL 中拼接…...
Vue前端开发-路由其他配置
在路由文件中,除了跳转配置外,还可以进行路径重定向配置,如果没有找到对应的地址,还可以实现404的配置,同时,如果某个页面需要权限登录,还可以进行路由守卫配置,接下来,分…...
框架建设实战7——定时任务组件
在金融系统中,或者其他对账系统里,往往离不开分布式定时任务。用来做查证或者重试处理。 分布式job目前一般有如下三种: 1.elastic job 当当出品,比较老牌。新公司用的应该不多了。 2.xxl-job 个人开源项目。便于二开;有简洁的后管配置界面,方便接入。 3.powerjob …...
mybatis 整合 ehcache
pom.xml <!-- ehcache依赖 --><dependency><groupId>org.mybatis.caches</groupId><artifactId>mybatis-ehcache</artifactId><version>1.1.0</version></dependency>ehcache.xml <?xml version"1.0" en…...
【PlantUML系列】用例图(三)
目录 一、组成部分 二、典型案例 一、组成部分 参与者(Actors):使用关键字 actor 后跟参与者的名称。用例(Use Cases):使用关键字 usecase 后跟用例的名称和编号(可选)。系统边界…...
发送请求时遇到了数据库完整性约束错误 1048 Column ‘platform‘ cannot be null
可以这样解决 在 Vue 2 中封装接口请求时,确保每次请求都包含 platform Header 参数的最佳实践是通过创建一个全局的 Axios 实例,并为这个实例设置默认的 Header。这样可以确保所有通过该实例发送的请求都会自动包含 platform 参数。此外,你…...
三菱FX3U模拟量产品的介绍
FX3u可编程控制器模拟量产品包括:特殊适配器、特殊功能模块的连接 1、连接在FX3U可编程控制器的左侧。 2、连接特殊适配器时,需要功能扩展板。 3、最多可以连接4台模拟量特殊适配器。 4、使用高速输入输出特殊适配器时,请将模拟量特殊适配器连…...
pdf转图片
目录 pdf2image库 PyMuPDF库 python-office库 pdfplumber库 pdf2image库 安装:pip install pdf2image 使用时会报错:pdf2image.exceptions.PDFInfoNotInstalledError: Unable to get page count. Is poppler installed and in PATH? 需要安装 po…...
低延时RS译码器优化设计【附代码】
✨ 长期致力于RS码、低延时、功耗优化、译码器研究工作,擅长数据搜集与处理、建模仿真、程序编写、仿真设计。 ✅ 专业定制毕设、代码 ✅ 如需沟通交流,点击《获取方式》 (1)改进型RiBM迭代展开算法加速关键方程求解: …...
文档版本混乱、变更无通知、示例代码过期?Perplexity DevDocs监控体系搭建指南(含GitHub Action自动告警模板)
更多请点击: https://intelliparadigm.com 第一章:文档版本混乱、变更无通知、示例代码过期?Perplexity DevDocs监控体系搭建指南(含GitHub Action自动告警模板) 核心痛点与监控目标 现代开发者文档(如 P…...
PPTTimer终极指南:Windows演示时间管理的免费开源解决方案
PPTTimer终极指南:Windows演示时间管理的免费开源解决方案 【免费下载链接】ppttimer 一个简易的 PPT 计时器 项目地址: https://gitcode.com/gh_mirrors/pp/ppttimer 在重要的演示、会议或培训中,时间控制往往成为成功的关键。你是否曾在演讲时频…...
地理学者必抢的AI协同时代入场券:NotebookLM+QGIS工作流搭建指南(仅限首批内测用户验证版)
更多请点击: https://intelliparadigm.com 第一章:NotebookLM地理学研究辅助的范式革命 从静态文献到动态知识图谱 NotebookLM 通过语义切片与向量对齐技术,将地理学经典文献(如《人文地理学导论》《自然地理学原理》ÿ…...
Git Common Errors
Git Common Errors 1. 这篇文章解决什么问题? Git 报错时,最容易让人慌的不是错误本身,而是不知道它在说哪一层出了问题。 常见错误包括: 1. not a git repository 2. remote origin already exists 3. failed to push some r…...
基于MCP与Apify构建自动化特许经营尽职调查智能体
1. 项目概述与核心价值最近在梳理一些自动化数据采集和商业智能分析的项目时,我遇到了一个非常有意思的工具:apifyforge/franchise-due-diligence-mcp。这个项目名字听起来有点长,但拆解一下就能明白它的核心价值——它是一个基于MCP…...
量子生成分类技术:原理、优势与应用解析
1. 量子生成分类技术概述量子生成分类(Quantum Generative Classification, QGC)是一种基于量子计算原理的新型机器学习范式,它从根本上改变了传统分类任务的实现方式。与常见的判别式学习方法不同,QGC采用生成式学习策略…...
处理器与FPGA异构SoM设计:架构、协同与工程实践
1. 项目概述:当“大脑”与“加速器”合二为一最近几年,但凡涉及到边缘计算、工业视觉或者通信基带这些对实时性和算力有双重“压榨”需求的领域,传统的单一架构芯片越来越显得力不从心。CPU(中央处理器)擅长复杂的逻辑…...
从零构建Claude代码:深入Transformer架构与自回归生成实现
1. 项目概述:从零构建你自己的Claude代码最近在开发者社区里,一个名为“woodx9/build-your-claude-code-from-scratch”的项目引起了我的注意。这个标题直译过来就是“从零开始构建你的Claude代码”,它指向了一个非常具体且富有挑战性的目标&…...
Java后端工程师必备:系统学习大模型应用开发(收藏版)
本文深入探讨了Java后端工程师如何系统性地学习AI应用开发,从基础的CRUD操作到大模型的集成,包括RAG、Tool Calling、MCP、Agent等关键技术。文章强调了AI应用开发不仅是调用大模型接口,而是将大模型能力融入真实业务系统,实现理解…...
