Oracle:在使用参数时防止SQL注入的正确方法是不可能的



我有一个C#程序,它对Oracle数据库执行一些操作。操作之一-创建一个新帐户。

CREATE USER {login} IDENTIFIED BY {password}

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

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

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

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

我用以下方式解决它:我用逃避登录

new SqlCommandBuilder().QuoteIdentifier(name);

和带有简单的密码

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

因为它是查询中的文字。

我认为在这种情况下,您可以使用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();
}

对于密码字段,您也应该这样做,但如果您想允许simple_sql_name不允许的某些字符,则需要小心。。。可能不需要密码,因为即使它们是注入代码,它们也不会造成太大伤害,因为在识别部分(IDENTIFIED BY(之后,CREATE USER过程应该只接受有限的一组关键字,所以如果你在之后甚至设置了password EXPIRE,它们可能无法在不出错的情况下注入太多。。。

最新更新