•
3 min read

AI套壳站SaaS的思路转变: 技术,市场,安全和妥协

AI套壳站SaaS的思路转变: 技术,市场,安全和妥协

姊妹篇: 朋友 emptyex 从攻击者视角写的 Your AI App’s “Free Trial” Might Be Free Forever. 本文是守方视角. English version: Yes, My AI App’s “Free Trial” Was Free Forever. Here’s the Other Side.


背景

去年底想试试做AI套壳站: 靠信息差和关键词获利. 于是自己上线了 aibodyeditor.io,一个AI修人像的小工具: 上传照片,用prompt让AI改身形,换泳装,试衣服.

web版2026年3月底上线,8月出了iOS和Android双端App.

八个月下来,整体而言是交学费买经验. 亏损是为了后面做准备. 还有很多因为自己作为程序员的mindset too young too simple而造成的安全漏洞.

整体情况:

数量
web 注册用户约 3,000
web 出图(登录 + 匿名)约 25,000 次
App 用户约 11,000
App 出图请求约 21,000 次,约一半失败,相当一部分是被模型的安全过滤拦下
付费用户几十个

简单来说,营收够交服务器钱,不够交学费.

除了生意上找词,找需求的经验积累之外,最大的收获是在朋友的帮助下,给自己的cyber security意识上了一个发条. 在AI时代,攻防双方都有AI加持,人的经验和expertise反而成了最重要的变量. 试水SaaS的过程中见识到的各种羊毛党和黑灰产白嫖手段,涨了教训,也开了眼界.

再次感谢我的朋友 emptyex 花的时间和精力. emptyex是我认识的最聪明,最有韧性的人之一. 他凭自己的努力拿下了cyber security里含金量最高的那几张证书,几乎集齐了全家桶. 这次能请他在我的小站上练一次手,顺带分享经验,对我而言是运气.

他把这次测试的全过程写成了一篇文章: Your AI App’s “Free Trial” Might Be Free Forever. 从攻击者那一侧看同一个故事,建议和本文对照着读. 如果读者有cyber security方面的问题,或者有合作需求,欢迎联系emptyex.


一、当初为什么选template/framework快速迭代

独立产品,第一原则是快. 所以每一个技术决策在当时看都很合理. 但它们会不断累积,最后变成security债务,导致白嫖.

web用了一个现成的SaaS模板. 登录,Stripe,积分,管理后台全套自带,两周就能上线. 模板本身没有太大问题,问题在我们没有理解和熟悉它,就盲目丢给AI改动,把模板当成了”已经想清楚的东西”. 后来才发现,模板把前端传来的模型名和参数原样交给Replicate —— 包括”关掉安全过滤”这个参数. 用户在浏览器里改一个字段,就能用UI上根本没有的模型,还能顺手把过滤关了. 线上真有人这么干过,9次. emptyex的抓包截图里也能看到,请求体里 provider 和 model 两个字段是明晃晃摆着的.

图像模型选Replicate,不自己部署. 按次计费,换模型改一行配置. 我们换了好几轮: Seedream → Grok → 试过一个便宜一半,快六倍的模型(这个要自己处理NSFW请求) → 三天后换回了Grok.

那么,为啥不直接用又快又好还便宜的模型呢? 原因在于它的safety guardrail时松时紧: 有的时候健身房的运动背心都不给过,有的时候敏感图片又过了. 而且它拦下请求时不报错,而是返回一张写着NSFW的占位图,状态照样是”成功”,用户的积分照扣.

做人像编辑这个业务,一个用户上传真人照片,模型给他生成了不该生成的敏感内容,后果直接落在回款上. 各家收款门户的policy对此都有严格规范: Stripe会冻结账户,Apple和Google会下架,往重了说有法律问题. 所以在”便宜快”和”过滤靠得住”二选一的时候,宁可每张图多花一倍的钱.

也许工程上有更方便更优雅的做法,这得留到未来解决.

App不做登录. RevenueCat自带匿名ID,Apple和Google账号本身就是用户系统,加登录页只会掉转化. 这个决定省了大量工程,也埋下了后面一半的雷: 身份就是一串随时能换的匿名ID.

