Fork me on GitHub

RBAC管理系统审计记录

RBAC管理系统审计记录

环境搭建

环境依赖

  • Windows
  • idea2022
  • jdk 8
  • RBAC源码
  • phpstudy的mysql 5.6.7

简易搭建流程(Windows下)

  • 直接使用idea打开项目,然后选中右上角的项目构建
  • 项目中有几处需要修改:
    ○ 1、 要开启phpstudy的mysql,然后创建rbac数据库,并将源码中的rbac.sql数据导入进数据库
    ○ 2、在全局中搜索application.yaml文件,修改其中的数据库密码为phpstudy中设置的用户名密码
    ○ 3、使用admin/123456登录炼石计划后台进入系统
    ○ 4、使用admin/admin登录sql监控
    ○ 5、使用idea自动下载系统所需所有依赖包
    ○ 6、 系统访问url:http://127.0.0.1:8088

系统审计

  • java代码审计,一般都是基于maven的web项目,然后使用spring框架,或者是基于tomcat的web项目,使用spring框架
  • 审计时,要先关注pom.xml文件,这个文件是Maven进行工作的主要配置文件。在这个文件中我们可以配置Maven项目的groupId、artifactId和version等Maven项目必须的元素;可以配置Maven项目需要使用的远程仓库;可以定义Maven项目打包的形式;可以定义Maven项目的资源依赖关系等等。

漏洞审计

SQL注入

  • 从pom.xml文件中可以发现是使用了mybatis进行sql语句的操作

mybatis

  • MyBatis支持两种参数符号,一种是#,另一种是$。
  • 使用参数符号#的句子:
  • <select id="selectPerson" parameterType="int" resultType="hashmap"> SELECT * FROM PERSON WHERE ID = #{id}</select>
  • MyBatis会创建一个预编译语句,生成的代码类似于
    * // Similar JDBC code, NOT MyBatis…String selectPerson = "SELECT * FROM PERSON WHERE ID=?";PreparedStatement ps = conn.prepareStatement(selectPerson);ps.setInt(1,id);
  • 参数会在SQL语句中用占位符”?”来标识,然后使用prepareStatement来预编译这个SQL语句。
  • 在默认情况下,MySQL Connector/J只不过是把selectPerson做了一下转义,前后加了双引号,拼接到SQL语句里面,然后再交给MySQL执行。另一种使用参数符号$时,MyBatis直接用字符串拼接把参数和SQL语句拼接在一起,然后执行。这种操作就是十分危险的了,很容易产生sql注入
  • 所以对于mybatis进行sql操作的,我们可以直接搜索${来判断

mybatis拼接sql有下面两种方式:


#{} 告诉mybatis创建一个预编译语句(PreparedStatement)参数,在JDBC中,这样的一个参数

在SQL中会由一个"?"来标识,并被传递到一个新的预处理语句中

${} 仅仅是纯粹的string替换,在动态SQL解析阶段将会进行变量替换,类似于直接替换字符串,会

导致SQL注入产生。

一些不能使用#{}的场景:

表名/字段名 如果预编译了,就没法查了

order by/group by

like模糊查询

in
  • 直接搜索关键字${
  • 所以我们在代码审计阶段进行SQL注入漏洞挖掘时,应关注 xxxMapper.xml 中使用 ${} 凭借SQL的地方。推荐使用搜索关键字符,win快捷键 CTRL+SHIFT+F (PS.设计xml的目的是用作数据交换,当然也可以用作保存数据。xml保存数据具有平台无关,规范化。通过提供方提供的读取程序就可以读取出xml数据。)
  • 调出 Find in path ,file mask选择文件夹类型为*.xml,输入关键字符${}(在文件中查找)
  • 点击进⼊DictMapper.xml向上找调⽤src/main/resources/mybatis-mappers/DictMapper.xml
  • 先双击DictMapper.xml文件定位到关键字,然后跟id=getFuzzyDictByPage到声明处DictDao.java,然后再转到函数引用文件到DictServicelmpl.java,在通过跟踪调用到DictController.java文件

注入点一:/api/dict

 http://127.0.0.1:8088/api/dict?page=1&limit=10&dictName=if(1=1,1,exp(710))

dictName参数为注⼊点

注入点二:/api/user

http://127.0.0.1:8088/api/user?

page=1&limit=10&userName=if(2=2,1,exp(710))&nickName=if(1=1,1,exp(710))
userName和nickname处均存在注入

越权漏洞

越权删用户

  • 漏洞代码
@Override  
public int deleteUser(Integer userId) {  
    checkUserAllowed(new MyUser(userId));  
    roleUserDao.deleteRoleUserByUserId(userId);  
    userJobDao.deleteUserJobByUserId(userId);  
    return userDao.deleteUserById(userId);  
}
  • 观察这段代码可以发现会先对输入的可控userid进行check,然后会先删除role再删除用户,其中没有任何的其他鉴权
  • 跟一下checkUserAllowed()函数到UserServiceImpl.java文件
public void checkUserAllowed(MyUser user) {  
    if (!StringUtils.isEmpty(user.getUserId()) && user.isAdmin())  
    {  
        throw new MyException(ResultCode.ERROR,"不允许操作超级管理员用户");  
    }  
}
  • 这里可以发现只要userid不为空或者不是管理员就可以删除,中间也未做其他鉴权判断,这样就导致会产生越权删除其他用户风险
posted @ 2024-10-12 11:06  Konmu  阅读(8)  评论(0编辑  收藏  举报