SSRF 与开放重定向漏洞防御实战

深度讲解 SSRF(服务端请求伪造)与开放重定向漏洞:攻击原理与利用链(内网探测、云元数据窃取、内部服务攻击)、URL 解析与 DNS 重绑定绕过、协议走私,以及完整的防御方案(IP 白名单、DNS 二次校验、云元数据保护、重定向治理)。

导语:一台能"访问内网"的服务器

SSRF(Server-Side Request Forgery,服务端请求伪造)的核心是:服务端在替攻击者发请求,而攻击者可以控制请求的目标。如果某个功能会按照用户传入的 URL 去抓取网页、加载图片、下载文件,攻击者就能让它去访问内网、云元数据、Redis 等"本不该被外部看到"的目标。

一句话总结: SSRF 的本质是"服务器变成了攻击者的代理"——攻击者打不到内网,就借这台服务器的手去打;防御的关键是"永远不信任用户给的 URL"。


1. SSRF 攻击原理

1.1 攻击者的思维

正常场景:
  用户请求「转码缩略图」→ 服务端访问 https://example.com/img.jpg → 返回缩略图

攻击场景:
  攻击者传 https://169.254.169.254/latest/meta-data/iam/security-credentials/
        → 服务端替攻击者访问云厂商元数据接口 → 返回临时云凭证
  攻击者传 http://127.0.0.1:6379/...  → 服务端替攻击者访问本地 Redis
  攻击者传 http://10.0.0.5:8080/...   → 服务端替攻击者扫描内网

1.2 常见功能入口

功能可能存在的 SSRF 点
URL 转码/缩略图?url= 参数直接抓取远程图片
网页快照/打印服务端无头浏览器访问用户传入 URL
Webhook 回调配置里填任意 URL,服务端主动请求
文档/CSV 导入支持"从 URL 导入"外部文件
消息卡片/预览服务端去抓取链接的 og 信息
反向代理/网关代理目标地址由用户可控

SSRF 常见于"服务端需要访问外网资源"的功能,且用户能控制目标 URL。


2. 高价值攻击面:云元数据与内部服务

2.1 云厂商元数据接口(云上 SSRF 的王炸)

几乎所有云厂商都提供实例元数据服务,用于实例获取自己的配置与临时凭证:

AWS:      http://169.254.169.254/latest/meta-data/
Azure:    http://169.254.169.254/metadata/instance?api-version=2021-01-01
GCP:      http://metadata.google.internal/computeMetadata/v1/
阿里云:    http://100.100.100.200/latest/meta-data/

攻击链示例(AWS):

# 1) 读取临时 IAM 凭证
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
# 返回一个角色名,例如 web-app-role

curl http://169.254.169.254/latest/meta-data/iam/security-credentials/web-app-role
# 返回 AccessKeyId / SecretAccessKey / Token(短期有效)

# 2) 用拿到的凭证,直接调用 AWS API 提权/拖数据
aws s3 ls s3://内部存储桶 --profile stolen

一句话总结: 云上 SSRF 往往一步到位——拿到临时凭证就能横向访问存储桶、数据库、任意实例。元数据接口是 SSRF 防御的第一优先保护区。

2.2 内网横向攻击

内网扫描:   http://10.0.0.1/ ~ http://10.0.0.254/
                用超时与响应差异,逐段摸清内网存活主机与端口
Redis 未授权: http://127.0.0.1:6379/ 配合 gopher:// 写 crontab/SSH key
内部管理台:   http://内网IP:8080/ 未授权访问的监控/管理面板
数据库/ES:    http://内网IP:9200/ ES、:3306 MySQL、:6379 Redis

3. 绕过姿势:为什么简单黑名单总被击穿

3.1 URL 解析不一致(Parser Differential)

攻击者最常用的手法,是让服务端对 URL 的理解与防御代码不一致:

绕过 IP 黑名单的常见写法:
  http://2130706433/               # 127.0.0.1 的十进制整数形式
  http://0x7f000001/               # 十六进制
  http://0177.0.0.1/               # 八进制
  http://127.1/                    # 省略写法
  http://0/                        # 0.0.0.0
  http://[::1]/                    # IPv6 回环
  http://127.0.0.1%23foo/          # URL 编码
  http://127.0.0.1.nip.io/         # DNS 解析到 127.0.0.1
  http://user:pass@127.0.0.1/      # 用户名密码混淆

3.2 重定向与协议走私

