Share via


xp_cmdshell (Transact-SQL)

Windows のコマンド シェルを起動し、実行用の文字列に渡します。出力は、テキストの行として返されます。

トピック リンク アイコンTransact-SQL 構文表記規則

構文

xp_cmdshell { 'command_string' } [ , no_output ]

引数

  • 'command_string'
    オペレーティング システムに渡すコマンドを含む文字列を指定します。command_string のデータ型は varchar(8000) または nvarchar(4000) で、既定値はありません。command_string に、二重引用符を 2 組以上含めることはできません。command_string で参照するファイル パスまたはプログラム名にスペースがある場合は、引用符を 1 組指定する必要があります。ファイル パスやファイル名に埋め込まれたスペースに関する問題が発生する場合は、その問題への対処方法として 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 は、同期して動作します。制御は、コマンド シェルのコマンドが完了するまで呼び出し元に返されません。

ポリシー ベースの管理を使用するか、sp_configure を実行すると、xp_cmdshell を有効または無効にできます。詳細については、「セキュリティ構成について」および「xp_cmdshell オプション」を参照してください。

重要な注意事項重要

xp_cmdshell をバッチ内で実行し、エラーが返された場合、バッチは失敗します。これは新しい動作です。以前のバージョンの Microsoft SQL Server では、バッチは続行されていました。

xp_cmdshell プロキシ アカウント

sysadmin 固定サーバー ロールのメンバー以外のユーザーが xp_cmdshell を呼び出した場合は、##xp_cmdshell_proxy_account## という資格情報に格納されているアカウント名とパスワードによって、Windows への接続が行われます。このプロキシ資格情報が存在しない場合、xp_cmdshell は失敗します。

プロキシ アカウントの資格情報は、sp_xp_cmdshell_proxy_account を実行して作成できます。このストアド プロシージャは、Windows のユーザー名とパスワードを引数にとります。たとえば次のコマンドでは、Windows ドメイン ユーザー SHIPPING\KobeR 用のプロキシ資格情報が、Windows パスワード sdfh%dkc93vcMt0 で作成されます。

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 を使用して構成することもできます。そのためには、オブジェクト エクスプローラーでサーバー名を右クリックして [プロパティ] をクリックし、[セキュリティ] タブの [サーバーのプロキシ アカウント] セクションを使用します。

  3. Management Studio で、master データベースを使用して GRANT exec ON xp_cmdshell TO '<somelogin>' ステートメントを実行し、xp_cmdshell を実行する権限を sysadmin 以外の特定のユーザーに与えます。指定したログインが master データベース内のユーザーにマップされている必要があります。

これで、管理者以外のユーザーが xp_cmdshell を使用してオペレーティング システムのプロセスを起動できるようになりました。起動されたプロセスは、構成したプロキシ アカウントの権限を使用して実行されます。CONTROL SERVER 権限を持つユーザー (sysadmin 固定サーバー ロールのメンバー) には、引き続き、xp_cmdshell によって起動された子プロセスで SQL Server サービス アカウントの権限が与えられます。

xp_cmdshell がオペレーティング システムのプロセスを起動するときに使用される Windows アカウントを確認するには、次のステートメントを実行します。

xp_cmdshell 'whoami.exe'

別のログインのセキュリティ コンテキストを確認するには、次のコマンドを実行します。

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

A. 実行可能ファイルの一覧を返す

次の例では、ディレクトリ コマンドを実行する xp_cmdshell 拡張ストアド プロシージャを示します。

EXEC master..xp_cmdshell 'dir *.exe'

B. Windows の net コマンドを使用する

次の例では、ストアド プロシージャでの xp_cmdshell の使用を示します。この例では、net send を使用して、SQL Server インスタンスがこれからシャットダウンすることをユーザーに通知し、net pause を使用してサーバーを一時停止した後、net stop を使用してシャットダウンします。

CREATE PROC shutdown10
AS
    EXEC xp_cmdshell 'net send /domain:SQL_USERS ''SQL Server 
        shutting down in 10 minutes. No more connections 
        allowed.', no_output
    EXEC xp_cmdshell 'net pause sqlserver'
    WAITFOR DELAY '00:05:00'
    EXEC xp_cmdshell 'net send /domain: SQL_USERS ''SQL Server 
        shutting down in 5 minutes.', no_output
    WAITFOR DELAY '00:04:00'
    EXEC xp_cmdshell 'net send /domain:SQL_USERS ''SQL Server 
        shutting down in 1 minute. Log off now.', no_output
    WAITFOR DELAY '00:01:00'
    EXEC xp_cmdshell 'net stop sqlserver', no_output

C. 出力を返さない

次の例では、xp_cmdshell を使用して、クライアントに出力を返さずにコマンド文字列を実行します。

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

D. 戻りステータスを使用する

次の例では、xp_cmdshell 拡張ストアド プロシージャでステータス番号も表示します。リターン コード値は、変数 @result に格納されます。

DECLARE @result int
EXEC @result = xp_cmdshell 'dir *.exe'
IF (@result = 0)
   PRINT 'Success'
ELSE
   PRINT 'Failure'

E. さまざまな内容をファイルに書き込む

次の例では、@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

F. コマンドの結果をファイルにキャプチャする

次の例では、現在のディレクトリの内容を、現在のサーバー ディレクトリにある dir_out.txt というファイルに書き込みます。

DECLARE @cmd sysname, @var sysname
SET @var = 'dir/p'
SET @cmd = @var + ' > dir_out.txt'
EXEC master..xp_cmdshell @cmd