防止 SQL 注入,同时让用户在查询结束时输入自己的条件
Preventing SQL injection while letting the user enter their own condition at the end of the query
在我的程序中,我有一个查看 Contacts 信息给用户的查询。 table 通常显示没有过滤器的所有行。我想添加一个选项,让用户在 SELECT
语句的末尾写入自己的条件,以查看他们需要的信息。所以如果我的主要查询是这样的:
SELECT * FROM CONTACTS
用户可以写条件
WHERE FirstName LIKE '%Michael%'
在文本框中。
但是,我知道这不是很安全并且容易 SQL 注入。但是如何防止用户输入恶意命令,例如
WHERE 1=1; DROP TABLE Contacts
在文本框中?现在我正在对某些关键字进行检查,例如如果过滤器包含 DELETE、DROP、UPDATE 等,查询将不会 运行。但我认为这不是一个非常安全的解决方案。
我认为这个功能在设计上是不可取的:用户不仅需要了解数据库的工作原理,还需要知道正确的语法 和 数据模型。
尝试通过提供预定义条件来掩盖这一点,例如 "where the user name contains..." 或 "the last name is"。
在 C# 端使用参数化查询来确保用户提供的输入经过清理。
你说得对,这不安全。没有安全的方法可以完全按照您的意愿行事。任意 SQL 过滤器意味着用户同样可以使用 WHERE id IN (SELECT x FROM OPENROWSET(...))
选择,例如,still 允许 DROP TABLE
执行。
您可以做的是提供您自己的过滤器语法,并使用您自己的语法解析器,将其翻译成SQL。您可以确保仅允许 SQL 中安全使用的功能。某些 ORM 可能提供开箱即用的此类功能,否则您将不得不自己创建一些东西。
允许用户在 {SQL} 查询 末尾写入“他们自己的条件”,可能会在您的应用程序中造成安全漏洞容易出现 SQL injection attack.
之类的事情
如果您仍希望继续,请考虑以下几点:
- 使用正则表达式将输入限制为最基本的形式(例如 phone 数字只允许 0-9 和连字符)
- 在最低级别(即存储过程)实施您的保护机制
- 对于存储过程中的动态查询...永远不要将字段名称传递到存储过程中
- 从不 运行 拥有不必要的特权。
- 使用自己的登录名登录应用程序的用户通常应该只对存储过程具有 EXEC 权限。
- 如果使用动态SQL,应该限制在读取操作,这样用户只需要SELECT权限。
- 登录数据库的网站不应有任何提升的权限,最好只有 EXEC 和(可能)SELECT 权限。
- 永远不要让网站以管理员身份登录!
- 总是使用参数化语句。
- 进行代码审查以检查二次攻击的可能性。
- 确保错误消息不会泄露应用程序或数据库的内部架构。
再说一遍...实施时要非常非常小心!
补充阅读
这是无法回答的。您需要一个允许 SQL 条件的搜索引擎,这就是 SQL 注入的定义。
这里有一些解决方法:
- 使用网格控件 : 您可以在网格内显示查询结果并允许用户
使用网格来过滤结果。这很容易实现(您不需要重新发明轮子)并且用户友好。此外,一些网格提供了非常强大的过滤选项。我能看到的唯一缺点是,您经常会从数据库中检索到比您实际需要的更多的结果。
- 创建您自己的过滤器语法:您可以编写自己的过滤器语法(hvd 解决方案)。这将需要大量工作,如果您遗漏了某些内容,您可能仍会遇到安全漏洞。
- 编写一个条件构建工具 : 您可以提供一个条件构建工具。这对用户非常友好,但最终可能不够灵活。
- 导出为 CSV :您可以提供一个工具将查询结果导出为 CSV,以便在 Excel 中轻松利用或 计算。这对于使用电子表格应用程序的有经验的用户来说非常友好。
在我的程序中,我有一个查看 Contacts 信息给用户的查询。 table 通常显示没有过滤器的所有行。我想添加一个选项,让用户在 SELECT
语句的末尾写入自己的条件,以查看他们需要的信息。所以如果我的主要查询是这样的:
SELECT * FROM CONTACTS
用户可以写条件
WHERE FirstName LIKE '%Michael%'
在文本框中。
但是,我知道这不是很安全并且容易 SQL 注入。但是如何防止用户输入恶意命令,例如
WHERE 1=1; DROP TABLE Contacts
在文本框中?现在我正在对某些关键字进行检查,例如如果过滤器包含 DELETE、DROP、UPDATE 等,查询将不会 运行。但我认为这不是一个非常安全的解决方案。
我认为这个功能在设计上是不可取的:用户不仅需要了解数据库的工作原理,还需要知道正确的语法 和 数据模型。
尝试通过提供预定义条件来掩盖这一点,例如 "where the user name contains..." 或 "the last name is"。
在 C# 端使用参数化查询来确保用户提供的输入经过清理。
你说得对,这不安全。没有安全的方法可以完全按照您的意愿行事。任意 SQL 过滤器意味着用户同样可以使用 WHERE id IN (SELECT x FROM OPENROWSET(...))
选择,例如,still 允许 DROP TABLE
执行。
您可以做的是提供您自己的过滤器语法,并使用您自己的语法解析器,将其翻译成SQL。您可以确保仅允许 SQL 中安全使用的功能。某些 ORM 可能提供开箱即用的此类功能,否则您将不得不自己创建一些东西。
允许用户在 {SQL} 查询 末尾写入“他们自己的条件”,可能会在您的应用程序中造成安全漏洞容易出现 SQL injection attack.
之类的事情如果您仍希望继续,请考虑以下几点:
- 使用正则表达式将输入限制为最基本的形式(例如 phone 数字只允许 0-9 和连字符)
- 在最低级别(即存储过程)实施您的保护机制
- 对于存储过程中的动态查询...永远不要将字段名称传递到存储过程中
- 从不 运行 拥有不必要的特权。
- 使用自己的登录名登录应用程序的用户通常应该只对存储过程具有 EXEC 权限。
- 如果使用动态SQL,应该限制在读取操作,这样用户只需要SELECT权限。
- 登录数据库的网站不应有任何提升的权限,最好只有 EXEC 和(可能)SELECT 权限。
- 永远不要让网站以管理员身份登录!
- 总是使用参数化语句。
- 进行代码审查以检查二次攻击的可能性。
- 确保错误消息不会泄露应用程序或数据库的内部架构。
再说一遍...实施时要非常非常小心!
补充阅读
这是无法回答的。您需要一个允许 SQL 条件的搜索引擎,这就是 SQL 注入的定义。
这里有一些解决方法:
- 使用网格控件 : 您可以在网格内显示查询结果并允许用户 使用网格来过滤结果。这很容易实现(您不需要重新发明轮子)并且用户友好。此外,一些网格提供了非常强大的过滤选项。我能看到的唯一缺点是,您经常会从数据库中检索到比您实际需要的更多的结果。
- 创建您自己的过滤器语法:您可以编写自己的过滤器语法(hvd 解决方案)。这将需要大量工作,如果您遗漏了某些内容,您可能仍会遇到安全漏洞。
- 编写一个条件构建工具 : 您可以提供一个条件构建工具。这对用户非常友好,但最终可能不够灵活。
- 导出为 CSV :您可以提供一个工具将查询结果导出为 CSV,以便在 Excel 中轻松利用或 计算。这对于使用电子表格应用程序的有经验的用户来说非常友好。