概述
之前写过跨站请求伪造(CSRF)。相对 CSRF「借浏览器的身份」,服务端请求伪造(SSRF, Server-Side Request Forgery) 是借 服务器自己的身份 去访问资源。
攻击者诱导或控制应用侧发起的请求目标(URL、主机、协议),让服务器:
- 读本不该对外的内部地址
- 访问云厂商实例元数据
- 打内网管理面、Redis、Elasticsearch 等
- 在部分场景下把响应内容回显给攻击者(读文件/扫端口)
目标应用只要「能从 URL 拉数据」或「能把数据推到 URL」,就可能中招:网页预览、Webhook、导入远程图片、文档转换、SSO/元数据拉取、监控探测……
和 CSRF 的对比
| CSRF | SSRF | |
|---|---|---|
| 谁发请求 | 受害者浏览器 | 目标服务器 |
| 凭什么有权限 | 浏览器自动带 Cookie | 服务器在内网/有角色权限 |
| 典型目标 | 用户态改密、转账 | 内网服务、元数据、本机 |
攻击面直觉
攻击者 --> 业务应用(可配置 URL) --> 内网/127.0.0.1/169.254.169.254
常见危险目标:
http://127.0.0.1/http://localhost- 内网段
10.0.0.0/8、172.16.0.0/12、192.168.0.0/16 - 云元数据
http://169.254.169.254/(AWS/阿里云/GCP 等路径不同) file://、gopher://、dict://等另类协议(视客户端库而定)
常见入口
- 远程图片/头像拉取
- 页面截图、PDF 渲染、Office 预览
- Webhook / 回调 URL 测试
- 从 URL 导入数据、RSS、字幕
- 内部 HTTP 客户端封装不严,参数直接进
host
利用与危害(简)
- 信息泄露:内网 banner、错误信息、若回显则读响应体
- 云凭据:元数据里的临时密钥可导致更大横向
- 打内网未鉴权服务:老 Redis、ES、admin
- 协议走私/特殊库:部分场景升级为更强利用(依赖组件)
防护清单
1. 网络层(最有效)
- 应用出站默认拒绝,仅放行明确依赖的外部域名
- 禁止访问链路本地与云元数据地址
- 生产与管理面分段
2. 应用层 URL 校验
- 允许列表 优于黑名单(黑名单永远被 DNS rebinding、IP 编码、跳转绕过)
- 解析后校验 最终 IP 是否为公网允许范围,而不是只看 hostname 字符串
- 禁止或严格限制重定向跟随
- 固定协议为
https(如业务允许)
3. 响应处理
- 不要把原始响应体直接回显给用户
- 限制响应大小与超时
- 使用专用「出口代理」角色,最小权限
4. 云侧
- 启用 IMDSv2 等要求会话头的元数据访问
- 实例角色最小权限
自查问题
- 系统里有哪些「用户可控 URL → 服务端请求」的功能?
- 出站 ACL 是否存在?
- 是否禁用了危险协议?
- 安全测试是否覆盖 DNS rebinding 与 302 跳内网?
小结
SSRF 的本质是 把服务器的网络位置与身份交给了攻击者指定的目标。修漏洞不只是正则拦 localhost,而是 出站控制 + 严格 URL 策略 + 不回显。和 CSRF 一样,它提醒我们:安全边界不在「我写的业务逻辑」,而在「系统实际能触达哪里」。
相关阅读:跨站请求伪造(CSRF)(若站内路径不同请以标签「安全」检索)。
案例化自检(应用安全)
上线前问开发:
- 是否存在「用户输入 URL → 服务端请求」?
- 是否跟随重定向?最多几次?
- 是否校验解析后的 IP 段?
- 响应是否回显给用户?
- 出网策略是否默认拒绝?
任一「否」都要有工单。
小结
SSRF 是云时代的常客。把出站与 URL 处理当成统一安全设计,而不是单个接口的临时正则。