为了提升用户的浏览安全,IETF 提出了名为“Incrementally Better Cookies”(逐步改进的 Cookie)的计划,旨在解决 CSRF 和其他客户端安全问题。
随后,Chrome 等主流浏览器实施了这些改动,引入了 SameSite 属性,有效缓解了传统的 CSRF 攻击。这是否意味着 CSRF 攻击已完全成为历史?答案显然是否定的。
在对主流 Web 应用进行安全审计时,我们发现客户端路径遍历(Client-Side Path Traversal, CSPT)可以被巧妙地用来重新“复活” CSRF 攻击,这为现代应用安全带来了新的挑战。
这篇博客是对相关研究的简要介绍,详细的研究成果、方法论以及深入分析可以在发布的白皮书中找到。
https://www.doyensec.com/resources/Doyensec_CSPT2CSRF_Whitepaper.pdf
我们的研究从客户端路径遍历的基础入手,展示在 CSRF 攻击中常见的源点(sources)和 汇点(sinks)。为了验证这一发现的影响力与创新性,我们分析并展示了多个主流 Web 消息应用中的实际漏洞,包括 Mattermost 和 Rocket.Chat 等。
此外,为了帮助安全研究人员更高效地发现 CSPT 源点和汇点,我们专门开发并发布了一款 BurpSuite 插件。
插件地址: https://github.com/doyensec/CSPTBurpExtension
什么是客户端路径遍历?
每位安全研究人员都应该了解经典的路径遍历漏洞。这类漏洞使攻击者可以通过类似于 ../../../../ 的有效载荷,读取超出预期目录范围的服务端文件。
然而,与服务器端路径遍历攻击不同,客户端路径遍历攻击的目标是利用这种漏洞,将前端发起的合法请求“重定向”到攻击者控制的 API 端点,而非读取文件。

尽管路径遍历漏洞在服务器端应用中非常常见,但客户端路径遍历的相关案例却鲜有曝光。我们找到的首个案例是 Philippe Harewood 在 Facebook 漏洞赏金计划中报告的一个漏洞。
从那时起,与客户端路径遍历相关的参考资料寥寥可数,主要包括以下几项:
1. 2021 年 Sam Curry 的推文
https://x.com/samwcyo/status/1437030056627523590
2. Johan Carlsson 在 GitLab 中发现的 1-Click CSRF 漏洞
https://gitlab.com/gitlab-org/gitlab/-/issues/365427
3. Medi 提出的 CSS 注入漏洞,该漏洞入选 Portswigger 2022 年 Web 黑客技术 Top 10
https://mr-medi.github.io/research/2022/11/04/practical-client-side-path-traversal-attacks.html
4. Antoine Roly (Erasec) 提交的 CSRF 漏洞
https://erasec.be/blog/client-side-path-manipulation/
5. OWASP 关于客户端 CSRF 的参考和Soheil Khodayari 和 Giancarlo Pellegrino 的研究论文
https://www.usenix.org/system/files/sec21-khodayari.pdf
长期以来,客户端路径遍历漏洞经常被忽视,许多人可能仅将其视为影响较低的漏洞。但实际上,它可以用于强制终端用户在 Web 应用程序上执行未授权的操作,这种潜在危害使其成为值得深入研究和防御的重要攻击面。
如何实现跨站请求伪造 (CSPT2CSRF)
本次研究起源于我们在多次 Web 安全评估中利用客户端路径遍历漏洞的经历。然而,我们发现社区缺乏足够的文档来探讨如何利用它实施 CSRF 攻击(即 CSPT2CSRF)的完整链条和潜在影响。
来源(Source)
在研究过程中,我们注意到一个普遍的认知偏见:研究人员通常认为用户输入必须来自前端表单。然而,与 XSS 类似,任何用户可控的输入都可能导致 CSPT(例如 DOM 型、反射型、存储型),常见的来源包括:
- URL 片段 (Fragment)
- URL 查询参数 (Query Parameters)
- 路径参数 (Path Parameters)
- 从数据库注入并最终渲染到前端的数据
评估来源时,还需要考虑漏洞是需要在特定用户操作下触发,还是在页面加载时自动触发。这种复杂性将直接影响漏洞的最终严重性评级。
接收端(Sink)
CSPT 的本质是“重定向”了一个由前端代码发起的合法 API 请求。因此,攻击者可能无法完全控制该请求的 HTTP 方法、请求头和请求体。这些限制与漏洞的具体来源密切相关。
同一个前端代码中可能存在不同的输入源,每个源触发的请求行为(如 GET/POST/PATCH/PUT/DELETE)可能不同。因此,每个 CSPT2CSRF 攻击都需要明确描述其来源(Source)和接收端(Sink),以便准确评估漏洞的复杂性和严重性。
攻击者的目标
作为攻击者,我们的目标是找到共享相同限制条件(如方法、头部)的所有高影响接收端。实现这一目标的方法包括:
- 查看 API 文档
- 进行 源代码审查
- 使用 Semgrep 规则进行模式匹配
- 使用 Burp Suite Bambda 过滤器进行流量筛选
CSPT2CSRF 的 “Bambda” 过滤器
“Bambda” 是我们在研究中开发的辅助脚本,旨在帮助安全研究人员快速从海量流量中定位潜在的客户端路径遍历漏洞的接收端。借助此工具,可以更高效地评估漏洞的潜在影响和利用价值。
下图展示了一个示例 Bambda 脚本,它用于筛选出指向特定主机 (api.target.com)、使用 POST 方法、包含 JSON 参数且具有 organizationId 字段的请求,这类请求可能就是潜在的 Sink。

