渗透测试漏洞报告:ChatCut.io

测试目标
chatcut.io / Supabase Backend
报告日期
2026-02-10
安全研究员
黄镇 (YELLOWTOWN)
整体风险评估
严重 (CRITICAL)

# 漏洞摘要

在对 chatcut.io 后端 API 进行安全测试期间,发现了 九个 主要的安全漏洞。这些漏洞允许攻击者绕过现有的速率限制机制,通过暴力破解手段获取敏感权限,通过越权操作生成或绑定邀请码,以及最严重的——直接通过前端泄露的管理员密钥接管整个数据库。

# 详细报告

漏洞描述

系统的 OTP 验证接口允许用户通过 6 位数字验证码登录。虽然系统配置了基础的速率限制(返回 HTTP 429),但未实施严格的“账户锁定策略”。攻击者可以通过脚本控制请求速率,在触发限频后短暂休眠并重试,从而在验证码有效期内遍历所有可能的 6 位数字组合,最终接管受害者账户。

复现步骤 (PoC)

{
  "email": "bobisuperplus@gmail.com",
  "token": "{{RANDOM_6_DIGIT_CODE}}",
  "type": "email",
  "gotrue_meta_security": {}
}
[!] 线程-8 限频 (429),休眠 5s...
...
[+] 爆破成功! 有效 Token: 551457
[+] 响应片段: {"access_token":"eyJhbGciOiJIUzI1NiIs...", ...}

危害分析

  • 攻击者可完全接管任意已知邮箱的账户。
  • 绕过密码验证机制,获取用户私有数据。

修复建议

  • 实施指数退避与账户锁定(连续失败 5-10 次锁定 15 分钟)。
  • 对频繁触发 429 的 IP 实施封禁。
  • 缩短验证码的 TTL (Time To Live)。

漏洞描述

/functions/v1/validate-invite-code 接口用于校验用户输入的邀请码。该接口允许高频尝试,且仅依靠简单的限频防御。攻击者可通过字典攻击或随机生成并验证的方式,批量获取系统中有效的邀请码。

复现步骤

POST /functions/v1/validate-invite-code HTTP/1.1
...
{"code": "TEST_CODE"}

修复建议

增加人机验证 (如 Cloudflare Turnstile),并限制单个用户/IP 每日验证失败总次数。

漏洞描述

/functions/v1/ensure-user-invite-codes 接口完全信任请求体中的 userId 参数,而非从 JWT 中提取。任意登录用户都可以修改 userId,为其他任意用户(甚至未激活用户)触发邀请码生成逻辑,导致邀请码无限制生成。

复现步骤

POST /functions/v1/ensure-user-invite-codes HTTP/1.1
Authorization: Bearer <Attacker_Token>
Content-Type: application/json

{
  "userId": "00000000-0000-0000-0000-000000000000"
}

修复建议

删除请求体中的 userId 字段。在云函数中使用 Supabase Auth 上下文 (auth.uid()) 获取当前请求者身份。

漏洞描述

/functions/v1/bind-invite-code 接口错误信任了请求体中的 userId 参数。攻击者可将 userId 修改为任意受害者的 ID,强制将受害者绑定为自己的下线,骗取平台拉新奖励。

复现步骤

POST /functions/v1/bind-invite-code HTTP/1.1
Authorization: Bearer <Attacker_Token>
Content-Type: application/json

{
  "code": "ATTACKER_CODE",
  "userId": "VICTIM_ID"
}

漏洞描述

在应用的 JS 配置文件 https://api.chatcut.io/js/config.js 中,直接硬编码了 Supabase 的 serviceRoleKey。该密钥拥有数据库的最高管理员权限(Bypass RLS),能无视任何行级安全策略,对数据库进行任意读写、删除甚至清空操作,并能调用 Auth Admin API 接管任意用户。

提取与验证

curl -X GET 'https://zbmtvctzvlnrutraynqq.supabase.co/auth/v1/admin/users' \
-H 'apikey: <SERVICE_ROLE_KEY>' \
-H 'Authorization: Bearer <SERVICE_ROLE_KEY>'
=== Checking Prod Env ===
[*] JWT Role Claim: service_role
[CRITICAL] JWT 显示这是最高权限的 Service Role Key!
[!!!] 验证成功: 成功调用 Admin API 获取用户列表。
      当前用户总数: 1
      示例用户: martin_cai@qq.com (ID: 51213e41-db8f-4ff7-9a39-de79966c64b5)

修复建议 (紧急)

  • 立即轮换密钥:在 Supabase 控制台重新生成新的 service_role 密钥。
  • 代码大清洗:彻底从前端代码库中移除对此密钥的所有引用。
  • 审查日志:检查过去一段时间内使用该 Key 的异常操作日志。

在子域名 transcription.chatcut.io 的前端 JS 代码中,发现了硬编码的 Google Gemini API Key (AIzaSyD9uv5jYX_CGs3B9ahO-mq9nEv7Uq-58Xg)。建议移除硬编码并在 Google Cloud Console 中配置 Referrer 限制。

在测试环境 beta1.chatcut.io 的前端代码中,发现了名为 api-secretWEBHOOK_SECRET 的高熵字符串变量 (GGBfa2zy9JyR6vUZ6C9Q6wHnjTcxpZ8r)。极有可能是内部服务凭证或后门,需立即核查用途并隔离测试环境。

漏洞描述

应用通过前端 JS 代码直接连接到 Realtime 服务。用于系统广播的 WebSocket Topic realtime:any 允许未授权用户(仅需公开的 Anon Key)订阅并发送广播消息。攻击者可向所有在线用户实时发送伪造内容(如钓鱼链接)。

点击查看 WebSocket 注入证据
Realtime Broadcast Evidence

漏洞描述

Edge Function /functions/v1/user-messages 存在 IDOR 漏洞:后端逻辑读取请求体中的 userId 参数来返回消息,而未校验是否与 JWT 中的 sub 一致。攻击者可以遍历 UUID 获取全量用户的私密通知记录。

点击查看越权获取数据
Data Leak Evidence

安全性验证通过项

数据读取越权 (RLS)

即使攻击者为他人生成了邀请码,也无法通过 REST API 读取。Supabase 的 RLS 策略有效阻止了跨用户读操作。

JWT 伪造攻击

系统拒绝了 None 算法签名和剥离签名的伪造 Token。且正确校验了 Token 的过期时间 (exp)。

OTP 绕过

/auth/v1/verify 接口正确校验 OTP 代码,拒绝了使用 JWT Token 充当 OTP 的尝试。