记一次Spring boot框架代审与思考
caigo 发表于 福建 漏洞分析 1289浏览 · 2024-08-23 12:49

项目介绍

这是一款基于SpringBoot+SpringSecurity的RBAC权限管理系统。原本只想着做成基于SpringSecurity的权限管理系统,但随着功能的增加感觉有些刹不住车了,之后可能会往后台管理系统方向发展。无任何重度依赖,非常适合新手练习上手,项目文档从零开始,十分详细。

项目搭建

项目地址:https://gitee.com/witmy/my-springsecurity-plus

这个地址项目的是目前最新版,文章中审计的是先前的版本,部分漏洞最新版也存在,这个在文章中会说明,我会把老版本的漏洞产生代码段与新版本做对比,方便更直观理解漏洞的产生

打开项目等待maven加载

修改配置文件,创建对应数据库

my-springsecurity-plus\src\main\resources\application.yml

导入sql文件

sql文件:my-springsecurity-plus\docs\sql\my-springsecurity-plus.sql

导入完成后,配置spring boot,jdk版本1.8

配置完成后启动项目即可

http://127.0.0.1:8088/login.html

管理员账号:admin/123456

漏洞挖掘

SQL注入

检查pom.xml文件,发现导入了mybatis依赖

初步判断使用,全局搜索关键词${

第一处

my-springsecurity-plus\src\main\resources\mybatis-mappers\DictMapper.xml

根据id搜索Dao层对应方法

往上查调用到controller层

接着查调用

查到controller文件,查看myDict是从哪来的,分析下这段代码

@RequestMapping定义了基础路由 /api/dict

@Api 是Swagger文档生成标记控制器的

@Autowired:注入 DictService 服务类,用于业务逻辑处理

index():处理 GET /api/dict/index请求,返回视图名 system/dict/dict。需要 dict:list 权限。

getDictAll():处理 GET /api/dict 请求,返回字典列表。需要 dict:list 权限,并记录操作日志 (@MyLog("查询字典列表"))。使用 PageTableRequestMyDict 作为请求参数,调用 dictService.getDictPage() 返回分页数据。

什么?你说你看不懂代码?GPT啊!!!

初期代码基础差,要学会使用工具,在这些信息中我们只提取我们需要的信息分析

首先这处功能点是在字典管理(代码中有注释,路由是触发/api/dict)

结合xml中的sql语句%%,应该是查询字典的功能

带入getDictPage方法执行的参数myDict会通过参数传递所以可控

分析完后,开始漏洞复现

在后台找到字典查询的功能点

burp抓包

参数名跟代码中对应上,保存数据包Sqlmap一把搜哈

漏洞存在,新版本中这处注入修复了

第二处

my-springsecurity-plus\src\main\resources\mybatis-mappers\DeptMapper.xml

一样的思路根据id关键字追到controller层调用

跟到controller层调用

my-springsecurity-plus\src\main\java\com\codermy\myspringsecurityplus\admin\controller\DeptController.java

这一处有点不一样,如果通过后台访问功能点数据包中是没有params这个参数的,这一块代码段也没发现params参数,那么它是哪来的呢?这一处卡了我很久

全局搜索params

定位到了这个类:my-springsecurity-plus-master\src\main\java\com\codermy\myspringsecurityplus\admin\entity\BaseEntity.java

注释中也表明了是请求参数,params是Map类型的,如果为空就是new一个空的map,有值就会返回

通过类定位发现这是个抽象类,我们看下谁继承了它

通过继承的类名也可以看出都是些数据库操作类,我们看下controller的导入

发现是存在的,那么我们构造对应url

http://192.168.37.1:8088/api/dept/build?params["dataScope"]=1

报错400,不应该啊?

考虑到可能是字符的问题,url编码一下

http://192.168.37.1:8088/api/dept/build?params%5B%22dataScope%22%5D=1

发现可以解析了,上sqlmap

新版本这处没改

XSS(存储型)

由于这套系统只有后端管理,可以尝试的功能点不多,依旧是选择管理员能交互到的功能

我们先创建一个普通用户看下能操作哪些功能

那么就是在这两处尝试插入xss了

第一处

创建完成时已经弹窗了,基本确定了

模拟管理员查看用户

第二处

模拟管理员

这个最新的也有,没对参数做校验

垂直越权

查找用户操作的功能点,找到用户删除这个功能点,抓下包

数据包中校验删除用户的条件貌似是userID,我们执行看下数据库执行记录

看来是通过urse_id确认删除目标的,正常功能我们只能删除下级用户

那么我们可以尝试下删除同级用户

成功删除test6

最新版无法越权删除用户,貌似是加上JWT身份认证的原因,在做删除用户操作前会通过JWT校验用户权限

druid未授权(不存在)

虽然不存在但是分析过程我感觉不错也写上

在pom.xml文件中看到了druid的依赖

在后台发现确实存在对应功能

在代码中查看对应配置,发现是允许访问Druid的监控界面

我们在未登录的情况下尝试访问

发现实际上是有做限制的,限制了访问ip,仅允许本地访问,我尝试了xff,绕过不了,说明不是从这里获取IP

我尝试在源码中寻找,发现是存在获取ip的代码段

但是跟踪getIP这个方法的调用,没发现异常到这里就断了,这时我想到是不是把代码封装在jar里了,使用maven下载源代码

这次搜索报错信息

Sorry, you are not permitted to view this page.

定位到这个文件

我一看路径,果然是jar包里面的,全局搜索文件名

定位到验证代码段,代码中可以看出是关键是isPermittedRequest这个方法,我们跟进去看下

看样子这个getRemoteAddress方法就是获取IP的了,继续跟进方法

先判断remoteAddressHeader != null,查看remoteAddressHeader是个常量为null,那么直接看下面的if

通过request.getRemoteAddr()方法获取ip,确认了ip获取的方法

我尝试搜索了一下这个方法

没想到第一篇就这么劲爆,看来这个方法是有绕过可能的

由于环境在本地,本地搭建dns服务器(过程就不放了),搭建完成后再次尝试

寄,本地再起个测试环境看下获取到的ip

客户端ip为:192.168.37.130

服务端ip为:192.168.37.1

呜呜呜!欺骗我感情

自此判断不存在druid未授权

新版本取消了post方法的未授权访问,也就说可以未授权看到登入界面,但是登入不了,难崩

Spring boot Actuator未授权访问

这个其实是我之前一直没注意到的一个点,Spring boot框架已经成为java的主流之一,很多系统都采用Spring boot搭建,关于它上面的安全,确实应该重视,我自己也在思考总结思路,之后应该会专门出一篇见解下Spring boot的审计方向

这篇不会提太多

依旧是通过pom.xml发现引入了Actuator依赖

稍微看过java审计文章的就会发现pom.xml对于java代审而言真的很重要,是可以等到很多信息的,要重点查看

在配置文件中寻找配置查看开放的端点

如果设置了management.endpoints.web.exposure.include*,就可以在 /actuator 看到所有存在的端点

但是它这里只开放了这几个

/info
显示任意的应用信息
展示了关于应用的一般信息,这些信息从编译文件比如 META-INF/build-info.properties 或者 git 文件比如 git.properties 或者任何环境的 property 中获取

/health
显示应用的健康信息(当使用一个未认证连接访问时显示一个简单的’status’,使用认证连接访问则显示全部信息详情)
health一般只展示了简单的UP和DOWN状态

/beans   
//显示一个应用中所有Spring Beans的完整列表

/env    
//显示来自Spring的 ConfigurableEnvironment的属性
可能会泄露数据库账号密码等敏感信息

/metrics   
//展示当前应用的metrics信息
获得每个度量的名称,其中主要监控了JVM内容使用、GC情况、类加载信息等

比较重点的是/env,可能会泄露配置文件信息(并不是说其它没有)

针对env这种路径下泄露的密码会用*进行脱敏,想要获取对应的明文密码,可以尝试通过分析heapdump数据的方式

但是很可惜这套系统没有开放/heapdump端点

新版本也是直接不允许未授权访问/actuator了

Swagger API泄露

依旧是通过pom.xml发现依赖

也设置了静态资源,也就是未授权了

尝试访问

http://127.0.0.1:8088/swagger-ui.html#/

提供了很多接口,但是能不能用,得测试

我们可以访问它提供的api地址

http://127.0.0.1:8088/v2/api-docs

然后使用工具批量爬取接口测试存活

swagger-hack

项目地址:https://github.com/jayus0821/swagger-hack

python swagger-hack2.0.py -u "http://ip:8088/v2/api-docs"

测试结果会保存在csv文件中

新版本和老版本这块没差别

总结

关于Spring boot框架常见的漏洞平时我确实没有注意,更多的都是通用漏洞和组件挖掘为主,对于框架易产生的漏洞较为疏忽,接触的也少,要让自己的思路扩展开来,多个攻击面出洞的几率就更高。这套源码实际上属于半成品,很多功能点都没开发,不知道后面作者会不会加,部分漏洞修补的也比较潦草。

附件:
  • my-springsecurity-plus.zip 下载
0 条评论
某人
表情
可输入 255