SpringBoot

介绍

Spring Boot是由Pivotal团队提供的一套开源框架,可以简化spring应用的创建及部署。它提供了丰富的Spring模块化支持,可以帮助开发者更轻松快捷地构建出企业级应用。Spring Boot通过自动配置功能,降低了复杂性,同时支持基于JVM的多种开源框架,可以缩短开发时间,使开发更加简单和高效。

Web应用-路由响应

创建项目

选择Spring Initializr

修改服务器URL:https://start.aliyun.com(速度更快版本更稳定)

img

img

新建文件controller/IndexController

image-20250105212242572

image-20250105214314327

访问错误路由,触发springboot经典报错

image-20250105213521729

无参数:

get访问attackxuget,触发getindex方法,页面回显get test

image-20250105213228733

post访问attackxupost,触发postindex方法,页面回显post test

image-20250105213427716

有参数:

get访问attackxu_get,触发get_g方法,页面回显“get test”和传递的参数name值

image-20250105214356505

get访问attackxu_post,触发post_p方法,页面回显“post test”和传递的参数name值

image-20250105214510637

代码

package cn.attackxu.springboottest.controller;

import org.springframework.web.bind.annotation.*;

@RestController//指示让方法的回显值作为页面的相应内容
public class IndexController {
//无参数
@RequestMapping(value = "/attackxuget",method = RequestMethod.GET)
//@GetMapping("/attackxuget")或者使用第二种方法声明路由
//Get路由,当GET访问/attackxuget时会触发getindex方法,回显“get test”
public String getindex(){
return "get test";
}

@RequestMapping(value = "/attackxupost",method = RequestMethod.POST)
public String postindex(){
return "post test";
}

//有参数
// 指定GET请求的访问路由,带参数名name
@RequestMapping(value = "/attackxuget_g",method = RequestMethod.GET)
public String get_g(@RequestParam String name){
return "get test"+name;
}
// 指定POST请求的访问路由,带参数名name
@RequestMapping(value = "/attackxupost_p",method = RequestMethod.POST)
public String post_p(@RequestParam String name){
return "post test"+name;
}
}

数据库应用-Mybatis

在 JAVA 中分析 SQL 注入,采用什么数据库驱动,其使用访问数据库方法不同,所以造成的安全问题也不同。

创建项目

image-20250105215358626

image-20250105215508142

phpstudy开启mysql

项目添加 Mybatis & 数据库驱动

  • 若创建项目时选择了 MySQL Driver 和 MyBatis Framework 两个依赖,则项目文件 pom.xml 中会自动添加下面内容
  • 创建项目时若未选择上述两个依赖,则需要手动在 pom.xml 中的 dependencies 标签中添加以下内容
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>

image-20250105220029579

项目配置数据库连接信息

默认配置信息文件为 src/main/resources/ 目录下的 application.properties,这里手动改为了 application.yml

然后清空文件内容,写入下面代码

spring:
datasource:
url: jdbc:mysql://localhost:3306/demo01
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver

image-20250105220324322

创建 User 类用来操作数据库数据

创建entity.User,生成get(),set(),tostring()方法

image-20250105221144413

package cn.attackxu.springbootmybatils.entity;

public class User {
private Integer id;
private String username;
private String password;

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

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;
}

@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}

创建 Mapper 动态接口代理类实现

image-20250105221317249

package cn.attackxu.springbootmybatils.mapper;

import cn.attackxu.springbootmybatils.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface UserMapper {
@Select("select * from admin")
public List<User> findAll();

@Select("select * from admin where id=1")
public List<User> findID();
}

创建 Controller 实现 Web 访问调用

package cn.attackxu.springbootmybatils.controller;

import cn.attackxu.springbootmybatils.entity.User;
import cn.attackxu.springbootmybatils.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 GetadminController {
//调用UserMapper
@Autowired
private UserMapper UserMapper;

//路由地址
@GetMapping("/getadmin")
//方法类型要和返回值类型对应List<User>
public List<User> getadmindata(){
List<User> all= UserMapper.findAll();//引入局部变量接收UserMapper.findAll()的值,并回显到页面
return all;
}

@GetMapping("/getid")
//方法类型要和返回值类型对应List<User>
public List<User> getadminid(){
List<User> all= UserMapper.findID();//引入局部变量接收UserMapper.findAll()的值,并回显到页面
return all;
}


}

查询实现

配置完成后,浏览器访问/getadmin,触发getadmindata()方法,回显查询结果,与数据库一致

image-20250105224551255

image-20250105224601066

访问/getid

image-20250105224648085

image-20250105224658514

安全问题-mybatis sql语句注入风险

#和$符号

三种可注入情况

模版引擎-Thymeleaf

不安全的模版版本
日常开发中:语言切换页面,主题更换等传参导致的 SSTI 注入安全问题
漏洞参考:https://mp.weixin.qq.com/s/NueP4ohS2vSeRCdx4A7yOg

创建项目

image-20250105230907878

image-20250105230936032

使用模板渲染,必须在resources目录下创建templates存放html文件

image-20250105231140653

遇到问题:路径访问并没有从模板渲染,而是当成字符串显示操作

img

原因:@RestController包含了 @ResponseBody 和 @Controller 的功能。@ResponseBody index当做字符串显示操作

解决方式:更换为@Controller 没有ResponseBody index当做资源文件去渲染

安全问题

日常开发中:语言切换页面,主题更换等传参导致的SSTI注入安全问题

案例:

例如:更换中英文页面模板

img

img

启动项目,并输入对应路由访问,指向渲染文件的文件名

注入为:

