Firmar un Procedimiento Almacenado, no sólo nos permitirá poder comprobar en un futuro sí ha sido alterado o no, sino que además, nos permitirá poder utilizar SQL Dinámico dentro de nuestros Procedimientos Almacenados sin necesidad de conceder permisos sobre las tablas a los usuarios, lo que nos dará un puntito adicional de seguridad, especialmente ante ataques de SQL Injection.
Es fácil de comprender, que una vez que hemos firmado un Procedimiento Almacenado (utilizando ADD SIGNATURE), podremos ver su firma (consultado sys.certificates y sys.crypt_properties). Por lo tanto, podremos tomar nota de ella, y si pasado un tiempo, comprobamos que la firma ha cambiado, probablemente será que el Procedimiento Almacenado también lo ha hecho. Es decir, la utilización de las firmas digitales en este sentido, proporciona un procedimiento sencillo de comprobar rápidamente si nuestro código ha sido modificado, algo especialmente útil para fabricantes de software, para controlas si sus clientes han alterado el código de base de datos.
Sin embargo, quizás la verdadera utilidad es otra, que voy a intentar explicar a continuación.
Uno de los conceptos básicos de seguridad en SQL Server son las Cadenas de Propiedad (Ownership Chains), lo cual quiere decir, que si un usuario tiene permisos de ejecución de un Procedimiento Almacenado, no es necesario que también tenga permisos sobre las tablas a las que accede dicho procedimiento, siempre y cuando tanto el Procedimiento Almacenado como las tablas pertenezcan al mismo Esquema. En consecuencia, cuando un usuario intenta ejecutar un Procedimiento Almacenado, SQL Server comprueba si tiene o no permisos. Sin embargo, si dicho Procedimiento Almacenado necesita acceder a una tabla que pertenece al mismo esquema que el procedimiento, SQL Server omitirá la comprobación de seguridad, es decir, el usuario ejecutará con éxito el procedimiento sin tener permisos sobre las tablas subyacentes. Sin embargo, este comportamiento no se cumple para el código SQL Dinámico que se ejecute dentro de un Procedimiento Almacenado, en cuyo caso, si dicho SQL Dinámico accede a una tabla, el usuario necesitará permisos tanto para ejecutar el procedimiento como para acceder a esa tabla.
En la siguiente pantalla capturada, vemos un caso de ejemplo, en el que un usuario intenta ejecutar dos Procedimientos Almacenados. El usuario sólo tiene permisos de ejecución sobre dichos procedimientos. Ambos procedimientos son similares, pero el primero utiliza SQL Dinámico. Como podemos ver, la ejecución es fallida, al no tener permisos sobre la tabla subyacente.
Este escenario resulta algo comprometido, ya que si por algún motivo tenemos Procedimientos Almacenados que utilizan SQL Dinámico, nos veremos obligados a conceder permisos directos sobre las tablas (u otros objetos subyacentes), lo cual es un punto en contra de la seguridad de nuestra base de datos. Pero además, el propio hecho de utilizar SQL Dinámico nos está exponiendo a SQL Injection. Así que, este escenario no mola nada. Y es aquí, donde la Firma Digital de Procedimientos Almacenados viene en nuestra ayuda. Me explico. Lo que podemos hacer es lo siguiente:
- Crear un Certificado en nuestra Base de Datos (CREATE CERTIFICATE).
- Crear un Usuario desde el Certificado en nuestra Base de Datos (CREATE USER FROM CERTIFICATE).
- Concedemos permisos sobre las tablas (u otros objetos subyacentes) al Usuario creado desde el Certificado.
- Firmamos Digitalmente el Procedimiento Almacenado con el Certificado creado anteriormente (ADD SIGNATURE BY CERTIFICATE).
Sería algo como lo siguiente, tan sólo unas pocas líneas de código.
De este modo, ahora un usuario que sólo tenga permisos de ejecución sobre el Procedimiento Almacenado, podrá ejecutarlo sin problemas y sin necesidad de tener concedidos permisos adicionales.
No podía faltar un poco de código TSQL, para quien desee descargárselo y probarlo por sí mismo, sirviendo también a modo de ejemplo.
Por último, aprovecho para añadir algunos enlaces de interés sobre este tema, para quien desee profundizar algo más:
Poco más por hoy. Como siempre, confío que la lectura resulte de interés.