web提供匿名试用. 不注册就能免费修3张. 拉新利器,早期注册转化率很好看.

每一个决定都是妥协. 到最后,从security的角度合在一起看,债务集中爆发了. 在emptyex的测试下,整个站四面漏风,像个中学生做的玩具项目,完全没有考虑容错.


二、跑冒滴漏的案例

1. 一份订阅,养了十一个账号

App不登录,用户身份是RevenueCat的匿名ID. 聪明的用户发现,卸载重装,ID就变了.

重装之后再请求server,Worker发现一个”新用户”,去RevenueCat反查: 这人是订阅会员吗? RevenueCat凭商店凭证一看,是,同一个人. 于是Worker又发了一个月的额度.

结果: 一份Play订阅挂了11个账号. 这位用户付了一个月的钱,拿到大约十倍的额度.

教训: 额度属于订阅,不属于账号ID.

2. 沙盒购买,零元购

Apple和Google都有沙盒环境,测试购买不花钱. 我们的webhook读了 environment 字段,日志里也打印了,但判断逻辑里从来没用过它.

一笔沙盒购买 = 一个月真额度 + Pro会员.

数据库里14个账号标着”订阅中”,一张真实的IAP流水都没有.

教训: 收权限的事照做,发权限的事必须验明正身.

3. 盗版APK占了新注册的七成

从来没想过自己这么小体量的App还能被盗版拆包. 在南美,Android版被人解包重新分发. 新注册里七成来自盗版包,每台设备白领3个免费额度,零付费.

上了Google的Play Integrity: 包必须是Play装的,账号必须有许可,设备必须过完整性检查. 可上线当晚自己一测,卸载重装 —— Integrity照样通过,照样再领一份. 因为 Integrity证明的是”包和账号是真的”,不证明”这台设备领过没有”. 又补了一刀按设备去重.

修复以后,注册赠送的每周发放量: 2,484 → 364 → 88.

教训: 一道闸只回答一个问题. 想清楚你要问的是哪一个.

4. 失败就退款,于是失败变成了免费重试

模型拦下请求,我们退积分. 这听起来很公道.

但一个总是被拦的人,就拥有了无限次免费重试. 14天里,1,788个免费用户被拦了2,207次,最多一个人退了67次. 他们在干什么,prompt是什么内容,嗯,懂的都懂.

教训: 现在,从没付过钱的用户,失败退款最多两次. 付费用户不受影响.

5. 匿名试用: 成本超过了全站收入

我一开始就因为不信任邮箱注册,只保留了Google账号登录. 但匿名试用这一块,我天真地以为浏览器指纹就能挡住大部分不懂技术的人.

想法是: 先倚仗指纹,一个指纹3个积分; 同一个IP换着指纹来,超过10次就把整个IP段临时封掉.

聪明的用户很快发现: 指纹在客户端算,改一下就是新人. 封IP,刷子就换VPN. 封IP段,刷子换VPS出口. 看Cloudflare的数据,荷兰,日本,新加坡,瑞士的流量里,九成以上来自少数几个重度网段.

最高纪录: 同一句prompt跑了540次.

到9月,匿名试用一个月出图近一万张,成本超过了全站同期收入. 8月我还在文档里写”匿名试用是最划算的获客渠道”,两个月后亲手关掉.

emptyex的报告把这件事讲得很清楚: 指纹永远只是一个君子协定,你永远无法信任前端的东西. 就像他文中提到的,改掉 _abe_fp 就是另一个人; 而IP限额对VPN和proxy用户也形同虚设.

于是选择变成两难: 要么留着匿名试用,接受指纹随时可换的漏洞. 叠上IP限额也只是把门槛抬高一点,问题还在那里. 要么干脆关掉,接受转化率下滑. 站在用户的角度想想,Costco试吃了,买起来才不会犹豫.

教训: 最后的决定是关掉. 会买的,一定会买; 不会买的,试用了,也不会买.

