🔐 为什么 SSRF 能打到“你以为外面碰不到”的内网

很多人第一次看到 SSRF(Server-Side Request Forgery,服务端请求伪造)时,会误以为它只是“让服务器帮我访问一个网址”。问题没这么简单。真正危险的地方在于,请求不是从攻击者电脑发出去的,而是从你的业务服务器、云主机、容器、函数计算环境里发出去的。也就是说,攻击者借用了“服务器的网络位置”和“服务器的身份”。你前端用户访问不到 127.0.0.1,访问不到 169.254.169.254,也碰不到 Kubernetes API、Redis、Consul、内部管理面板,但你的应用服务器很可能可以。只要业务里存在“根据用户输入去拉取 URL”的功能,比如图片抓取、网页预览、Webhook 回调测试、导入远程文件、头像同步,SSRF 就有机会出现。

它为什么会发生?根子通常不是“少了一个过滤”,而是设计上默认相信了“用户给的 URL 只是普通外链”。现实里 URL 不是一个简单字符串,它能指向内网 IP、环回地址、IPv6、本地域名,甚至还能借重定向跳转到你原本不想访问的地方。更糟的是,很多程序员只做了表面校验,比如禁止 127.0.0.1,结果攻击者改用十进制 IP、IPv6 映射、DNS 解析变化,或者先访问一个看起来正常的域名,再被 302 重定向到内网地址。补丁式拦截会越补越乱,因为特殊情况太多了。

真正的防法不是写一堆 if/else 去猜攻击者会怎么绕,而是把“服务器代替用户访问任意 URL”这件事收紧成一个小得多的问题。业务上如果只需要抓取你自家 CDN 的资源,那就只允许固定域名和固定协议;如果必须支持第三方地址,就在出网层做白名单和网段封锁,直接禁止访问内网、元数据地址和管理平面;同时关闭自动跟随重定向,或者每跳都重新校验目标地址。云环境里还要单独保护实例元数据服务,比如 AWS IMDSv2,就是因为历史上太多 SSRF 最后都不是“读了个页面”,而是拿到了临时凭证,再一路横向移动。你要防的不是“有人访问了一个奇怪网址”,而是“服务器替别人做了不该做的网络动作”。

🧪 你在做“导入头像 by URL”功能,代码先检查用户输入必须以 https://trusted.example.com/ 开头,然后后端请求这个地址下载图片。测试时有人提交的链接确实是这个域名,但服务器最终却访问到了内网服务。最可能的问题是什么?

💡 核心记忆:SSRF 的本质不是“访问了恶意网址”,而是“攻击者借你的服务器身份和网络位置去碰本来碰不到的东西”。
#Security