SQL Server 2000的安全策略(二)
8、以最低許可權帳戶身份進行開發
通常情況下,保護開發伺服器安全的最佳方法,就好似它正在生產環境中執行那樣對它進行保護。您離這個目標越接近,那麼就可以越自信於您開發的程式碼可以在一個安全的生產環境中正常執行。
在開發過程中,大家都著迷於使用具有 sysadmin 或 dbo SQL Server 許可權的帳戶,直到部署之前才轉換為一個許可權更低的帳戶。使用這種方法存在著一個問題:將設計人員的許可權集還原為最低的所需許可權集與在開發應用程式過程中編寫這些許可權集相比,前者要困難得多。
鑑於部署應用程式之前您要決定可以取消哪些許可權,所以請不要使用 SQL sysadmin 帳戶開發 T-SQL 程式碼。如果使用 SQL sysadmin 帳戶,可能會造成這樣的結果,即應用程式會以比所需許可權更多的特權帳戶執行。因此,開發時請改為使用具有最低許可權的帳戶。
使用這樣的帳戶進行開發時,您會逐漸地升高授予的特定許可權,以 EXEC(執行)一些必需的儲存過程、從某些表進行 SELECT(選擇)等。請編寫這些 GRANT 語句,以便可以將同樣的最低許可權輕鬆部署到生產環境中,而不會出現任何基於猜測的操作。
這種理念同樣適用於測試。執行臨時測試以及結構更加複雜的測試時,所使用帳戶擁有的許可權集和使用者許可權應該與在生產環境中所使用帳戶擁有的許可權集和使用者許可權完全相同。
在開發過程中使用最低許可權帳戶的另一個優點在於,您可以避免不小心編寫出需要危險許可權或過高許可權的程式碼。例如,假設您需要在 T-SQL 中與第三方 COM 元件進行互動。為此,一種方法是傳送一個 SQL 批處理命令,它直接呼叫 sp_OACreate 和 sp_OAMethod 來操縱該 COM 物件。在應用程式使用 sysadmin 帳戶連線 SQL Server 的開發環境中,上述方法效果很好。但是,當您嘗試將已經開發完成的應用程式準備用於生產部署時,您就會發現如果使用許可權較低的帳戶,那麼該方法不會奏效。為了讓該應用程式能夠使用非 sysadmin 帳戶在生產環境中正常執行,您必須針對 sp_OACreate 顯式授予 EXECUTE 許可權。請考慮一下,如果某個使用者最終找到了一個方法,可以使用該應用程式登入執行任意程式碼,並利用此許可權針對 SQL Server 例項化一個類似Scripting.FileSystemObject 的 COM 物件,將會產生怎樣的安全隱患?
9、T-SQL指令碼安全
有一些 T-SQL 命令和擴充套件儲存過程,它們具有自己獨特的安全考慮事項。
(1)sp_OACreate 及其相關的系統過程系列
例如 sp_OAMethod、sp_OAGetProperty 等。透過授予應用程式登入直接訪問這些過程的許可權,會帶來該安全問題。為了避免此問題的發生,請絕對不要編寫直接呼叫 sp_OA 過程的應用程式程式碼,而要將對這些過程的所有引用都打包在您自己的 T-SQL 儲存過程中,並只授予訪問這些包裝儲存過程的許可權。另外,請不要允許應用程式程式碼將 COM 物件或方法的名稱作為可由包裝過程無條件呼叫的字串進行傳遞。
(2) 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 srcshare' + @filename + ' destshare'
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 destshare & '
使用這個 @filename 引數,將要執行的字串為 copy srcshare & del /S /Q destshare & destshare。和號 (&) 被作業系統命令直譯器處理為命令分隔符,因此該字串將被 CMD.EXE 視為三個互不相關的命令。其中第二個命令 (del /S /Q destshare) 將嘗試刪除 destshare 中的所有檔案。透過利用該儲存過程中某個 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
+ dbo.fn_escapecmdshellstring (@filename)
+ '
EXEC master.dbo.xp_cmdshell @cmd
(3)允許執行動態構建的查詢的命令
EXEC() 和 sp_executesql。轉義對資料庫引擎可能具有特殊意義的字元序列。在 T-SQL 中,注入式攻擊中最常用的兩個字串為單引號字元 (') 和註釋字元序列 (--)。 SQL 注入式攻擊的風險並不是避免動態 SQL 的唯一理由。任何透過這些命令動態執行的查詢都將在當前使用者的安全上下文中執行,而不是在該儲存過程所有者的上下文中執行。這就意味著,使用動態 SQL 可能會強制您授予使用者直接訪問基表的許可權。以下面的儲存過程為例:
CREATE PROC dbo.usp_RetrieveMyUserInfo
AS
SELECT * FROM UserInfo WHERE UserName = USER_NAME()
此過程會限制當前使用者,使其無法檢視其他任何使用者的資料。但是,如果此過程中的 SELECT 語句是透過動態 EXEC() 或透過 sp_executesql 執行的,您則必須授予使用者對 UserInfo 表的直接 SELECT 許可權,這是因為這個動態執行的查詢是在當前使用者的安全上下文中執行的。如果使用者能夠直接登入伺服器,他們則可以使用此許可權跳過該儲存過程提供的行級安全,檢視所有使用者的資料。
小結
(1)總而言之,下面的建議將有助於您開發在 SQL Server 中安全執行的 T-SQL 程式碼:
★ 保護您的開發 SQL Server 的安全,就好像它是一個生產伺服器一樣。這樣有助於確保您開發安全的程式碼,還可以幫助您定義應用程式正常執行所需的最低許可權集。 ★ 進行 T-SQL 開發和測試時請使用具有最低許可權的 SQL Server 帳戶。不要使用 sysadmin 或 dbo 帳戶。 ★ 對於允許 T-SQL 執行任意外部程式碼的儲存過程,要非常注意,如 sp_OACreate 和 xp_cmdshell。如果必須使用這些擴充套件,則一定要考慮它們獨特的安全隱患。 ★ 請遵照保護 T-SQL 開發的最佳方法,其中包括:將使用者提供的資料以顯式引數進行傳遞、編寫可避免 SQL 注入式攻擊的程式碼、避免使用不必要的動態 SQL、授予訪問儲存過程的許可權而不要授予直接訪問基表的許可權。 ★ 安全的 T-SQL 才能構成安全的應用程式。利用下面的資源可以確保您的伺服器進行了安全配置,並確保您擁有一個安全的資料庫客戶端應用程式。
(2)去掉當前使用者以下許可權:
名稱 預設最低角色 xp_cmdshell Sp_OACreate sysadmin 固定伺服器角色的成員 Sp_OADestroy sysadmin 固定伺服器角色的成員 Sp_OAGetErrorInfo sysadmin 固定伺服器角色的成員 Sp_OAGetProperty sysadmin 固定伺服器角色的成員 Sp_OAMethod sysadmin 固定伺服器角色的成員 Sp_OASetProperty sysadmin 固定伺服器角色的成員 Sp_OAStop sysadmin 固定伺服器角色的成員 EXEC() 使用者上下文 sp_executesql 使用者上下文 Xp_regaddmultistring Xp_regdeletekey Xp_regdeletevalue Xp_regenumvalues Xp_regread Public資料庫角色成員 Xp_regremovemultistring Xp_regwrite sp_makewebtask
--指令碼如下:
USE MASTER
GO
DECLARE @curr_user VARCHAR(128), @access_ctrl_sql VARCHAR(128)
SET @curr_user = USER_NAME()
-- 1. xp_cmdshell
SET @access_ctrl_sql = 'DENY EXECUTE ON xp_cmdshell TO ' + @curr_user
EXEC(@access_ctrl_sql)
IF @@ERROR <> 0
BEGIN
GOTO ERROR_HANDLE
END
-- 2. Sp_OACreate
SET @access_ctrl_sql = 'DENY EXECUTE ON Sp_OACreate TO ' + @curr_user
EXEC(@access_ctrl_sql)
IF @@ERROR <> 0
BEGIN
GOTO ERROR_HANDLE
END
-- 3. Sp_OADestroy
SET @access_ctrl_sql = 'DENY EXECUTE ON Sp_OADestroy TO ' + @curr_user
EXEC(@access_ctrl_sql)
IF @@ERROR <> 0
BEGIN
GOTO ERROR_HANDLE
END
-- 4. Sp_OAGetErrorInfo
SET @access_ctrl_sql = 'DENY EXECUTE ON Sp_OAGetErrorInfo TO ' + @curr_user
EXEC(@access_ctrl_sql)
IF @@ERROR <> 0
BEGIN
GOTO ERROR_HANDLE
END
-- 5. Sp_OAGetProperty
SET @access_ctrl_sql = 'DENY EXECUTE ON Sp_OAGetProperty TO ' + @curr_user
EXEC(@access_ctrl_sql)
IF @@ERROR <> 0
BEGIN
GOTO ERROR_HANDLE
END
-- 6. Sp_OAMethod
SET @access_ctrl_sql = 'DENY EXECUTE ON Sp_OAMethod TO ' + @curr_user
EXEC(@access_ctrl_sql)
IF @@ERROR <> 0
BEGIN
GOTO ERROR_HANDLE
END
-- 7. Sp_OASetProperty
SET @access_ctrl_sql = 'DENY EXECUTE ON Sp_OASetProperty TO ' + @curr_user
EXEC(@access_ctrl_sql)
IF @@ERROR <> 0
BEGIN
GOTO ERROR_HANDLE
END
-- 8. Sp_OAStop
SET @access_ctrl_sql = 'DENY EXECUTE ON Sp_OAStop TO ' + @curr_user
EXEC(@access_ctrl_sql)
IF @@ERROR <> 0
BEGIN
GOTO ERROR_HANDLE
END
-- 9. xp_readmail
SET @access_ctrl_sql = 'DENY EXECUTE ON xp_readmail TO ' + @curr_user
EXEC(@access_ctrl_sql)
IF @@ERROR <> 0
BEGIN
GOTO ERROR_HANDLE
END
-- 10. xp_regread
SET @access_ctrl_sql = 'DENY EXECUTE ON xp_regread TO ' + @curr_user
EXEC(@access_ctrl_sql)
IF @@ERROR <> 0
BEGIN
GOTO ERROR_HANDLE
END
-- 11. sp_makewebtask
SET @access_ctrl_sql = 'DENY EXECUTE ON sp_makewebtask TO ' + @curr_user
EXEC(@access_ctrl_sql)
IF @@ERROR <> 0
BEGIN
GOTO ERROR_HANDLE
END
SUCCESS_HANDLE:
BEGIN
print '為使用者 ' + @CURR_USER + ' 收回重要的儲存過程執行許可權成功'
RETURN
END
ERROR_HANDLE:
BEGIN
print '為使用者 ' + @CURR_USER + ' 收回重要的儲存過程執行許可權失敗'
RETURN
END
GO
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/66009/viewspace-796001/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- SQL Server 2000的安全策略(一)SQLServer
- SQL Server 2000 shrink tempdbSQLServer
- SQL Server2000的OpenXML特性 (轉)SQLServerXML
- [zt] SQL Server 2000複製SQLServer
- SQL SERVER 2000 解除安裝SQLServer
- 監視 SQL Server 2000 阻塞SQLServer
- SQL Server 2000 建立統計SQLServer
- SQL Server中的未文件化的dbcc命令(適用於SQL Server 2000)SQLServer
- SQL Server 2005和SQL Server 2000資料的相互匯入SQLServer
- SQL Server 2000中的觸發器使用SQLServer觸發器
- 不同網段sql server 2005 連線 sql server 2000的問題SQLServer
- SQL SERVER 2000壓力測試SQLServer
- 打死也不用SQL Server 2000 了SQLServer
- SQL Server CE和SQL Server 2000/2005中的ISNULL函式的異同SQLServerNull函式
- 認識SQL Server2000 Server Role 和 Database RoleSQLServerDatabase
- l有Sql Server2000 的JDBC映絛?,SQLServerJDBC
- [zt] 揭祕SQL Server 2000中的Bookmark LookupSQLServer
- SQL Server 2000中的資料同步問題SQLServer
- 《轉》Sql Server 2005(64位) 連線Sql Server 2000(32位) .SQLServer
- sql server 2000 備份與還原SQLServer
- java 連結sql server 2000 問題JavaSQLServer
- SQL SERVER 2000壓力測試 (轉)SQLServer
- SQL Server2000 重溫筆記SQLServer筆記
- SQL Server 2000 許可權問題SQLServer
- [轉]SQL Server 2000定時執行SQL語句SQLServer
- 【轉帖】認識SQL Server2000 中的CheckPointSQLServer
- SQL Server2000表複製的原理問題SQLServer
- 怎麼解決SQL server 2000的中文問題?SQLServer
- SQL Server 2008連線區域網內的SQL Server 2000資料庫SQLServer資料庫
- SQL Server 2000與2005歸納SQLServer
- SQL Server2000 許可權問題SQLServer
- SQL Server 2000記憶體管理內幕SQLServer記憶體
- Hibernate配置連線SQL SERVER2000SQLServer
- SQL SERVER 2000新增功能介紹1 (轉)SQLServer
- 關於SQL Server 2000的日誌檔案壓縮SQLServer
- SQL Server 2000 的分頁查詢(儲存過程)SQLServer儲存過程
- 在安裝有sql server2000的基礎上裝sql server 2005遇到的問題SQLServer
- SQL Server 2000 如何建立一個新例項 ?SQLServer