未登录用户能读到什么,内容系统的权限边界容易漏在哪
未登录用户实际能读到哪些内容,往往不由主文章的可见性决定,而由附属对象和接口层各自的边界决定。一篇设为私密的正文挡住了,可它的评论、附件、预览地址如果没有跟着收紧,等于从侧门又开了一条通道。权限边界容易漏的地方,大多不在列表页,而在这几条容易被忽略的路径上。
近期一份公开的安全公告正好说明了这一点:WordPress 在 7.1.3 版本修复了「私密与未发布文章的评论可被未授权读取」一项。主内容本身是私密的,问题出在评论这个附属数据没有继承主内容的可见性判断——这几乎是所有越权读取最典型的形态。
主内容守住了,附属数据为什么漏
主文章和它挂载的数据通常是两套读取逻辑。正文走的是内容权限判断,评论、附件、自定义字段往往走各自独立的查询接口。写的时候容易默认「附属数据跟着主内容走」,但真正执行时,评论接口可能只按「文章 ID 是否存在」返回,而不去核对这篇文当前状态是不是私密或未发布。
漏点就在这句话上:状态过滤只写在了主内容一侧。只要有任何一条子资源查询绕开了状态判断,私密内容就以碎片的形式暴露出去。附件、评论、留言、相关推荐列表都属于这一类「看着是别人的字段,其实是自己该守的边界」。
接口层最容易忽略的过滤
列表型接口是第二个漏点。详情接口会检查单篇是否可读,列表接口却常常直接按分类或标签返回条目,把「未发布」「回收站」里的记录一并带出来。接口只要多返回一条状态,就越权一份内容。
还有一个更隐蔽的位置:搜索与聚合。站内搜索把标题、摘要、正文片段拼在一起返回,如果索引没有按状态过滤,私密标题可能以「命中片段」的形式出现在结果里。
预览与草稿的边界怎么划
草稿预览是有意设计,但要有边界。文档状态一般分正式、草稿、待发布、回收站四类:待发布是排了时间还没到点,草稿是还在编辑,回收站是删除后待清理。给编辑和审校用的预览链接,本身是合理需求,问题在于它是不是长期有效、能不能被搜索引擎收录、离职后还能不能访问。
安全的划法是:预览只走带签名的短期链接,且预览地址不参与抓取。删除正式文档应移入回收站而不是物理删除,恢复也只在受控入口发生,避免「已删除」的数据被公开接口重新读出来。
站内的三层控制
站内一般靠三层把边界收口:用户分组决定登录与否能看到的范围,文档状态决定内容本身处于哪个生命周期,接口暴露范围决定哪些能力默认对工具开放。
| 控制层 | 管什么 | 典型漏点 | 收口方式 |
|---|---|---|---|
| 用户组权限 | 未登录 / 普通 / VIP 分组各能访问哪些内容 | 只挡页面不挡接口 | 权限判断下沉到数据查询层 |
| 文档状态 | 正式、草稿、待发布、回收站的可见性 | 子资源不继承状态过滤 | 评论附件一律回查主内容状态 |
| 接口暴露 | 高危能力是否对外可调 | 全站级操作默认可达 | 高危域默认关闭,需显式开启 |
AnQiCMS 在这三点上的对应做法是:用户管理和 VIP 分组用来给不同用户组设置访问权限;文档状态区分正式、草稿、待发布与回收站,删除走回收站而非物理删除;接口按能力域设置暴露范围,备份、升级、多站点这类全站级操作的高危域默认关闭,需要显式开启才可达。三者叠加,才把「侧门」一条条堵上。
常见问题
问:只把私密文章的详情页挡住够不够? 答:不够。评论、附件、搜索片段、列表接口是各自独立的读取路径,任何一条没做状态过滤都会泄露。权限判断要落到数据查询层,而不是只在页面渲染层。
问:草稿预览链接会不会被搜索引擎抓到? 答:要区分对待。预览入口应当不进索引、链接短期有效;如果预览地址长期可达且可被收录,等于把未发布内容公开。
问:高危接口为什么要默认关闭? 答:默认开放意味着任何一个可用凭证或可绕过的鉴权都能触发全站级操作。把多站点、备份这类能力的暴露范围设为默认关闭,是在缩小一旦被越权后的影响半径。