我有一种情况,我想从具有不同参数的游标执行动态获取的方法。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;';
执行动态数量的绑定变量require DBMS_SQL.BIND_VARIABLE
。从本地动态SQL切换DBMS_SQL
到恼人的过程,但这将使您传递绑定变量而无需担心注入。