Share via


xp_cmdshell (Transact-SQL)

Genera una shell dei comandi di Windows e passa una stringa per l'esecuzione. L'eventuale output viene restituito in forma di righe di testo.

Icona di collegamento a un argomentoConvenzioni della sintassi Transact-SQL

Sintassi

xp_cmdshell { 'command_string' } [ , no_output ]

Argomenti

  • 'command_string'
    Stringa che contiene un comando da passare al sistema operativo. command_string è di tipo varchar(8000) o nvarchar(4000) e non prevede alcun valore predefinito. command_string può contenere una sola coppia di virgolette doppie. È obbligatorio utilizzare una sola coppia di virgolette doppie se i percorsi di file o i nomi di programma a cui viene fatto riferimento in command_string contengono spazi. In caso di problemi nell'utilizzo di spazi incorporati nelle stringhe, valutare l'utilizzo di nomi di file in formato FAT 8.3 come soluzione alternativa.

  • no_output
    Parametro facoltativo che indica che non è richiesta la restituzione di output al client.

Valori di codice restituiti

0 (esito positivo) o 1 (esito negativo)

Set di risultati

L'istruzione xp_cmdshell seguente restituisce un elenco dei file con estensione exe contenuti nella directory corrente.

EXEC xp_cmdshell 'dir *.exe';
GO

Le righe vengono restituite in una colonna di tipo nvarchar(255). Se si specifica l'opzione no_output verrà restituito unicamente il messaggio seguente:

The command(s) completed successfully.

Osservazioni

Il processo di Windows generato da xp_cmdshell dispone degli stessi diritti di sicurezza dell'account del servizio SQL Server.

La stored procedure xp_cmdshell funziona in modo sincrono, ovvero il controllo viene restituito al chiamante solo dopo il completamento del comando della shell.

Per abilitare e disabilitare xp_cmdshell, è possibile utilizzare la gestione basata sui criteri oppure eseguire sp_configure. Per ulteriori informazioni, vedere Informazioni su Configurazione superficie di attacco e Opzione xp_cmdshell.

Nota importanteImportante

Se si esegue xp_cmdshell all'interno di un batch e viene restituito un errore, l'intero batch avrà esito negativo. Questa è una differenza funzionale rispetto alle versioni precedenti di Microsoft SQL Server in cui l'esecuzione del batch continuerebbe.

Account proxy per xp_cmdshell

Se viene chiamata da un utente non membro del ruolo predefinito del server sysadmin, la stored procedure xp_cmdshell si connette a Windows utilizzando il nome di account e la password archiviati nella credenziale denominata ##xp_cmdshell_proxy_account##. Se questa credenziale proxy non esiste, l'esecuzione di xp_cmdshell avrà esito negativo.

È possibile creare la credenziale per l'account proxy eseguendo sp_xp_cmdshell_proxy_account. Questa stored procedure accetta un nome utente e una password di Windows come argomenti. Il comando seguente, ad esempio, crea una credenziale proxy per l'utente di dominio di Windows SHIPPING\KobeR con la password di Windows sdfh%dkc93vcMt0.

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

Per ulteriori informazioni, vedere sp_xp_cmdshell_proxy_account (Transact-SQL).

Autorizzazioni

Poiché gli utenti malintenzionati talvolta tentano di elevare i propri privilegi tramite xp_cmdshell, xp_cmdshell è disabilitato per impostazione predefinita. È possibile abilitarlo utilizzando sp_configure o la gestione basata su criteri. Per ulteriori informazioni, vedere Opzione xp_cmdshell.

Quando viene abilitato per la prima volta, per l'esecuzione di xp_cmdshell è richiesta l'autorizzazione CONTROL SERVER e il processo Windows creato da xp_cmdshell presenta lo stesso contesto di sicurezza dell'account di servizio di SQL Server. L'account di servizio di SQL Server è spesso dotato di un numero di autorizzazioni superiore a quello necessario per il lavoro eseguito dal processo creato da xp_cmdshell. Per migliorare la sicurezza, l'accesso a xp_cmdshell deve essere limitato agli utenti con privilegi elevati.

Per consentire agli utenti non amministratori di utilizzare xp_cmdshell e a SQL Server di creare processi figlio con il token di sicurezza di un account con privilegi più bassi, attenersi alla procedura seguente:

  1. Creare e personalizzare un account utente locale di Windows o un account di dominio con i privilegi minimi richiesti dai processi.

  2. Utilizzare la routine di sistema sp_xp_cmdshell_proxy_account per configurare xp_cmdshell per l'utilizzo di un account con privilegi minimi.

    Nota

    È possibile configurare questo account proxy anche utilizzando SQL Server Management Studio facendo clic con il pulsante destro del mouse su Proprietà sul nome del server in Esplora oggetti e cercando nella scheda Sicurezza la sezione Server proxy account.

  3. In Management Studio, utilizzando il database master, eseguire l'istruzione GRANT exec ON xp_cmdshell TO '<somelogin>' per offrire a specifici utenti non sysadmin la possibilità di eseguire xp_cmdshell. L'accesso specificato deve essere mappato a un utente nel database master.

Gli utenti non amministratori possono ora utilizzare xp_cmdshell per avviare processi del sistema operativo che vengono eseguiti con le autorizzazioni dell'account proxy configurato. Gli utenti che dispongono dell'autorizzazione CONTROL SERVER (membri del ruolo predefinito del server sysadmin ) continueranno a ricevere le autorizzazioni dell'account di servizio di SQL Server per i processi figlio avviati da xp_cmdshell.

Per determinare l'account di Windows utilizzato da xp_cmdshell quando si avviano processi del sistema operativo, eseguire l'istruzione seguente:

xp_cmdshell 'whoami.exe'

Per determinare il contesto di sicurezza per un altro accesso, eseguire gli elementi seguenti:

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

Esempi

A. Restituzione di un elenco di file eseguibili

Nell'esempio seguente viene mostrato l'utilizzo della stored procedure estesa xp_cmdshell per eseguire un comando di directory.

EXEC master..xp_cmdshell 'dir *.exe'

B. Utilizzo dei comandi net di Windows

Nell'esempio seguente viene illustrato l'utilizzo di xp_cmdshell in una stored procedure. In questo esempio viene utilizzato il comando net send per avvisare gli utenti della chiusura imminente di un'istanza SQL Server, il server viene quindi sospeso con il comando net pause e infine il server viene chiuso con il comando 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. Esecuzione di un comando senza restituzione dell'output

Nell'esempio seguente viene mostrato l'utilizzo della stored procedure xp_cmdshell per eseguire una stringa di comandi senza restituire alcun output al client.

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

D. Restituzione del codice di stato

Nell'esempio seguente la stored procedure estesa xp_cmdshell viene impostata per la restituzione di un codice di stato. Il valore di codice restituito viene archiviato nella variabile @result.

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

E. Scrittura del contenuto di una variabile in un file

Nell'esempio seguente il contenuto della variabile @var viene scritto in un file denominato var_out.txt nella directory corrente del server.

DECLARE @cmd sysname, @var sysname
SET @var = 'Hello world'
SET @cmd = 'echo ' + @var + ' > var_out.txt'
EXEC master..xp_cmdshell @cmd

F. Memorizzazione del risultato di un comando in un file

Nell'esempio seguente il contenuto della directory corrente viene scritto nel file dir_out.txt nella directory corrente del server.

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