渗透测试漏洞报告:ChatCut.io
# 漏洞摘要
在对 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-secret 和 WEBHOOK_SECRET 的高熵字符串变量
(GGBfa2zy9JyR6vUZ6C9Q6wHnjTcxpZ8r)。极有可能是内部服务凭证或后门,需立即核查用途并隔离测试环境。
漏洞描述
应用通过前端 JS 代码直接连接到 Realtime 服务。用于系统广播的 WebSocket
Topic realtime:any 允许未授权用户(仅需公开的 Anon
Key)订阅并发送广播消息。攻击者可向所有在线用户实时发送伪造内容(如钓鱼链接)。
漏洞描述
Edge Function
/functions/v1/user-messages 存在 IDOR 漏洞:后端逻辑读取请求体中的
userId 参数来返回消息,而未校验是否与 JWT 中的 sub 一致。攻击者可以遍历 UUID
获取全量用户的私密通知记录。
安全性验证通过项
数据读取越权 (RLS)
即使攻击者为他人生成了邀请码,也无法通过 REST API 读取。Supabase 的 RLS 策略有效阻止了跨用户读操作。
JWT 伪造攻击
系统拒绝了 None 算法签名和剥离签名的伪造 Token。且正确校验了 Token 的过期时间
(exp)。
OTP 绕过
/auth/v1/verify 接口正确校验 OTP 代码,拒绝了使用 JWT Token 充当
OTP 的尝试。