boolean matches(ProxyHttpRequestResponse requestResponse)
boolean isCorrectHost = requestResponse.request().httpService().host().equalsIgnoreCase("api.target.com");
boolean isPostRequest = requestResponse.request().method().equalsIgnoreCase("POST");
boolean isJSON = requestResponse.request().hasParameters(HttpParameterType.JSON);
boolean hasMandatoryParam = requestResponse.request().hasParameter("organizationId", HttpParameterType.JSON);
return isCorrectHost && isPostRequest && isJSON && hasMandatoryParam;
利用 GET 类型 Sink 的 CSPT2CSRF 链
在某些场景中,可以通过利用 Client-Side Path Traversal (CSPT) 和 GET 类型的 Sink 来实现攻击:
- 通过开放重定向泄露敏感数据:利用开放重定向将与源相关的敏感数据泄露到攻击者控制的 URL。
- 通过开放重定向加载恶意数据:加载攻击者提供的恶意脚本或数据,从而触发 XSS 攻击。
挑战在于,由于开放重定向漏洞被广泛关注,以及现代前端框架安全性的提升,寻找这类可直接利用的漏洞难度很大。
尽管如此,研究表明,即使某些状态更改操作没有直接使用 GET Sink,也可以通过 CSPT2CSRF 进行链式利用,而无需依赖开放重定向或触发 XSS。
CSPT2CSRF 的链式攻击
在实际应用中,通常可以将一个利用 GET Sink 的 CSPT2CSRF 与另一个状态更改型(如 POST)的 CSPT2CSRF 进行链式组合。
通过这种方式,即使单独的漏洞看似影响有限,结合起来也可以执行更复杂的攻击,进而影响系统的核心功能。这种链式利用展示了 CSPT2CSRF 的灵活性,尤其是在现代单页面应用 (SPA) 中。

- 第一原语:GET CSPT2CSRF
- 来源:查询参数中的
id 参数。
- 接收点: 针对某个 API 端点的 GET 请求。
- 第二原语:POST CSPT2CSRF
- 来源: 第一个请求返回的 JSON 数据中的
id 字段。
- 接收点: 针对另一个 API 端点的 POST 请求。
为了将这些原语进行链式利用,必须找到一个 GET sink,并且攻击者需要能够控制其返回的 JSON 数据中的某个字段(如 id)。有时,后端可能会直接授权并信任前端回显的 JSON 数据。
我们发现最常见的 gadget 是滥用应用的文件上传/下载或内容读取功能。攻击者可以上传一个包含恶意 id 值的文件(如 JSON 格式),然后通过第一个 GET 型 CSPT 请求读取该文件,获取并传递这个 id,最终触发第二个 POST 型 CSPT 请求,完成状态更改。
在白皮书中,我们通过一个 Mattermost 的实际案例详细说明了这一攻击链。
工具与社区分享
这项研究已在 2024 年 OWASP Global AppSec Lisbon 大会上由 Maxence Schmitt(@maxenceschmitt)进行了展示。演示文稿可以通过以下链接查看。
https://www.doyensec.com/resources/Doyensec_CSPT2CSRF_OWASP_Appsec_Lisbon.pdf
此外,我们将研究成果集成并发布了一款 Burp Suite 插件 —— CSPTBurpExtension,用于自动化发现客户端路径遍历漏洞的源点(Source)和汇点(Sink)。

总结
我们认为 CSPT2CSRF 这类漏洞被许多安全研究人员忽视,而大多数前端开发人员对此更是一无所知。我们希望这项工作能够引起大家对这类攻击面的重视,并帮助安全研究人员和防御者更好地保护现代应用程序。
作为技术交流的一部分,我们也欢迎你来到 云栈社区 的相关板块,与更多安全从业者探讨 Web安全 与 渗透测试 的实战经验。
技术案例浅析
让我们通过一个简化案例来理解攻击过程。核心思路是构建一个漏洞利用链。
首先,攻击者需要找到一个客户端路径遍历(CSPT)漏洞。通常,当前端拼接 API 请求路径时,如果未对用户输入进行过滤,就可能形成漏洞源点(Source)。
http://localhost:8065/doyensec/channels/channelname?telem_action=under_control&forceRHSOpen&telem_run_id=../../../../../../api/v4/caches/invalidate
当受害者访问上述恶意链接时,前端会提取 telem_run_id 参数的值(../../../../../../api/v4/caches/invalidate)并拼接到某个基础路径后,从而错误地向 /api/v4/caches/invalidate 端点发起请求。由于该请求是由受害者浏览器从前端上下文发起的,它会自动携带会话 Cookie 和 CSRF Token。

但这只是一个清理缓存的低危端点。攻击者会进一步寻找更高危的汇点(Sink),例如插件安装接口。通过将路径遍历指向 /api/v4/plugins/install_from_url,并配合相应的查询参数,就可能实现远程代码执行(RCE)。

这个技术巧妙之处在于,它利用了前端应用固有的“代理”或“路由转发”行为,将看似无害的路径遍历,转变为了能够绕过 SameSite Cookie 和 CSRF Token 防护的强授权请求,极大地扩展了攻击面。
原文参考及致谢:https://blog.doyensec.com/2024/07/02/cspt2csrf.html