Oracle默认使用定义者权限(AUTHID DEFINER),过程以创建者身份执行,易成提权入口;显式声明AUTHID CURRENT_USER可强制以调用者权限运行,提升安全性。
存储过程定义权限模型选错,是提权入口
oracle默认用definer's rights(定义者权限),意味着过程以创建者身份运行——哪怕调用者只有connect权限,只要过程里写了grant dba to ...,执行就生效。这是绝大多数提权案例的起点。
真正安全的做法是显式声明AUTHID CURRENT_USER,让过程以调用者权限运行。此时即使过程内容危险,调用者没对应权限也执行失败。
- 错误写法:
CREATE OR REPLACE PROCEDURE pwn_proc IS BEGIN ... END;(隐式DEFINER'S RIGHTS) - 正确写法:
CREATE OR REPLACE PROCEDURE pwn_proc AUTHID CURRENT_USER IS BEGIN ... END; - 已有过程改权限需重建,
ALTER PROCEDURE ...不支持修改AUTHID
EXECUTE IMMEDIATE拼接用户输入,等于交出数据库控制权
所有提权链都依赖动态SQL执行。一旦在EXECUTE IMMEDIATE中拼接用户可控的字符串(如表名、列名、甚至GRANT语句),攻击者就能注入任意SQL。
绑定变量只防“值”注入,不防结构注入。所以:1能绑dept_id,但不能绑table_name。
- 高危写法:
EXECUTE IMMEDIATE 'GRANT DBA TO ' || user_input; - 安全替代:白名单校验 +
DBMS_ASSERT.SIMPLE_SQL_NAME(user_input),非法字符直接抛ORA-44001 - 别信
REPLACE(user_input, '''', ''''''),Unicode单引号、宽字节截断都能绕过
授予PUBLIC或低权限用户EXECUTE权限,是提权跳板
攻击者需要能调用目标过程才能触发漏洞。如果过程被GRANT EXECUTE ON pwn_proc TO PUBLIC,任何用户都能执行它。
尤其警惕SYS包中存在注入点的过程(如DBMS_CDC_SUBSCRIBE.ACTIVATE_SUBSCRIPTION),它们默认可被PUBLIC调用。
- 检查命令:
SELECT grantee, privilege FROM dba_tab_privs WHERE table_name = 'PWN_PROC'; - 最小化授权:
GRANT EXECUTE ON pwn_proc TO trusted_user;,而非TO PUBLIC - 禁用非必要SYS包调用:
REVOKE EXECUTE ON sys.dbms_cdc_subscribe FROM PUBLIC;
自治事务(AUTONOMOUS_TRANSACTION)放大提权危害
提权函数常带PRAGMA AUTONOMOUS_TRANSACTION,目的是绕过调用链的事务上下文,让GRANT操作立即生效,不受外层回滚影响。
这种设计本身无害,但配合DEFINER'S RIGHTS和拼接SQL,就成了提权闭环。
- 看到
AUTONOMOUS_TRANSACTION就要查两件事:是否在DEFINER'S RIGHTS过程里?是否拼接了用户输入? - 普通业务逻辑极少需要自治事务,滥用会破坏一致性;提权场景下它几乎总是恶意信号
- 审计重点:
SELECT text FROM dba_source WHERE UPPER(text) LIKE '%AUTONOMOUS_TRANSACTION%' AND owner = 'SYS';
GRANT当业务逻辑,把PUBLIC当默认选项。这些做法在测试环境可能永远不暴露问题,直到攻击者找到那条拼接路径。











