Files

5.9 KiB
Raw Permalink Blame History

审核 / 处置 / 举报(长版明细)

审核 / 处置 / 举报

  • 线上通道 = 七牛(ai.qiniuapi.com/v3/text/censor,antispam);[security] text_censor_source = qiniu|aliyun|auto。 七牛只硬拦涉政/暴恐/色情,review 放行 → 裁决在 censor/policy.go + moderation.Check。
  • 新增审核调用点必须走 moderation.Check(直调 censor.Text 绕过档位)。不可用时 fail-closed。
  • ⚠️ 圈内黑话(代称+群体标签+避雷叙述)通用审核拦不住,别指望词库;靠处置 + 举报 + 人工判断。
  • 严格度 lax/standard/strict 存 users.moderation_strictness;受处置用户强制 strict: moderation.EffectiveStrictness(ctx, userID, raw)(7 个入口已改)。查询失败回退用户设置 (否则 DB 抖动会让全站突然加严)。处置期内拒绝保存 + 设置页 disabled。
  • ⚠️ 同请求渲染只能用 ctx.SetError / SetInternalError,不能用 *Flash:flash 写 session,下次请求才读 → 提示静默丢失。Set*Flash + Redirect 才是正常模式。扫描法:找 flash 调用 → 向下第一个 Success(/Redirect(。
  • 处置四级:L1 停止分发/L2 收窄公开(新回答强制私密、禁 set-public)/L3 冻结发布(仍可收信)/ L4 整页停用(/restricted)。到期靠 expires_at,无 cron;restrict 是替换语义;比较用 RestrictionAtLeast。
  • ⚠️ L2 强制私密必须在审核通过之后,且与写回答同一条 UPDATE(AnswerByIDPrivate): 拆开会留下「公开+已作答」窗口,第二条失败还会变成「私密+无回答」。
  • ⚠️ ListAPI(/api/v1/user/{domain}/questions)不经过 Pager 中间件,L4 与页面密码必须自己校验。
  • ⚠️ 整箱分享卡 ShareCard 与单题分享卡都要拦,且拦截必须在缓存查询之前(否则 30 分钟内仍给旧图)。
  • 举报 POST /_/{domain}/{qid}/report:免登录 + 验证码 + 限流;同 IP 同题唯一索引 → 幂等且提示与首次一致(否则成了内容存在性探测器)。箱主只看「被举报 N 次」,不给 IP。
  • 闭环:删除/设私密/hide-public → MarkAcceptedByQuestion;待处理超 30 天视为过期。 ⚠️ hide-public 里必须先快照目标 ID 再更新(更新后带 is_private=false 的子查询恒为空集)。
  • 告警:24h≥8 或 7d≥20 → 邮件到 [security] security_alert_email(24h 冷却);单条恰好 3 人举报 → 提醒箱主。 ⚠️ 该邮箱为空时静默跳过、无日志;改配置必须重启。
  • /rules 是处置依据页(四语言);注册页必须勾 agree_rules(服务端同样校验),改 e2e 脚本要同步。
  • restrict/unrestrict 默认给箱主发通知(按 users.language,mail/restriction-notice.html), 只含级别名/到期/规则链接,不含 --reason;--no-notify 跳过。--days > 90 要 --force。 ⚠️ 到期自动解除不发信(读表比较时间)。

蜜罐(2026-10-21)

  • 落点是改写 f.NotFound(不是新中间件):NotFound 只在路由表落空时触发 → 与业务路由零交集; 位于全局 Use 链之后(body 已限 12 MiB);组级 CSRF 不作用于它。
  • flamego 短路机制:context.run() 在 ResponseWriter().Written() 为真时 return → 写完响应不调 ctx.Next() 即止。
  • 蜜罐命中的路径由蜜罐自己 autoban.Record,autoban 中间件须跳过(否则一次请求计两遍,阈值减半)。
  • HoneypotHit 不嵌 dbutil.Model(审计证据只追加,不软删)。
  • 假页只含 canary + 假信息;错误提示不区分「用户不存在」与「密码错误」(防用户名枚举)。
  • 密码 CLI 默认脱敏;告警邮件含明文凭据 → 收件人只能是运维本人。

蜜罐封禁与 enable_auto_ban 解耦(2026-10-21 线上实测修复)

  • ⚠️ Record() 第一行 if !b.enabled { return } 会让 enable_auto_ban=false 连坐蜜罐 → 蜜罐只落库不封禁(实测命中 70+ 次零封禁)。已修:新增 RecordHoneypot() 独立通道 + 独立阈值/时长。
  • IsBanned() 不得受 enabled 约束:enabled 只控制「是否主动创建封禁」,不控制「是否尊重已有封禁」。
  • RecordHoneypot 的键必须与 Record 一致(同样 shared.LimitKey 归一化),否则 IsBanned 判不出来。
  • 备份/配置/密钥泄露扫描(/backup.zip、/db.sql、/id_rsa.pem)文件名主体随机,只有后缀稳定 → 用 path.Base() 后缀匹配表,不能只靠子串("/.zip" 匹配不到 /backup.zip)。

蜜罐表体积与自动清理(2026-10-21)

  • honeypot_hits 是只追加审计表,写入完全由外部扫描流量驱动(不可预期、不可节流) → 必须有自动保留期清理,否则表体积只增不减。
  • 两道闸:时间(honeypot_retain_days)+ 数量(honeypot_max_rows)。数量闸不可省 —— 攻击者可用海量源 IP 在保留期内把表撑爆。
  • ⚠️ PG 的 DELETE 只标记死元组,表文件不会变小;无 VACUUM 时表体积单调膨胀 (实测 22→52 MB)。清理后必须 VACUUM (ANALYZE),但注意 VACUUM 不缩小文件、 只让空间可复用(止住增长即可,不必 VACUUM FULL)。
  • ⚠️ VACUUM 不能在事务块/函数体内执行 → GORM 走 Exec()(Raw 处理器,不包事务)可行。
  • ⚠️ 清理器的 runOnce 必须自己再挡一次 retainDays<=0,否则「保留 0 天」= 全删光。
  • 索引:GORM 去掉 struct tag 的 index 不会删既有库上的旧索引 → 需显式 DropIndex。 删索引前先用 EXPLAIN 确认零查询使用(provider 索引实测 10 万行 648 kB 且零使用)。
  • CLI honeypot size 报告行数/磁盘占用/时间跨度 —— 把「有没有臃肿」交给运维自查。