云帆
白昼

DIY 手绘贴纸项目的安全设计与攻防实践

发布于十二月 29, 2025
-查看
3分钟 阅读

项目背景与系统边界

1. 项目核心功能

用户可以:
  • 手绘任意图案 (自由轨迹)
  • 添加系统内置贴纸
  • 输入自定义文字
  • 生成最终可下载/打印的贴纸图片

2. 风险类型

  • :用户捕获前端请求后,不断重放试错,以规避规则或自动化尝试生成绘画内容。
  • :用户在客户端层篡改贴纸列表接口,使返回内容被替换为其自定义贴纸 URL,实现未授权内容注入。
  • :在 Windows 虚拟机中,用户通过篡改系统字体,将某个 Unicode 字符替换成自定义矢量图,从而绕过字符白名单、敏感词检测等规则。
  • :用户使用自动化脚本(如 Python + PyAutoGUI)模拟鼠标行为,实现自动绘画、批量攻击或异常高频率操作。
后续的安全设计, 都是围绕上面的风险类型所展开

3.请求重放攻击

工程事实: 只要请求能从客户端发出去, 它就一定能被完整复现. 所以前端做的任何
, 在重放攻击面前都只是
前端能限制的是
, 但是攻击者可能攻击的是
.
  • 一次性Token
  • 请求签名 + 时间窗
  1. 一次性Token ->
解决: 请求次数的问题
设计流程
userId、场景类型(DIY贴纸)、创建时间、
即使有 token, 攻击者仍然可能:改参数、改内容、延迟几小时再重放
  1. 请求签名 + 时间窗(防参数篡改 & 延迟重放)
解决: 请求内容是否被篡改、是否被延迟重放
防护解决问题
防参数篡改
防延迟重放
防瞬时多次重放
前端签名, 后端验签, 并检查: 1. 是否在合理时间窗口内(3-10s内) 2. nonce是否重复使用

4.贴纸接口劫持

问题现象:
解决思路: 进行贴纸安全校验, 强制校验贴纸
白名单
  • 操作贴纸(插入、编辑、渲染)时,必须对贴纸资源进行
    • 路径只能来自官方 CDN 域名,如 xxx.cdn.com/...
    • 文件名、文件 hash 需与官方贴纸库匹配。
    • 不允许用户传入第三方 URL 或本地路径。
  • 即便用户劫持接口、篡改返回值,前端添加贴纸的动作仍会被拒绝,从而彻底封堵自定义贴纸注入风险。
在贴纸系统中,我把前端渲染和服务端生成彻底拆开。前端在交互阶段可以使用 URL 渲染,但在最终生成阶段只提交 stickerId 和操作参数 服务端通过 stickerId 映射官方资源并完成合成,从架构上保证即便前端被劫持,最终产物仍然是可信的。
提交给服务端的正确数据结构
❌ 错误方式(永远不要)
✅ 正确方式(你现在的设计)

服务端完整处理流程

  1. 校验 stickerId 是否官方
  2. 服务端决定用哪个资源
  3. 从官方 CDN 加载资源
  4. 服务端合成最终贴纸
  5. 生成最终图片 / PDF / 贴纸文件

设计理由

攻击 1: 我前端换成自定义贴纸 -> ❌ 服务端根本不认 URL
攻击 2: 我接口劫持返回第三方 URL -> ❌ 成阶段不会用它
攻击 3: 我篡改提交参数 -> ❌ 服务端拒绝

5.前端字符重建 —— 禁止字体替换伪造字符

。攻击者可能在客户端或虚拟机中替换系统字体文件,把正常字符渲染成任意图形,从而绕过敏感词检测或注入不合规内容。

问题本质

然而
  • Unicode 只是字符编号
  • 真正显示的是字体文件里的矢量轮廓(glyph)

如何防御

  • : 不依赖客户端系统字体,将字符渲染过程完全掌控在前端
  • : 将用户输入转换为 Unicode codePoint 数组,例如:
  • : 前端使用项目内置字体文件或矢量库,而非依赖系统字体
  • : 将字符转换为矢量路径绘制,而不是直接用系统 fillText 渲染。
字符 → 矢量路径 → Canvas
Tags:
#前端安全