5.9 KiB
5.9 KiB
审核 / 处置 / 举报(长版明细)
审核 / 处置 / 举报
- 线上通道 = 七牛(
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报告行数/磁盘占用/时间跨度 —— 把「有没有臃肿」交给运维自查。