Asp.net mvc 4 处理撇号';从ODP.net发送到Oracle的

Asp.net mvc 4 处理撇号';从ODP.net发送到Oracle的,asp.net-mvc-4,oracle11g,odp.net,Asp.net Mvc 4,Oracle11g,Odp.net,我将向存储过程发送一些信息,存储过程将把信息放入数据库。 存储过程动态构建查询,因此我必须小心发送给它的内容。 我习惯于在前端(我使用的是asp.net MVC)或web服务上从所需参数中提取任何恶意字符。这是可行的,但是如果我需要输入一个像O'brian这样的名字呢?还是不能?我将需要能够输入到甲骨文。我可以在动态构建这些特定参数时将q[]包装起来,但我认为这不起作用。odp.net是否有任何特殊方法调用可以神奇地处理这种特殊情况? 或者我需要自己专门编写代码吗?ODP.net提供了.net代

我将向存储过程发送一些信息,存储过程将把信息放入数据库。
存储过程动态构建查询,因此我必须小心发送给它的内容。 我习惯于在前端(我使用的是asp.net MVC)或web服务上从所需参数中提取任何恶意字符。这是可行的,但是如果我需要输入一个像O'brian这样的名字呢?还是不能?我将需要能够输入到甲骨文。我可以在动态构建这些特定参数时将q[]包装起来,但我认为这不起作用。odp.net是否有任何特殊方法调用可以神奇地处理这种特殊情况?

或者我需要自己专门编写代码吗?

ODP.net提供了.net代码和Oracle之间的接口。如果您是在将控制权传递给proc之后构建动态sql,那么odp.net可以为您做的事情就不多了

危险在于字符串,在本例中为varchar。它实际上只是一个字符串或类似的东西,有人可以在代码中注入一些额外的sql。只要绑定变量始终是单个字符串(即,一组未转义的单引号),恶意用户就不会做太多的事情

所以我认为有一些规则可以让你考虑这个问题:

1)仅在绝对必要时使用varchar/clob参数。

2)Varchar/clob绑定值应始终在生成的sql中用单引号括起来:

好:

坏的:

3)用字符串中的两个单引号替换任何单引号

'where myval=''' || replace(p_my_val, '''', '''''') || ''''
我认为在这一点上,你会降低你的风险。下面是oracle方面的完整工作示例。我还在sql中包含了一个绑定变量“l_fname”,并用“using”填充,以防您有其他变量总是在查询中(vs有条件地追加),并且总是以相同的顺序

--create the ref cursor (simulates cmd.Parameters.Add)
var c refcursor;
--vvvvvvvvv simulates your stored proc vvvvvvvvvvvv
declare 
  l_lname varchar2(200) :='O''brian';
  l_fname varchar2(200) :='Bob';
  l_sql varchar2(2000);
begin
  l_sql := 'select * from dual where dummy!=:l_fname ' || 'and dummy!=''' || replace(l_lname, '''','''''') || '''';
  dbms_output.put_line(l_sql);
  open :c for l_sql using replace(l_fname, '''', '''''');
end;
--^^^^^^^^^ ends yoru stored proc ^^^^^^^^^^^^^^^^^
/
--debugging within oracle only:
print c;

<强>也考虑是否需要动态SQL。在最终sql字符串之外执行的几乎任何逻辑都可以在其内部执行,即:

if( p_my_var is not null ) then
  p_sql = p_sql || ' and myval = ''' || replace(p_my_val, '''', '''''') || ''''
可能是

and p_my_val is null or myval=p_my_val
我强烈推荐在SQLServer中使用上述方法。我还建议在Oracle中进行此操作,但它不会像在sql server中那样短路,因为在执行计划中没有考虑绑定值,导致在某些情况下(至少在10g中)绑定值不是最佳值。在这种情况下,请改用以下方法:

and myval=decode(p_my_val, null, col1, p_my_val);

存储过程在做什么?很少需要动态构建查询。但是,如果您这样做了,您应该仍然使用绑定变量,而不是将字符串文本连接在一起。如果使用绑定变量,则无需担心转义字符。你也不必担心SQL注入攻击。当你说绑定变量时,你是在谈论Oracle存储过程吗?@JustinCave-如果存储过程正在构建动态SQL,那么他绝对需要担心转义和注入攻击。如果您正在动态构建sql,那么注入是一个问题,句号。@b_levitt-假设在对“O'Brian”等值使用绑定变量后,存储过程仍然连接调用方的输入以生成sql语句,那么sql注入仍然是可能的,你不必担心像“O'Brian”这样的值会被转义。然而,存储过程很少需要这样操作。绝大多数情况下,将通过添加适当的
DBMS\u ASSERT
调用而不是转义字符来处理。@Justin Cave-同意。那我们就在同一页了。关于DBMS_断言(特别是DBMS_ASSERT.ENQUOTE_LITERAL)的绝妙技巧。Justin Cave指出DBMS_ASSERT包包含DBMS#u ASSERT.ENQUOTE#u LITERAL函数,该函数将有效地将my#2和#3减少到“where myval=”| DBMS_ASSERT.ENQUOTE#u LITERAL(p#u my#val)我认为我绕过了这个问题,通过简单地添加第二个撇号来避开存储过程中的撇号,但现在它添加了两个撇号,而以前只有一个,存储过程将崩溃。这很令人沮丧。我已经编辑了我的答案,加入了一个工作脚本。我还收回了我对DBMS_ASSERT.ENQUOTE_LITERAL的评论。虽然它确实添加了开始和结束引号,但它不转义引号。仅当字符串包含它们时,它才会抛出错误。
and p_my_val is null or myval=p_my_val
and myval=decode(p_my_val, null, col1, p_my_val);