Redis未授权访问漏洞

目录

什么是Redis未授权访问?

安装Redis

漏洞产生条件

绑定0.0.0.0 开启安全模式

绑定0.0.0.0 关闭安全模式

不绑定IP地址 开启安全模式

不绑定IP地址 关闭安全模式

漏洞演示

利用Redis写webshell

利用"公私钥"认证获取root权限

利用crontab反弹shell

Pyhton脚本自动化测试

避免Redis未授权访问漏洞

采用绑定IP的方式来进行控制。

设置密码,以提供远程登陆


什么是Redis未授权访问?

Redis 默认会绑定在 0.0.0.0:6379 ip和端口,如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,上面的配置将会将 Redis 服务暴露到公网上,如果在没有设置密码认证(一般为空)的情况下,会导致任意用户在可以访问目标服务器的情况下未授权访问 Redis 以及读取 Redis 的数据。

攻击者在未授权访问 Redis 的情况下,利用 Redis 自身的提供的config 命令,可以进行写文件操作,攻击者可以成功将自己的ssh公钥写入目标服务器的 /root/.ssh 文件夹的authotrized_keys 文件中,进而可以使用对应私钥直接使用ssh服务登录目标服务器。

总结一下该漏洞产生的前提条件为:

1、redis绑定的ip和端口是:0.0.0.0:6379,并且没有添加任何策略来防止其他非信任ip访问,直接暴露在公网

2、可以免密码远程登录

注:本篇的实验是参考别的大佬总结的文章进行学习+练习的

安装Redis

既然是Redis授权访问,那么必须要有Redis,Redis(Remote DItionary Server 远程字典服务器) 是一个高性能的(key/value)分布式内存数据库,基于内存运行,并支持持久化的NoSQL数据库,是当前最热门的NoSQL数据库之一, 也被人们称为数据结构服务器。

安装包就直接去官网下载:Redis

这里安装就不再赘述了,跟着官方文档进行安装即可,或者也可以看我之间写过的一篇安装文章:初识Redis——Redis概述、安装、基本操作-CSDN博客

注:本次实验需要两台Linux主机,均需要安装Redis

漏洞产生条件

安装完成后,可以查看一下redis的配置文件:

vim /root/redis-stable/redis.conf

Redis未授权访问漏洞_第1张图片 

可以看到这里有绑定的ip地址,安全模式的状态,和绑定的端口

现在我们可以测试一下什么情况下我们可以执行命令:

绑定0.0.0.0 开启安全模式

Redis未授权访问漏洞_第2张图片

现在启动redis:

Redis未授权访问漏洞_第3张图片

现在使用攻击机连接尝试执行命令,可以发现安全模式起作用了,可以连接上,但是不可以执行命令:

Redis未授权访问漏洞_第4张图片

错误信息:

(错误)DENIED Redis正在保护模式下运行,因为已启用保护模式,并且没有为默认用户设置密码。在这种模式下,只接受来自环回接口的连接。如果你想从外部计算机连接到Redis,你可以采用以下解决方案之一:
1)只需禁用保护模式,通过从服务器运行的同一主机连接到Redis,从环回接口发送命令“CONFIG SET protected mode no”,但如果你这样做,请确保Redis不能从互联网上公开访问。使用CONFIG REWRITE将此更改永久化。
2) 或者,您也可以通过编辑Redis配置文件,将保护模式选项设置为“no”,然后重新启动服务器来禁用保护模式。
3) 如果手动启动服务器只是为了测试,请使用“--protected mode no”选项重新启动服务器。
4) 为默认用户设置身份验证密码。注意:您只需要执行上述操作之一,服务器就可以开始接受来自外部的连接

绑定0.0.0.0 关闭安全模式

Redis未授权访问漏洞_第5张图片

然后尝试使用攻击机连接执行命令:

可以看到成功的连接了,并且执行命令也成功了

不绑定IP地址 开启安全模式

Redis未授权访问漏洞_第6张图片

使用攻击机连接产生执行命令:

Redis未授权访问漏洞_第7张图片

发现与上面的一样,能连接上,但是无法执行命令

不绑定IP地址 关闭安全模式

Redis未授权访问漏洞_第8张图片

然后在攻击机尝试连接并且执行一下命令:

发现是可以执行命令的

那么现在就可以总结一下漏洞产生的条件了:

  1. 未开启登录验证,并且把IP绑定到0.0.0.0,protected-mode关闭

  2. 未开启登录验证,没有设置绑定IP,protected-mode关闭

漏洞演示

有了上面的利用条件,现在就可以演示一下Redis未授权访问的实验了:

Redis服务器:192.168.159.200,且绑定ip为0.0.0.0:6379 ,安全模式关闭

攻击机:192.168.159.202

