select any table是高危权限,应禁用;正确做法是按最小权限原则,仅授予应用所需的特定表/视图select权限,并显式授予create session,禁用connect、resource等隐含高危权限。

只给 SELECT 权限,别碰 ANY TABLE
第三方应用通常只需要读取特定表或视图,SELECT ANY TABLE 是最常被误用的权限——它绕过所有对象级隔离,等于开放整个数据库的读能力。一旦被利用,敏感数据(如 hr.employees、finance.accounts)全在暴露范围内。
正确做法是:明确列出应用真正需要的表/视图,逐条授权:
GRANT SELECT ON app_config TO thirdparty_app;GRANT SELECT ON order_summary_v TO thirdparty_app;- 若视图依赖底层表(比如含
SYSDATE或函数),确认该视图创建者(如app_owner)本身已拥有对应表的SELECT权限,否则视图会查不到数据
登录权限必须显式授予 CREATE SESSION
新建用户后默认连数据库都连不上,会报 ORA-01045: user THIRD_PARTY_APP lacks CREATE SESSION privilege。很多团队以为“建了用户就能用”,结果应用启动失败卡在连接阶段。
最小必要组合只有两个:
CREATE USER thirdparty_app IDENTIFIED BY "P@ssw0rd2026";GRANT CREATE SESSION TO thirdparty_app;
不要顺手加 CONNECT 角色——它隐含 CREATE TABLE、CREATE VIEW 等无关权限;更不能授 RESOURCE,它自带 UNLIMITED TABLESPACE,可能被用于写临时数据甚至持久化恶意内容。
避免字典视图越权访问,慎用 SELECT ANY DICTIONARY
某些监控类或 ORM 框架会尝试查 DBA_TABLES、ALL_TAB_COLUMNS 等字典视图来自动发现结构。但 SELECT ANY DICTIONARY 直接暴露全部元数据,包括加密列标识、审计策略、甚至密码哈希存储位置(如 SYS.USER$)。
替代方案更安全:
- 如果只是需要知道某几张表的字段,手动建一个只含必要信息的视图(如
v_app_table_cols),再授SELECT给应用用户 - 若必须支持自动发现,限制为
SELECT ON ALL_TAB_COLUMNS+SELECT ON ALL_TABLES,且确保这些视图不暴露OWNER为SYS或SYSTEM的行(可用WHERE owner NOT IN ('SYS','SYSTEM')过滤) - 绝对不要授
DBA_*系列视图——它们是权限测绘的黄金入口
验证时一定要用真实连接测试,别信“没授权就安全”
权限模型不是靠“没给就不行”保障的,而是靠“给了才可行”。常见疏漏点:
- 忘记授
SELECT给视图依赖的序列(如视图里用了nextval),导致查询报ORA-00942 - 视图定义中引用了同义词(
Synonym),而同义词指向的对象未对目标用户开放SELECT - 用户默认
current_schema不是目标 schema,查sales_summary时没带 schema 前缀,实际查的是当前用户的同名对象(可能不存在)
上线前必须用该用户账号真实执行:
CONNECT thirdparty_app/P@ssw0rd2026; SELECT * FROM app_owner.order_summary_v WHERE ROWNUM <p>并故意试一条不该能查的:<code>SELECT * FROM hr.employees;</code> —— 必须稳定返回 <code>ORA-00942</code>,而不是静默空结果。</p><p>真正难控的从来不是“给了什么”,而是“没意识到还缺什么”和“以为没给就真没给”。</p>











