El procedimiento almacenado xp_cmdshell

El procedimiento almacenado xp_cmdshell es un mecanismo para ejecutar programas o comandos en el sistema operativo desde el código TSQL sin requerir del uso de jobs (trabajos). Este procedimiento Genera un shell de comandos de Windows para ejecutar los comandos batch o programas que se pasan como parámetro.

Si bien no es una buena práctica utilizar procedimiento almacenado xp_cmdshell, es bastante habitual encontrar como administrador de bases de datos SQL Server, aplicaciones que lo usan. A veces, aunque menos frecuentetemente, puede ser necesario acceder a los comandos del sistema operativo para ejecutar algún programa por fuera del SQL Server. En estos casos tenemos que tener mucho cuidado en como permitimos la ejecución del xp_cmdshell, y como le otorgamos permisos para que el usuario pueda acceder a los objetos usados por el programa con los mínimos permisos posibles. En este artículo analizaremos algunos detalles.

Con este procedimiento almacenado extendido podemos ejecutar una aplicación o programa por lotes (batch program). Por lo tanto, no solo se pueden ejecutar programas con extensión EXE sino que también se pueden ejecutar archivos de lotes (BAT o CMD).

Debemos tener sumo cuidado en cómo se utiliza este procedimiento almacenado ya que si el contexto de ejecución de estos comandos tiene permisos de administrador local del equipo el código o programa ejecutado en el shell de Windows puede realizar algunas acciones como administrador del equipo. Por ello es necesario reducir estos permisos al máximo.

Como habilitar la ejecución del xp_cmdshell

En SQL Server el uso de xp_cmdshell está desactivado por defecto (por omisión) como mecanismo de protección para minimizar la superficie de riesgo de seguridad y evitar la ejecución de código no deseado o peligroso fuera del SQL Server. Por ello, ni siquiera los administradores del SQL Server (rol o función de servidor sysadmin) podrán ejecutar el xp_cmdshell si previamente no habilitan la ejecución del mismo.

Permisos para un usuario sysadmin

Si ejecutamos el siguiente SQL como sysadmin vemos que se encuentra deshabilitado

-- Ejecuto el xp_cmdshell

exec xp_cmdshell 'dir c:\*.*'

El resultado es:

Msg 15281, Level 16, State 1, Procedure xp_cmdshell, Line 1 [Batch Start Line 0]
SQL Server blocked access to procedure 'sys.xp_cmdshell' of component 'xp_cmdshell' because this component is turned off as part of the security configuration for this server. A system administrator can enable the use of 'xp_cmdshell' by using sp_configure. For more information about enabling 'xp_cmdshell', search for 'xp_cmdshell' in SQL Server Books Online.

Para poder ejecutar el procedimiento almacenado extendido xp_cmdshell primero debemos habilitarlo haciendo haciendo:



-- Muestro las opciones avanzadas

EXEC sp_configure 'show advanced options', 1
GO
RECONFIGURE
GO

-- Habilito la ejecucion del xp_cmdshell

EXEC sp_configure 'xp_cmdshell', 1
GO
RECONFIGURE
GO

Resultado

Configuration option 'show advanced options' changed from 1 to 1. Run the RECONFIGURE statement to install.
Configuration option 'xp_cmdshell' changed from 0 to 1. Run the RECONFIGURE statement to install.

Si volvemos a ejecutar el scrip TSQL anterior con un usuario con el rol syadmin del SQL Server ahora nos responde sin error y obtenemos la información del directorio raíz del disco C:.

El proceso de Windows creado por xp_cmdshell dispone de los mismos derechos de seguridad que la cuenta de servicio de SQL Server. Esta cuenta ya tenía los permisos adecuados en la raíz del disco para ver el directorio.

Permisos para un usuario no administrador

Vamos a probar ahora con un login que no es administrador y solo tiene permisos mínimos. Para ello creamos un nuevo login.


--Creo el login para prueba sin permisos

CREATE LOGIN [Prueba_xp_cmdshell]
WITH PASSWORD=N'Pass1234',
DEFAULT_DATABASE=[master],
CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
 

Cuando intentamos ejecutar el xp_cmdshell por este usuario que no pertenece al rol sysadmin obtenemos el siguiente error.

Msg 229, Level 14, State 5, Procedure xp_cmdshell, Line 1 [Batch Start Line 0]
The EXECUTE permission was denied on the object 'xp_cmdshell', database 'mssqlsystemresource', schema 'sys'.