http://127.0.0.1:8080/?lang=%7bnew java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("calc").getInputStream()).next()%7d__::.x](http://127.0.0.1:8080/?lang=__%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22calc%22).getInputStream()).next()%7d::.x)

控制传入参数可以导致RCE

img

监控系统-Actuator

介绍

SpringBoot Actuator 模块提供了生产级别的功能,比如健康检查,审计,指标收集,HTTP 跟踪等,帮助我们监控和管理 Spring Boot 应用。

Actuator断点图

image-20250115102143915

创建项目

image-20250115094320241

image-20250115094412891

服务端

image-20250115095400512

image-20250115095432928

客户端

image-20250115095611870

配置监控

application.properties:

# 这个配置项是用于指定要暴露的web端点。*表示暴露所有端点。
management.endpoints.web.exposure.include=*
# 这个配置项用于指定是否显示健康检查的详细信息。always表示总是显示详细信息。
management.endpoint.health.show-details=always

安全问题

当我们访问路由,会泄露敏感信息

image-20250115102343005

安全配置:
在 application.properties 进行如下配置,关闭某些端点的启用,防止敏感信息泄露
从这里也可以看出来,/actuator/env 和 /actuator/heapdump 这两个目录下爆出来信息是很敏感

management.endpoint.env.enabled=false
management.endpoint.heapdump.enabled=false

再次尝试访问/actuator/env,/actuator/heapdump就会访问失败

heapdump泄露

通过访问得到相应的heapdump包,可以用工具进行分析,取到配置信息(分析提取出敏感信息(配置帐号密码,接口信息 数据库 短信 云应用等配置)

image-20250115102743300

访问路径下载文件

工具:JDumpSpider提取器

可以帮助我们自动化从中提取敏感信息,里面包含类信息,可以直接到很多配置信息

用法:

java -jar JDumpSpider-1.1-SNAPSHOT-full.jar heapdump文件

img

img

还可以使用jdk自带工具进行分析(需要手动分析,一般不适用,而且要掌握查询语法)

工具:jvisualvm分析器

img

img

其他安全问题:https://blog.csdn.net/drnrrwfs/article/details/125242990

还可以分析得到使用一些组件,去尝试组件的安全问题

接口系统-Swagger

介绍

Swagger 是当下比较流行的实时接口文文档生成工具。接口文档是当前前后端分离项目中必不可少的工具,在前后端开发之前,后端要先出接口文档,前端根据接口文档来进行项目的开发,双方开发结束后在进行联调测试。

参考:https://blog.csdn.net/lsqingfeng/article/details/123678701

2版本和3版本差异

application.properties

# 应用服务 WEB 访问端口
server.port=8002
# 设置路径匹配策略为Ant路径匹配器
spring.mvc.pathmatch.matching-strategy=ant_path_matcher

2.9.2

<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>

3.0.0

<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>

2.X 版本启动需要在启动文件添加注释 @EnableSwagger2
3.X 版本不需注释,写的话是 @EnableOpenApi

2.X 访问路径:http://ip:port/swagger-ui.html
3.X 访问路径:http://ip:port/swagger-ui/index.html

img

安全问题

自动化测试:Postman
泄漏应用接口:用户登录,信息显示,上传文件等
可用于对未授权访问,信息泄漏,文件上传等安全漏洞的测试

打开postman打开工作台,在左侧找到API

img

打开API导入生成的swagger页面提供的API:http://127.0.0.1:8080/v3/api-docs

img

导入成功后点击Api Documentation,点击右侧的运行,勾选想要测试的接口,执行即可

img

也可以批量化测试

img

img

身份鉴权-JWT技术

介绍

JWT ( JSON Web Token ) 是由服务端用加密算法对信息签名来保证其完整性和不可伪造;
Token里可以包含所有必要信息,这样服务端就无需保存任何关于用户或会话的信息;
JWT用于身份认证、会话维持等。由三部分组成,header、payload与signature。

https://developer.aliyun.com/article/995894

JWT格式:

在其紧凑的形式中,JWT由以点(.)分隔的三个部分组成,它们是:

  • Header
  • Payload
  • Signature

类似:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Cookie、Session、JWT来实现身份验证

Cookie存储在浏览器
Session存储在服务器
JWT存储在浏览器

版本不兼容

image-20250115114652112

解决方式:

  1. 更换jwt低版本
  2. 更换jdk高版本

image-20250115114858093

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXNzd29yZCI6IjEyMzQ1NiIsInVzZXJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiJ9.vbGmm09EQAjp5Lfk16wjnRtf0pw9OS_dZCWQPWzL-8w

image-20250115115024905

如果我们直接修改payload,但是没有加上密钥,生成的jwt结果发送后会导致服务器接收后解密错误(没有密钥)所以无法直接进行修改jwt的payload部分来进行身份篡改(jwt中Signature部分就是为了防篡改)

为什么说jwt是安全的?

因为token解密加密需要密钥,密钥都保存在服务端里。你可以轻易伪造出用户信息但是得不到密钥,就无法通过服务端token解密,鉴权失败。
所以很多开发者往往是密文能被解密,就认定通过。

安全问题

https://saucer-man.com/information_security/377.html

打包部署-JAR&WAR

参考:https://mp.weixin.qq.com/s/HyqVt7EMFcuKXfiejtfleg

可以用7-zip打开生成的jar包

image-20250115140752224

image-20250115141016600

无源码下载泄漏风险:网站应用是运行jar的形式,类似exe客户端

没有泄露的风险
源码泄漏也需反编译

得到jar包-反编译

最简单的 jar 包反编译方法:解压缩直接将 jar 包解压出来后使用 IDEA 直接打开项目,会自动反编译得到源码,不过项目里面的注释会消失。