MongoDB角色继承仅admin库支持跨库引用,非admin库角色写其他库角色名会报RoleNotFound;rolesInfo默认不显示继承权限,需加showPrivileges:true;用户多角色权限为并集,易越界;内置角色须显式指定db字段才跨库生效。

角色继承只在admin库才允许跨库引用
非admin库创建的角色,roles字段里写其他库的角色名(比如{ role: "read", db: "logs" }),MongoDB会直接报RoleNotFound: role 'read' not found——不是静默忽略,而是命令失败。但很多人误以为“没报错就成功了”,结果权限根本没生效,却以为用户已获得跨库访问能力。
真正能跨库继承的,只有在admin库中创建的角色。例如:
use admin
db.createRole({
role: "app_read_all",
privileges: [],
roles: [
{ role: "read", db: "orders" },
{ role: "read", db: "customers" }
]
})
这个角色才能被授予任意用户,并使其同时拥有两个库的只读权限。
rolesInfo默认不显示继承来的权限
执行db.runCommand({rolesInfo: "myapp_role"})返回的privileges字段,只包含该角色**直接定义**的权限,完全不展开它从其他角色继承的内容。这导致你肉眼检查时,以为权限很窄,实际运行时却有更大范围的操作能力。
必须显式加参数才能看到完整视图:
-
db.runCommand({rolesInfo: "myapp_role", showPrivileges: true})—— 正确方式 - 漏掉
showPrivileges: true,就等于在盲查权限边界
尤其当角色继承链较长(比如A→B→C→内置角色),不加这个参数,根本看不出最终生效的find到底覆盖哪些库、哪些集合。
用户绑定多个角色时权限是叠加的,不是取交集
MongoDB对用户的授权是“所有绑定角色的权限并集”。这意味着:哪怕每个角色单独看都符合最小权限原则,合在一起就可能越界。
常见错误组合:
- 给用户同时绑定
{ role: "readWrite", db: "temp" }和{ role: "dbAdmin", db: "admin" } - 看似一个是临时库写入,一个是管理库操作,但
dbAdmin自带listDatabases、dropDatabase等高危命令,且作用于所有库 - 攻击者只要拿下这个用户凭证,就能删掉任意数据库
更隐蔽的是:这些角色可能分属不同团队维护,没人主动检查它们叠加后的实际效果。
自定义角色误用内置角色上下文
内置角色如read、readWrite默认绑定到当前数据库上下文。你在test库执行db.createRole(..., roles: ["read"])},它继承的是test.read,不是analytics.read。
想复用其他库的内置角色,必须显式带db字段:
- ✅
{ role: "read", db: "analytics" }—— 明确指定目标库 - ❌
"read"—— 默认落在当前库,容易误判权限范围
这个细节在角色迁移、备份恢复或跨环境同步时极易出错:同一段角色定义脚本,在不同库下执行,实际权限完全不同。
最危险的不是配置错误本身,而是错误之后没有明显报错,也没有日志提示——权限系统照常运行,直到某次误操作或攻击触发越权行为才暴露问题。

