Nos indica que no lo podemos ejecutar porque no tenemos permisos. Por lo tanto debemos asignar el permiso de ejecución. En este punto si revisamos la ayuda de SQL Server podemos verificar que nos dice que una de las posibilidades es asignar el permiso CONTROL SERVER para poder ejecutar xp_cmdshell. El permiso CONTROL SERVER no es adecuado para usuarios comunes (que no son administradores) ya que posibilita tomar el control total del SQL Server. Por lo tanto, vamos a usar el otro mecanismo y asignar solo el permiso de ejecución del procedimiento almacenado. Para ello debemos crear el usuario dentro de la base de datos master relacionado con el login y asignar solo el permiso de ejecución del procedimiento almacenado.


--Como syadmin le asigno los permisos para hacer la prueba

USE [master]
 GO
 CREATE USER [Prueba_xp_cmdshell]
 FOR LOGIN [Prueba_xp_cmdshell]
 GO
 

-- Asigno el permiso de ejecucion al usuario
 
GRANT EXECUTE ON [sys].[xp_cmdshell]
 TO [Prueba_xp_cmdshell]
 GO

Luego de asignar el permiso, podemos ejecutar el xp_cmdshell pero todavía obtenemos este error.

Msg 15153, Level 16, State 1, Procedure xp_cmdshell, Line 1 [Batch Start Line 0]
 The xp_cmdshell proxy account information cannot be retrieved or is invalid. Verify that the '##xp_cmdshell_proxy_account##' credential exists and contains valid information.

Este error nos indica que no puede obtener la información de la cuenta proxy. Nos falta un paso más.

Cuenta proxy para el xp_cmdshell

Si el xp_cmdshell es utilizado por un usuario que no es sysadmin del SQL Server, en lugar de usar para ejecutar los comandos las credenciales de la cuenta de servicio del SQL Server, usa las credenciales de la cuenta proxy ##xp_cmdshell_proxy_account##. Esta cuenta proxy contiene el usuario y la contraseña del usuario de Windows con la que el proceso del xp_cmdshell ejecuta los comandos en el sistema operativo.

IMPORTANTE: Solo puede haber una cuenta proxy ##xp_cmdshell_proxy_account## por instancia

Ejemplo para crear la cuenta proxy:


-- Asigno la proxy account

EXEC sp_xp_cmdshell_proxy_account
N'sqltotal\Mariano',
N'Pass12345678'

Si asignamos a la cuenta proxy ##xp_cmdshell_proxy_account## una cuenta con pocos permisos es muy probable que obtengamos el siguiente error:

Msg 15121, Level 16, State 200, Procedure xp_cmdshell, Line 1 [Batch Start Line 0]
 An error occurred during the execution of xp_cmdshell. A call to 'LogonUserW' failed with error code: '1385'.

Este error nos indica que no puede iniciar el Shell de comando de Windows por lo que debemos darle permisos de iniciar secion como proceso por lotes (Log on as a batch job)

En este link hay un artículo de mi blog que explica más detalles y cómo resolver este problema

xp_cmdshell emite CALL TO LOGONUSERW FAILED WITH ERROR CODE 1385

En el siguiente link hay otra solución a problemas durante la creación de la cuenta proxy ##xp_cmdshell_proxy_account## debido a permisos requeridos por la cuenta para poder funcionar.

##xp_cmdshell_proxy_account## No se pudo crear la credencial

Luego de asignar la cuenta proxy como administrador local y sysadmin del SQL Server verificamos que es posible ejecutar el procedimiento almacenado xp_cmdshell sin ser administrador y sin asignar permisos de CONTROL SERVER.

Conclusiones y recomendaciones al usar xp_cmdshell

  • No es recomendable utilizar el procedimiento almacenado xp_cmdshell.
  • Para poder ejecutarlo se requiere habilitar su ejecución en la configuración del SQL Server utilizando el procedimiento almacenado sp_configure.
  • Los administradores pueden ejecutar el procedimiento xp_cmdshell el cual utiliza la cuenta de servicio del SQL Server
  • Los usuarios que no son administradores utilizan la cuenta proxy que debe estar definida.
  • La creación de la cuenta proxy tiene problemas conocidos
  • Si no somos administradores solo debemos tener permiso de ejecución en el procedimiento almacenado xp_cmdshell y no hace falta asignar el permiso CONTROL SERVER o el rol sysadmin.

 

 


Dejá un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *