xp_cmdshell (Transact-SQL)

適用於:SQL Server

繁衍 Windows 命令殼層,並傳入字串以供執行。 任何輸出會以文字列的形式傳回。

Transact-SQL 語法慣例

語法

xp_cmdshell { 'command_string' } [ , NO_OUTPUT ]

引數

'command_string'

包含要傳遞至作業系統之命令的字串。 command_string為 varchar(8000)nvarchar(4000),沒有預設值。 command_string不能包含一組以上的雙引號。 如果command_string中參考的檔案路徑或程式名稱中有任何空格,則需要單一引號。 如果您在內嵌空格時遇到問題,請考慮使用 FAT 8.3 檔名作為因應措施。

NO_ OUTPUT

選擇性參數,指定不應傳回任何輸出給用戶端。

傳回碼值

0 (成功)或 1 (失敗)。

結果集

執行下列 xp_cmdshell 語句會傳回目前目錄的目錄清單。

EXEC xp_cmdshell 'dir *.exe';
GO

數據列會在 nvarchar(255) 資料行中傳回。 NO_OUTPUT如果使用 選項,只會傳回下列輸出:

The command(s) completed successfully.

備註

產生的 xp_cmdshell Windows 進程具有與 SQL Server 服務帳戶相同的安全性許可權。

警告

xp_cmdshell 是功能強大的功能,預設為停用。 xp_cmdshell 您可以使用原則式管理或執行 sp_configure來啟用和停用。 如需詳細資訊,請參閱 Surface area configuration and xp_cmdshell (server configuration option) 。 使用 xp_cmdshell 可觸發安全性稽核工具。

xp_cmdshell 以同步方式運作。 在命令殼層命令完成之前,控件不會傳回給呼叫端。 如果在 xp_cmdshell 批次內執行並傳回錯誤,批次將會失敗。

xp_cmdshell Proxy 帳戶

由不是系統管理員固定伺服器角色成員的使用者呼叫時,xp_cmdshell會使用儲存在 ##xp_cmdshell_proxy_account## 認證中的帳戶名稱和密碼連線到 Windows。 如果此 Proxy 認證不存在,則 xp_cmdshell 失敗。

您可以執行 sp_xp_cmdshell_proxy_account來建立 Proxy 帳戶認證。 作為自變數,此預存程式會採用 Windows 使用者名稱和密碼。 例如,下列命令會為具有 Windows 密碼 sdfh%dkc93vcMt0的 Windows 網域使用者SHIPPING\KobeR建立 Proxy 認證。

EXEC sp_xp_cmdshell_proxy_account 'SHIPPING\KobeR', 'sdfh%dkc93vcMt0';

如需詳細資訊,請參閱 sp_xp_cmdshell_proxy_account (Transact-SQL)

權限

因為惡意用戶有時會嘗試使用 xp_cmdshell來提升其許可權, xp_cmdshell 所以預設會停用。 使用 sp_configure原則式管理 來啟用它。 如需詳細資訊,請參閱 xp_cmdshell 伺服器組態選項

第一次啟用時, xp_cmdshell 需要 CONTROL SERVER 許可權才能執行,而 所 xp_cmdshell 建立的 Windows 進程與 SQL Server 服務帳戶的安全性內容相同。 SQL Server 服務帳戶通常具有比 所建立 xp_cmdshell程式所執行之工作所需的許可權還多。 若要增強安全性,應將 存取 xp_cmdshell 限制為高度特殊許可權的使用者。

若要允許非系統管理員使用 xp_cmdshell,並允許 SQL Server 使用較低許可權帳戶的安全性令牌建立子進程,請遵循下列步驟:

  1. 建立和自定義 Windows 本機用戶帳戶或網域帳戶,其中包含您程式所需的最低許可權。

  2. sp_xp_cmdshell_proxy_account使用系統程序來設定xp_cmdshell為使用該最低許可權帳戶。

    注意

    您也可以使用 SQL Server Management Studio 來設定此 Proxy 帳戶,方法是以滑鼠右鍵按兩下 物件總管 中的伺服器名稱上的 [屬性],然後查看 [伺服器 Proxy 帳戶] 區段的 [安全性] 索引卷標。

  3. 在 Management Studio 中,使用 master 資料庫執行下列 Transact-SQL 語句,讓特定非系統管理員 用戶能夠執行 xp_cmdshell。 指定的用戶必須存在於 master 資料庫中。

     GRANT exec ON xp_cmdshell TO N'<some_user>';
    

現在,非系統管理員可以使用 啟動操作系統進程 xp_cmdshell ,而這些進程會以您設定的 Proxy 帳戶許可權執行。 具有 CONTROL SERVER 許可權的使用者(系統管理員固定伺服器角色的成員)會繼續接收 由 啟動xp_cmdshell之子進程之 SQL Server 服務帳戶的許可權。

若要判斷啟動作業系統進程時所使用的 xp_cmdshell Windows 帳戶,請執行下列語句:

EXEC xp_cmdshell 'whoami.exe';

若要判斷另一個登入的安全性內容,請執行下列 Transact-SQL 程式代碼:

EXEC AS LOGIN = '<other_login>';
GO
xp_cmdshell 'whoami.exe';
REVERT;

範例

A. 傳回可執行檔案清單

下列範例顯示執行目錄命令的 xp_cmdshell 擴充預存程式。

EXEC master..xp_cmdshell 'dir *.exe'

B. 傳回無輸出

下列範例會使用 xp_cmdshell 來執行命令字串,而不將輸出傳回用戶端。

USE master;

EXEC xp_cmdshell 'copy c:\SQLbcks\AdvWorks.bck
    \\server2\backups\SQLbcks', NO_OUTPUT;
GO

C. 使用傳回狀態

在下列範例中 xp_cmdshell ,擴充預存程式也會建議傳回狀態。 傳回碼值會儲存在變數 @result中。

DECLARE @result INT;

EXEC @result = xp_cmdshell 'dir *.exe';

IF (@result = 0)
    PRINT 'Success'
ELSE
    PRINT 'Failure';

D. 將變數內容寫入檔案

下列範例會將變數的內容 @var 寫入目前伺服器目錄中名為 var_out.txt 的檔案。

DECLARE @cmd SYSNAME,
    @var SYSNAME;

SET @var = 'Hello world';
SET @cmd = 'echo ' + @var + ' > var_out.txt';

EXEC master..xp_cmdshell @cmd;

E. 將命令的結果擷取至檔案

下列範例會將目前目錄的內容寫入目前伺服器目錄中名為 dir_out.txt 的檔案。

DECLARE @cmd SYSNAME,
    @var SYSNAME;

SET @var = 'dir /p';
SET @cmd = @var + ' > dir_out.txt';

EXEC master..xp_cmdshell @cmd;