Oracle:在无法使用参数时防止SQL注入的正确方法

Oracle: correct way to prevent SQL Injection when using parameters is not possible

提问人:berliner 提问时间:11/15/2020 更新时间:11/15/2020 访问量:669

问:

我有一个 C# 程序,它可以在 Oracle 数据库上执行一些操作。其中一项操作 - 创建一个新帐户。

CREATE USER {login} IDENTIFIED BY {password}

问题是我不能在这里使用参数,因为这种类型的查询不支持它。我没有找到关于为什么不支持它的确切文档,但我想它类似于这里描述的内容(DDL 操作不支持参数):如何使用 SqlCommand 创建具有参数化数据库名称的数据库?

所以我的问题是 - 如何在 Oracle 中专门防止以下情况下的 SQL 注入?是否应该使用正则表达式来验证登录名和密码?如果是这样,它可能是什么?目前尚不清楚,因为正如 Oracle 文档所说,“不带引号的标识符不能是 Oracle SQL 保留字。带引号的标识符可以是保留字,但不建议这样做。如何检查我的登录名是否不是任何保留字?等等。

对于MS SQL,我有类似的情况

CREATE LOGIN {login} WITH PASSWORD=N'{password}'

我正在通过以下方式解决它:我用

new SqlCommandBuilder().QuoteIdentifier(name);

和密码与简单的

password.Replace("'", "''");

因为它是查询中的文字。

C# Oracle SQL 注入

评论


答:

3赞 aleroot 11/15/2020 #1

我认为在这种情况下,您可以使用DBMS_ASSERT,按照使用 DBMS_ASSERT 检查用户名的存储过程示例:

create or replace procedure procedure_create_user
   (user_name IN varchar2 , u_password IN varchar2 )
  IS
    tmp_query varchar(150);
    user_name_upper varchar(30) := UPPER(user_name) ;
  BEGIN
    tmp_query := 'create user C##' || dbms_assert.simple_sql_name(user_name_upper) || ' identified by ' || u_password;
    EXECUTE IMMEDIATE ( tmp_query );

    tmp_query := 'grant create session to C##' || user_name_upper ;
    EXECUTE IMMEDIATE ( tmp_query );
  END;
  /

然后,您可以调用此过程并创建用户:

exec procedure_create_user('alessio', 'llll');

在 C# 中,您应该能够按以下方式调用存储过程:

 using (OracleConnection connection = new OracleConnection("ConnectionString"))
    using (OracleCommand command = new OracleCommand("procedure_create_user", connection))             
    {
          command.CommandType = CommandType.StoredProcedure;
          command.Parameters.Add("user_name", OracleDbType.Varchar2).Value = "alessio";
          command.Parameters.Add("u_password", OracleDbType.Varchar2).Value = "llll";

          connection.Open();
          command.ExecuteNonQuery();
    }

对于密码字段,您应该执行相同的操作,但是如果要允许某些字符,则需要小心...密码可能不是必需的,因为即使它们是注入代码,它们也不应该造成太大的伤害,因为在识别 section() 之后,该过程应该只接受一组有限的关键字,所以如果你在之后设置了 PASSWORD EXPIRE,他们可能没有太多可以注入而不会出错......simple_sql_nameIDENTIFIED BYCREATE USER

评论

0赞 berliner 11/16/2020
谢谢,听起来这是最好的方法。我不确定密码 - simple_sql_name不符合密码要求。可能我会根据要求使用正则表达式进行手动验证