直接撤销PUBLIC默认权限需分步验证、按包评估并保留回退路径;盲目执行REVOKE可能导致STANDARD包失效、对象INVALID及ORA-06553错误,甚至数据库无法登录。
直接撤销 public 的默认权限不是“一键清理”操作,而是一场需要分步验证、按包评估、留有回退路径的权限收敛行动。盲目执行 revoke 可能导致 standard 包失效、大量对象变 invalid、应用报 ora-06553,甚至数据库无法登录。
哪些 EXECUTE 权限必须优先回收
Oracle 官方明确建议从 PUBLIC 撤销以下高危包的执行权限,因为它们可被任意用户用于文件读写、网络外连、代码注入等攻击链:
-
UTL_FILE:读写数据库服务器本地文件系统 -
UTL_HTTP、UTL_TCP、UTL_SMTP:发起任意 HTTP/TCP/SMTP 请求,常被用于 SSRF 或反向 shell -
DBMS_RANDOM:虽看似无害,但配合其他漏洞可辅助预测或绕过逻辑校验 -
CTX_DOC、DBMS_EXPORT_EXTENSION、DBMS_SQL:历史上存在多个提权 CVE,非必要不开放
执行示例(需 SYSDBA):
REVOKE EXECUTE ON sys.utl_file FROM PUBLIC; REVOKE EXECUTE ON sys.utl_http FROM PUBLIC; REVOKE EXECUTE ON sys.utl_tcp FROM PUBLIC;
注意:REVOKE 语句中必须显式指定 schema(通常是 sys),否则会报 ORA-00942: table or view does not exist。
撤销 SELECT ANY TABLE 后的连锁反应
这是最易踩坑的操作。一旦执行 REVOKE SELECT ANY TABLE FROM PUBLIC,所有依赖数据字典视图的内置包(如 STANDARD、DBMS_STANDARD)将立即变为 INVALID,后续任何 PL/SQL 编译或登录都可能失败,典型错误是:
ORA-06553: PLS-213: STANDARD package not accessible
这不是 bug,而是 Oracle 的设计机制:很多核心包在编译时隐式引用了 ALL_* 或 DBA_* 视图,而这些视图依赖 SELECT ANY TABLE 授权链。
补救方式只有两种:
- 立即运行
@?/rdbms/admin/utlrp.sql重新编译全部无效对象(需数据库在线,但不能保证 100% 成功) - 若已无法登录,只能从 RMAN 备份恢复,或重建数据字典(
@?/rdbms/admin/catalog.sql+@?/rdbms/admin/catproc.sql),风险极高
结论:除非你完全掌控所有应用逻辑且确认无任何依赖数据字典的自定义包,否则不要碰 SELECT ANY TABLE 对 PUBLIC 的授权。
如何安全地批量检查与清理
别靠记忆或文档猜——用 SQL 精确识别当前暴露面:
查 PUBLIC 拥有的高危 EXECUTE 权限:
SELECT table_name, owner FROM dba_tab_privs
WHERE grantee = 'PUBLIC' AND privilege = 'EXECUTE'
AND table_name IN ('UTL_FILE','UTL_HTTP','UTL_TCP','UTL_SMTP','DBMS_RANDOM');查是否误授了敏感对象给 PUBLIC:
SELECT owner, table_name FROM dba_tab_privs
WHERE grantee = 'PUBLIC' AND privilege = 'SELECT'
AND owner NOT IN ('SYS','SYSTEM','XDB','CTXSYS');关键点:
- 只对明确知晓用途的对象执行
REVOKE,不批量扫 - 每次
REVOKE后,立刻查SELECT object_name FROM dba_objects WHERE status = 'INVALID',确认影响范围 - 生产环境务必在维护窗口执行,并提前备份
dba_tab_privs快照:CREATE TABLE public_privs_bak AS SELECT * FROM dba_tab_privs WHERE grantee = 'PUBLIC';
为什么不能直接删掉 PUBLIC 角色
PUBLIC 不是普通角色,而是 Oracle 内置的隐式组,无法被 DROP ROLE 或 DROP USER 删除。试图用 REVOKE CONNECT FROM PUBLIC 或 REVOKE CREATE SESSION FROM PUBLIC 会导致整个数据库无法建立新会话——连 sqlplus / as sysdba 都可能失败。
真正可控的是“授权内容”,不是“角色本身”。加固的本质是做减法:只保留 DUAL、SYSDATE 这类无副作用对象的访问,其余一律按需显式授予具体用户或角色。
最容易被忽略的一点:撤销权限后,必须验证所有中间件连接池、定时任务脚本、DBA 工具(如 OEM、Toad、DBeaver)是否仍能正常工作——它们往往隐式依赖某些被撤掉的包或视图。


















