游客发表
2019年,某电商平台的一位程序员在调试商品图片加载功能时,发现服务器居然能访问公司内网的管理后台。他把图片URL从正常的CDN地址改成http://192.168.1.100/admin,服务器二话不说就把后台页面抓回来渲染了。这个无心的测试,暴露的就是SSRF漏洞。
SSRF,全称Server-Side Request Forgery,服务端请求伪造。名字听着绕口,原理其实一句话就能说清:攻击者让服务器替自己去访问本不该访问的资源。服务器通常处于内网环境中,能接触到外网用户碰不到的内部系统——数据库管理面板、云服务元数据接口、Redis、Memcached,这些东西外网直接访问不了,但服务器自己可以。SSRF就是借服务器这只手,去够那些够不着的地方。
这种漏洞最常出现在哪里?任何接受URL参数然后去请求的功能。比如“在线图片裁剪”——你给一个图片链接,服务器下载后处理;比如Webhook配置——你填一个回调地址,服务器往那发请求;再比如PDF生成、网页截图、RSS订阅抓取。功能本身没问题,问题出在服务器没有对用户提交的URL做足够严格的校验。
攻击者利用SSRF能干什么?最直接的是端口扫描。提交http://127.0.0.1:6379、http://127.0.0.1:3306,根据返回时间差异或报错信息,就能判断内网哪些端口开着。再进一步,如果内网有未授权的Redis,可以通过SSRF写入SSH公钥或者计划任务,直接拿下服务器。云环境里更危险——AWS、阿里云、腾讯云都在169.254.169.254这个地址上暴露元数据接口,攻击者通过SSRF能拿到临时凭证,进而控制整个云账号。Capital One那起著名的数据泄露,就是SSRF配合元数据接口搞出来的。
防御这件事,说简单也简单,说难也难。简单在于核心思路就一条:白名单。只允许服务器访问你明确认可的地址,其他一律拒绝。难在于URL的解析和校验有很多坑。比如http://127.0.0.1可以写成http://0177.0.0.1、http://2130706433、http://[::1],各种进制和IPv6写法能把简单的黑名单绕过。还有DNS重绑定攻击——第一次解析域名指向合法IP,校验通过后第二次解析指向内网IP。所以光靠正则匹配或者字符串黑名单,基本防不住。
比较靠谱的做法是:解析URL后拿到目标IP,判断IP是否属于内网段(10.0.0.0/8、172.16.0.0/12、192.168.0.0/16、127.0.0.0/8、169.254.0.0/16等),然后直接拿这个IP去建立连接,而不是重新做一次DNS解析。同时禁用不必要的协议,只允许http和https,把file://、gopher://、dict://这些挡在外面。如果业务场景允许,把请求经过一个代理层做统一过滤也是常见方案。
我自己的观察是,SSRF在代码审计中出现的频率比SQL注入高得多。原因不复杂——SQL注入这些年被框架和ORM挡掉了大半,但URL请求这件事太分散了。每个业务模块都可能自己写一段file_get_contents或者requests.get,安全团队很难统一管控。而且很多开发者压根没意识到,让服务器去访问用户提供的URL本身就是个危险动作。
如果你在写代码时遇到“根据用户输入的URL获取内容”这种需求,先停下来想三秒:这个URL真的需要用户完全控制吗?能不能改成从固定列表里选?能不能只允许特定域名?能不能把请求放到独立的沙箱环境里跑?多问这几句,SSRF的口子就能堵住大半。
友情链接