Oracle PL/SQL动态SQL安全底线是:用户输入的值必须用USING绑定,结构名必须经DBMS_ASSERT校验或白名单限制;拼接字符串即高危,EXECUTE IMMEDIATE必须配USING,不可拼接user_input。
oracle pl/sql中动态sql的安全底线只有一条:所有用户输入的值,必须走 using 子句绑定;所有用户输入的结构名(表名、列名、排序字段),必须经 dbms_assert 校验或白名单限制。拼字符串就是开后门,没有例外。
EXECUTE IMMEDIATE 必须配 USING,不能拼 user_input
只要 SQL 字符串里出现 || 拼接用户变量,风险就已成立——哪怕只拼一个单引号或空格。Oracle 不会解析拼接后的字符串是否“看起来像 SQL”,它直接执行整条语句。
- ❌ 错误写法:
EXECUTE IMMEDIATE 'SELECT * FROM emp WHERE name = ''' || user_name || ''''——user_name是' OR 1=1 --就全表泄露 - ✅ 正确写法:
EXECUTE IMMEDIATE 'SELECT * FROM emp WHERE name = :n' USING user_name——:n是占位符,user_name仅作为值传入,不参与语法解析 -
USING的参数顺序、数量、类型必须和 SQL 中占位符严格一致;命名绑定(如:n)只是可读性优化,Oracle 仍按出现顺序匹配,不是靠名字查 - 多个参数时逗号分隔:
USING val1, val2, val3,不是USING (val1, val2, val3)
IN 子句不能直接绑数组,得用 MEMBER OF 或固定占位符
WHERE id IN (:a, :b, :c) 看似合理,但参数个数不确定时 Oracle 会报 ORA-01008: not all variables bound。绑定变量不支持运行时动态展开列表。
- ❌ 错误写法:
EXECUTE IMMEDIATE 'SELECT * FROM t WHERE id IN :ids' USING id_list——:ids不是合法占位符语法 - ✅ 安全做法一:
WHERE id MEMBER OF :id_list,绑定sys.odcinumberlist(1,2,3)类型的嵌套表 - ✅ 安全做法二:预设最多 N 个参数(如 10 个),SQL 写成
WHERE id IN (:1,:2,...,:10),未用参数传NULL,再加AND id IS NOT NULL - ❌ 千万别用
LISTAGG拼字符串再INSTR查——这等于绕开绑定,重回高危区
表名、列名等结构信息不能绑,但也不能随便拼
绑定变量只适用于值(WHERE 条件、SET 赋值),不适用于对象名。但直接拼 table_name 或 order_by_col 同样危险,必须分层校验。
-
DBMS_ASSERT.SIMPLE_SQL_NAME(user_table)可校验标识符是否符合 Oracle 命名规范,非法字符(如分号、空格、双横线)会直接抛异常 -
DBMS_ASSERT.SQL_OBJECT_NAME更严格,只接受真实存在的对象名(需有对应权限),适合对已知 schema 的强约束场景 - 别信正则过滤,
^[a-zA-Z0-9_]+$挡不住 Unicode 变体或宽字节截断攻击 - 真要动态排序字段,用
CASE预置逻辑 + 白名单判断:ORDER BY CASE WHEN p_sort = 'name' THEN name WHEN p_sort = 'id' THEN id END
DBMS_SQL 比 EXECUTE IMMEDIATE 更易出错,95% 场景没必要用
DBMS_SQL 灵活度高,但代价是显式管理游标、定义列、绑定、执行、关闭。漏关游标会快速触发 ORA-01000: maximum open cursors exceeded,且硬解析多、性能差。
-
EXECUTE IMMEDIATE要求 SQL 结构相对固定(比如列数、WHERE 条件数可预期),但覆盖了绝大多数业务场景 - 只有极少数情况才需要
DBMS_SQL:例如列名完全由元数据驱动、WHERE 条件动态组合且数量不可控 - 若真要用
DBMS_SQL,必须在异常分支也调用DBMS_SQL.CLOSE_CURSOR,不能只依赖正常流程 - 权限配置不能忽略:
DEFINER'S RIGHT下即使用了绑定变量,也可能因缺少行级控制导致越权查询
最常被忽略的点是:结构名校验和值绑定必须同时存在,缺一不可;而开发时最容易下意识把“已经用了绑定变量”当成安全终点,却放过了表名拼接这个更隐蔽的入口。


















