必须用SYSDBA身份执行并同步清理utl_file_dir参数,否则仅撤销EXECUTE权限无效;因utl_file_dir设为'*'或宽路径时,攻击者可通过其他PL/SQL入口绕过PUBLIC限制直接调用UTL_FILE,官方建议撤销权限+删除utl_file_dir,改用CREATE DIRECTORY模式。

必须用 SYSDBA 身份执行,且需同步清理 utl_file_dir 参数,否则权限撤销形同虚设。
为什么只 revoke EXECUTE 不够
UTL_FILE 的实际危害不只来自 EXECUTE 权限本身,更依赖底层操作系统路径的开放性。如果 utl_file_dir 初始化参数仍设为 '*' 或宽泛目录(如 '/tmp'),攻击者一旦拿到其他可执行 PL/SQL 的入口(比如被注入的存储过程、有 CREATE PROCEDURE 权限的用户),就能绕过 PUBLIC 权限限制,直接调用 UTL_FILE —— 因为权限检查发生在包内函数调用时,而 UTL_FILE.FILE_TYPE 变量声明和 FOPEN 调用可在任意合法 PL/SQL 块中完成。
常见错误现象:REVOKE EXECUTE ON UTL_FILE FROM PUBLIC; 执行成功,但扫描工具仍报高危;或 DBA 误以为已加固,实则攻击面未收敛。
- Oracle 官方明确建议:撤销 EXECUTE 权限 + 清理或删除
utl_file_dir配置 - 从 Oracle 12c 起,
utl_file_dir已被废弃,应改用CREATE DIRECTORY+ 显式授权模式 - 若数据库版本 utl_file_dir 改为具体、受限目录(如
'/u01/app/oracle/utlfile'),而非'*'
正确执行 revoke 的前提与步骤
撤销操作本身简单,但失败常因身份或上下文错误。必须确保:
- 使用
sqlplus / as sysdba连接,不能用普通 DBA 用户(如 SYSTEM)——REVOKE EXECUTE ON UTL_FILE FROM PUBLIC是系统级对象权限操作,仅 SYS 或具有ADMIN OPTION的用户能执行 - 确认当前实例是目标库(尤其 RAC 环境),避免在错误节点上操作
- 执行后无需 COMMIT(Oracle 权限变更不走事务),但已有会话若已解析并缓存了含 UTL_FILE 的 PL/SQL,可能短暂仍可调用;新会话立即生效
- 验证是否成功:
SELECT table_name FROM dba_tab_privs WHERE grantee='PUBLIC' AND privilege='EXECUTE' AND table_name='UTL_FILE';应无返回
撤销后必须检查的两个关键点
权限撤掉只是第一步,真正风险藏在残留配置和间接授权链里:
-
utl_file_dir参数是否仍存在?查:SHOW PARAMETER utl_file_dir;若值非NULL或空字符串,需在 spfile/pfile 中移除并重启(11g 及之前)或用ALTER SYSTEM SET utl_file_dir='' SCOPE=SPFILE;(12c+,但注意该参数已废弃) - 是否有非 PUBLIC 用户或角色仍拥有
EXECUTE ON SYS.UTL_FILE?查:SELECT grantee, privilege FROM dba_tab_privs WHERE table_name = 'UTL_FILE' AND privilege = 'EXECUTE' AND grantee NOT IN ('SYS', 'SYSTEM');—— 尤其警惕开发角色、ETL 账号、第三方应用账号 - 是否存在通过角色间接获得的 EXECUTE 权限?例如某角色
APP_DEVELOPER被授予了 UTL_FILE,而用户ETL_USER拥有该角色。此时仅 revoke PUBLIC 无效,必须逐层清理角色链
最易被忽略的是:UTL_FILE 的替代方案(如外部表、Data Pump、CREATE DIRECTORY)若配置不当,反而会引入新的路径暴露风险。撤销不是终点,而是重新设计文件访问路径治理的起点。


















