查DBA权限必须同时检查三类路径:角色授予(DBA_ROLE_PRIVS)、口令文件(V$PWFILE_USERS)和CDB上下文(CDB_ROLE_PRIVS),缺一不可,否则高权限用户将逃逸审计。
DBA 是角色,不是系统权限,所以 DBA_SYS_PRIVS 里永远不会有 'DBA' 这条记录。想确认谁被授了 DBA 角色,必须查 DBA_ROLE_PRIVS 并过滤 GRANTED_ROLE = 'DBA'。
GRANTEE 是用户名(注意:Oracle 内部全大写存储,'scott' 查不到,必须用 'SCOTT')ADMIN_OPTION = 'YES' 表示该用户能用 GRANT DBA TO ... WITH ADMIN OPTION 再授出去,属于高危配置DEFAULT_ROLE = 'YES' 表示登录即自动激活 DBA 角色,无需手动 SET ROLE DBA
SELECT ANY DICTIONARY 或 DBA 权限,否则直接报 ORA-00942,不是 SQL 写错了一个用户可能没被授 DBA 角色,但已在口令文件中被标记为 SYSDBA = 'TRUE'——这意味着他能绕过密码验证、审计和角色控制,直接以最高权限登录并执行 ALTER SYSTEM。这类权限不体现在 DBA_ROLE_PRIVS 中,但风险等同甚至更高。
SELECT USERNAME, SYSDBA, SYSOPER FROM V$PWFILE_USERS
SELECT ANY DICTIONARY 或 SELECT_CATALOG_ROLE 才能访问,普通 DBA 用户默认无权查V$PWFILE_USERS 不包含通过 OS 认证(如 OS_AUTHENT_PREFIX)获得 SYSDBA 的用户,这部分得单独排查SYSDBA = 'TRUE',就必须纳入你的高权限清单,不能只盯 DBA 角色在 CDB 架构中,DBA_ROLE_PRIVS 默认只返回当前容器(PDB)的数据。如果 DBA 角色是在 CDB$ROOT 中授予的,你在 PDB 里查不到任何记录,但该用户实际拥有跨所有 PDB 的 DBA 权限。
SELECT SYS_CONTEXT('USERENV', 'CON_NAME') FROM DUAL
CDB_ROLE_PRIVS:SELECT GRANTEE, CON_ID FROM CDB_ROLE_PRIVS WHERE GRANTED_ROLE = 'DBA' AND CON_ID = 0
CON_ID = 0 表示 CDB 级别;非零值是具体 PDB ID,需逐个检查或加 IN 条件你看到用户被授了 DBA 角色,但执行 CREATE TABLE 却报 ORA-01031: insufficient privileges?很可能是角色没激活,或者刚切换过角色但视图还没刷新。这时 SESSION_PRIVS 是唯一能告诉你“此刻到底能干啥”的视图。
SELECT * FROM SESSION_PRIVS,结果只有 PRIVILEGE 一列,干净无干扰SET ROLE ALL 后立刻生效,而 USER_SYS_PRIVS 不变SESSION_PRIVS 不含对象权限,也不管你有没有登录权限——CREATE SESSION 永远不会出现在这里,它是连接时隐式赋予的查 DBA 权限这事,关键不在 SQL 写得多漂亮,而在是否覆盖了三类独立路径:角色授予(DBA_ROLE_PRIVS)、口令文件(V$PWFILE_USERS)、CDB 上下文(CDB_ROLE_PRIVS)。漏掉任意一条,都可能让高权限用户从审计视野里彻底消失。