6. 能用Worker去掉服务器,就别用VPS

这条不是安全事件,但最吓人.

整台VPS要维护一大堆容器,Tailscale组网还会和路由地址冲突. 中间经历了RackNerd主机升级,又经历了Tailscale自动更新后登出,顺手把整台机器的DNS带走. 所有容器出网解析全断,web整整12天零注册零出图.

而我自己的监控盯着首页,首页被Cloudflare缓存着,一直200. 监控全程绿灯,没有告警.

教训: 首页200证明的只是CDN活着.


三、更为专业的视角

上面这些,都是我们自己对账对出来的. 不断救火,疲于奔命. 每一次都是”怎么这个月成本这么高”,然后才知道,哦,原来还有这样的漏洞.

10月我和emptyex提起我的SaaS,他好奇,花了一个下午看了看. 他的报告(细节在他那篇文章里)指出三件事:

  1. 改一个本地值,免费试用就能无限续. 而且他顺手发现,页面显示额度看的是localStorage,上传接口看的是cookie,两边各管各的 —— 这正是我们自己从没注意过的一条缝.
  2. prompt注入能让AI把系统提示词印到图上. 泄出来的是上游prompt改写器的提示词,不含我们的机密,但这条路本身是通的.
  3. 水印是前端盖上去的. 接口直接把原图地址给了浏览器,右键新标签页打开,就是无水印原图.

拿着他的报告,我们回头做了一次白盒复查,又扯出来几条: 前面说的”客户端指定模型”,App的失败退款循环,还有并发出图”N张只扣一份积分”,都是这一轮挖出来的.

我们之前也让AI扫过代码,它找到过不少问题. 但有些东西AI扫不出来: 它看的是代码有没有bug,攻击者看的是这个系统信任了谁.

而AI时代的脚本小子,不用再懂具体的细节,可以直接用廉价的token反复尝试. 重要的还是具备安全的思维和视角,而不是仅仅以程序员和business的角度思考问题.


四、修复

10月23日修复上线:

问题修法
客户端指定模型和参数模型由服务端决定,入参白名单,图片只认自己的存储域名
水印在前端水印在Cloudflare边缘合成,匿名用户手里从来没有原图地址
匿名试用被刷关掉,改成Google登录后免费一次
并发出图只扣一份积分扣不够就整笔回滚,任务不落库
App失败退款循环免费用户退款限两次
iOS不带设备ID也能领赠送不带就不发

prompt注入那条暂时没动: 泄的是上游的提示词,我们这一侧没有机密可泄. 真要堵,得上内容闸,这是下一阶段的事.

关匿名试用是最难下的决心. 它曾经是转化最好的入口. 但算账很简单: 一个月近万张免费图,换来的注册转化从17.6%一路掉到3.9%. 关掉是值得的,因为它已经不是获客渠道,是给刷子开的免费GPU.


五、所有的漏洞,都是缺乏安全意识的脑洞

本质其实就是一句话:

我们信任了客户端自报的东西.

模型名来自客户端,指纹来自客户端,设备ID是客户端的,“我是新用户”是客户端说的,连IP都是可以伪造的请求头.

现在我们做任何会花钱的接口,先问三个问题:

  1. 这个身份,谁证明的?
  2. 价格和模型,谁定的?
  3. 绕过前端直接打接口,会怎样?

答不上来,就别急着上线.


六、最后

现在做AI应用的生意不好做. 模型成本是实打实的,用户愿意付的钱很少,而想白嫖的人比付钱的人勤奋得多. 一个小团队,产品,增长,合规,安全全得自己扛,安全永远排在”等有空再说”.

AI能帮你写代码,也能帮你扫代码,但它和你站在同一边,看到的是同一个视角. 找一个真正的攻击者看一眼,哪怕只看一个下午,值得.

再次感谢 emptyex. 他的文章从攻击者那一侧讲了同一个故事,证据链比我这篇完整得多: Your AI App’s “Free Trial” Might Be Free Forever. 如果你也在做AI产品,先读他那篇,再回来对照自己的站.