技术开发 频道

SQL注入安全威胁

  通过代码来预防

  为您的数据库提供最大的安全,您必须使用多种技术。第一道防线是预防在

  用户界面。

  只要您正在使用一个数据库,您必须先了解您的数据,因为只有你更好地理

  解您的数据,你才能更好地将能够保护它。在测试程序中Employees 表的

  FirstName 字段是被用做在用户表里的用户名字段。本字段最大长度为10 个字符,

  但测试程序并不限制用户的输入为10 个字符。这是一个令人震惊的缺陷。假如

  我们把限制输入10 个字符的话可以避免刚才我们举例的攻击事件。不过,并非

  所有的输入栏位很短,因此作为安全防卫,输入长度检查只是一部分。如果最大

  长度是20 个字符,我们只限制最多输入20 个字符吗?下面是一个例子,只需要

  19 个字符来关闭数据库:

  ' or 1=1;shutdown—

  假设我们把一些特殊的字符,比如分号,等于号,确认为无效的输入,然后

  用正则表达式验证来检查这些无效的字符和错误的输入。作为一套有效的输入标

  准的解决方案不仅仅限制这些字符的输入,也需要防护黑客通过SQL 的char 函

  数来使用一个独立的ASCII 来转化成字符来实现SQL 注入的输入.尽管在限制这

  些字符输入,但是这方法是相对还是很合适的, Visual Studio.NET 具有这样的

  一个正则表达式验证控制,极大地简化了在ASP.NET 网页中使用正则表达式。

  数据类型检查有助于发现错误的输入。用户界面往往接受日期,时间和数字

  输入的文本字段,虽然用户可以在文本框中输入任何他们想输入的,程序可以检

  查输入数据,看它是否是正确的数据类型。例如,如果一个输入文本框映射到

  EmployeeID 列,那么您应该检查任何用户输入,看它是否是整数型数据。只有

  在输入正确的数据类型将输入传递给数据库服务器进行处理。在数据类型的验证

  的时候,这些错误的输入会被提示失败。

  最根本的缺陷不是允许错误输入,而是这些错误的输入可以被执行。开发人

  员乐于用动态SQL,因为很方便,但是却没有办法在应用程序的设计阶段控制

  实际运行的SQL。

  通过存储过程来预防

  存储过程可以在创建的时候被编译,但是这些SQL 语句在创建的时候会被

  冻结住,参考上面的例子

  ' or 1=1—

  利用Stored Proc Login 按钮,SQL 事件探查器显示实际执行:

  exec ValidateUser @FirstName = N''' or 1=1--',@LastName = N''

  Where @FirstName contains the following characters: ' or 1=1—

  当FirstName 包含' or 1=1—这样的字符时,无论你输入的@FirstName 还是

  @LastName,存储过程将始终只有执行在创建时候所定义在存储过程中的

  SELECT 语句。SQL 语句的执行是不会因为输入而改变。此存储过程包含2 个

  输入,都是字符串,不管这些输入字符串包含什么,都会被总是当作字符串。即

  使一个分号被视为普通的输入字符,而不是SQL 语句分隔符。

  需要特别声明的是, 存储过程本身并不防范SQL 注入,也就是说如果存储

  过程本身使用动态SQL 的话它也可以SQL 注入。在一个取名为sp_excutesql 的

  存储过程中建立SQL 字符串在执行的时候与在应用程序中建立SQL 字符串在执

  行的时候一样易受攻击。有一点需要澄清的是:一个存储过程并不一定是易受

  SQL 注入的攻击和它的取名无关。这完全取决于用户怎样使用它。

  以下是SQL 事件探查表明在执行时有一个企图绕过身份验证,而使用一个

  参数化查询:

  exec sp_executesql

  N'select EmployeeID from Employees

  where FirstName = @FirstName and LastName = @LastName',

  N'@FirstName nvarchar(4000),@LastName nvarchar(4000)'

  , @FirstName = N''' or 1=1--'

  , @LastName = N''

  正如你所看到的,一个参数化查询是类似于存储过程,因为它处理的输入作

  为参数,而不是字符串,可以改变文字的查询字符串。如果您下载并审查代码示

  例,您将看到的代码,以参数化查询与代码调用一个存储过程是非常相似的。

  有一种误解,即认为动态SQL 是需要的。这不一定是正确的。参考下面这

  个例子,搜索页面的房地产信息列表。客户提出多个搜索条件(价格,卧室的数

  量,浴室等)。并不是每次每个搜索条件都被输入,所以这样的SQL 的where 条

  件可能会因此变化。动态SQL 往往使用在类似情况下。但是,您可以提高代码,

  构造一个动态SQL 语句在运行时建立一个参数化查询代替。当然还可以建立一

  个具有很多where 条件存储过程,这是因为,防范在一个参数化查询的时候SQL

  注入,存储过程是最安全办法。参数查询要求有权限操作对应用系统的表和视图,

  这是在安全数据上不被推荐的方法。

  当存储过程被执行的时候,它不需要具有任何表或者视图的权限的。

  在“Calling Stored Procedures from ADO.NET”中提到了在.NET 环境中调用

  存储程序。

  通过最小的权限来预防

  最基本的安全原则就是尽可能赋予最小的权限,用户只要具有完成操作任务

  最低的权限。客户在使用的时候不可以随便的具有一些操作数据库的权限,像增

  删改动表,关闭数据库等。当黑客企图删除一个表,但并没有权利这样做,就不

  会取得成功的。

  结论

  提高安全的非常好的做法就是可以防止数据库的权限的泄漏。使用forethought

  和精心设计的应用是在保护你的利益。虽然动态SQL 有其用途,就应该尽早作

  出决定,就以它是否将是最好的选择。如果可能的话,你应该考虑预存程序在设

  计早期阶段,因为他们的执行是不依赖用户输入的改变。你也应该彻底检查代码

  地看到,它不适合入侵。开发人员必须考虑像一个黑客,以便充分评估中的弱点

  及其应用。

0
相关文章