普通使用者竟這樣執行xp_cmdshell儲存過程!
01環境需求 SQL Server 2005 及之後的版本 02背景 xp_cmdshell 是一個很危險的儲存過程,通過它,可以訪問作業系統的資源,但有時候我們也需要使用它來實現一些特殊的處理。 從安全的角度來考慮,禁用 xp_cmdsehll 是最保險的,即使為了特殊目的而要求使用它,也最好能夠編寫一些實現這個特殊目的的使用者儲存過程,只在這個使用者儲存過程中使用 xp_cmdshell,而普通使用者只能使用這些使用者儲存過程。 03正確的解決辦法 下面的示例顯示如何使普通使用者在不具有執行儲存過程 xp_cmdshell 的許可權下,呼叫包含了執行 xp_cmdshell 程式碼的使用者儲存過程的方法。 具有執行xp_cmdshell許可權的登入 USE master; GO -- 1.a. 建立登入 CREATE LOGIN Cmd_Login WITH PASSWORD = N'Pwd.123', CHECK_POLICY = OFF; GO -- 1.b. 這個登入是內建的, 不允許登入, 這樣可以減少安全隱藏 DENY CONNECT SQL TO Cmd_Login; GO -- 1.c. 因為要呼叫xp_cmdshell , 所以在master 中要有使用者, 並具有許可權 CREATE USER Cmd_Login FOR LOGIN Cmd_Login WITH DEFAULT_SCHEMA = dbo; GRANT EXECUTE ON sys.xp_cmdshell TO Cmd_Login; GO 使用者資料庫 USE tempdb; GO -- 2.a 為執行xp_cmdshell 許可權的登入建立使用者 CREATE USER Cmd_Login FOR LOGIN Cmd_Login WITH DEFAULT_SCHEMA = dbo; GO
-- 2.b 測試儲存過程 CREATE PROC dbo.p WITH EXECUTE AS N'Cmd_Login' -- 指定儲存過程的執行時的上下文 AS EXEC master.sys.xp_cmdshell 'dir c:/' GO 呼叫儲存過程的普通登入 USE master; GO -- 3.a 登入 CREATE LOGIN test WITH PASSWORD = N'abc.123', CHECK_POLICY = OFF; GO -- 3.b 資料庫使用者 USE tempdb; GO CREATE USER test FOR LOGIN test; GO -- 3.c 執行儲存過程的許可權 GRANT EXECUTE ON dbo.p TO test; GO -- 3.d 執行測試 EXECUTE AS LOGIN = N'test'; GO EXEC dbo.p; GO REVERT;
GO -- 4. 刪除測試 DROP PROC dbo.p; DROP USER test; DROP USER Cmd_Login; USE master; DROP LOGIN test; DROP USER Cmd_Login; DROP LOGIN Cmd_Login; 04補充說明 多數情況下,資料庫的所有者是 sa 一類的 sysadmin 固定伺服器角色的成員,所以在這種情況下,也可以直接指定使用資料庫所有者作為儲存過程執行的安全上下文。 使用者的資料庫 USE tempdb; GO -- 2.b 測試儲存過程 CREATE PROC dbo.p WITH EXECUTE AS N'dbo' -- 指定儲存過程的執行時的上下文 AS EXEC master.sys.xp_cmdshell 'dir c:/' GO 呼叫儲存過程的普通登入 USE master; GO -- 3.a 登 CREATE LOGIN test WITH PASSWORD = N'abc.123', CHECK_POLICY = OFF;
GO -- 3.b 資料庫使用者 USE tempdb; GO CREATE USER test FOR LOGIN test;
GO
-- 3.c 執行儲存過程的許可權 GRANT EXECUTE ON dbo.p TO test;
GO -- 3.d 執行測試 EXECUTE AS LOGIN = N'test'; GO EXEC dbo.p; GO REVERT;
GO 刪除測試 DROP PROC dbo.p; DROP USER test; USE master; DROP LOGIN test; 使用前述方法的時候,例項中需要有 xp_cmdshel l代理帳戶(預設是沒有的), 否則會收到下面的錯誤資訊。 訊息15153,級別16,狀態1,過程xp_cmdshell,第1 行xp_cmdshell 代理帳戶資訊無法檢索或無效。請驗證'##xp_cmdshell_proxy_account##' 憑據存在並且包含有效的資訊。 可以使用下面的程式碼建立xp_cmdshell代理帳戶。 USE master; GO DECLARE @user sysname, @password sysname, @sql varchar(1000); -- 在作業系統中為xp_cmdshell 代理帳戶建立windows 使用者 SELECT @user = N'XpCmdAccount', @password = N'P@ssw0rd.', @sql = 'NET USER "' + @user + '" "' + @password + '" /ADD';
EXEC sys.xp_cmdshell @sql; -- 建立xp_cmdshell 代理帳戶 SELECT @user = CONVERT(sysname, SERVERPROPERTY(N'MachineName'))
- N'/' + @user;
EXEC sp_xp_cmdshell_proxy_account @user, @password; 最後說明一點,要使用xp_mdshell,得將伺服器的“xp_cmdshell”選項開啟,參考如下的程式碼。 EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;
原文釋出時間為:2018-09-10 本文作者:鄒建 本文來自雲棲社群合作伙伴“資料和雲”,瞭解相關資訊可以關注“資料和雲”。