xp_cmdshell (Transact-SQL)

Crea un shell de comandos de Windows y lo pasa a una cadena para ejecutarlo. Los resultados se devuelven como filas de texto.

Icono de vínculo a temasConvenciones de sintaxis de Transact-SQL

Sintaxis

xp_cmdshell { 'command_string' } [ , no_output ]

Argumentos

  • 'command_string'
    Es la cadena que contiene un comando que se pasa al sistema operativo. El parámetro command_string es de tipo varchar(8000) o nvarchar(4000) y no tiene valor predeterminado. El parámetro command_string no puede contener más de un conjunto de comillas dobles. Es necesario un único par de comillas dobles si hay espacios en las rutas de acceso a archivos o en los nombres de programa a los que hace referencia command_string. Si tiene problemas con espacios incrustados, considere el uso de nombres de archivo de tipo FAT 8.3 como solución.

  • no_output
    Es un parámetro opcional que especifica que no se devuelven resultados al cliente.

Valores de código de retorno

0 (correcto) o 1 (error)

Conjuntos de resultados

La ejecución de la instrucción xp_cmdshell devuelve una lista de directorios del directorio actual.

EXEC xp_cmdshell 'dir *.exe';
GO

Las filas se devuelven en una columna de tipo nvarchar(255). Si se utiliza la opción no_output, solo se devolverá lo siguiente:

The command(s) completed successfully.

Comentarios

El proceso de Windows creado por xp_cmdshell dispone de los mismos derechos de seguridad que la cuenta de servicio de SQL Server.

xp_cmdshell opera de forma sincrónica. No se devolverá el control al llamador hasta que el comando del shell de comandos esté completo.

Es posible habilitar y deshabilitar xp_cmdshell con Administración basada en directiva o ejecutando sp_configure. Para obtener más información, vea Descripción de la configuración del área expuesta y xp_cmdshell (opción).

Nota importanteImportante

Si se ejecuta xp_cmdshell en un lote y devuelve un error, se producirán errores en el lote. Es un cambio de comportamiento. En versiones anteriores de Microsoft SQL Server, el lote continuaría su ejecución.

Cuenta de proxy xp_cmdshell

Cuando es llamada por un usuario que no pertenece al rol fijo de servidor sysadmin, xp_cmdshell se conecta a Windows con el nombre de cuenta y la contraseña almacenados en la credencial con el nombre ##xp_cmdshell_proxy_account##. Si no existe esta credencial de proxy, xp_cmdshell registrará errores.

Para crear la credencial de cuenta de proxy, debe ejecutar sp_xp_cmdshell_proxy_account. Como argumentos, este procedimiento almacenado utiliza un nombre de usuario y una contraseña de Windows. Por ejemplo, el siguiente comando crea una credencial de proxy para el usuario de dominio de Windows SHIPPING\KobeR que tiene la contraseña de Windows sdfh%dkc93vcMt0.

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

Para obtener más información, vea sp_xp_cmdshell_proxy_account (Transact-SQL).

Permisos

Dado que, a veces, usuarios malintencionados intentan elevar sus privilegios utilizando xp_cmdshell, xp_cmdshell está deshabilitado de forma predeterminada. Utilice sp_configure o la administración basada en directivas para habilitarlo. Para obtener más información, vea xp_cmdshell (opción).

Cuando se habilita por primera vez, xp_cmdshell requiere el permiso CONTROL SERVER para la ejecución y el proceso de Windows creado por xp_cmdshell tiene el mismo contexto de seguridad que la cuenta de servicio de SQL Server. La cuenta de servicio de SQL Server a menudo tiene más permisos de los necesarios para el trabajo que realiza el proceso creado por xp_cmdshell. Para mejorar la seguridad, el acceso a xp_cmdshell debería estar restringido a usuarios con permisos elevados.

Para permitir a los usuarios que no son administradores utilizar xp_cmdshell y permitir que SQL Server cree procesos secundarios con el token de seguridad de una cuenta con menos permisos, siga estos pasos:

  1. Cree y personalice una cuenta de usuario local de Windows o una cuenta de dominio con los permisos mínimos que los procesos requieran.

  2. Utilice el procedimiento de sistema sp_xp_cmdshell_proxy_account para configurar xp_cmdshell de modo que use esa cuenta con permisos mínimos.

    Nota

    También puede configurar esta cuenta de proxy utilizando SQL Server Management Studio haciendo clic con el botón secundario en Propiedades en su nombre del servidor en el Explorador de objetos y buscando en la pestaña Seguridad la sección Cuenta de proxy del servidor.

  3. En Management Studio, con la base de datos maestra, ejecute la instrucción GRANT exec ON xp_cmdshell TO '<somelogin>' para dar a usuarios concretos que no sean sysadmin la capacidad de ejecutar xp_cmdshell. El inicio de sesión especificado debe asignarse a un usuario en la base de datos maestra.

Ahora los usuarios que no son administradores pueden iniciar los procesos del sistema operativo con xp_cmdshell y esos procesos se ejecutan con los permisos de la cuenta de proxy que haya configurado. Los usuarios con el permiso CONTROL SERVER (miembros del rol fijo de servidor sysadmin) seguirán recibiendo los permisos de la cuenta de servicio de SQL Server para los procesos secundarios que inicia xp_cmdshell.

Para determinar la cuenta de Windows que va a usar xp_cmdshell al iniciar los procesos del sistema operativo, ejecute la siguiente instrucción:

xp_cmdshell 'whoami.exe'

Para determinar el contexto de seguridad de otro inicio de sesión, ejecute lo siguiente:

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

Ejemplos

A. Devolver una lista de archivos ejecutables

En el siguiente ejemplo se muestra el procedimiento almacenado extendido xp_cmdshell ejecutando un comando de directorio.

EXEC master..xp_cmdshell 'dir *.exe'

B. Usar comandos de red de Windows

En el siguiente ejemplo se muestra el uso de xp_cmdshell en un procedimiento almacenado. En este ejemplo se notifica a los usuarios mediante net send que una instancia de SQL Server va a cerrarse, pausa el servidor mediante net pause y lo cierra con 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. No devolver resultados

En el siguiente ejemplo se utiliza xp_cmdshell para ejecutar una cadena de comandos sin devolver los resultados al cliente.

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

D. Utilizar el estado de retorno

En el siguiente ejemplo, el procedimiento almacenado extendido xp_cmdshell también sugiere el estado de retorno. El valor del código de retorno se almacena en la variable @result.

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

E. Escribir el contenido de variables en un archivo

En el siguiente ejemplo se escribe el contenido de la variable @var en un archivo denominado var_out.txt en el directorio actual del servidor.

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

F. Capturar el resultado de un comando en un archivo

En el siguiente ejemplo se escribe el contenido del directorio actual en un archivo denominado dir_out.txt en el directorio actual del servidor.

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