Technical Deep Dive

为什么 3Commas 被偷 $22M
而 TVSBot 的设计不会

2026-06-03·8 分钟阅读·架构 / 安全

2022 年 12 月,加密自动交易最大品牌 3Commas 发生史上最严重的 API key 外泄 — 100 万把交易所 key 托管在他们数据库,外泄 10 万把,链上分析师 ZachXBT 验证 44 名受害者损失 $14.8M,总被盗估计 $22M。

这不是「他们被骇」的故事,是「托管模型的单点失灵」的故事。本文拆解事件、 解释为什么这种设计迟早会出事、以及 TVSBot 怎么避开。

第一幕:事件时间线

2022 年 10-11 月:用户开始回报「我没下单,但账户在 FTX (FTT) 自动交易」。3Commas 初始回应是「用户自己 phishing」。

2022 年 12 月 28 日:骇客在 Twitter 公开部分 API key 文件,附带下载链接。经 ZachXBT 与独立研究员交叉验证,这些 key 对应的 账户确实有发生未授权交易。

12 月 29 日:3Commas CEO Yuriy Sorokin 承认事件, 并请求 Binance、OKX、KuCoin 等交易所配合「revoke 所有 3Commas 托管的 API key」。这个请求本身揭露了一个关键事实 — 3Commas 无法自行修复用户资金损失,因为 key 属于别人的平台, 他们只能请求别人撤销。

第二幕:技术根因

托管型 bot 平台的标准架构长这样:

用户 → bot 平台
        ├── 加密储存 API key + secret(资料库)
        ├── 解密后呼叫交易所 API 下单
        └── 结果回报给用户

这看起来合理 — key 加密了嘛。但这个设计有一个 共同失灵点(single point of failure):数据库 + 解密密钥,是 100 万个用户的单一信任端。

一旦数据库被 dump(无论透过 SQLi、云端配置错误、内部人员 leak), 加上解密密钥也外泄(多数平台密钥跟 DB 在同个云环境), 所有用户 key 同时暴露。

这就是 3Commas 发生的事:根据事件报告,密钥管理跟 DB 在同一个云服务内, 一次入侵全部攻陷。

更糟的是:托管的 key 通常有 Trade + Withdraw 权限

很多 bot 平台为了「方便用户开启更多策略类型」(自动转仓、跨币套利等), 建议用户把 Withdraw 权限也勾起来。3Commas 部分受害用户就是这种状态 — 攻击者直接从交易所提币到自己钱包。

第三幕:TVSBot 的架构为什么不同

我们从第一天就为避开这个失灵模式而设计,具体 3 条:

1. 绑定时拦下有提币权限的 key(最关键)

绑定 API key 时,系统会向交易所确认这把 key 的权限:在 Binance、OKX、 Bitget,开了 Withdraw(提币)的 key,或权限查不到、无法确认的 key, 一律拒绝绑定。Bybit、BingX、Gate.io 目前无法自动检查,请自行确认没有勾选提币。更早之前绑定的 key,按「检查」时会重新确认提币权限,有开就会显示警告。

这代表:只要 key 没开提币权限,即使 key 被偷,攻击者也无法提币。最坏情况是 wash trade 损失少量手续费,资金锁在交易所账户。

2. 加密密钥跟 DB 物理分离

DB 在 Supabase(一个云厂商),FERNET_MASTER_KEY 存在 Fly secrets(不同云厂商)。攻击者要同时打穿两个独立的云环境才能解密 key — 这比打穿单一服务难太多。

密钥也不会进 git、不会进 DB backup、不会存任何 log。连我们自己 admin 直查 DB 也只能看到 base64 加密字符串。

3. IP 白名单:我们目前给不出固定 IP,请不要启用

各交易所 API 都支持 IP 白名单,理论上是很好的一层防护。但老实说:TVSBot 的后端跑在 Fly.io 的共用出口上,没有固定的对外 IP,所以我们给不出一个能让你 填进白名单的地址 —— 填了只会让下单被交易所拒绝。在我们买到固定出口 IP 之前, 请不要启用白名单,改用「只勾 Trade、不勾提币 + 开在子账号」来限缩风险。 有了固定 IP 我们会直接显示在 API Keys 页上。

4. 信号双重验证

每个用户的 webhook URL 带独立 token,payload 内另带 secret 双重验证。 一个外泄无法绕过另一个 — 攻击者要同时偷到 URL token 和 secret 才能伪造信号。

第四幕:「但你也是托管啊」— 观念厘清

有人会说:「TVSBot 不也是托管 API key 吗?跟 3Commas 一样的设计?」

技术上 key 确实在我们 DB 里。但实质上差异巨大:

面向TVSBot3Commas(事件当时)
提币风险低(绑定时拦下开了提币的 key;Bybit / BingX / Gate.io 需自行确认)有,部分用户开了 Withdraw
加密密钥位置不同云厂商同云环境
加密算法公开✓ Fernet AES-128-CBC未公开实现细节
Bug bounty✓(见 /security)当时无
事件披露时效承诺72 小时内事件后 2 个月才承认

第五幕:你能做的事

无论用 TVSBot 或任何 bot 平台,以下 3 件都是你的责任,没人能代劳:

  1. 不要勾 Withdraw 权限 — 这是最重要的一条,比所有 技术设计都重要
  2. 不要启用 IP 白名单 — TVSBot 目前没有固定的对外 IP, 填了会让下单被交易所拒绝;改用「只勾 Trade、不勾提币 + 开在子账号」
  3. 定期轮换 key — 至少每 3 个月,更短更好

结语:信任不是免费的

3Commas 事件后,加密 bot 行业普遍意识到「托管模型」是核心问题。 有些平台转向「pure non-custodial」(浏览器扩展、本地代理), 有些加强加密设计(HSM、多重签名)。

我们的选择是「实用主义 non-custodial」: 技术上托管但结构上保证资金安全(绑定时拦下有提币权限的 key + 加密密钥物理分离 + 多层验证)。

我们认为这个 trade-off 在使用体验(用户不用装 extension)跟安全保证 之间取得最佳平衡。但每个人风险偏好不同 — 如果你要绝对 non-custodial, 也理解。

有任何安全建议或漏洞回报,请寄到 security@tvsbot.com。Bug bounty 详情见 /security 页。