当前位置:首页 > 综合

ssrf 漏洞

某个深夜,漏洞安全研究员老周收到一条告警:内网运维平台的漏洞某个接口,被人用一条畸形请求打穿了。漏洞对方提交的漏洞URL参数里,赫然写着一个内网IP——http://192.168.1.10:6379。漏洞那是漏洞公司的Redis服务器,没设密码,漏洞直接暴露在应用层的漏洞“代理”之下。攻击者没进DMZ,漏洞没碰防火墙,漏洞就靠这个接口当跳板,漏洞往Redis里塞了条定时任务,漏洞反弹了个shell回来。漏洞

这就是漏洞SSRF,服务端请求伪造。漏洞核心问题只有一个:你的服务器替用户去访问了任意URL,而它自己根本不知道那是什么。大多数开发者写代码时,脑子里默认“用户传的链接就是给我用的”,可服务器不是浏览器,它带着内网IP、云主机元数据、甚至Unix套接字的访问权限。一个看似无害的“图片预览”“网页截图”“URL检测”功能,就能把内网大门撬开一条缝。

我见过最典型的案例,是某个云厂商的控制台。用户提交一个回调地址,后台就去请求它——本意是验证URL有效性。结果有人把地址填成http://169.254.169.254/latest/meta-data/,那是云服务器的实例元数据服务,里面躺着临时密钥。几秒钟,攻击者就拿到了该账号的最高权限。整个过程没有爆破,没有提权,就是一次普通的HTTP GET。

修复SSRF说难也难,说简单也简单。最粗暴的办法是白名单,只允许请求你预设的域名或IP段。但这在业务灵活的场景下不现实——比如一个允许用户自定义Webhook的工具,你总不能只让他连自己的服务器。那就退一步:做DNS解析校验。把用户输入的域名解析成IP,检查是不是内网地址、保留地址、链路本地地址。但别高兴太早,攻击者会用DNS rebinding绕过——第一次解析给你看公网IP,第二次解析成内网IP。你得在连接建立后重新校验一次实际连接的IP,或者干脆禁用重定向,把HTTP库的follow_redirects关掉。

还有个细节,很多人忽略:URL解析的差异。Python的urlparse和Java的URI对特殊字符的处理不同。攻击者用http://127.0.0.1@evil.com,看起来域名是evil.com,但某些库会忽略@前面的内容,直接连到127.0.0.1。更阴的是用十进制、十六进制、八进制表示IP,比如http://2130706433,解析出来就是127.0.0.1。你写黑名单的时候,得把这些变体全堵上。

我自己做代码审计时,最讨厌看到那种“用户传URL,后台直接get”的写法。哪怕你加了协议限制,只允许http和https,也能被file://协议绕过——前提是你没过滤协议名。别用字符串拼接,用正规的URL解析库,把协议、主机、端口拆开分别校验。

说到底,SSRF的本质是信任边界没划清。你的服务器是内网的一等公民,它不该被当成一个普通的HTTP客户端来使。每次写这种功能前,先问一句:这个请求真的需要用户来控制目标地址吗?如果非做不可,那就把能想到的坑都填平——校验IP、禁重定向、锁协议、限制端口、超时设短、响应内容别原样返回。

老周后来把那台Redis的漏洞补上了,加了ACL,改了默认端口。但他说,如果攻击者换一种方式,比如打内网的K8s API Server,或者扫一遍内网端口再决定下一步,那后果就不是丢一台缓存服务器的事了。SSRF这玩意儿,平时看不见,一旦被利用,就是一条笔直的通向内网的高速公路。你唯一能做的,就是别让服务器变成那个随便替人开门的前台。

分享到: