转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 数据库 >> Sql Server >> 正文
[转载] 编写安全的 Transact-SQL         

[转载] 编写安全的 Transact-SQL

作者:闵涛 文章来源:闵涛的学习笔记 点击数:2096 更新时间:2007/11/14 12:56:49

编写安全的 Transact-SQL

Bart Duncan
Microsoft Corporation 本页内容 简介 简介 保护开发 SQL Server 的安全 保护开发 SQL Server 的安全 以最低权限帐户身份进行开发 以最低权限帐户身份进行开发 遵照保护 T-SQL 的最佳方法 遵照保护 T-SQL 的最佳方法 了解具有独特安全考虑事项的 T-SQL 命令 了解具有独特安全考虑事项的 T-SQL 命令 小结 小结 参考资料 参考资料

简介

关于如何以安全的方式部署 SQL Server,存在大量很好的信息源。但是,这些资源的目标用户通常都是那些对已经开发好的应用程序执行保护任务的数据库管理员。另外,还有很多内容讨论了如何编写安全的 .NET 和 ASP.NET 代码,其中包括访问 SQL Server 的 .NET 代码。然而,很多这样的资源关注的是在应用服务器上运行的数据访问代码,而不是在 SQL Server 中执行的 Transact-SQL (T-SQL) 代码。本专栏则将注意力投射到如何开发在 SQL Server 上安全运行的 T-SQL 代码。

返回页首返回页首

保护开发 SQL Server 的安全

开发安全 T-SQL 的第一步是保护开发 SQL Server 的安全。为什么要想方设法地锁定一个不保存真实数据的 SQL Server 实例,而从不将它展示给最终用户呢?这是因为,这样会强制您编写更安全的 T-SQL,并且当将您的应用程序部署到生产中时,也会更加容易地保护该应用程序。下面是几个具体的步骤,采用这些步骤您就可以快速保护开发服务器:

在开发或测试 SQL Server 中,至少应该有一个正在运行的、最新的 Service Pack 和 SQL 安全修补程序,这样才能确保您的客户能够在此 SQL Server 版本上成功运行您的应用程序。

默认情况下,SQL Server 2000 Service Pack 3a 会禁用称为“交叉数据库所有权链接”的不安全功能。在开发服务器上安装 SP3 时,如果让该 Service Pack 禁用“交叉数据库所有权链接”,则有助于验证您正在基于安全的服务器配置编写 T-SQL 代码。

找出开发 SQL Server 上常见的安全配置问题的一种简便方法是针对该服务器运行 Microsoft Baseline Security Analyzer。除了这种方法之外,还可以利用本专栏“参考资料”部分列出的资源;这些资源提供了一些附加步骤,可帮助您保护开发 SQL Server 的安全。

通常情况下,保护开发服务器安全的最佳方法,就好似它正在生产环境中运行那样对它进行保护。您离这个目标越接近,那么就可以越自信于您开发的代码可以在一个安全的生产环境中正常运行。

返回页首返回页首

以最低权限帐户身份进行开发

在开发过程中,大家都着迷于使用具有 sysadmin 或 dbo SQL Server 权限的帐户,直到部署之前才转换为一个权限更低的帐户。使用这种方法存在着一个问题:将设计人员的权限集还原为最低的所需权限集与在开发应用程序过程中编写这些权限集相比,前者要困难得多。

鉴于部署应用程序之前您要决定可以取消哪些权限,所以请不要使用 SQL sysadmin 帐户开发 T-SQL 代码。如果使用 SQL sysadmin 帐户,可能会造成这样的结果,即应用程序会以比所需权限更多的特权帐户运行。因此,开发时请改为使用具有最低权限的帐户。

使用这样的帐户进行开发时,您会逐渐地升高授予的特定权限,以 EXEC(执行)一些必需的存储过程、从某些表进行 SELECT(选择)等。请编写这些 GRANT 语句,以便可以将同样的最低权限轻松部署到生产环境中,而不会出现任何基于猜测的操作。

这种理念同样适用于测试。执行临时测试以及结构更加复杂的测试时,所使用帐户拥有的权限集和用户权限应该与在生产环境中所使用帐户拥有的权限集和用户权限完全相同。

