我有一个场景,我想从具有不同参数的游标中执行动态获取的方法。这些参数值将替换为循环中的值(使用Get_Parameter_Value___(head_rec_.objkey,parameter_);
),如以下示例所示。
PROCEDURE Dynamic_exe(
keyvalue_ IN VARCHAR2)
IS
param_str_ VARCHAR2(2000);
temp_param_str_ VARCHAR2(2000);
method_stmt_ VARCHAR2(100);
CURSOR get_method IS
SELECT exe_method
FROM method_tab
BEGIN
param_str_ := Substr(rec_.exe_method,Instr(rec_.exe_method,'(')+1,(Instr(rec_.exe_method,')')-1)-Instr(rec_.exe_method,'('));
temp_param_str_ := param_str_;
method_stmt_ := rec_.exe_method;
WHILE temp_param_str_ IS NOT NULL LOOP
IF (Instr(temp_param_str_,',') > 0 )THEN
parameter_ := trim(Substr(temp_param_str_,1,Instr(temp_param_str_,',')-1));
temp_param_str_ := Substr(temp_param_str_,Instr(temp_param_str_,',')+1);
ELSE
parameter_ := trim(temp_param_str_);
temp_param_str_ := NULL;
END IF;
parameter_value_ := Get_Parameter_Value___(head_rec_.objkey,parameter_);
method_stmt_ := REPLACE(method_stmt_,parameter_,''''||parameter_value_||'''');
END LOOP;
FOR rec_ IN get_method LOOP
EXECUTE IMMEDIATE 'BEGIN '||method_stmt_||'; END;';
END LOOP;
END Dynamic_exe;
这是不安全的,SQL注入可以为此完成,我需要一个与绑定变量关联的解决方案,有人对此有解决方案吗?
通过使用DBMS_ASSERT.SQL_OBJECT_NAME
来保护方法名,并使用DBMS_SQL
和绑定变量来保护参数,可以消除SQL注入的可能性。
如果值与现有对象不同,DBMS_ASSERT.SQL_OBJECT_NAME
将引发错误。 (尽管对于包,它只检查包名称是否存在,而不检查过程名称。 但过程名称必须仍然是实际名称。
例如,如果包名称存在,则该函数将仅返回名称:
SQL> select dbms_assert.SQL_OBJECT_NAME('test_package.test_procedure') name from dual;
NAME
--------------------------------------------------------------------------------
test_package.test_procedure
但是任何SQL注入恶作剧都会引发异常(如有必要,您可以捕获并处理该异常):
SQL> select dbms_assert.sql_object_name('; delete from employees;') from dual;
select dbms_assert.sql_object_name('; delete from employees;') from dual
*
ERROR at line 1:
ORA-44002: invalid object name
ORA-06512: at "SYS.DBMS_ASSERT", line 401
不要将整个语句构建为字符串,而是添加:bind_variable_n
和DBMS_SQL
来运行它。
所以最终的字符串将看起来像这样(在循环中添加绑定变量号):
method_stmt_ := 'begin '||method_name||'(:1, :2); end;';
执行动态数量的绑定变量需要DBMS_SQL.BIND_VARIABLE
。 从本机动态 SQL 切换到DBMS_SQL
会很烦人,但它可以让您传入绑定变量而没有任何注入问题。