重定向跟随(Redirect following):
  攻击者传一个「自身合法」的 URL(如 https://safe.example.com)
  该地址 302 跳到 http://169.254.169.254/... → 服务端跟随 → 打到元数据
  防御方只校验了初始 URL,没限制后续跳转目标

协议走私(Protocol smuggling):
  用 file://、gopher://、dict:// 等非常规协议
  读取本地文件(/etc/passwd)、或构造 Redis 协议报文

3.3 DNS Rebinding(DNS 重绑定)

攻击者域名 evil.com 的 DNS 记录在「第一次解析」返回公网 IP(通过校验),
「第二次解析」返回 127.0.0.1(绕过校验)。

校验时解析出的是安全 IP → 服务端真正建连时再次解析 → 得到内网 IP。
防御:对「校验用的 DNS 解析」与「实际建连的 IP」都做校验,或直接按 IP 发起请求。

一句话总结: SSRF 绕过是「解析差异 + 重定向 + 协议 + DNS 时序」的组合拳,黑名单式防御必然漏——必须白名单 + 二次校验。


4. 防御方案:纵深组合

4.1 输入侧:URL 白名单 + 协议白名单

① 协议白名单:只允许 http:/https:,其余(file/gopher/dict/ftp)一律拒绝
② 域名白名单:只允许业务需要的域名/后缀,其余一律拒绝
③ 若必须开放任意 URL:把「抓取」放到专用隔离服务(如 headless 容器),
   且该服务无内网路由、无云凭证、无敏感权限

4.2 网络侧:DNS/IP 二次校验

// 校验伪代码:解析 → 检查 IP → 按 IP 建连(而非按域名)
ips := net.LookupIP(host)
for _, ip := range ips {
    if isPrivate(ip) || ip.IsLoopback() || isCloudMetadata(ip) {
        return error("目标地址不允许访问")
    }
}
// 禁止跟随重定向;若必须跟随,对每个跳转目标重新执行同样的 IP 校验

4.3 云元数据保护(IMDSv2)

AWS IMDSv2:强制 Token 化——请求必须带 PUT 换取的 token,普通 GET 不再返回数据
            (阻断「一次 GET 拿凭证」的经典 SSRF 利用链)
阿里云/腾讯云:默认即需要请求头(如 metadata token 或 header 校验)
最佳实践:给所有出网请求加「禁止访问元数据地址」的网络层规则(如安全组/策略)

4.4 架构层兜底

网络最小化:抓取/回源服务放在独立网段,只放行必要的出网规则
内网分段:即使 SSRF 发生,也摸不到核心数据库/管理面
最小权限:给抓取服务所在角色最低权限(无 IAM 写权限、无其他云资源访问权)
出网代理白名单:企业内网通过代理放行「白名单目标」,从源头阻断任意出网

一句话总结: SSRF 防御四件套——协议/域名白名单 + DNS/IP 二次校验 + 云元数据保护 + 出网网络最小化。单靠一层必然被绕过,必须叠加。


5. 开放重定向漏洞(Open Redirect)

5.1 漏洞原理

经典代码:
  // ❌ 直接信任参数作为跳转目标
  redirect(request.getParameter("redirect_url"));

攻击场景:
  https://safe.example.com/login?redirect_url=https://evil.com/phish
  → 用户以为在安全站点,点击后被带到钓鱼站

危害(常被低估):
  ① 钓鱼:跳转到仿冒登录页
  ② OAuth token 窃取:授权回调跳转被劫持,Authorization Code / Token 泄露给攻击者
  ③ 信任利用:用于构造「安全域名」的恶意链接,绕过邮件/IM 的域名信誉检查

5.2 防御与修复

✅ 白名单跳转:
  只在白名单域名/路径内跳转(如 /login?next=/dashboard,仅允许站内相对路径)
  站内跳转一律用相对路径或后端映射,不直接拼接用户输入
✅ 服务端统一处理:
  跳转目标由后端校验后再下发,前端不直接渲染用户可控 URL
✅ 若必须支持外链跳转:
  用「中间跳转页 + 二次确认」,或在跳转时校验目标 host 白名单

❌ 避免:
  直接 redirect(user_input)
  用正则只匹配开头(https://evil.com#https://safe.example.com 可绕过)

一句话总结: 开放重定向常被当作"低危",但它能放大钓鱼与 OAuth 凭证窃取——修复原则是「跳转目标必须白名单化或站内化」,绝不信任用户输入。


6. 检测与测试

6.1 自动化与人工结合

① 代码审计:grep 所有「取用户输入 → 发起 HTTP 请求」的代码路径
② 扫描:SAST(污点分析标记 URL 流向)+ 半自动 SSRF 检测(改 IP 看响应差异)
③ 手工验证:核心点必须人工验证
   - 输入本地/元数据地址,观察响应内容是否回显
   - 内网探测用「计时差异 + 状态码差异」确认连通

6.2 验证的注意点

不要在生产盲扫内网网段(可能触发安全告警、打爆内部服务);
在测试环境用「回显式」判断(如把目标改成自己可控的监听服务,
观察服务端是否真的回连),比盲扫更准确。

7. SSRF 防御避坑清单

坑后果对策
只做 IP 黑名单变形写法/Nginx 转发全漏白名单 + 二次校验
只校验初始 URL重定向链打到内网限制/校验每个跳转目标
允许 file:// 等协议本地文件读取协议白名单 http/https
不保护元数据接口一次 GET 拿云凭证IMDSv2 + 网络层禁访
抓取服务在内网主干扫到数据库/管理面独立网段 + 出网最小化
回源服务用高权限角色凭证被拖走横向扩散最小权限角色
直接信任 redirect 参数钓鱼/OAuth 凭证泄露跳转白名单化

8. 总结

SSRF 是"借刀杀人"型漏洞,云上价值极高、绕过手段极多,黑名单必死、白名单起步。记住四道防线:

防线要点
输入协议白名单 + 域名白名单
网络DNS/IP 二次校验 + 按 IP 建连 + 不跟随重定向
云IMDSv2 + 元数据地址网络级禁访
架构抓取服务隔离网段 + 最小权限 + 出网代理白名单

开放重定向则记住一句:跳转目标永远白名单化或站内化。把这两类漏洞当成"服务端替用户访问外部世界"的统一问题来治理,就能从架构上根治,而不是逐个补洞。

延伸阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「安全」更多文章

  1. 威胁情报与 APT 防御实战
  2. 漏洞全生命周期管理实战
  3. 系统安全基线配置与加固实战