Redis缓存数据库安全加固指导(一)
背景
在众多开源缓存技术中,Redis无疑是目前功能最为强大,应用最多的缓存技术之一,参考2018年国外数据库技术权威网站DB-Engines关于key-value数据库流行度排名,Redis暂列第一位,但是原生Redis版本在安全方面非常薄弱,很多地方不满足安全要求,如果暴露在公网上,极易受到恶意攻击,导致数据泄露和丢失。
本文主要是在原生开源软件Redis3.0基础上,系统的在安全特性方面进行的增强,很多增强点涉及了开源代码的修改,后续章节阐述的Redis缓存数据库的安全规范, 理论上适用于所有应用Redis的产品。
本系列共连载三篇,分九个章节,本文从合法监听接口,未公开接口,访问通道控制三个章节阐述了Redis缓存数据库加固措施
1、合法监听接口
1.1 端口使用非默认端口
安全问题:Redis Server监听的端口默认为6379,容易被扫描攻击。
解决方案:修改为非默认端口,并在端口矩阵中说明。
1.2 监听地址不允许包括*
安全问题:Redis支持监听0.0.0.0。
解决方案:因为如果有多网卡,应该将监听地址设置为只有数据库客户端需要连接的网卡地址。如果只允许本机访问,应该只监听127.0.0.1。
1.3 隐蔽的RedisCluster端口
安全问题:官方RedisCluster方案缺省会增加一个集群端口,且是在客户端端口偏移10000,这个问题非常隐蔽。
解决方案:在端口矩阵中对额外的这个集群端口有说明。修改源码,新增一个redis.conf偏移量配置项cluster-port-increment,缺省配置+1,这样可以做到端口范围可控,避免冲突。
2、未公开接口
2.1 账号管理(重要)
安全问题:Redis只有一个超户,权限过大。
解决方案:权限最小化原则,增加配置项,角色区分超户,普通用户和只读用户三种。
|
角色 |
redis.conf对应配置项 |
权限说明 |
|
超户 |
requirepass |
所有功能。 |
|
普通用户 |
requireuserpass |
不能进行管理类命令,如shutdown等 |
|
只读用户 |
requirereaduserpass |
在普通用户基础上,进一步限制只能进行读操作。没有script命令权限。 |
普通用户不能进行的操作有:
|
命令 |
解释 |
|
save |
SAVE 命令执行一个同步保存操作,将当前Redis 实例的所有数据快照(snapshot) 以RDB 文件的形式保存到硬盘。 |
|
bgsave |
在后台异步(Asynchronously) 保存当前数据库的数据到磁盘。 |
|
bgrewriteaof |
执行一个AOF 文件重写操作。重写会创建一个当前AOF 文件的体积优化版本。即使BGREWRITEAOF 执行失败,也不会有任何数据丢失,因为旧的AOF 文件在BGREWRITEAOF 成功之前不会被修改。 |
|
shutdown |
停止所有客户端 如果有至少一个保存点在等待,执行SAVE 命令 如果AOF 选项被打开,更新AOF 文件 关闭redis 服务器(server) |
|
sync |
用于复制功能(replication) 的内部命令。 |
|
psync |
用于复制功能(replication) 的内部命令。 |
|
replconf |
暂无用处 |
|
monitor |
实时打印出Redis 服务器接收到的命令,调试用。 |
|
slaveof |
SLAVEOF 命令用于在Redis 运行时动态地修改复制(replication) 功能的行为。 |
|
debug |
调试命令 |
|
config |
配置参数 |
|
restore |
反序列化给定的序列化值,并将它和给定的key 关联。 |
|
migrate |
将key 原子性地从当前实例传送到目标实例的指定数据库上,一旦传送成功,key 保证会出现在目标实例上,而当前实例上的key 会被删除。 |
|
dump |
序列化给定key ,并返回被序列化的值,使用RESTORE 命令可以将这个值反序列化为Redis 键 |
2.2 Redis-cli隐藏密码
安全问题:通过在redis-cli指定-a参数,密码会被ps出来,属于敏感信息。
解决方案:修改Redis源码,在main进入后,立即隐藏掉密码,避免被ps出来。(可参考开源Mysql代码)
2.3 Redis-cli工具使用说明
对于需在现网维护阶段使用的命令/参数、端口等接入方式(包括但不限于产品的生产、调测、维护用途),需通过产品资料等向客户或监管机构公开或受限公开。
2.4 禁止在脚本中通过sudo方式切换用户执行redis-cli
安全问题: redis-cli访问参数带密码敏感信息,会被ps出来,也容易被系统记录操作日志。
解决方案:改为通过API方式(Python可以使用redis-py)来安全访问,禁止通过sudo方式切换到dbuser账号使用redis-cli。
重现条件:可以通过iptables禁掉redis端口来模拟重现。
3、访问通道控制
3.1 预共享秘钥认证(重要)
安全问题:Redis原生认证存在重放攻击:只是简单的交互一次auth xxx
解决方案:采用预共享秘钥(对称加密算法+随机数的双向认证),同时在方案设计上做到最大限度兼容,让客户端改造成本最小,目前平台配套目前支持客户端有:Java,Python,C,Lua。
方案设计如下:
Redis认证协议变更,其中auth命令区分两种功能,通过首字母区分:
|
auth命令含义 |
区分 |
|
认证第一阶段:客户端传递随机数 |
请求:auth <RAND_C 响应:-ERR >TokenBA |
|
认证第二阶段 |
auth >TokenAB |
预共享秘钥认证时序图

