Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 防止在IN子句内连接字符串的SQL注入_C#_Sql_Oracle_Sql Injection - Fatal编程技术网

C# 防止在IN子句内连接字符串的SQL注入

C# 防止在IN子句内连接字符串的SQL注入,c#,sql,oracle,sql-injection,C#,Sql,Oracle,Sql Injection,我有一个变量,它是一个字符串数组。我想传递变量的所有值,将变量的所有元素连接成一个字符串 但我不确定这是否会带来SQL注入的风险。 我的代码: 我尝试将查询更改为使用参数化查询: string query = @"UPDATE MYTABLE SET STATUS = 'X' WHERE TABLEID in (:ids)"; OracleCommand dbCommand = (OracleCommand)this.Databa

我有一个变量,它是一个字符串数组。我想传递变量的所有值,将变量的所有元素连接成一个字符串

但我不确定这是否会带来SQL注入的风险。 我的代码:

我尝试将查询更改为使用参数化查询:

string query = @"UPDATE MYTABLE
                SET STATUS = 'X'
                WHERE TABLEID in (:ids)";

OracleCommand dbCommand = (OracleCommand)this.Database.GetSqlStringCommand(query) as OracleCommand;

dbCommand.Parameters.Add(":ids", OracleType.VarChar).Value = concatenateStrings(ids);
this.Database.ExecuteNonQuery(dbCommand, this.Transaction);

但它不起作用。有什么想法吗?

在PL/SQL包中创建一个PL/SQL过程,如下所示:

TYPE TArrayOfVarchar2 IS TABLE OF MYTABLE.TABLEID%TYPE INDEX BY PLS_INTEGER;

PROCEDURE UPDATE_MYTABLE(TABLEIDs IN TArrayOfVarchar2) IS
BEGIN

    FORALL i IN INDICES OF TABLEIDs
    UPDATE MYTABLE SET STATUS = 'X' WHERE TABLEID = TABLEIDs(i);

END;
using (OracleCommand cmd = new OracleCommand("BEGIN UPDATE_MYTABLE(:tableId); END;"), con))
{
  cmd.CommandType = CommandType.Text;
  // or
  // OracleCommand cmd = new OracleCommand("UPDATE_MYTABLE"), con);
  // cmd.CommandType = CommandType.StoredProcedure;
  var par = cmd.Parameters.Add("tableId", OracleDbType.Varchar2, ParameterDirection.Input);
  par.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
  par.Value = sa;
  par.Size = sa.Length;

  cmd.ExecuteNonQuery();
}
然后打这样的电话:

TYPE TArrayOfVarchar2 IS TABLE OF MYTABLE.TABLEID%TYPE INDEX BY PLS_INTEGER;

PROCEDURE UPDATE_MYTABLE(TABLEIDs IN TArrayOfVarchar2) IS
BEGIN

    FORALL i IN INDICES OF TABLEIDs
    UPDATE MYTABLE SET STATUS = 'X' WHERE TABLEID = TABLEIDs(i);

END;
using (OracleCommand cmd = new OracleCommand("BEGIN UPDATE_MYTABLE(:tableId); END;"), con))
{
  cmd.CommandType = CommandType.Text;
  // or
  // OracleCommand cmd = new OracleCommand("UPDATE_MYTABLE"), con);
  // cmd.CommandType = CommandType.StoredProcedure;
  var par = cmd.Parameters.Add("tableId", OracleDbType.Varchar2, ParameterDirection.Input);
  par.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
  par.Value = sa;
  par.Size = sa.Length;

  cmd.ExecuteNonQuery();
}

作为一种快速且局部的方法,我们假设TABLEID字段的类型为NUMBER solution,您可以验证sa中的每个项都是有效的整数:

一般情况下,您可以尝试使用绑定变量,请注意复数形式:我们必须创建许多绑定变量:

C具有OracleCollectionType.plSqlAssociationArray类型,用于将数组传递给PL/SQL关联数组数据类型,但这不能用于SQL查询,因为它只是PL/SQL数据结构