在开发过程中使用最低权限帐户的另一个优点在于,您可以避免不小心编写出需要危险权限或过高权限的代码。例如,假设您需要在 T-SQL 中与第三方 COM 组件进行交互。为此,一种方法是发送一个 SQL 批处理命令,它直接调用 sp_OACreatesp_OAMethod 来操纵该 COM 对象。在应用程序使用 sysadmin 帐户连接 SQL Server 的开发环境中,上述方法效果很好。但是,当您尝试将已经开发完成的应用程序准备用于生产部署时,您就会发现如果使用权限较低的帐户,那么该方法不会奏效。为了让该应用程序能够使用非 sysadmin 帐户在生产环境中正常运行,您必须针对 sp_OACreate 显式授予 EXECUTE 权限。请考虑一下,如果某个用户最终找到了一个方法,可以使用该应用程序登录执行任意代码,并利用此权限针对 SQL Server 实例化一个类似 Scripting.FileSystemObject 的 COM 对象,将会产生怎样的安全隐患?

返回页首返回页首

遵照保护 T-SQL 的最佳方法

防御一系列称为“SQL 注入式”的安全漏洞是至关重要的。通常情况下,您会使用多层防护来抵御 SQL 注入式攻击:

执行用户提供输入的验证(例如,强制数据类型和最大字符串长度)。

