5

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

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

4

4 回答 4

10

与其他视图相反,可以安全地执行此操作(只需查看Data Explorer)。以下是您可以做的四件事来实现它:

账户安全

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

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

查询调控器

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

隔离

最安全的做法是还使用托管在专用服务器上的专用、经过净化的报告数据库。这确保了任何查询都不会影响生产,无论是在性能方面还是在服务器或帐户遭到破坏方面。sql server 中有一些功能,例如 SSIS,您可以使用这些功能自动从生产中填充您的报告数据库。

使用产品

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

在这种情况下,可能值得查看 Stack Overflow 的Data Explorer。这是一个允许不受信任的用户构建任意查询的工具。该项目是开源的,因此您可以亲眼看到他们为确保安全所做的工作,或者甚至只是分叉该项目供您自己使用。再次值得一提的是,该工具的安全性的很大一部分是它旨在用于专用的、经过清理的数据库,因此它不会免除您对其他项目的要求。

不过,当一切都说完了,我认为设置一些视图并通过报告服务提供访问权限的评论可能是您最好的选择。

于 2013-04-04T16:41:05.230 回答
4

我认为您只能通过提供指定 SQL 的直接方式来实现您所需要的。

然而,这不一定是个问题。基本上,您只需要一个 SQL 子集来定义表达式(在 SELECT 中计算出的 solumns)和谓词(在 WHERE 中进行过滤)。这可以用自制的解析器来处理,它有足够的能力来做所有需要的事情,然后将表达式“编译”成真正的 SQL 代码,而不是直接注入任何东西。

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

于 2013-04-04T16:34:45.383 回答
1

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

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

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

于 2013-04-04T16:48:09.260 回答
0

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

于 2013-04-05T07:05:11.967 回答