不幸的是,它不支持将数组传递给可在SQL查询中使用的SQL集合数据类型

解决方法之一是要求DBA创建一个简单函数,将PL/SQL关联数组转换为SQL集合,然后将其用作查询中的中间步骤:

CREATE TYPE varchar2s_array_type IS TABLE OF VARCHAR2(100)
/

CREATE PACKAGE utils IS
  TYPE varchar2s_assoc_array_type IS TABLE OF VARCHAR2(100) INDEX BY PLS_INTEGER;

  FUNCTION assoc_array_to_collection(
    p_assoc_array IN varchar2s_assoc_array_type
  ) RETURN varchar2s_array_type DETERMINISTIC;
END;
/

CREATE PACKAGE BODY utils IS
  FUNCTION assoc_array_to_collection(
    p_assoc_array IN varchar2s_assoc_array_type
  ) RETURN varchar2s_array_type DETERMINISTIC
  IS
    p_array varchar2s_array_type := varchar2s_array_type();
    i PLS_INTEGER;
  BEGIN
    IF p_assoc_array IS NOT NULL THEN
      i := p_assoc_array.FIRST;
      LOOP
        EXIT WHEN i IS NULL;
        p_array.EXTEND();
        p_array(p_array.COUNT) := p_assoc_array(i);
        i := p_assoc_array.NEXT(i);
      END LOOP;
    END IF;
    RETURN p_array;
  END;
END;
/
然后,您可以将代码更改为使用的成员,而不是在SQL语句中:

UPDATE MYTABLE
SET    STATUS = 'X'
WHERE  TABLEID MEMBER OF utils.assoc_array_to_collection(:ids)
并使用类似“我不是C用户”的方式绑定参数,因此这只是为了让您大致了解该方法,即使语法不完全正确:


然后,您可以在许多查询中重用通用函数。

dbCommand.Parameters。AddWithValue@mydata,ids在第一个示例中,如果我的第一个id为1';删除表MYTABLE;-例如,然后你会有一些trouble@TrishSiquian它不起作用。基本上,您所做的与我在第二个示例中尝试做的相同。@Rafalon,这就是为什么我要征求关于如何防止SQL注入的建议。@Rafalon与某些数据库不同,Oracle不允许在一条语句中使用两个命令,因此这种SQL注入攻击会引发错误。还有其他一些攻击方法,如1或1=1绕过过滤器并更新每一行或每一个1并存在。从password_表中选择1,其中user='Admin'和hash='0123456'查找是否存在其他表和敏感数据。您可以验证sa中的每个项是否为有效整数-如果所有内容都假定为整数,OP只需将参数更新为int[]而不是string[],并避免使用正则表达式。不过,你的第二个建议对我来说很好。@hvd:没有必要-RDMS Number和.Net int long可以是完全不同的类型,例如Number20超过long,这就是为什么int[]而不是string[]是一个危险的决定。然而,我们经常使用NumberN作为键,在这种情况下,我的第一个部分解将工作读取decimal[],而不是int[]。我的观点是,你的假设,一切都必须是一个整数,这只是一个假设。没有任何东西可以阻止TABLEID成为文本列,而OP没有使用int[]或long[]或decimal[]这一事实至少是一个弱迹象,表明它不是整数列。如果不使用插值字符串,是否可能?所以它也可以支持遗留的.net framework?@rcs:当然,插入的字符串可以更改为它们的字符串。格式等效。不幸的是,由于某种原因,我可能无法在数据库中创建该过程,因此我更喜欢用C语言完成的解决方案。
UPDATE MYTABLE
SET    STATUS = 'X'
WHERE  TABLEID MEMBER OF utils.assoc_array_to_collection(:ids)
var par = cmd.Parameters.Add(":ids", OracleDbType.Varchar2, ParameterDirection.Input);
par.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
par.Value = ids;
par.Size = ids.Length;
cmd.ExecuteQuery();