Oracle 从PL/SQL中的集合创建SQL注入证明动态where子句

Oracle 从PL/SQL中的集合创建SQL注入证明动态where子句,oracle,plsql,sql-injection,oracle12c,dynamicquery,Oracle,Plsql,Sql Injection,Oracle12c,Dynamicquery,我需要执行一个查询,其中where子句是根据用户输入生成的。输入由0对或多对VARCHAR2组成 例如: [('firstname','John') ,('lastname','Smith') ,('street','somestreetname')] 这将转化为: where (attrib = 'firstname' and value = 'John') and (attrib = 'lastname' and value = 'Smith') and (attrib = 'stree

我需要执行一个查询,其中where子句是根据用户输入生成的。输入由0对或多对VARCHAR2组成

例如:

[('firstname','John')
,('lastname','Smith')
,('street','somestreetname')]
这将转化为:

where (attrib = 'firstname' and value = 'John') 
and (attrib = 'lastname' and value = 'Smith')
and (attrib = 'street' and value = 'somestreetname')
这不是实际的数据结构,因为有多个表,但对于本例,让我们保持简单,并假设值在1个表中。此外,我知道括号在这种情况下是不必要的,但我把它们放在那里,以使事情清楚

我现在要做的是循环它们并将它们关联到SQL字符串。我制作了一个存储过程来生成这个where子句,它可能也不是很安全,因为我只是连接到原始查询

如下所示,我尝试获取与请求的参数相对应的节点ID:

l_query := select DISTINCT n.id from node n, attribute_values av
where av.node_id = n.id ' || getWhereClause(p_params)

open l_rc
for l_query;
fetch l_rc bulk collect into l_Ids;
close l_rc;
但这并不安全,所以我正在寻找一种能够保证安全性并防止SQL注入攻击发生的方法

有人知道这是如何以安全的方式进行的吗?我想使用绑定,但是当您不知道参数的数量时,我不知道如何使用绑定


DB:v12.1.0.2(我认为)

它仍然有点不清楚和笼统,但假设您有一个模式级集合类型,类似于:

create type t_attr_value_pair as object (attrib varchar2(30), value varchar2(30))
/
create type t_attr_value_pairs as table of t_attr_value_pair
/
然后,可以将集合中的属性/值对用于绑定:

declare
  l_query varchar2(4000);
  l_rc sys_refcursor;
  type t_ids is table of number;
  l_ids t_ids;
  l_attr_value_pairs t_attr_value_pairs;

  -- this is as shown in the question; sounds like it isn't exactly how you have it
  p_params varchar2(4000) := q'^[('firstname','John')
,('lastname','Smith')
,('street','somestreetname')]^';

begin
  -- whatever mechanism you want to get the value pairs into a collection;
  -- this is just a quick hack to translate your example string
  select t_attr_value_pair(rtrim(ltrim(
     regexp_substr(replace(p_params, chr(10)), '(.*?)(,|$)', 1, (2 * level) - 1, null, 1),
     '[('''), ''''),
    rtrim(ltrim(
      regexp_substr(replace(p_params, chr(10)), '(.*?)(,|$)', 1, 2 * level, null, 1),
      ''''), ''')]'))
  bulk collect into l_attr_value_pairs
  from dual
  connect by level <= regexp_count(p_params, ',') / 2 + 1;

  l_query := 'select DISTINCT id from attribute_values
    where (attrib, value) in ((select attrib, value from table(:a)))';

  open l_rc for l_query using l_attr_value_pairs;
  fetch l_rc bulk collect into l_ids;
  close l_rc;

  for i in 1..l_ids.count loop
    dbms_output.put_line('id ' || l_ids(i));
  end loop;
end;
/
或使用表集合表达式的联接:

  select DISTINCT av.id
  bulk collect into l_ids
  from table(l_attr_value_pairs) t
  join attribute_values av on av.attrib = t.attrib and av.value = t.value;
其他集合类型将需要不同的方法



或者,您仍然可以为每个属性/值对构建带有一个条件的
where
子句,同时仍然使它们绑定变量-但是您需要两个级别的动态SQL。

看看。您可以使用集合,但具体的方式取决于您的实际查询-您的示例没有意义,因为没有一行会匹配所有矛盾的条件。我意识到这是编造的,但仍然。。。您是否在寻找与任何属性/值对匹配的ID?还有,您是如何接收参数的?您的示例应该是JSON吗?基本上,我有一些节点(我收集了其中的id)链接到属性和值。所以我收集所有有这些参数的ID。我的参数是通过Soap-so-XML传递的。在创建查询之前,我解析它们并将它们放入一个集合中。希望这能澄清问题。我更改了查询以更好地反映正在发生的事情。我对“将转换为”部分进行了更多的评论,该部分与相互排斥。我想你真的想
这些,那么找到匹配任何属性/值对的ID?哇,谢谢你。我不知道这些事情有一半是可能的。我一直在网上寻找解决方案,但这是我第一次看到这样的解决方案。我将研究它们,看看它们在我的特殊情况下是否可用。
  select DISTINCT av.id
  bulk collect into l_ids
  from table(l_attr_value_pairs) t
  join attribute_values av on av.attrib = t.attrib and av.value = t.value;