必须联合查询DBA_TAB_PRIVS和DBA_SYS_PRIVS才能全面识别PUBLIC权限:前者查显式授予的对象权限(如SELECT ON EMP),后者查高危系统权限(如SELECT ANY TABLE),缺一则漏掉间接访问能力。
直接查 dba_tab_privs 里 grantee = 'public' 只能抓到“显式授予”的对象权限,漏掉大量真实可访问的对象——比如通过角色间接授予的、或系统默认开放的(如 oracle timeten 创建的表)。合规检查必须补全系统权限视角。
查 PUBLIC 显式拥有的对象权限(表/视图/序列/过程等)
这是最常被查、也最容易误判为“全部”的部分。注意:只覆盖直接 GRANT ... TO PUBLIC 的情况,不包含角色继承路径。
SELECT GRANTOR, OWNER, TABLE_NAME, PRIVILEGE, GRANTABLE FROM DBA_TAB_PRIVS WHERE GRANTEE = 'PUBLIC'- 若要聚焦高危操作,加条件:
AND PRIVILEGE IN ('SELECT', 'INSERT', 'UPDATE', 'DELETE', 'EXECUTE') - 特别留意
OWNER是SYS或SYSTEM的记录,例如UTL_FILE、DBMS_LOB被EXECUTE授予 PUBLIC,是典型攻击面 -
GRANTABLE = 'YES'表示 PUBLIC 还能把该权限再转授出去,风险翻倍
查 PUBLIC 实际能执行的系统权限(绕过角色链就失效)
很多用户以为没在 DBA_TAB_PRIVS 里看到 PUBLIC,就等于“没权限”,但系统级操作(如 CREATE ANY TABLE)可能让 PUBLIC 用户间接获得对象创建/删除能力,甚至接管对象所有权。
SELECT PRIVILEGE, ADMIN_OPTION FROM DBA_SYS_PRIVS WHERE GRANTEE = 'PUBLIC'- 重点盯住带
ANY的权限,如SELECT ANY TABLE、EXECUTE ANY PROCEDURE—— 它们能让 PUBLIC 绕过对象级授权直接操作几乎所有对象 -
ADMIN_OPTION = 'YES'意味着 PUBLIC 可以把该系统权限再授予别人,极危险 - 这个结果和
DBA_TAB_PRIVS必须合并看,缺一不可
为什么不能只靠 DBA_TAB_PRIVS 判断 PUBLIC 是否有权限
因为 Oracle 权限模型存在两条独立生效路径:对象权限直授 + 系统权限泛授。而 PUBLIC 不是用户也不是角色,它不会出现在 DBA_ROLE_PRIVS 或 USER_ROLE_PRIVS 中,只能靠 GRANTEE 字段“露头”。
- 某张表 A 的
SELECT权限先授给角色HR_ROLE,再把HR_ROLE授给 PUBLIC —— 这种链式授权在DBA_TAB_PRIVS里完全不可见 -
SESSION_PRIVS查不到 PUBLIC,因为它只反映当前会话生效权限,而 PUBLIC 是个逻辑组,不是会话实体 - TimeTen 等中间件建表时默认
GRANT ALL ON xxx TO PUBLIC,这种行为不会写进用户角色关系链,只留痕于DBA_TAB_PRIVS - 真正影响访问控制的是最终效果,不是授权路径是否“可见”
实际审计时,DBA_TAB_PRIVS 和 DBA_SYS_PRIVS 必须联合扫描,且需人工确认每条记录是否业务必需。哪怕只有一行 EXECUTE ON UTL_HTTP FROM PUBLIC,都足以让任意普通用户发起外联请求——这点容易被忽略,但恰恰是渗透测试最常打穿的点。


















