Learning Man's Blog

Redis Rce 简析

字数统计: 1.1k阅读时长: 4 min
2019/07/10 Share

总的下来,利用主从连接断开恢复后全量备份写入 so 进行加载调用

也可以当做任意文件上传,配合之前的利用方式进行攻击

0x0?

之前 redis 常用的利用方式基本三种

  1. 写 shell 或文件
    1. 绝对路径
    2. 可写权限
  2. 写 ssh 公钥
    1. 需要相关用户权限
  3. 写 cron(tab) 反弹 shell
    1. 目前只能 centos

注意有两点

  1. 高版本 redis 会在 redis 权限下启动,非 root,对 1、2 限制很大
  2. 只能 centos,是因为ubuntu、debian等系统会改文件权限为644,cron会显示需要600

新方法的好处

  1. 无利用save写文件时存在的脏数据影响
  2. 利用 module 加载 so,只要有兼容系统版本的 so 即可

0x00 Protocol

redis-server 支持两种协议

  1. Plaintext:明文(通过 空格符分割)

     SET keyname value\n
  2. 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>即可

同步步骤

  1. Slave 端启动与 Master 的连接
  2. Slave 试图继续部分(或完全)重新同步
  3. Master 通过发送一段命令流(a stream of commands)来保证 Slave 进行更新, 以便复制 Master 的任何数据变化

流程图

0x02 攻击流程

  1. 登录 target 设置为的从服务器

     > slaveof <ip> <port>
  2. 设置 dbfilename

     > config get dbdir
     > config get dbfilename # 此步骤用于最后恢复
     > config set <dbdir>/<evil_so_name>
  3. 建立虚假 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心跳测试,但与攻击无关

  4. 传输完毕 so 后,执行slaveof no one取消主备设置,避免可能的污染

  5. 在 target 上执行 module load &#x3c;dbdir + evil_so_name>,执行命令


能触发全量备份的关键点在于步骤 2、3 执行时,redis-master 相当于在断线情况下重新上线的,这样从服务器会直接会向主服务器发送 Rsync 确认是否要备份以及备份的方式是差异还是全量,通过传递假的备份内容(即 so)写入到目标机上,再利用 redis module 拓展功能进行加载,实现了命令执行

下面动图中,左侧为 master,右侧为 slave,可以看到在 master 上线后,左下角的窗口接收到了 psync 请求


补一张静态图

-w822

利用工具

0x03 临时文件

适用于 config 命令被禁止时,通过稳定的保存路径及文件名传输 so

syncWithMaster函数中,可以看到临时文件命名规则

-w612

注意,作者是通过传输 payload 时,提供一个错误(更大)的长度,即$ + len(payload)+N + \r\n + payload + \r\n,使从服务器生成临时文件

  • Unixtime:精确到秒,可通过time命令获取
  • Pid:为 redis -> process_id,可通过info server获取

-w478

但是需要注意临时文件存活时间极短,后会覆盖 dump.rdb

-w1433

但是我直接module load ./dump.rdb不也可以么???,尝试简单修改下 exp,可以看图中显示是可以的,所以有点不理解为什么一定要利用短命的 temp

-w1663

0x04 Redis 集群

学习中

参考资料

CATALOG
  1. 0x0?
  2. 0x00 Protocol
  3. 0x01 主从模式
  4. 0x02 攻击流程
    1. 利用工具
  5. 0x03 临时文件
  6. 0x04 Redis 集群
  7. 参考资料