直接结论:只要普通用户持有CREATE ANY类权限就无法防止越权,必须回收且无替代方案;因其允许在任意schema(如SYSTEM)创建过程,再通过EXECUTE IMMEDIATE执行动态SQL提权至DBA。

直接结论:只要普通用户持有 CREATE ANY 类权限(如 CREATE ANY PROCEDURE、CREATE ANY TABLE),就无法真正防止其越权——这不是配置疏漏问题,而是权限模型本身的高危设计。必须回收,没有替代方案。
为什么 CREATE ANY PROCEDURE 等同于 DBA 权限?
这类权限允许用户在任意 schema 下创建对象,包括 SYSTEM 或 SYSAUX 下的存储过程。一旦创建成功,就能通过 EXECUTE IMMEDIATE 执行任意动态 SQL,进而绕过所有对象级权限控制。
- 常见错误现象:
SELECT * FROM session_privs显示只有CREATE ANY PROCEDURE和EXECUTE ANY PROCEDURE,但执行GRANT DBA TO self_user后立刻获得全部系统权限 - 真实攻击链:用户
hacker创建system.h1过程 → 调用EXECUTE IMMEDIATE 'GRANT DBA TO hacker'→ 登录后拥有 160+ 项特权 - 关键点:Oracle 不校验
EXECUTE IMMEDIATE中的语句是否属于调用者权限范围,只检查当前会话是否具备执行该过程的权限
哪些 ANY 权限必须立即回收?
不是“建议避免”,而是“生产环境严禁存在”。以下权限一旦授予非 DBA 用户,等同于交出数据库控制权:
-
CREATE ANY PROCEDURE/EXECUTE ANY PROCEDURE:可提权至 DBA -
SELECT ANY TABLE:可读取SYS.USER$、SYS.OBJ$等核心字典表,暴露密码哈希与对象结构 -
UPDATE ANY TABLE/DELETE ANY TABLE:可篡改审计日志、角色分配表等安全元数据 -
GRANT ANY PRIVILEGE:可给自己或他人授予任意权限,完全绕过审批流程
检查命令:SELECT grantee, privilege FROM dba_sys_privs WHERE privilege LIKE '%ANY%'
回收后如何满足开发/运维真实需求?
不能只删权限,得给替代路径。重点是把“任意”变成“指定”:
- 开发需要建过程?→ 创建专用角色
APP_DEVELOPER,仅GRANT CREATE PROCEDURE TO APP_DEVELOPER,再GRANT APP_DEVELOPER TO dev_user(仅限自身 schema) - DBA 需批量建表?→ 使用预定义脚本 +
DBMS_SCHEDULER任务,在受限上下文中执行,不开放交互式CREATE ANY TABLE - 报表需跨 schema 查询?→ 用视图封装 +
GRANT SELECT ON view_name TO report_user,而非授SELECT ANY TABLE - 已有 DBLink 需安全访问?→ 建立只读视图(如
remote_emp_view),GRANT SELECT ON remote_emp_view TO dblink_user,并确保基表权限未开放
容易被忽略的残留风险点
回收权限只是第一步,真正难的是清理“已生效的越权能力”:
- 已存在的恶意过程不会自动失效,必须人工扫描
DBA_OBJECTS中OWNER = 'SYSTEM'且OBJECT_TYPE = 'PROCEDURE'的异常对象 - 用户可能已通过
CREATE ANY PROCEDURE创建了长期驻留的触发器或 job,需检查DBA_TRIGGERS和DBA_SCHEDULER_JOBS - 角色继承关系可能隐藏权限:执行
SELECT * FROM role_role_privs查看是否有中间角色间接赋予了ANY权限 - Database Vault 规则若未启用,即使回收了权限,也无法阻止已获 DBA 权限的用户后续操作
权限回收不是单次操作,而是持续巡检动作。每次上线新应用前,都应跑一遍 dba_sys_privs 和 dba_tab_privs 审计脚本,否则防线形同虚设。


