说明:Redis为文本协议, 安全随机数长度固定为32字节的可显示字符串,连接2个随机数的分隔符为”@”。
主要认证流程:
1.客户端向服务端执行命令: auth <RAND_C
1) 首字母<表示是认证第一阶段。(便于服务端从协议层区分)
2) RAND_C表示客户端生成安全随机数。
2.服务端产生响应错误回复
1) 获取RAND_C,并生成RAND_S
2) 产生TokenBA=AES128(RAND_S@RAND_C)
3) 响应错误回复:-ERR >TokenBA
说明:错误描述为服务端生成的安全随机数。
3.客户端验证
1) 验证TokenBA是否合法
解密出RAND_S@RAND_C,看看RAND_C是否是自己生成的随机数
2) 客户端产生TokenAB=AES128(RAND_C@RAND_S@dbname@ossdbuser@pwd)
3) 调用认证接口: auth >TokenAB
4.服务端认证
1) 验证TokenAB是否合法
解密出RAND_C@RAND_S,看看RAND_S是否是自己生成的随机数
2) 验证用户和密码合法性: dbname@ossdbuser@pwd
3.2 认证时加上库名
安全问题:Redis没有库名,系统如果只通过用户名+密码,容易猜测和攻击。
解决方案:通过认证时带上库名, 因为每个服务的库名都配置不同,增加攻击复杂度, 认证格式以dbname@dbuser@pwd区分。
3.3 端口矩阵
安全问题:Redis也是一种数据库服务,一般一个进程占用一个端口,集群还会额外多占用一个端口。
解决方案:在端口矩阵写明系统申请的Redis端口范围。
3.4 客户端认证超时时间
安全问题:原生Redis没有限制客户端认证超时时间,存在慢攻击。
解决方案:修改源码,限制在60秒内认证成功,否则服务器将主动断开连接。
说明: 控制完成客户端认证的时间上限。这可以防止无效客户端长时间占用连接通道。
3.5 支持SSL通信
安全问题:增加SSL通信可以提高数据传输的安全。
解决方案:
1.不改动官方源码,通过在客户端和服务端部署SSL Proxy,类似stunnel。
2.支持SSL可配置,涉及开源代码修改。
说明:因为Redis属于交互密集型,每秒处理几万次请求,支持SSL后性能会有比较大损失。
3.6 支持ACL控制
安全问题:目前Redis没有ACL控制。
解决方案:
1. 目前基于平台共享秘钥,其中秘钥是随机生成,每套系统不一样,间接也做到了IP范围控制。
2. 通过iptables控制进一步限制接入IP范围。
3. 如果要具体控制到用户+IP级别,类似Mysql认证。作者antirez已经意识到这个问题,有望在未来版本提供,链接如下:Multi users AUTH and ACLs for Redis
3.7 Jedis客户端相关
安全问题:官方推荐Java客户端Jedis集群最新版还不支持认证。
解决方案:增加认证参数,与服务端共享秘钥认证保持一致。
安全问题:Jedis认证接口密码为参数string。
解决方案:Jedis客户端认证新增一套char[]接口。
3.8 集群认证相关
1. RedisCluster多主多从,内部高度自制,因此Redis的认证masterauth需要加密保存到配置文件。
2.配置集群关系时,基于Gossip协议,Cluster meet需要有认证保护。
Redis缓存数据库安全加固指导(一)的更多相关文章
- Redis缓存数据库安全加固指导(二)
背景 在众多开源缓存技术中,Redis无疑是目前功能最为强大,应用最多的缓存技术之一,参考2018年国外数据库技术权威网站DB-Engines关于key-value数据库流行度排名,Redis暂列第一 ...
- Azure Redis 缓存使用注意事项与排查问题文档整理
StackExchange.Redis 使用名为 synctimeout 的配置设置进行同步操作,该设置的默认值为 1000 毫秒. 如果同步调用未在规定时间内完成,StackExchange.Red ...
- 缓存工厂之Redis缓存
这几天没有按照计划分享技术博文,主要是去医院了,这里一想到在医院经历的种种,我真的有话要说:医院里的医务人员曾经被吹捧为美丽+和蔼+可亲的天使,在经受5天左右相互接触后不得不让感慨:遇见的有些人员在挂 ...
- Windows下Redis缓存服务器的使用 .NET StackExchange.Redis Redis Desktop Manager
Redis缓存服务器是一款key/value数据库,读110000次/s,写81000次/s,因为是内存操作所以速度飞快,常见用法是存用户token.短信验证码等 官网显示Redis本身并没有Wind ...
- 总结:如何使用redis缓存加索引处理数据库百万级并发
前言:事先说明:在实际应用中这种做法设计需要各位读者自己设计,本文只提供一种思想.准备工作:安装后本地数redis服务器,使用mysql数据库,事先插入1000万条数据,可以参考我之前的文章插入数据, ...
- .NET基于Redis缓存实现单点登录SSO的解决方案[转]
一.基本概念 最近公司的多个业务系统要统一整合使用同一个登录,这就是我们耳熟能详的单点登录,现在就NET基于Redis缓存实现单点登录做一个简单的分享. 单点登录(Single Sign On),简称 ...
- Redis缓存连接池管理
import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.util.Assert;import ...
- ssm+redis 如何更简洁的利用自定义注解+AOP实现redis缓存
基于 ssm + maven + redis 使用自定义注解 利用aop基于AspectJ方式 实现redis缓存 如何能更简洁的利用aop实现redis缓存,话不多说,上demo 需求: 数据查询时 ...
- Windows Azure Redis 缓存服务
8月20日,Windows Azure (中国版)开始提供Redis缓存服务,比较国际版的Microsoft Azure晚了差不多一年的时间.说实话,微软真不应该将这个重要的功能delay这么长时间, ...
随机推荐
- 如何利用sql注入进行爆库
SQL注入能做什么 在<SQL注入基础>一文介绍了SQL注入的基本原理和实验方法,那接下来就要问一下,SQL注入到底能什么? 估计很多朋友会这样认为:利用SQL注入最多只能获取当前表中的所 ...
- 三维重建:GitHub百度Apollo 2.0
GitHub:https://github.com/ApolloAuto/apollo 1. 关于Apollo的数据:Apollo的数据会如何开放? 自动驾驶数据将包括具有高分辨率图像和像素级别标注的 ...
- oracle数据库跨库查询
create public database link mylink connect to orclname identified by orclpasswd using 'ORCL'; drop p ...
- (转)淘淘商城系列——Redis持久化方案
http://blog.csdn.net/yerenyuan_pku/article/details/72858975 Redis中设置key的过期时间 Redis中的expire命令用于设置key的 ...
- POJ_1018_(dp)
Communication System Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 28273 Accepted: ...
- 05C语言数组
C语言数组 一维数组 类型符 数组名[常量表达式] #include <stdio.h> int main(){ ] = {,,,}; int a; ;a<;a++){ printf ...
- Django - 模版之继承
模版继承: 当多个html有共同之处时,需要建立一个模版html(master.html) 1.在模版html中,写入公共的部分: 备注:在模版中,我们可以指定多个block ,其中,可以在标题,cs ...
- FATE HDU - 2159
解法 完全背包但是又有别的条件(忍耐值为体力经验是价值) ①首先杀怪是有上限s的,所以需要记录杀怪的数量并且if时候还需要加上条件 ②最后还得遍历一下从小到大遍历当前dp范围内是不是已经有够经验的那么 ...
- C语言中指针的加减运算
参考文章,值得一看 char arr[3]; printf("arr:\n%d\n%d\n%d\n", arr, arr + 1, arr + 2); char *parr[3]; ...
- Turtle-可视化界面画圣诞树
圣诞节(Christmas)又称耶诞节.耶稣诞辰,译名为“基督弥撒”,是西方传统节日,起源于基督教,在每年公历12月25日.弥撒是教会的一种礼拜仪式.圣诞节是一个宗教节,因为把它当作耶稣的诞辰来庆祝, ...