Din*_*age 1 oracle plsql dynamic
我有一种情况,我想从具有不同参数的游标执行动态获取的方法。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;
Run Code Online (Sandbox Code Playgroud)
这是不安全的,可以为此执行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
Run Code Online (Sandbox Code Playgroud)
但是任何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
Run Code Online (Sandbox Code Playgroud)
而不是将整个语句构建为字符串,而是添加:bind_variable_n并DBMS_SQL运行它。
因此,最终的字符串将如下所示(在循环中添加绑定变量编号):
method_stmt_ := 'begin '||method_name||'(:1, :2); end;';
Run Code Online (Sandbox Code Playgroud)
执行动态数量的绑定变量require DBMS_SQL.BIND_VARIABLE。从本地动态SQL切换DBMS_SQL到恼人的过程,但这将使您传递绑定变量而无需担心注入。