服务器端请求伪造SSRF漏洞的利用与防御措施
摘要:# 服务器那点事儿:当你的应用成了黑客的“免费代理” 前两天帮朋友公司做渗透测试,碰到个挺有意思的事儿。他们新上线的电商系统,功能花里胡哨,结果我在一个商品图片上传功能里,硬是看到了他们内网数据库的监控页面——你敢信?问题就出在SSRF上。 说白了,S…
服务器那点事儿:当你的应用成了黑客的“免费代理”
前两天帮朋友公司做渗透测试,碰到个挺有意思的事儿。他们新上线的电商系统,功能花里胡哨,结果我在一个商品图片上传功能里,硬是看到了他们内网数据库的监控页面——你敢信?问题就出在SSRF上。
说白了,SSRF(服务器端请求伪造)这玩意儿,就是让你的服务器“替”黑客去干坏事。很多开发兄弟一听“服务器漏洞”,总觉得离自己挺远。但其实吧,我见过的案例里,十个有六个的漏洞入口,都是那些看似人畜无害的功能:什么图片在线处理、PDF生成、网页预览……这些需要服务器去“取”外部资源的地方,最容易埋雷。
一、SSRF到底是怎么“玩”的?
先别被术语吓着。咱们打个比方:
你开了家代购店(服务器),顾客(用户)跟你说:“老板,帮我去三里屯那家网红店买杯咖啡。”正常情况下,你跑去买了,没问题。
但要是顾客说:“老板,帮我去后厨保险柜里,看看今天营业额多少,顺便拍个照。”——你这要是真去了,不就出大事了?
SSRF就是黑客通过你店里的“代购服务”(服务器功能),让你这个“老板”跑去不该去的地方(内网、云服务元数据接口、本地管理后台),把信息偷出来,甚至直接搞破坏。
真实案例时间:去年某云厂商有个著名事件,攻击者就是利用一个SSRF漏洞,让应用服务器去请求云平台的元数据服务(169.254.169.254),直接拿到了临时密钥,然后……就没有然后了,数据被拖了一大批。很多公司把服务放到云上,以为高枕无忧,结果自家应用的漏洞成了“内鬼”。
更绝的是,有些SSRF还能绕过防火墙。因为请求是从受信任的内部服务器发出去的,防火墙通常对“自己人”很宽松。这就好比,小偷进不了小区大门(外网防火墙),但忽悠你家保姆(应用服务器)从里面把门打开了。
二、黑客的“工具箱”里都有啥?
你以为黑客就是简单地改个URL,把 https://example.com/image.jpg 改成 http://192.168.1.1/admin ?太天真了。现在的玩法,花样多得很。
1. 玩转URL的“七十二变”
很多过滤机制就盯着“http://”、“localhost”这些关键词。但你知道 http://127.0.0.1 可以用 http://0177.0.0.1(八进制)或者 http://2130706433(十进制)代替吗?或者直接用 http://0.0.0.0 ?再高级点的,利用URL解析差异:http://example.com@127.0.0.1,在某些解析器眼里,这可能是访问127.0.0.1,而不是example.com。
(我见过最离谱的绕过,是利用了一个开源库的URL解析bug,让 http://attacker.com#@127.0.0.1 被解析到了本地。当时开发小哥看到日志都懵了:“这语法不对啊!”——但服务器认啊。)
2. 协议不只是HTTP
别只盯着HTTP/HTTPS。如果服务器支持,file:///etc/passwd 能直接读文件,dict:// 可以探测端口服务,gopher:// 更是能构造各种协议包,威力巨大。虽然现在很多库默认禁了这些,但保不齐哪个老系统或者配置失误就给留了门。
3. 利用重定向“洗白”
有些防护策略是:服务器先自己访问一次目标URL,检查是不是“安全”的,安全了再真正处理。黑客就搞个自己的网站,返回一个302重定向,Location头指向 http://127.0.0.1:8080。检查时,看到的是黑客的“安全”网站,真正执行时,却跟着重定向跑到内网去了。防不胜防。
三、防御?光靠黑名单真的会“裸奔”
很多团队一听说要防SSRF,第一反应就是:“加个黑名单!把localhost、127.0.0.1、内网段都禁了!” 想法挺好,但说实话,靠黑名单的防护,基本等于裸奔。
首先,黑名单永远列不完。IP格式千变万化(前面说了),还有各种DNS技巧(比如指向内网IP的域名)。其次,云环境下,元数据服务的IP(169.254.169.254)是固定的,但你能保证未来不出现新的内部服务端点?
那到底该怎么防?我自己的经验是,三板斧下去,能挡掉99%的问题:
第一板斧:白名单,别犹豫
最根本的,就是只允许访问你明确知道的、必要的地址。比如你的应用只需要从阿里云OSS和腾讯云COS拉图片,那就只放行 *.oss.aliyuncs.com 和 *.cos.ap-beijing.myqcloud.com 这类域名。其他一律拒绝。别给服务器“自由发挥”的空间。
第二板斧:统一出口,严格审计 所有需要出站请求的功能,不要让它直接用服务器环境去请求。搞一个专用的、权限最小化的请求代理服务。这个服务单独部署,网络层做严格限制(比如只能访问外网特定端口),并且所有请求都有详细的日志记录:谁、什么时候、请求了什么地址、返回状态码是什么。一旦发现异常请求(比如频繁尝试内网地址),立马告警。
第三板斧:关闭无用协议,更新基础库
在应用层面,明确禁用掉 file://、gopher://、dict:// 这些用不到的危险协议。同时,确保你用的HTTP客户端库(比如Python的requests、Java的HttpClient)是最新版本,很多老版本有默认行为不安全或者存在解析漏洞的问题。
四、出了事怎么办?别光重启
真遇到SSRF攻击告警,第一步千万别急着重启服务或者修复漏洞。一重启,日志可能就没了,攻击链就断了。
- 立马拉日志:找到那个可疑的请求,看看攻击者尝试访问了哪些内部地址。这能帮你判断他的意图:是单纯探测,还是已经拿到了数据?
- 检查相关内部系统:他尝试访问的数据库、管理后台、元数据服务,立刻检查这些系统的访问日志和近期的变更记录,看是否有未授权的成功访问。
- 评估影响范围:根据攻击可能触达的系统,评估数据泄露风险。该改密码的改密码,该轮换密钥的轮换密钥。
- 最后才是修复和上线:根据攻击手法,把漏洞堵死,然后才更新服务。
说到底,SSRF漏洞能成气候,往往不是技术有多难防,而是开发和运维的思维有盲区。总觉得“我的服务器怎么会去攻击自己?”,却忘了服务器背后执行的,是别人精心构造的指令。
防护方案再高级,也抵不上写代码时多问一句:“这个功能,万一用户给我个奇怪的地址,会发生什么?” 很多大事故,起点就是这么一点“没想到”。
行了,今天就聊到这。下次再看到你们项目里有“URL参数”、“远程资源获取”这种功能,不妨多盯两眼,说不定就拦住了一个大坑。

