2. 服务端请求生命周期与SSRF注入点

要治理SSRF,先要看清一个服务端请求从“用户可控输入”到“真正发出网络连接”之间,究竟经过了哪些环节。SSRF的本质并不是某个函数有漏洞,而是用户可控的数据在某个环节被当作目标地址使用,且缺少足够的约束与校验。因此,定位注入点的关键,是把一次服务端请求拆成可观察的生命周期阶段,再逐段追问:这一段里,哪些值来自外部?它们是否被校验?校验是否可被绕过?

典型的一次服务端出站请求,会经历如下阶段:业务入口接收参数 → URL/地址拼接与解析 → 协议与主机判定 → DNS解析 → 建立TCP连接 → 发送HTTP请求 → 接收并处理响应。SSRF注入点可能出现在其中任意一段,而且往往不是单点,而是“入口宽松 + 解析歧义 + 校验与使用不一致”的组合。

服务端请求生命周期与SSRF注入点分布 ① 业务入口 接收URL/参数 ② URL解析 协议/主机/端口 ③ 校验判定 黑白名单/正则 ④ DNS解析 域名→IP ⑤ 建立连接 TCP/端口 ⑥ 响应处理 回显/转发 注入点 A 参数直连 url=用户输入 注入点 B 解析歧义 @ / # / 编码 注入点 C 校验绕过 正则/黑名单 注入点 D DNS重绑定 解析与连接不一致 注入点 E 重定向跟随 302→内网 注入点 F 响应回显 探测内网 各阶段防御控制点与判断依据 入口白名单 仅允许业务域名 统一解析器 解析结果即连接目标 IP段黑名单 10/172.16/192.168/127 禁止重定向 或逐跳校验 响应最小化 不回显原始响应体 关键判断: • 解析出的IP是否与校验时使用的IP一致?不一致则存在DNS重绑定风险。 • 是否允许跟随重定向?若允许,重定向目标是否重新经过完整校验? • 协议是否被限制为http/https?file、gopher、dict等协议是否被显式拒绝? • 响应内容是否直接返回给用户?若返回,攻击者可利用状态码/耗时/内容差异探测内网。 • 出站流量是否经过统一代理或网关?若经过,可在网络层做二次拦截。

一、业务入口:参数直连是最常见的注入点

很多SSRF的起点非常朴素:接口接收一个URL参数,然后直接交给HTTP客户端发起请求。例如图片抓取、Webhook回调、URL预览、远程文件下载、PDF渲染、数据导入等场景,都会出现类似 url、target、callback、imageUrl 这样的参数。如果这个参数没有经过任何限制,攻击者就可以把它替换为 http://127.0.0.1:6379、http://169.254.169.254/latest/meta-data/ 或内网管理地址。

这一层的防御重点不是“过滤关键字”,而是明确业务到底需要访问哪些目标。如果业务只需要访问固定的几个域名,就应该使用白名单,而不是黑名单。白名单的粒度可以是完整域名、域名后缀或IP段,但必须与业务实际需求对齐。

二、URL解析:歧义与不一致是绕过校验的温床

URL解析阶段是SSRF防御中最容易出错的地方。不同语言、不同库对同一个URL字符串的解析结果可能不同。例如 http://evil.com@127.0.0.1/,有的解析器把 evil.com 当作用户名、127.0.0.1 当作主机;有的则可能把整个字符串当作主机。再比如 http://127.0.0.1#@evil.com、http://127.0.0.1%2f@evil.com、十进制IP http://2130706433/、八进制 http://0177.0.0.1/ 等写法,都可能让校验逻辑与实际连接目标不一致。

正确的做法是:先解析、再校验、后使用,并且校验和连接必须使用同一个解析结果。不要用字符串匹配去判断主机,而应取出解析后的host字段,再对其做规范化处理(如转小写、去除末尾点、还原编码),然后判断是否在白名单内。

三、DNS解析:解析与连接分离带来的重绑定风险

即使校验时域名解析到的是公网IP,真正建立连接时DNS可能返回另一个内网IP,这就是DNS重绑定。防御方式有两种:一是解析一次,把IP固定下来,后续连接直接使用该IP,并在Host头中保留原域名;二是在连接层再次校验目标IP,确保实际连接的地址仍然合法。两者结合更稳妥。

四、连接建立与响应处理:重定向与回显是最后两道口子

很多HTTP客户端默认跟随重定向。攻击者可以提供一个返回302的合法公网地址,重定向到内网目标。因此,要么禁止跟随重定向,要么在每一跳都重新执行完整校验。响应处理阶段同样关键:如果服务端把目标返回的内容、状态码、响应时间甚至错误信息原样返回给用户,攻击者就能利用这些差异探测内网端口开放情况。防御上应最小化回显,只返回业务必需的信息,并对错误信息做统一处理。

定位SSRF注入点时,可以沿着“用户输入 → 解析 → 校验 → 连接 → 回显”这条链路逐段追问:这个值来自哪里?在这一段被如何使用?校验和使用是否一致?只要有一处不一致,就可能成为注入点。

五、架构层面的注入点:不止在代码里

SSRF也可能出现在架构层。例如反向代理、API网关、消息队列消费者、定时任务、CI/CD流水线、Serverless函数等,只要它们会代表服务端发起出站请求,就可能成为跳板。尤其是微服务架构中,服务间调用如果信任了上游传入的URL,风险会沿着调用链放大。因此,治理SSRF不能只盯着单个接口,还要梳理所有出站请求的发起方,建立统一的出站策略。

生命周期阶段典型注入点核心防御动作
业务入口url参数直连HTTP客户端白名单限制目标域名/IP段
URL解析解析歧义、编码绕过统一解析器,校验与连接使用同一结果
校验判定黑名单不全、正则缺陷改为白名单,规范化后判断
DNS解析DNS重绑定固定解析IP,连接层二次校验
连接建立重定向跟随、协议滥用禁止重定向或逐跳校验,限制协议
响应处理响应回显、错误信息泄露最小化回显,统一错误处理

把这张生命周期图记在脑子里,后续无论是做代码审计、渗透测试还是安全设计,都可以按阶段逐项检查。SSRF的治理不是加一个正则就结束,而是要在每个阶段都保证“用户可控的数据不会未经校验地变成网络连接的目标”。