可以将SqlServer配置为不执行作为字符串提交的存储过程吗?

时间:2009-09-18 20:18:49

标签: sql-server security sql-injection

情景A:

SqlConnection con = new SqlConnection(myConnString);
SqlDataAdapter adp = new SqlDataAdapter("EXEC spGetUserInfo 42", con);
DataSet ds;
adp.Fill(ds);

情景B:

SqlConnection con = new SqlConnection(myConnString);
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText = "spGetUserInfo";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@UserID", 42));
SqlDataAdapter adp = new SqlDataAdapter(cmd);
DataSet ds;
adp.Fill(ds);

问题

在讨论如何强化SqlServer以防止sql注入攻击与修改调用数据库的底层应用程序代码分开时,提出了一个问题,即是否可以将SqlServer配置为不执行以场景A的方式编写的存储过程,仅允许以场景B的方式编写的执行请求。理论是,如果底层应用程序没有执行输入验证,方案A将容易被注入,允许类似“EXEC spGetUserInfo 42; drop database foo; - ”的可能性当SqlServer无法将“42; drop database foo; - ”转换为整数时,Scenario B将无法执行。

是否可以将SqlServer配置为不执行以场景A方式调用的存储过程?

3 个答案:

答案 0 :(得分:2)

据我所知,并且我很难找到一种方法。

我能想到的最接近的事情是以某种方式对网络做一些事情,以便与SQL Server的RPC连接被允许,因为“.StoredProcedure”调用通常来自RPC,但动态SQL请求不能。但是,我对网络管理和服务器管理知之甚少,不知道这是否可行。

另一种(更标准的)方法是简单地向用户/应用 CONNECT访问您的数据库,但不能访问任何数据库的对象。然后在自己的SCHEMA中创建存储过程,并授予其所有者/模式对数据库对象(表,视图,任何其他存储过程等)的正常访问权限。最后,授予用户对该Schema中存储过程的EXECUTE访问权限。这仍然不会阻止每个可能的动态SQL场景,但它确实会消除它们的危险(以及大多数它们的观点)。

答案 1 :(得分:2)

错误是SQL Server数据库引擎永远不会阻止这种情况发生。原因是,只要SQL Server知道这些命令何时进入SQL Server,命令基本相同。客户端计算机上的驱动程序是格式化的。

保护数据库引擎免受SQL注入的唯一方法是在应用程序层处理它。

答案 2 :(得分:0)

编辑:我纠正了,我回过头来阅读TDS标准:

http://www.sybase.com/content/1040983/Sybase-tds38-102306.pdf

TDS_LANGUAGE命令 通过网络支持本机参数,因此事实上SQL Server接收参数化查询的方式。

至于是否有办法强制使用参数而不接受CommandText中的参数,我不知道如何这样做。