一夜之间多了 5000+ 个账号,我和 Claude 给自研 GTD 做了一次线上演习 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
femto
V2EX    程序员

一夜之间多了 5000+ 个账号,我和 Claude 给自研 GTD 做了一次线上演习

  •  
  •   femto 13 小时 49 分钟前 426 次点击

    昨天,我的自研 GTD 系统后台突然多了 5000 多个新增账号,actions 也陡增了 3000 多条。

    第一反应当然是:难道产品突然爆火了? 几分钟之后我冷静下来:这更像是一场「恶意注册 / 接口攻击」,而不是增长奇迹。

    这篇文章想简单记录一下:

    • 这次攻击是怎么暴露出来的
    • 我是怎么用 Claude Code 快速排查问题的
    • 我对「小产品的安全边界」的几个反思

    希望能给同样在做小产品 / side project 的同学一点参考:就算你现在只有几十个真用户,也值得认真对待安全和风控。


    一、事情是怎么被发现的?

    先简单说一下背景。 我用 Claude Code 搭了一套自己的 GTD 系统,名字叫 GTD Pro,灵感来自 OmniFocus ,目前主要是我自己和少量真实用户在用,线上版本在这里: https://gtd.nebulame.com/

    按照正常节奏,这个系统一天新增用户只有几个人,有时候甚至是 0 。结果昨天我在后台看统计时,发现:

    • 账号总数在很短时间里突然多了 5000+ 个
    • actions 表里多了 3000+ 条明显无效的数据

    问题在于:

    • 我并没有做任何大规模推广
    • 真实的活跃用户,其实只有几十个

    所以这波「暴涨」明显不正常。

    我简单做了几件事:

    1. 按时间排序,发现这些账号几乎集中在一个很短的时间窗口内创建
    2. 看标识/行为,很多请求模式非常机械、重复
    3. 对比真实用户的使用行为,路径和频率完全不一样

    基本可以确认:这是一次针对后端 API 的「恶意注册 + 写入」攻击,而不是自然增长。


    二、这次攻击到底发生了什么?(攻击情况一览)

    从日志里复盘了一下,大概情况是这样的:

    • 攻击开始时间:2025-12-30 00:28 左右
    • 持续时间:从 00:28 一直持续到 05:07 左右
    • 攻击方式:不停地往两个接口打请求:
      • POST /api/auth/register 注册接口被高频调用
      • POST /api/inbox Inbox 创建接口被高频调用

    几小时之内,数据变成了这样:

    • 用户数:从 38 个涨到 5512 个(+5474 个恶意账号)
    • Actions:从 119 条涨到 3209 条(+3090 条无效记录)
    • 数据库大小:从大约 400KB 涨到 12MB 左右(体积直接放大了 30 倍)

    从时间分布和请求模式看,很明显这不是正常用户增长,而是脚本在持续轰炸注册接口和 Inbox 接口。这里可以放上 Claude Code 帮我整理出来的攻击摘要和时间线截图,我也是在它的提示下,开始给系统补上第一轮安全防护。


    三、我和 Claude Code 做了一次「线上演习」

    这次排查其实花的不是很多精力,更多是靠 Claude Code 帮我把问题结构化了一遍。

    大概流程是这样:

    1. 我把相关的日志片段、数据特征、接口设计,整理成一个简化版描述
    2. 丢给 Claude Code ,让它帮我:
      • 分析可能的攻击路径
      • 提出优先级最高的几条防护建议
      • Review 一下现有的注册 / 写入接口设计

    Claude 给出的几个方向非常实用:

    • 后端 API 暴露在公网,没有最基本的 rate limit
    • 注册和写入接口缺少「人类门槛」,脚本可以无限请求
    • 没有给「可疑账号」打标 / 隔离,只是直接进入正式业务表

    我对照这些建议,很快做了第一轮处置:

    • 给这批可疑账号和对应 actions 打上标记,而不是直接物理删除
    • 在业务逻辑上先软删除:统计、报表、产品逻辑里一律不算它们
    • 开始在代码里补上 rate limit 和简单风控策略

    这次体验对我来说有点意思:

    • 不是「 AI 帮我写了一大堆代码」,而是
    • 「 AI 帮我快速梳理威胁模型 + 设计第一版防护方案」,我自己做关键决策和实现细节

    对一个只有几十个真实用户的小产品来说,这种「 AI + 人」的协作方式刚好合适。


    四、我给 GTD 系统加了三道基础安全锁

    这次事件之后,我给 GTD Pro 加了三道「基础安全锁」,也推荐给还在早期的独立开发者:

    1 )给注册和写入接口上闸门

    • 对注册接口加简单节流:同 IP / 同 UA / 同邮箱域名在单位时间的上限
    • 对写 actions 的接口也加上 rate limit ,避免有人用单一账号或脚本刷爆写入

    2 )引入一个「人类门槛」

    • 可以是邮箱验证 / 一次性验证码 / 极简验证码
    • 不一定要很重,但要让大规模脚本攻击的成本变高

    3 )业务上把「可疑流量」和「真实用户」彻底分开

    • 给这 5000 多个账号统一打上 is_suspicious = true
    • 统计和报表默认只看「未标记为可疑」的账号
    • 以后如果还有类似事件,可以快速对比行为模式、复用处理流程

    这次攻击也间接帮我确立了一个心态:

    • 只要你的产品暴露在公网,就默认会被扫、被撞、被试探
    • 安全不是「有大公司再做」,而是「你第一次被攻击的那天,就该开始认真设计」

    五、小产品也要有安全边界

    这次恶意注册事件,对我最大的提醒是:

    • 就算你现在只有几十个真实用户,也应该早点想好:
      • 注册/登录的边界
      • 写入数据的节流
      • 垃圾数据的隔离策略
    • AI 不只是用来给用户做「炫酷功能」,也可以拿来帮你做基础设施:
      • 设计威胁模型
      • 帮你 review 代码
      • 帮你想「最小代价的安全升级」

    严格来说,这次并不能算一场「大规模攻击」,更像是给我提了个醒:

    • 我的 GTD 不再只是本地小玩具
    • 它开始作为一个真正对外的在线服务存在

    六、如果你也想试试这套 GTD / 看看代码

    最后,留两个入口:

    如果你也在做自己的小工具、小产品,建议不要等到「出事了」再补安全。哪怕只是在注册接口前面多加几行简单的 rate limit 逻辑,都是一个好的开始。

    也欢迎你来试试 GTD Pro ,或者在 issue 里告诉我你遇到的安全/风控问题,我们可以一起继续把这套系统打磨得更像一个真正可依赖的「第二大脑」。

    如果你对我在做的通用 Agent 框架也感兴趣,可以看看:

    GTD Pro 目前主要跑在 Claude Code 上,后面也会逐步和这套 Agent 基础设施打通。

    1 条回复    2025-12-31 20:54:20 +08:00
    TrackBack
        1
    TrackBack  
       9 小时 6 分钟前
    后端和认证是自己搭的吗?
    用 supabase 这些服务的话,开箱就有 rate limit ,应该会好一些?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     788 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 17ms UTC 22:00 PVG 06:00 LAX 14:00 JFK 17:00
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86