🔐 SSRF 为什么总能绕过“只允许内网访问”的想象

很多人第一次见到 SSRF(Server-Side Request Forgery,服务端请求伪造)时,会把它理解成“攻击者让服务器替自己发一个请求”。这句话没错,但还不够危险。真正麻烦的地方在于,服务器所在的位置、网络权限、身份凭证,往往和外部用户完全不是一个级别。你在浏览器里访问不到的地址,应用服务器却可能轻松访问;你拿不到的云平台元数据接口,后端代码却默认能连。于是一个看起来只是“帮我抓一下图片 URL”或者“帮我读取远程 webhook 内容”的功能,突然就变成了进入内网的跳板。

它为什么会发生?根子通常不是“黑客太厉害”,而是产品和工程习惯出了问题。开发者喜欢写一些通用抓取能力,比如导入头像、预览链接、拉取回调、抓取 PDF、解析 Open Graph 信息。这些功能本质上都在做一件事:让服务器主动请求一个由用户提供的地址。如果这里没有严格限制目标协议、目标主机、跳转行为和解析结果,那用户给的就不再是“一个普通 URL”,而是一条让服务器替他探路的命令。最典型的情况是,开发者只在字符串层面做检查,比如“只要不是 127.0.0.1 就行”,结果攻击者换成 0.0.0.0、localhost 的变体、IPv6 写法、带 DNS 解析的域名,甚至先请求一个外部域名再 302 跳转到内网地址,过滤就成了摆设。

现实里最值钱的 SSRF 目标,不是首页,不是某个后台页面,而是云环境里的 metadata service。比如在 AWS 里,历史上很多 SSRF 攻击最后拿到的不是“一个页面内容”,而是实例角色的临时凭证。拿到这个东西,问题就从“读了一下内网接口”升级成“可以调用云 API 了”。这也是为什么现在很多云厂商都在推动更严格的元数据访问机制,比如 AWS IMDSv2 要求先拿 token,再访问元数据;它的目的不是让流程更麻烦,而是让那种“随手一发 HTTP 请求就能读凭证”的情况直接失效。

防 SSRF 不能靠一句“我们加个黑名单”。黑名单是补丁思维,迟早漏。更靠谱的做法是把“服务器能替用户访问什么”收窄成一个很小的白名单问题。比如这个功能如果只是抓头像,那就只允许 https,且只允许访问少数明确的公共域名;如果是 webhook 回调,就让它只打到预先登记过的目的地;如果业务上根本不需要服务器主动访问外部 URL,那就别做这个能力。再往下一层,网络出口也该有限制,应用容器不该随便访问内网管理面、云元数据地址、本机 loopback。代码层检查和网络层隔离都要有,缺一个都容易翻车。

🧪 你在审一个“网页截图”功能:用户提交任意 URL,后端用无头浏览器打开后返回截图。开发者说“没事,我们已经禁止了 127.0.0.1localhost,所以内网是安全的”。这句话最大的问题是什么?127.0.0.1localhost

💡 核心记忆:SSRF 的本质不是“请求长得可疑”,而是“你让服务器替用户决定它该连谁”。

#Security