必须用DBA_ROLE_PRIVS视图查全库DBA权限,因USER_ROLE_PRIVS和ALL_ROLE_PRIVS仅返回当前会话可见授权;关键字段包括ADMIN_OPTION(是否可转授)、DEFAULT_ROLE(登录是否自动激活)、COMMON(多租户下是否全局生效);需过滤GRANTEE为真实用户并用大写'DBA'匹配;同时须查V$PWFILE_USERS获取口令文件中的SYSDBA用户。
查谁有dba权限,必须用dba_role_privs视图,其他方式要么漏人,要么根本查不到真实授权关系。
为什么不能用USER_ROLE_PRIVS或ALL_ROLE_PRIVS
这两个视图只返回当前会话可见的角色授权——USER_ROLE_PRIVS只显示你自己被授予的角色,ALL_ROLE_PRIVS只显示你有权限访问的对象所属角色。它们对全局DBA名单完全无感。常见错误是登录后跑SELECT * FROM USER_ROLE_PRIVS WHERE GRANTED_ROLE = 'DBA',结果为空就以为“没人有DBA”,其实只是你自己没被授。
真正要覆盖全库,必须直连DBA_ROLE_PRIVS,且以具备SELECT ANY DICTIONARY或DBA角色的账号执行(如SYS、SYSTEM)。
DBA_ROLE_PRIVS里哪些字段真关键
光看GRANTEE和GRANTED_ROLE = 'DBA'远远不够,三个字段决定风险实质:
-
ADMIN_OPTION = 'YES':该用户能把DBA再授给别人,是权限扩散的起点,必须标记为高危 -
DEFAULT_ROLE = 'YES':登录即激活DBA角色;若为'NO',用户得手动SET ROLE DBA才生效,实际攻击面小得多 -
COMMON = 'YES'(多租户环境):表示该授权在CDB$ROOT和所有PDB都有效;'NO'则只限当前容器,跨PDB审计时容易漏掉
漏看DEFAULT_ROLE可能把“已授权但未激活”的用户误判为安全;忽略COMMON会在CDB迁移后丢失PDB级DBA清单。
查询语句怎么写才不踩坑
基础语句必须带过滤,避免返回无关角色嵌套或系统对象:
SELECT GRANTEE, ADMIN_OPTION, DEFAULT_ROLE, COMMON FROM DBA_ROLE_PRIVS WHERE GRANTED_ROLE = 'DBA' AND GRANTEE IN (SELECT USERNAME FROM DBA_USERS);
注意点:
-
GRANTED_ROLE必须写成'DBA'全大写,Oracle内部统一存储为大写,小写或带引号的"dba"会匹配失败 -
GRANTEE可能是用户名,也可能是另一个角色(比如APP_ADMIN),加IN (SELECT USERNAME FROM DBA_USERS)能排除中间角色,只留真实用户 - 如果报
ORA-00942: table or view does not exist,不是SQL错,是权限不足——立刻换SYS账号重试,别浪费时间改语句
别忘了V$PWFILE_USERS这个盲区
DBA_ROLE_PRIVS查的是角色授权,但SYSDBA登录权限走的是另一条路:口令文件。一个用户可能没被授DBA角色,却早就在V$PWFILE_USERS里SYSDBA = 'TRUE',能绕过所有角色控制直接进库执行ALTER SYSTEM。
必须同步运行:
SELECT USERNAME, SYSDBA, SYSOPER FROM V$PWFILE_USERS;
这个视图需要SELECT ANY DICTIONARY权限,且只反映口令文件内容——它不包含OS认证方式获得的SYSDBA(比如oracle用户直接sqlplus / as sysdba),那部分得靠操作系统层面审计补位。


















