1. 漏洞概述
SSRF (Server-Side Request Forgery,服务端请求伪造) 是一种由攻击者构造形成,由服务端发起请求的安全漏洞。
简单来说,当 Web 应用提供了从其他服务器获取数据的功能,但却没有对目标地址做严格过滤与限制时,攻击者就可以 把这台存在漏洞的服务器当作“跳板”。
这有什么危害呢?
因为请求是由目标服务器自己发出的,它 绕过了外网的防火墙限制。攻击者借此可以:
- 内网探测:扫描内网的主机存活状态和端口开放情况(通常外网是访问不到内网的,但服务器自己可以)。
- 攻击内网应用:向内网的 Redis、数据库等服务发送攻击 Payload。
- 读取本地文件 :利用强大的 伪协议(如
file://,dict://,gopher://)读取服务器上的敏感文件或执行复杂操作。
本关卡演示的是 PHP 中利用 curl 函数配置不当造成的 SSRF 漏洞。
2. 闯关实操 (Exploitation)
2.1 基础利用:HTTP/HTTPS 代理请求
打开关卡,点击页面上的超链接。观察浏览器地址栏,URL 为:http://localhost:8899/vul/ssrf/ssrf_curl.php?url=http://127.0.0.1/.../info1.php
页面展示了一首诗。这说明 ssrf_curl.php 通过 url 参数,去请求了 info1.php。
我们尝试让服务器去访问外网,将参数修改为百度:http://localhost:8899/vul/ssrf/ssrf_curl.php?url=https://www.baidu.com
回车后,页面显示了百度首页!此时,Pikachu 服务器变成了一个代理。

2.2 进阶利用:利用 file:// 协议读取本地文件
SSRF 最可怕的地方在于 PHP 的 cURL 支持多种伪协议。除了 http://,我们还可以利用 file:// 协议来读取服务器内部的本地磁盘文件。
因为我们知道靶场搭建在 Linux (Docker) 环境下,尝试构造读取 /etc/passwd 文件的 Payload:http://localhost:8899/vul/ssrf/ssrf_curl.php?url=file:///etc/passwd
发送请求后,成功读取到了服务器系统的底层账号信息!证明 SSRF 不仅能打网络,还能读本地。

3.【实战排错实录】Docker 环境下的 SSRF 深坑
在本次测试中,我尝试利用 SSRF 去访问本地自己写的一个包含 <?php phpinfo(); ?> 的 1.php 文件,却接连遭遇了两个大坑。如果你也是用 Docker 搭建的靶场,这段排错记录绝对能救命。
🔴 请求 8899 端口报错 Connection refused (拒绝连接)
现象 :
由于我的靶场在外部浏览器是通过 localhost:8899 访问的,于是我理所当然地构造了如下 SSRF 链接:.../ssrf_curl.php?url=http://127.0.0.1:8899/vul/ssrf/upload/1.php
结果后台 cURL 报错:Failed to connect to 127.0.0.1 port 8899: Connection refused。

原理解析(Docker 网络视角偏差):
要理解这个报错,必须搞懂 Docker 的端口映射原理。
启动容器时,我们用了 -p 8899:80,意思是将 宿主机(你的真实电脑)的 8899 端口,映射到 Docker 容器内部 的 80 端口。
- 你的浏览器视角(外部):你访问
8899端口,Docker 截获并转发给容器,一切正常。 - PHP cURL 视角(内部):SSRF 的请求是由 容器内部的 PHP 代码发出的 。当 PHP 去请求
127.0.0.1:8899时,它是在找 容器自己网卡 上的 8899 端口。但是容器内部的 Web 服务器(Apache)只监听了默认的 80 端口,根本没有 8899 端口!所以直接被操作系统拒绝。
✅ 解决办法:换位思考
SSRF 是站在目标服务器内部发起的请求。在容器内部,Web 服务就在 80 端口。所以去掉 8899 即可成功访问:.../ssrf_curl.php?url=http://127.0.0.1/vul/ssrf/upload/1.php

4. 源码分析 (Code Review)
后端 ssrf_curl.php 的代码非常短,但由于配置疏忽,导致了严重漏洞:
if(isset($_GET['url']) && $_GET['url'] != null){$URL = $_GET['url'];
$CH = curl_init($URL); // 初始化 cURL 会话
curl_setopt($CH, CURLOPT_HEADER, FALSE);
curl_setopt($CH, CURLOPT_SSL_VERIFYPEER, FALSE);
$RES = curl_exec($CH); // 核心:无条件执行请求
curl_close($CH) ;
// 直接将请求抓取到的结果输出到前端
echo $RES;
}
漏洞成因:
程序获取到了客户端传入的 $URL 变量后,直接将其传入了 curl_init() 和 curl_exec() 执行网络请求。
全过程 没有验证请求的协议 (允许了危险的 file:// 等)、 没有验证请求的域名 /IP(允许了访问 127.0.0.1 和内网网段)。盲目信任用户输入,将服务器变成了黑客的提线木偶。
5. 修复建议
防御 SSRF 漏洞,需要对向外发起的请求进行极其严格的限制:
- 限制请求的协议(白名单):
通常业务只需要 HTTP/HTTPS 协议,必须在代码层面明确禁用file://,gopher://,dict://等危险协议。php // cURL 限制仅允许 HTTP 和 HTTPS curl_setopt($CH, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); - 限制请求的 IP 地址(防止内网探测):
在发起请求前,解析目标 URL 的 IP 地址,如果发现 IP 属于内网保留地址(如127.0.0.0/8,192.168.0.0/16,10.0.0.0/8),则直接拦截请求。 - 使用白名单域名限制 :
如果业务明确知道需要请求的外部接口域名,建立一个严格的域名白名单,非白名单内的请求一律拒绝。