利用
讲一下若依框架的SQL注入漏洞,攻击手法十分简单,如下
https://blog.csdn.net/Guapichen/article/details/119212781(使用了师傅的原图)
注入点:在/system/role/list接口的params[dataScope]参数
注入点分析
若依框架使用的SQL框架是mybatis,使用xml写SQL语句。大家都知道,mybatis里,${}
此类写法是不转义的,而#{}
此类写法是转义的。
所以在若依框架中,找SQL注入漏洞,应该是全局搜索:
${
后缀名为.xml的文件
但是通过全局搜索,并没有找到xml文件,是因为idea有搜索条数限制
所以我们需要修改搜索条数,方法如下:
工具栏Help --> Find Action --> Registry --> 将改成10000
当我们搜索条数够多,加上文件后缀过滤,发现搜索到Mybatis的xml文件中含有${xxx}
任意打开红圈中的文件,可以看到${params,dataScope}
直接拼接在了SQL语句中,因此极有可能存在SQL注入
这段SQL查询的id为selectDeptList
,全局搜索selectDeptList
从Controller --> Mapper --> Service --> ServiceImpl,都没有过滤动作,因此判断存在SQL注入
若依对该漏洞的修复手段
可以看到在v4.6.2版本时修复了SQL注入问题
在码云上搜索4.6.2版本的改动情况
https://gitee.com/y_project/RuoYi/commit/e1cab(删括号)589f2acf4e835ad5ab310bdbe71f2dd646d
以/system/dept/list
接口为例,作调试,进行分析
该接口对应的Controller方法中,调用了selectDeptList
去查询部门列表
POST /system/dept/list?deptId=1&deptName=12&email=1&leader=1&orderNum=2&parentId=1&parentName=1&phone=1&remark=1&params%5bdataScope%5d=1 HTTP/1.1
Host: 10.10.1.216:8070
Content-Length: 0
accept: */*
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36
Origin: http://10.10.1.216:8070
Referer: http://10.10.1.216:8070/swagger-ui/index.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: JSESSIONID=ef4fff39-1df8-4b5e-92a9-841aee13afba
Connection: close
@RequiresPermissions("system:dept:list")
@PostMapping("/list")
@ResponseBody
public List<SysDept> list(SysDept dept)
{
List<SysDept> deptList = deptService.selectDeptList(dept);
return deptList;
}
selectDeptList
该方法含有DataScope的注解
DataScopeAspect.java中,对dataScopePointCut()
方法配置了DataScope的注解
在dataScopePointCut()方法执行前,下面有个doBefore()
方法,基本可以确定doBefore()方法包含对SQL注入的防护
进入clearDataScope()
方法,params对象
获取到所有的body参数。若params不为空且params继承于BaseEntity
,则清空params中的params[dataScope]
。
可以看到params的对象即为SysDept
类的实例,而SysDept类继承于BaseEntity
我看了所有xml中包含$params[dataScope]
的SQL方法对应的实体类,每一个类都继承于BaseEntity
。
因此若想产生SQL注入,可params instanceof BaseEntity
必然为true且params必不为空,从而导致dataScope被清空,从而使SQL注入无法生效
/**
* 拼接权限sql前先清空params.dataScope参数防止注入
*/
private void clearDataScope(final JoinPoint joinPoint)
{
Object params = joinPoint.getArgs()[0];
if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
{
BaseEntity baseEntity = (BaseEntity) params;
baseEntity.getParams().put(DATA_SCOPE, "");
}
}
/**
* 部门表 sys_dept
*
* @author ruoyi
*/
public class SysDept extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 部门ID */
private Long deptId;
/** 父部门ID */
private Long parentId;
/** 祖级列表 */
private String ancestors;
总结:若依框架对此次SQL注入的防护手段,就是在SQL方法生效之前,先把dataScope清空,即使xml中的SQL语句不变,SQL注入也无法生效了。