现在使用攻击机无密码连接Redis服务器就可以成功的执行命令了:

可以看到这样我们就可以直接查看Redis数据库中的数据了

利用Redis写webshell

现在已经可以访问redis服务了,然后可以写一个webshell做后续的攻击

利用前提:

1.在攻击机上能用redis-cli连上
2.开了web服务器,并且知道路径,还需要具有文件读写增删改查权限

第一个条件我们已经满足了,下面还需要满足第二个条件 ,我们可以将dir设置为一个目录a,而dbfilename为文件名b,再执行save或bgsave,则我们就可以写入一个路径为a/b的任意文件:

但是我在执行时出现了下面的问题:

查找文档发现是redis.conf里面的一个配置关闭导致的,开启该配置:
Redis未授权访问漏洞_第9张图片

开启后,再次修改设置就成功了

Redis未授权访问漏洞_第10张图片

这里的webshell就简单的使用为例

注意:上面的webshel最好使用下面这种方式来写

set x "\r\n\r\n\r\n\r\n"

这里的\r\n\r\n代表换行的意思,用redis写入的文件会自带一些版本信息,如果不换行可能会导致无法执行。

shell写入完成,我们在靶机上来证明:

可以看到webshell已经写入成功了

当数据库过大时,redis写shell的小技巧:、

');
exit();
?>

利用"公私钥"认证获取root权限

如果redis服务以root身份运行,那么攻击者可以给root账户写入SSH公钥文件,然后直接通过SSH登录目标服务器。

(1)靶机中开启redis服务:redis-server /etc/redis.conf

Redis未授权访问漏洞_第11张图片

(2)在靶机中执行 mkdir /root/.ssh 命令,创建ssh公钥存放目录(靶机是作为ssh服务器使用的)

(3)在攻击机中生成ssh公钥和私钥,密码设置为123456:

Redis未授权访问漏洞_第12张图片

(4)进入.ssh目录:cd .ssh/,将生成的公钥保存到1.txt:

Redis未授权访问漏洞_第13张图片

(5)现在在攻击机上连接靶机上的redis服务,将保存ssh的公钥1.txt写入redis:

远程登录靶机的redis服务:redis-cli -h 192.168.0.104,并使用 CONFIG GET dir 命令得到redis备份的路径:

Redis未授权访问漏洞_第14张图片

更改redis备份路径为ssh公钥存放目录,然后设置上传公钥的备份文件名字为authorized_keys,最后检查一下是否更改成功(查看有没有authorized_keys文件):

Redis未授权访问漏洞_第15张图片

(6)在攻击机上使用ssh免密登录靶机:ssh -i id_rsa [email protected]

Redis未授权访问漏洞_第16张图片

可以看到现在就成功的利用私钥成功登录的redis服务器!!!

利用crontab反弹shell

当权限足够时,也可以使用crontab来将靶机的shell反弹到攻击机:

先使用nc在攻击机上监听:

然后复制一个会话,连接redis服务器,写入反弹shell的crontab,然后设置dir和dbfilename:

Redis未授权访问漏洞_第17张图片

然后过一分钟左右就可以收到靶机的shell了:

Redis未授权访问漏洞_第18张图片

Pyhton脚本自动化测试

下面这个python脚本可以用来测试是否存在未授权或弱口令的情况:

#! /usr/bin/env python
# _*_  coding:utf-8 _*_
import socket
import sys
PASSWORD_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:
        pass
if __name__ == '__main__':
    ip=sys.argv[1]
    port=sys.argv[2]
    print check(ip,port, timeout=10)

避免Redis未授权访问漏洞

下面说两种避免redis未授权访问漏洞的方法

采用绑定IP的方式来进行控制。

在redis.conf文件找到如下配置

# 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改成你允许访问你的redis服务器的ip地址,表示只允许该ip进行访问,这种情况下,我们在启动redis服务器的时候不能再用:redis-server,改为:redis-server path/redis.conf 即在启动的时候指定需要加载的配置文件,其中path/是你上面修改的redis配置文件所在目录,这个方法有一点不太好,因为难免有多台机器访问一个redis服务。

设置密码,以提供远程登陆

打开redis.conf配置文件,找到requirepass,然后修改如下:

requirepass yourpassword
yourpassword就是redis验证密码,设置密码以后发现可以登陆,但是无法执行命令了。命令如下:
redis-cli -h yourIp -p yourPort//启动redis客户端,并连接服务器keys * //输出服务器中的所有key报错如下
(error) ERR operation not permitted
这时候你可以用授权命令进行授权,就不报错了命令如下:
auth youpassword

到此Redis未授权访问漏洞就到此学习完毕了(*^▽^*)

你可能感兴趣的:(数据库,安全,redis,数据库,缓存,web安全,web3,未授权,网络安全)