DBMS_SQL执行权限默认授予PUBLIC是Oracle兼容性设计,非漏洞;撤销它会导致系统功能异常,应限制具体用户权限而非PUBLIC,并通过审计、访问控制和代码审查等措施管控风险。
DBMS_SQL 执行权限被 PUBLIC 拥有是默认行为
oracle 安装后,dbms_sql 包默认会通过 grant execute on dbms_sql to public 开放执行权限。这不是漏洞,而是 oracle 历史兼容性设计——很多内置组件(如某些数据字典视图、pl/sql 编译器路径)依赖 public 可调用它。直接 revoke execute on dbms_sql from public 会导致部分系统功能异常,比如 dbms_metadata.get_ddl 失败、某些 select ... from user_objects 查询报错。
真正要做的不是 revoke,而是限制实际调用者
你真正想防的,是普通应用用户或恶意 PL/SQL 代码滥用 DBMS_SQL 动态执行任意语句。这不能靠撤掉 PUBLIC 权限解决,而应聚焦在「谁能在会话里调用它」上:
-
DBMS_SQL的实际执行受调用者当前角色和直接权限约束:即使 PUBLIC 有 EXECUTE 权,若用户没有CREATE SESSION+CREATE PROCEDURE或未被显式授予EXECUTE ON DBMS_SQL,仍无法在自己的 PL/SQL 块中使用它 - 检查高风险账号是否被误授了
EXECUTE ON DBMS_SQL:SELECT grantee, privilege FROM dba_tab_privs WHERE table_name = 'DBMS_SQL' AND privilege = 'EXECUTE';
- 对非 DBA 应用账号,用
REVOKE EXECUTE ON DBMS_SQL FROM app_user;(而非 PUBLIC)才安全有效
revoke from PUBLIC 后的典型报错及修复路径
一旦执行了 REVOKE EXECUTE ON DBMS_SQL FROM PUBLIC,常见现象包括:
-
ORA-06598: insufficient INHERITED PRIVILEGES:发生在编译含动态 SQL 的存储过程时 -
ORA-00942: table or view does not exist(但表明明存在):某些数据字典封装逻辑内部调用了DBMS_SQL,权限链断裂导致解析失败 -
DBMS_METADATA返回空或报ORA-31603:该包底层依赖DBMS_SQL构造查询 - 修复必须回退:
GRANT EXECUTE ON DBMS_SQL TO PUBLIC;;别试图用DEFINER'S RIGHTS或INHERIT PRIVILEGES绕过——Oracle 内部调用不走这些机制
更有效的替代控制方式
比起动 PUBLIC 这个全局开关,以下措施更精准且无副作用:
- 启用细粒度审计:
AUDIT EXECUTE ON SYS.DBMS_SQL BY ACCESS;,配合DBA_AUDIT_TRAIL监控谁在什么时间调用了它 - 用 Database Vault 或 Oracle Label Security 对敏感 schema 加访问控制,让
DBMS_SQL即便能执行,也无法触达关键对象 - 在应用层统一使用绑定变量 + 预定义 SQL 模板,彻底避免运行时拼接动态语句的需求
- 定期扫描用户代码:
SELECT owner, name, text FROM dba_source WHERE upper(text) LIKE '%DBMS_SQL%OPEN_CURSOR%' AND type = 'PROCEDURE';
,识别并重构高风险调用点
PUBLIC 权限本身不是攻击面,失控的调用上下文才是。改权限不如管住人、看清调用链、堵住入口点。










