WRAP仅防直接阅读源码,不防反编译、调试、SQL注入等;加密后不可逆,须保留原始SQL;版本不兼容,且依赖权限管控而非代码加密。
WRAP 是 Oracle 官方提供的唯一原生手段,但**它不是“防反编译”,而是“防直接阅读源码”**。真正能被反编译的,是未加密的 USER_SOURCE 视图内容;而 WRAP 加密后,该视图只显示乱码(Wrapped 标识),且无法通过任何 Oracle 内置函数还原。
不过,这个机制有硬边界:它不阻止运行时调试、不隐藏执行计划、不加密依赖对象(如表结构、视图定义)、更不防 SQL 注入或权限滥用。所以关键不在“能不能防”,而在“怎么用才不至于白忙活”。
WRAP 命令必须满足的 4 个脚本格式条件
常见错误是脚本看起来能跑,但加密后编译失败,报 ora-00900 或 ora-24344:
- 文件必须是纯 PL/SQL DDL 文本,不能含
SET、SPOOL、DEFINE、PROMPT等 SQL*Plus 指令 - 每个可编译单元(过程、函数、包体)末尾必须有单独一行的斜杠
/—— 少一个就编译报错 - 命令中
iname和oname路径必须写全,扩展名建议用.plb(不是.sql),避免误编辑或被 IDE 当作普通脚本打开 - 输入文件编码必须为 ASCII 或 UTF8(无 BOM),Windows 记事本默认带 BOM,会导致
wrap静默失败
DBMS_DDL.WRAP 与 CREATE_WRAPPED 的行为差异
二者都走 PL/SQL 接口,但结果完全不同:
-
DBMS_DDL.WRAP('CREATE OR REPLACE PROCEDURE p AS BEGIN NULL; END;')→ 只返回加密字符串,不创建对象,适合动态拼接后存入配置表或日志 -
DBMS_DDL.CREATE_WRAPPED('...')→ 直接在当前会话编译并创建对象,等价于先wrap iname=x.sql oname=x.plb再@x.plb - 两者都不校验语法、表是否存在、列名是否合法 —— 错误只在运行时暴露,比如调用时报
ORA-00942,而非编译时报错 - 动态拼接时单引号必须双写:
'... DBMS_OUTPUT.PUT_LINE(''hello''); ...',否则解析失败
加密后无法修改,也没有“解密编辑”路径
这是最容易被低估的运维现实:
- 加密后的
.plb文件不可逆,Oracle 不提供任何解密 API 或工具 - 想改一行逻辑?必须找回原始未加密的
.sql文件,改完再重跑wrap—— 没有中间态 - 19c 生成的
.plb在 12.2 数据库中无法编译,报ORA-24344或直接拒绝加载,版本不向下兼容 - 加密不等于安全:如果攻击者有
EXECUTE权限,仍可通过DBMS_DEBUG_JDWP或 PL/SQL debugger 跟踪执行流,甚至触发异常获取变量值
真正需要防护的,其实是权限和访问路径
单纯靠 WRAP 守不住业务逻辑,因为:
- 拥有
SELECT_CATALOG_ROLE或DBA角色的用户,可绕过USER_SOURCE直接查DBA_SOURCE(若未加密) - 若过程内调用
UTL_HTTP、UTL_FILE等高危包,权限未严格限制,逻辑再“加密”也挡不住越权操作 - 应用层若拼接 SQL 字符串传入过程参数,仍可能触发 SQL 注入 ——
WRAP对运行时行为零防护 - 审计重点应放在
GRANT EXECUTE ON xxx TO ...的审批链、以及V$SESSION中对敏感过程的调用频次监控上


















