简单竞态条件漏洞如何击垮全球SaaS平台

30 阅读4分钟

简单竞态条件漏洞如何击垮全球SaaS平台

在测试一个SaaS平台时,我发现了其作业提交系统中存在一个关键漏洞。通过利用超规格作业请求的竞态条件,我成功触发了全球服务中断,导致所有用户无法启动应用、创建笔记本或运行作业。

这个漏洞展示了小小的竞态条件加上缺失的验证如何升级为平台级的拒绝服务。

什么是竞态条件?

当两个或更多请求同时到达服务器,而后端没有正确处理并发时,就会发生竞态条件。系统没有单独验证每个请求,而是变得混乱并并行处理多个请求——攻击者可以利用这一点。

理解目标平台

我测试的SaaS平台提供基于云的项目环境,用户可以在其中启动应用程序、创建笔记本和提交计算作业。每个作业请求允许用户指定节点数量、工作池类型和资源限制等参数。

为确保稳定性,此类平台通常会对可同时创建的作业和节点数量实施限制。这些检查旨在防止滥用并保证所有用户的公平资源分配。

然而,我发现这些限制可以通过竞态条件漏洞绕过。

漏洞:作业创建中的竞态条件

该漏洞存在于作业创建API中:

POST /api/v1/jobs HTTP/2
Host: target.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
-WebKitFormBoundary

正常情况下,平台限制作业提交,节点数量限制为10个。但通过发送多个具有高node_count值的并发请求,我能够压垮后端调度程序。

这导致:

  • 作业无限期卡在提交状态
  • 应用程序启动失败
  • 平台上所有用户收到500内部服务器错误消息

复现步骤

  1. 在SaaS平台上创建账户
  2. 启动node_count=1000的作业创建请求
  3. 在Burp Suite中捕获请求并发送到Turbo Intruder
  4. 使用竞态条件脚本同时触发多个请求:
def queueRequests(target, wordlists):
    engine = RequestEngine(endpoint=target.endpoint, 
                         concurrentConnections=1, 
                         engine=Engine.BURP2)
    for i in range(20):
        engine.queue(target.req, gate='race1')
    engine.openGate('race1')
  1. 等待几分钟,然后尝试从另一个账户启动新作业或笔记本
  2. 观察:作业永不进展,应用程序失败,整个服务中断

影响

影响十分严重:

  • 全球服务中断:所有用户受到影响——作业卡住,应用无法启动
  • 拒绝服务(DoS):单个用户即可触发平台级DoS
  • 潜在财务损失:依赖该服务进行生产工作负载的企业客户将面临停机
  • 系统完整性风险:攻击者可重复触发此漏洞,使服务无法使用

CVSS评分(计算得出):9.8 严重

  • 可用性影响:高
  • 攻击向量:网络
  • 所需权限:低

赏金与项目响应

  • 报告日期:2024年9月23日
  • 初始响应:项目方要求立即停止测试,因为造成服务中断
  • 严重性:确认为严重但标记为信息性(违反不允许DoS测试的规则)
  • 最终状态:作为信息性关闭

虽然未获得赏金,但这个案例突显了即使是一个"简单"的竞态条件也能击垮整个SaaS平台。

关键要点

  • 始终为关键操作实施强大的并发控制
  • 速率限制和锁定机制应在后端实施,而不仅是在UI层
  • 竞态条件常常在标准测试中被遗漏——使用Turbo Intruder或自定义脚本进行测试
  • 作为漏洞猎人,一旦注意到服务中断就应立即停止测试,避免超出范围规则

结论

这个案例提醒我们,像缺失并发控制这样的小疏忽如何升级为全球中断。竞态条件仍然是SaaS平台中最被低估但最危险的漏洞之一。

作为猎人,我们需要在好奇心和责任之间取得平衡:证明问题存在,但要避免造成实际损害。

下次再见——祝黑客愉快!🐞⚡

联系与互动

💬 你在竞态条件漏洞方面有什么经验?

在Twitter上关注我:@a13h1_

继续鼓掌、评论和分享你的想法——你的支持激励我分享更多真实的漏洞赏金故事!