C# 如何在允许良性SQL注入的同时防止恶意SQL注入攻击?

C# 如何在允许良性SQL注入的同时防止恶意SQL注入攻击?,c#,sql-server,asp.net-mvc-4,sql-injection,C#,Sql Server,Asp.net Mvc 4,Sql Injection,我正在编写一个ASP.NET MVC4应用程序,它最终动态构建一个SQL SELECT语句,以便在以后存储和执行。动态SQL的结构由用户配置以用户友好的方式确定,带有标准复选框、下拉框和自由输入文本框。验证输入并使用参数化查询构建SQL字符串非常简单,但我需要允许高级用户能够输入自定义SQL,以便直接注入SELECT和WHERE子句。那么,我可以使用什么技术来清理自定义SQL表达式,或者防止来自聪明用户的不必要输入呢?我可以很容易地解析可疑关键字的字符串和黑名单插入/更新/删除/等等,但有些事情

我正在编写一个ASP.NET MVC4应用程序,它最终动态构建一个SQL SELECT语句,以便在以后存储和执行。动态SQL的结构由用户配置以用户友好的方式确定,带有标准复选框、下拉框和自由输入文本框。验证输入并使用参数化查询构建SQL字符串非常简单,但我需要允许高级用户能够输入自定义SQL,以便直接注入SELECT和WHERE子句。那么,我可以使用什么技术来清理自定义SQL表达式,或者防止来自聪明用户的不必要输入呢?我可以很容易地解析可疑关键字的字符串和黑名单插入/更新/删除/等等,但有些事情告诉我,这并不能100%地保护我


我很乐意提供更多关于我在这里做什么的详细信息,但我不确定还有哪些其他详细信息会有帮助,因为我觉得我的问题虽然可能不常见,但非常普遍。

我认为只有通过而不是提供一种直接的方式来指定SQL,才能实现您所需要的

然而,这不一定是个问题。基本上,您只需要SQL的一个子集来定义表达式(SELECT中的计算解)和谓词(WHERE中的过滤)。这可以通过一个自制的解析器来处理,该解析器的功能刚好足以完成所需的一切,但随后将表达式“编译”成真正的SQL代码,而不直接注入任何内容


然后,这将验证语法,并确保不会制造允许任何注入的构造。此外,它还允许您让代码生成器根据需要对生成的查询进行参数化(例如,代码生成器可以将所有文本作为查询参数传入)。

与其他视图相反,可以安全地执行此操作(只需查看)。以下是您可以采取的四项措施:

帐户安全 Sql Server将允许您限制用于连接数据库的帐户的可用权限。仅授予读取权限,并且仅授予相应的表。然后,有人可能会注入恶意代码,直到他们脸色发青,但在编译步骤会失败,因为他们没有足够的权限。这可能意味着对该访问使用与应用程序其他部分不同的连接字符串

请注意,这对sql代码很好,但也有其他类型的注入。如果在运行查询之前在页面上(全部或部分)向用户显示查询,还应注意javascript注入攻击,如跨站点脚本

查询管理器 您还希望防御拒绝服务攻击。Sql数据库使得这些事情很容易发生,即使是偶然的,也只是因为构造了一个低效的查询。为了应对这种威胁,您应该看看Sql Server中的功能。请注意,调整这家伙是棘手的

隔离 最安全的做法是使用专用的、经过消毒的报告数据库,该数据库托管在专用服务器上。这确保了任何查询都不会影响生产,无论是在性能方面,还是在服务器或帐户被破坏方面。sql server中有一些功能(如SSI),您可以使用这些功能从生产环境中自动填充报表数据库

使用产品 关于安全性的一点是,您永远不希望自己构建自己的安全系统。创建一些看似有效、通过测试、但存在细微缺陷的东西很容易,这些缺陷会导致以后的违规行为。您希望依靠供应商提供的产品作为核心竞争力,并提供支持和一定程度的赔偿。通常我会从身份验证系统的角度来讨论这一点,但这一规则也可以应用于sql注入防御

在这种情况下,可能值得检查堆栈溢出的原因。这是一个允许不受信任的用户构造任意查询的工具。这个项目是,所以你可以亲眼看看他们为确保安全所做的工作,或者干脆把这个项目交给你自己使用。再次值得一提的是,该工具的安全性很大一部分是用于专用的、经过消毒的数据库,因此它不会免除您的其他项目


尽管如此,我认为设置一些视图并通过reporting services提供访问的评论可能是您最好的选择。

我永远不会让用户对生产服务器运行自定义SQL语句。 哪些坏人可以直接尝试读取/写入/修改他们不应该读取/写入/修改的表,或者其他坏人可以破坏弱帐户并对您的服务器运行SQL语句

如果您有根据html输入创建sql语句的预构建系统,那么您可以在后端生成不会损害数据库的脚本。否则,如果用户想要非常定制的东西,那么让他们上传脚本,与SQL管理员一起检查,确保“安全执行”,并按计划运行


如果脚本被拒绝,请让用户知道它,并解释其自定义脚本被拒绝的原因。

使用存储过程,因此来自任何用户的任何内容都将作为参数插入,并且永远不会执行。

让用户生成自定义SQL表达式注定会带来灾难。见鬼,即使让他们在大表上运行<代码>选择< /代码>也会使你的应用程序停止。考虑使用SQL报告服务来控制一组视图。SSRS有一个强大的用户友好UI,可能适合您的目的。无论如何,我需要这样做。我们还在VisualFoxpro中开发了类似的应用程序,允许用户输入已使用多年的自定义SQL,但VFP处理动态bui