将用户定义的T-SQL查询限制为仅限SELECT类型

时间:2014-01-04 14:43:44

标签: c# sql sql-server

我正在开发一个应用程序,它为用户提供了一种定义SQL查询并对数据库运行的方法。查询的唯一目的是创建将用于构建报告的数据集。由于这是一个共享数据库(意味着每个帐户表有大量帐户),因此安全性非常重要。

我正在寻找验证提供的查询仅为SELECT类型的最佳方法 - 这意味着用户无法运行DELETE,UPDATE等。当然,验证必须是服务器端。该项目是用C#编写的。

第一项检查是验证查询是以SELECT开头的,但由于子查询,这还不够。我想验证查询字符串(C#)是否包含一些保留字,如:EXEC,DELETE,UPDATE,INSERT。

有没有办法去" hack"此验证(使用& nbsp或其他字符)?必须阻止哪些保留字?还有其他想法或想法吗?

非常感谢你的时间!

2 个答案:

答案 0 :(得分:2)

我还认为使用受限用户进行查询是一个好主意,但如果您正在使用解析器,我将使用Microsoft.SqlServer.Management.SqlParser.Parser namespace中提供的类。特别是,使用扫描程序class来标记查询字符串,然后将与您要阻止的操作相对应的令牌或令牌模式列入黑名单。这适用于处理边缘情况,其中禁止的关键字实际包含在方括号或引号中,并且不用作命令。执行此操作的代码如下所示:

Scanner scanner = new Scanner(new ParseOptions());
string query = "DELETE FROM MyTable WHERE 0 = 1";
scanner.SetSource(query, 0);
int state = 0, start, end, token;
bool pair, param;
do {
    token = scanner.GetNext(ref state, out start, out end, out pair, out param);
    // Do some stuff here with the token
} while (token != 128); // 128 signifies the end of the query

如果您检查分配给token的值,您会看到值与查询中的令牌顺序相匹配,因此值226对应DELETE,242对{ {1}},等等。您还可以使用开始和结束输出来检查令牌本身。据我所知,没有一个很好的文档页面列出了所有的令牌号码,因此您必须暂时使用它来确定哪些号码与您正在观看的令牌相匹配。

命名空间的DLL可以在C:\ Windows \ assembly \ Microsoft.SqlServer.Management.SqlParser.dll中找到。希望有所帮助。

答案 1 :(得分:0)

您是否可以为用户提供受限制的GUI,以便他们可以点击?这样,通过构造查询是正确的。

接下来的想法是创建一个只拥有正确权限的特殊用户。根据文档,这应该是100%可靠的(如果不是,则无法保护服务器)。但我不相信这100%,因为SQL Server中可能存在错误或您的安全实施。确定这对你来说是否足够。

或者,使用SMO解析查询并对其进行验证。确保它符合白名单格式(例如,只有一个SELECT,没有函数调用,没有EXEC,...)。这很难。