某RBAC管理系统
源码
已经下载至本地:
C:\Users\chenyuanhang\Documents\WorkSpace\security\RefiningStone-RBAC(最终版)
A、所需环境
本项目安装基于windows 10操作系统搭建而成。
1、Java环境部署
Java版本为8就行了
JDK下载链接:
https://www.oracle.com/java/technologies/downloads/#java8-windows
安装步骤操作简单,只需下一步即可,不过多赘述。
2、Maven环境部署
3、Mysql环境部署
个人偏好于使用phpstudy,它集成了很多常用组件,如apache,mysql等。作为练习,方便至极,一键启动即可使用。
启动cmd命令行,进入mysql数据库,命令:mysql -u root -p
,然后键入你的密码。
使用命令创建数据库:create database rbac;
导入rbac.sql
文件,该文件位于RefiningStone-RBAC
项目文件夹内。可以使用mysql工具导入
B、环境搭建
安装整体过程首先将数据导入mysql数据库中,然后将项目导入IDEA中,修改配置文件中数据库信息,点击启动即完成环境搭建。
使用idea打开项目
进入src - main - resources - application.yml
,对配置文件进行相关修改,主要修改Mysql数据库连接账号密码,具体可以去phpstudy下数据库处查看。
打开浏览器,键入http://127.0.0.1:8088/login.html
,访问项目。
渗透测试
目录爆破
使用dirsearch进行目录爆破
未授权访问
根据上面的结果可以看到有一些目录,首先先去看/actuator/env
,因为通过他可以看到 SpringBoot 载入了哪些 properties,以及 properties 的值(这个里面会自动用*替换 key、password、secret 等关键字的 properties 的值进行脱敏)
其他的一些常见的:
路径 | 描述 |
---|---|
/autoconfig | 提供了一份自动配置报告,记录哪些自动配置条件通过了,哪些没通过 |
/beans | 描述应用程序上下文里全部的Bean,以及它们的关系 |
/env | 获取全部环境属性 |
/configprops | 描述配置属性(包含默认值)如何注入Bean |
/dump | 获取线程活动的快照 |
/health | 报告应用程序的健康指标,这些值由HealthIndicator的实现类提供 |
/info | 获取应用程序的定制信息,这些信息由info打头的属性提供 |
/mappings | 描述全部的URI路径,以及它们和控制器(包含Actuator端点)的映射关系 |
/metrics | 报告各种应用程序度量信息,比如内存用量和HTTP请求计数 |
/shutdown | 关闭应用程序,要求endpoints.shutdown.enabled设置为true |
/trace | 提供基本的HTTP请求跟踪信息(时间戳、HTTP头等) |
登录爆破
之前看配置文件发现了1个账户:
本人以为就是登录密码,直接登录爆出用户名密码错误!因此以为代码出现bug,又查询数据库发现账号是admin
密码是加密的,因此本人被误导了,并一直追踪调试,最终还是没有解决,最终发现这个配置文件中账户并非登录账户!浪费了许久时间!
使用bp抓登录包:
响应包中文乱码,解决方案:改成UTF-8,以及font改成黑体
回归正题,尝试登录看看:
乱填验证码试试:
验证码格式不对?抓包发送试试:
居然没有爆出验证码格式不对,那说明这个验证码的格式校验在前端,究竟有没有校验这个验证码呢?
不管怎么输入,响应包只会返回“用户名或密码错误”,可能在校验密码错误的时候就返回了,还没到验证码校验这部分。
不管验证码了,直接尝试爆破:
设置payload,密码尽量设置哪种常见的dict,bp自带的不太行,少了很多东西。。。
爆破成功了,账号:admin
,密码:123456
果然验证码根本就没有校验,如果要检验的话,爆破起来就比较麻烦了。。。因为还要去找一些可靠的在线校验工具。。。
Druid登录爆破
之前目录探针时发现了druid登录的链接,访问看看:
试试用bp爆破:
获取到账号密码都为:admin
XSS测试
看见有输入框,就可以尝试xss,在角色管理
->新增
模块处存在xss,在菜单管理
->新增
那也存在xss注入,其他的模块就不一一测试了
提交后刷新页面就会弹窗。
在用户管理这里的查询也是,当插入payload时会引发全局异常
,此时会被记录得到异常操作日志
中。
这个项目还存在异常日志模块,并且触发了xss,
在系统管理->异常日志中加载错误记录时就会触发。
-
同样的,这样的xss有很多很多,因为很多地方都直接将错误记录了,对一些输入框的校验过滤可以说根本没有。
只要能触发全局异常,在加载异常日志的时候都会引发xss弹窗。
SQL注入
用bp插件SQLIPy sqlmap来扫描可能存在的sql注入,这个插件可以在bp自带的插件商店上下载,但是需要安装Jython
环境,安装之后打开bp设置,把安装之后的jython路径
填写上:
右键打开这个插件,调一下设置:
启动这个插件,把ip和端口号设置好,按照图上设置就行了,只要端口不冲突就行了,
打开sqlmap scanner,自己勾选一些设置,
划到最后面,开始扫描
你点击扫描之后可能没有反应,它这个插件响应很慢,开始之后挂在后台等一段时间再看
打开site map,可以查看到已经扫描到一些sql注入,是用户查询
部分存在SQL注入
字典查询
那块也存在sql注入
根据payload可以实现sql注入。
使用SQLmap
来扫描一下:
python sqlmap.py -r C:\Users\chenyuanhang\Documents\sqli.txt --dbs --batch
sqli.txt
文件如下:
GET /api/dict?page=1&limit=10&dictName=adf HTTP/1.1
Host: 127.0.0.1:8088
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Connection: close
Referer: http://127.0.0.1:8088/api/dict/index
Cookie: JSESSIONID=340D9A618B59A2E8B0A5EAA3DEC72448; remember-me=YWRtaW46MTcxMDMwMjI4ODcyNTowYjdiNjAxNzZhMzg3NGFiOTgxNWYwODY1M2YzYjNjYg
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
成功扫描出来一些数据库,执行如下:
来扫描出数据表来:
python sqlmap.py -r C:\Users\chenyuanhang\Documents\sqli.txt -D rbac --tables --batch
越权漏洞
创建一个用户agnoy
,弹框提示密码默认为:123456
使用agony
账户登录,发现仅仅只能操作test6
这个账号
先抓一下删除包,仔细一看,删除操作需要参数userId
,以及Cookie
注意:Cookie
值必须正确,不然将无法删除
userId
的值对应着数据库的表中user_id
的值
尝试一下能不能直接删除test1
用户,返回成功,乱码不重要,居然成功了。
登录admin
,查看test1
已经删除了
数据库也同步删除了,实现了越权删除。。。
代码审计
信息收集
-
pom.xml漏洞挖掘
通过分析pom文件,发现引入了swagger2,可能存在swagger接口文档泄露
发现fastjson版本<1.2.80,存在Fastjson漏洞。
使用Fastjson 1.2.56
版本,该版本存在漏洞,如下图所示:
在发现了第三依赖库存在漏洞版本时,可以进一步利用。
但有时,尽管使用了带有漏洞版本的组件,但并没有使用存在漏洞的相关函数。
比如Fastjson
反序列化漏洞,该项目实际并没有使用到parseObject
。
注意:
通过组件及版本寻找漏洞,最起码需要知道什么组件时干什么的,然后对于常见的组件看多了,也就知道什么版本有什么漏洞了,熟能生巧。
-
查看配置文件
配置文件都在src/main/resources
下面,名字通常为application.yml
或者application.properties
。配置文件中可能会存在数据库或其他组件的连接信息。
数据库连接信息账号密码:
还有一个不知道是什么账户密码,如下图所示:
未授权访问
查看到SpringSecurityConfig
这个配置文件下,
它放行了静态资源,包括一系列swagger-ui.html,和druid,actuator目录下的文件
,所以导致被目录爆破出来,从来达到未授权访问
越权漏洞
通过之前的渗透存在越权删除的情况下,直接逆向找到删除模块
先进入controller层找到对应的控制器
最终定位到函数,
进入checkUserAllowed
,发现仅仅做了校验是否为空,以及不能操作超级管理员,并未对其他权限的用户进行校验。。
跟着删除用户整体流程逻辑走下来,发现userId是从用户侧获取的,也没有将userId与所删除的数据做关联,而且userId也不是从session中获取的,从而导致任意用户都可以调用该接口进行删除。
并且用户ID值极易进行遍历,从而进行批量任意用户删除。
它直接接受用户输入的userID
值,但是并未做很深究的校验,从而导致这个userId
可控,从而导致随便一个普通用户就可以操作其他同等权限的用户。
验证码校验
定位到:com/codermy/myspringsecurityplus/security/filter/VerifyCodeFilter.java
这个文件,可以看到仅仅做了验证码不能为空的校验(下面并不是我注释的!)看到他只有在验证码为空时才会置空销毁掉缓存中存储的验证码,这也就是说不为空的时候就算使用了错误的验证码也可以通过校验,这就是验证码可以重用的原因。
这就导致你可以随意输入验证码。当然前端可能有些简单的校验,比如长度之类的。。。这都不是问题,
SQL注入漏洞挖掘
本项目基于Mybatis操作数据库,我们了解到Mybatis错误的配置会导致SQL注入漏洞的存在,这是我们挖掘SQL注入漏洞的入口点。
我们先来回顾下:
Mybatis拼接sql有下面两种方式:
#{}
告诉 MyBatis 创建一个预编译语句(PreparedStatement)参数,在 JDBC 中,这样的一个参数在 SQL 中会由一个“?”来标识,并被传递到一个新的预处理语句中,
${}
仅仅是纯粹的 string 替换,在动态 SQL 解析阶段将会进行变量替换,直接替换字符串,会导致SQL注入产生。
一些不能使用#{}
的场景:
表名/字段名
order by/group by
like模糊查询
in
因此,我们在代码审计阶段进行SQL注入漏洞挖掘,应关注xxxxMapper.xml
中使用${}
拼接SQL的地方,全局搜索关键字符。Windows快捷键CTRL+SHIFT+F
(如果快捷键冲突,需自己更改)。
调出Find in path
,File mask选择文件类型为*.xml
,键入关键字符${
,如下图所示:
这是UserMapper.xml
文件,存在使用${}
通过上述搜索,发现了SQL语句使用了like
语句并使用$
进行拼接参数,这种情况下无疑是存在SQL注入的。
这和我们渗透测试时发现的用户查询
功能存在SQL是对应的。。
我们逆向追踪所拼接的参数,看看是从前端哪个地方输入进来的。
①、通过搜索还发现src/main/resources/mybatis-mappers/DictMapper.xml
文件,第17行,存在使用like
语句以及$
拼接SQL。
安装了Free Mybatis Plugin
插件后,左侧会有绿色箭头,点击即可跳转到mapper接口处,也就是DAO层文件,如下图所示:
②、我们继续向前找到谁调用了DictDao.java
中的getFuzzyDictByPage
,Windows系统按住ctrl
键,鼠标左击getFuzzyDictByPage
进入该方法,或者说查看谁用了这个方法。如下图所示:
③、点击进入DICTServiceImpl.java
文件,发现getDictPage
函数中使用了getFuzzyDictByPage
,如下图所示:
④、继续按住ctrl
键,鼠标左击getDictPage
方法,点击后,直接进入到了DictController
文件中第43行,如下图所示:
找到Controller层后,发现并没有dictname
参数,因为Controller中以实体类接收表单数据。进入MyDict
发现该类为实体类,其中定义多个参数,如下图所示:
⑥、经过上述参数逆向追踪,确定了dictName为字典名称
位于查询字典功能
处,不出所料,在渗透测试中也发现字典查询
功能存在sql注入。
漏洞成因分析完了可能会有疑问使用拼接容易产生SQL注入,哪为什么不全部使用预编译?使用${}拼接是有一些有优点的,他可以实现一些动态的功能,比如指定表名,列名,排序字段等等。而在某一些场景下还真不能使用#{}去进行预编译。举个栗子:
- 模糊查询 like
就是上面发现的地方,拿另外一个sql语句来看:
select * from users where name like '%#{name}%'
这时候使用#号会直接报错,而经验不足的新手程序员就直接改成$号,这样如果没有对用户输入再有额外的过滤转义那势必产生SQL注入,而正确写法应该是这样的:
select * from users where name like contact('%', #{name}, '%')
而这个项目中存在注入的代码说这样写的:
di.dict_name like CONCAT('%', ${dictName}, '%')
- in之后有多个参数
in之后多个id查询时使用# 同样会报错,就比如:
select * from users where id in (#{ids})
正确用法应该是使用foreach标签,如下:
select * from users where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
- order by
使用#{}来动态拼接order by的字段或方向,可能会导致SQL注入,比如:
@Select("select * from user order by #{column} #{direction}")
List<User> selectUsers(@Param("column") String column, @Param("direction") String direction);
修改方案:使用${}。
@Select("select * from user order by ${column} ${direction}")
List<User> selectUsers(@Param("column") String column, @Param("direction") String direction);
或者也可以使用orderby方法来构建动态排序。
SelectStatementProvider selectStatement = select(user.allColumns())
.from(user)
.orderBy(sortColumn(sortSpecification(column, direction)))
.build()
.render(RenderingStrategies.MYBATIS3);
Swagger接口文档泄露
通过分析pom文件,发现引入了swagger2
尝试使用swagger2默认访问地址:Swagger UI
成功登录:
如果要进行操作的话,需要token!
XSS
在开发一个网站项目时,开发人员不可能将所有的参数分别做过滤或转义。最好的办法是统一写个过滤/转义XSS的Filter。
在本项目中全局搜索,没发现XSS相关过滤器(Filter)或拦截器(Interceptor)。初步判断存在XSS漏洞。
对后端简单分析后,初步判断存在XSS漏洞,然后我们对前端进行分析,是否有转义机制。
在了解了整个项目之后,发现前端使用了Thymeleaf模板引擎
和Layui框架
。
Thymeleaf中th:text
标签进行渲染的时候,默认对特殊字符进行了转义,th:utext
不会将字符转义。也就是说使用了th:utext
标签会出现XSS漏洞。经过全局搜索,发现只有两处使用了th:text
标签。没有地方使用th:utext
标签。
其经过分析src/resouces/templates/
下的html文件。发现本项目前端还使用了Layui框架
。
全局搜索Layui
关键字,得到layui使用版本为2.5.6
通过翻阅Layui的github中ISSUES发现该版本存在XSS漏洞。链接https://github.com/sentsin/layui/issues/711
在渗透测试阶段挖掘到了XSS漏洞。经过从代码层分析,该漏洞的出现主要分为两点:
- 一是:后端没有对用户输入的字符进行转义或过滤。
- 二是:使用的前端框架存在XSS漏洞版本,也没有对返回到前端的参数进行过滤或转义。
但是还有一个属性——th:value
,来到resources/templates/system/role/role-edit.html
这里使用了th:value
属性来设置输入框的值,而th:value
属性不会对HTML标签进行转义,恶意输入也会被浏览器执行,导致产生XSS。
知识补充:
Java中可用的10种方法,用于有效预防跨站脚本攻击(XSS)
-
输入验证和过滤:
- 在后端接口中,对用户提交的数据进行严格的验证和过滤。确保输入不包含恶意脚本。
- 使用白名单过滤,只允许特定的HTML标签和属性。
-
转义输出:
- 在将数据插入到页面中时,使用适当的转义函数,例如
htmlspecialchars
,以防止恶意脚本被执行。 - 对于前端模板引擎,确保插入的数据都经过了转义处理。
- 在将数据插入到页面中时,使用适当的转义函数,例如
-
Cookie 安全:
- 设置
HttpOnly
标志,以防止JavaScript访问敏感的Cookie信息。 - 使用
Secure
标志,仅在HTTPS连接中传输Cookie。
- 设置
-
CSP(内容安全策略) :
- 配置CSP以限制页面中可以执行的脚本来源。
- 禁止内联脚本,只允许从受信任的域加载脚本。
-
会话管理:
- 避免在URL中传递敏感信息,例如会话ID。
- 使用随机生成的会话ID,并定期更换。
-
HTTP响应头:
- 设置适当的
X-Content-Type-Options
和X-XSS-Protection
响应头。 - 启用浏览器的内置XSS过滤器。
- 设置适当的
-
使用安全的框架和库:
- 使用安全性良好的框架和库,例如Spring Security。
- 避免自己手动处理输入和输出,而是使用已有的安全解决方案。
Fortify扫描
待完成