转义对数据库引擎可能具有特殊意义的字符序列。在 T-SQL 中,注入式攻击中最常用的两个字符串为单引号字符 ('''') 和注释字符序列 (--)。

在 T-SQL 语句中,请不要将用户提供的值进行内联。请改为使用预处理语句和参数化。

SQL 注入式攻击在其他一些地方有详细的说明,所以在此我就不花大量时间来讨论这个问题的细节了。但是要强调一点,SQL 注入式问题并不只限于在应用层构建的 T-SQL 查询。只要执行一个部分由用户提供值构建的 T-SQL 查询,就可能会发生 SQL 注入式问题。这就是说,一个在内部构建查询字符串、并通过 EXEC() 命令或 sp_executesql 存储过程执行该查询的存储过程也可能会受到攻击。请参阅“参考资料”部分获得一些资源链接,这些资源提供了各种 SQL 注入式攻击类型的示例,还提供了一些保护代码免受这些攻击的技巧。

另一个最佳方法是避免针对基表授予权限。对于您希望用户能够执行的查询,您应该将其打包在存储过程中,并只对这些存储过程授予 EXECUTE 权限。如果您按照本指南进行操作,即使用户设法跳过了您的应用程序,直接登录到数据库,他们也无法回避您已经在存储过程中构建的任何数据验证、审核、业务规则或者行级安全限制。

返回页首返回页首

了解具有独特安全考虑事项的 T-SQL 命令

有一些 T-SQL 命令和扩展,它们具有自己独特的安全考虑事项。其中一个是 sp_OACreate 及其相关的系统过程系列(例如 sp_OAMethod、sp_OAProperty 等)。以前,我们曾经研究过一个潜在的安全问题,通过授予应用程序登录直接访问这些过程的权限,会带来该安全问题。为了避免此问题的发生,请绝对不要编写直接调用 sp_OA 过程的应用程序代码,而要将对这些过程的所有引用都打包在您自己的 T-SQL 存储过程中,并只授予访问这些包装存储过程的权限。另外,请不要允许应用程序代码将 COM 对象或方法的名称作为可由包装过程无条件调用的字符串进行传递。

另一个具有独特安全风险集的内置 SQL Server 扩展为 xp_cmdshell。这个系统存储过程可以运行任何可执行文件或系统命令。由于一些很显然的原因,xp_cmdshell 上的 EXEC 权限默认情况下仅为 sysadmin 用户,必须显示地为其他用户授予该权限。如果您需要应用程序在 SQL Server 上运行某个特定的命令或实用程序,则请注意,不要在应用程序中构建一个 xp_cmdshell 直接访问的相关内容。这样的风险与直接访问 sp_OACreate 的风险相似。一旦为某个帐户授予了 xp_cmdshell 的 EXEC 权限,该帐户不但能够执行您希望其访问的特定命令,而且能够执行成百上千个操作系统命令和其他可执行文件。与 sp_OACreate 相似,始终将 xp_cmdshell 调用打包在另一个存储过程中,避免直接在 xp_cmdshell 上授予 EXECUTE 权限。

您还应该避免将任何用户提供的字符串参数或者应用程序提供的字符串参数与将要通过 xp_cmdshell 执行的命令进行串联。如果无法达到上述要求,则必须了解,有一个专门针对 xp_cmdshell 的潜在的代码注入式攻击(至少在 SQL Server 中)。以下面的存储过程为例:

CREATE PROCEDURE usp_DoFileCopy @filename varchar(255) AS
DECLARE @cmd varchar (8000)
SET @cmd = ''''copy \\src\share\'''' + @filename + '''' \\dest\share\''''
EXEC master.dbo.xp_cmdshell @cmd
GO
GRANT EXEC ON usp_DoFileCopy TO myapplogin

通过将 xp_cmdshell 调用打包在您自己的存储过程中并只针对该 usp_DoFileCopy 存储过程授予 EXEC 权限,您已经阻止了用户直接调用 xp_cmdshell 以执行任意命令。然而,以下面的 shell 命令插入为例:

EXEC usp_DoFileCopy @filename = '''' & del /S /Q \\dest\share\ & ''''

使用这个 @filename 参数,将要执行的字符串为 copy \\src\share\ & del /S /Q \\dest\share\ & \\dest\share。和号 (&) 被操作系统命令解释器处理为命令分隔符,因此该字符串将被 CMD.EXE 视为三个互不相关的命令。其中第二个命令 (del /S /Q \\dest\share\) 将尝试删除 \\dest\share 中的所有文件。通过利用该存储过程中某个 shell 命令插入漏洞,用户仍然可以执行任意操作系统命令。针对此类攻击进行防御的一种方法是将命令字符串打包在一个 T-SQL 函数中,如下所示。这个用户定义的函数会添加 shell 转义符 (^),对出现的任何 & 字符或其他具有特殊意义的字符进行转义。

-- Function: fn_escapecmdshellstring
-- Description: Returns an escaped version of a given string
--              with carets (''''^'''') added in front of all the special 
--              command shell symbols. 
-- Parameter: @command_string nvarchar(4000)
--
CREATE FUNCTION dbo.fn_escapecmdshellstring (
  @command_string nvarchar(4000)) RETURNS nvarchar(4000) AS
BEGIN
  DECLARE @escaped_command_string nvarchar(4000),
    @curr_char nvarchar(1),
    @curr_char_index int    
  SELECT @escaped_command_string = N'''''''',
    @curr_char = N'''''''', 
    @curr_char_index = 1
  WHILE @curr_char_index <= LEN (@command_string)
  BEGIN
    SELECT @curr_char = SUBSTRING (@command_string, @curr_char_index, 1) 
    IF @curr_char IN (''''%'''', ''''<'''', ''''>'''', ''''|'''', ''''&'''', ''''('''', '''')'''', ''''^'''', ''''"'''')
    BEGIN
      SELECT @escaped_command_string = @escaped_command_string + N''''^''''
    END
    SELECT @escaped_command_string = @escaped_command_string + @curr_char
    SELECT @curr_char_index = @curr_char_index + 1 
  END
  RETURN @escaped_command_string
END

下面是消除了命令 shell 插入漏洞之后的存储过程:

CREATE PROCEDURE usp_DoFileCopy @filename varchar(255) AS
DECLARE @cmd varchar (8000)
SET @cmd = ''''copy \\src\share\'''' 
  + dbo.fn_escapecmdshellstring (@filename) 
  + '''' \\dest\share\''''
EXEC master.dbo.xp_cmdshell @cmd

第三个具有独特安全考虑事项的 T-SQL 命令集为那些允许执行动态构建的查询的命令:EXEC() 和 sp_executesql。SQL 注入式攻击的风险并不是避免动态 SQL 的唯一理由。任何通过这些命令动态执行的查询都将在当前用户的安全上下文中运行,而不是在该存储过程所有者的上下文中运行。这就意味着,使用动态 SQL 可能会强制您授予用户直接访问基表的权限。以下面的存储过程为例:

CREATE PROC dbo.usp_RetrieveMyUserInfo AS 
SELECT * FROM UserInfo WHERE UserName = USE

[1] [2]  下一页


[Access]sql随机抽取记录  [Access]ASP&SQL让select查询结果随机排序的实现方法
[操作系统]网络转载---64位操作系统与32位的区别  [系统软件](转载)Exploit,shellcode经验技巧杂谈
[系统软件]SQL语句性能优化--LECCO SQL Expert  [C语言系列]SQL Server到DB2连接服务器的实现
[C语言系列]SQL Server到SYBASE连接服务器的实现  [C语言系列]SQL Server到SQLBASE连接服务器的实现
[C语言系列]SQL Server连接VFP数据库的实现  [C语言系列]ASP+SQL Server之图象数据处理
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · Sql Server  · MySql
    · Access  · ORACLE
    · SyBase  · 其他
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台