授予DBA角色后仍无法SELECT SYS.USER$,因Oracle默认启用数据字典保护机制;O7_DICTIONARY_ACCESSIBILITY=false禁止ANY权限访问SYS对象,需显式授予SELECT ANY DICTIONARY或直接对象权限。
授予dba角色后仍无法select sys.user$等表,不是权限漏授,而是oracle默认启用的数据字典保护机制在起作用。
DBA角色不等于能读SYS下的数据字典表
DBA角色包含几百个系统权限(如SELECT ANY TABLE、UPDATE ANY TABLE),但Oracle从8i起默认禁止这些“ANY”类权限访问SYS schema下的对象——包括USER$、OBJ$、SEG$等核心基表。这是硬编码级保护,与角色或显式授权无关。
-
SELECT ANY TABLE只能查非-SYS用户的表,对SYS.USER$直接报ORA-00942: table or view does not exist或ORA-01031: insufficient privileges - 即使用户同时拥有
DBA和SELECT_CATALOG_ROLE,也仍然不能直接SELECT SYS.USER$,因为该角色只授予对DBA_*、ALL_*、USER_*视图的访问权,而非底层基表 -
SELECT ANY DICTIONARY是唯一能绕过此限制的系统权限,但它不包含在DBA角色中,需单独授予
O7_DICTIONARY_ACCESSIBILITY=false 是根本原因
这个隐式参数控制是否允许“ANY”权限穿透到SYS schema。Oracle 9i之后默认为false,意味着:
-
SELECT ANY TABLE→ 可查HR.EMPLOYEES、SCOTT.DEPT,但不可查SYS.USER$ -
EXECUTE ANY PROCEDURE→ 可调用DBMS_LOCK.SLEEP,但不可调用SYS.DBMS_SYSTEM(多数内部包) - 想恢复旧行为(Oracle 7风格),必须设
O7_DICTIONARY_ACCESSIBILITY=true并重启实例;但不推荐生产环境启用,会严重削弱字典安全性
安全且合规的访问方式只有三种
绕过保护机制不是靠调参,而是用Oracle设计好的接口:
- 优先使用
DBA_*视图:例如查用户信息用SELECT * FROM DBA_USERS,而非SELECT * FROM SYS.USER$;视图已做权限过滤和字段脱敏 - 需要底层信息时,显式授予
SELECT对象权限:GRANT SELECT ON SYS.USER$ TO your_user;(注意:仅限必要场景,且需DBA手动维护) - 极少数运维脚本需要全字典读取,才授予
SELECT ANY DICTIONARY;它比DBA更敏感,应严格审计使用范围
容易被忽略的关键点
很多人试过GRANT SELECT ON SYS.USER$ TO PUBLIC却失败,是因为SYS schema下的对象不允许被GRANT给PUBLIC或通过角色间接传递——所有对SYS对象的授权都必须是直接、显式的,并且接收者必须有SELECT ANY DICTIONARY或已被单独授予权限。另外,V$、X$等动态性能视图受另一套权限模型约束,和SYS基表不是一回事。


















