Denegar el acceso al esquema de información en SQL Server

13

Estoy buscando la mejor manera de deshabilitar el acceso al sys.tables/ Information Schemapara un usuario / grupo en SQL Server.

Encontré este hilo de 2008

Muestra una forma de denegar el acceso de esta [sys].[something]manera:

 DENY SELECT ON [sys].[columns] TO DenySystemTableSelectRole
 GO
 DENY SELECT ON [sys].[tables] TO DenySystemTableSelectRole
 GO
 DENY SELECT ON [sys].[syscolumns] TO DenySystemTableSelectRole
 GO
 DENY SELECT ON [sys].[sysobjects] TO DenySystemTableSelectRole
 GO

Pero no hay forma de cómo deshabilitar el acceso en Information Schema:

DENY SELECT ON INFORMATION_SCHEMA.TABLES To DenySystemTableSelectRole

Esto parece no funcionar.

¿Cómo puedo deshabilitar el acceso a información_esquema?

¿Y hay una manera más fácil de deshabilitar el acceso a todos sys/ information_schema?

Actualización: en realidad no puedo ejecutar las dos siguientes afirmaciones:

DENY SELECT ON [sys] TO reducedDBO
GO
DENY SELECT ON INFORMATION_SCHEMA To reducedDBO
GO

Traté de ejecutarlos en la base de datos específica donde existe el usuario, y también probé en el "maestro".

Todavía puedo correr:

 SELECT * from
 INFORMATION_SCHEMA.TABLES 

-> todavía devuelve resultados

 SELECT * from
 sys.TABLES 

-> ya no hay resultados

La inclusión SCHEMA::en la consulta hizo posible crear los asegurables

DENY SELECT ON SCHEMA::[sys] TO reducedDBO
GO
DENY SELECT ON SCHEMA::INFORMATION_SCHEMA To reducedDBO
GO

Pero ahora todavía puedo seleccionar toda la información de la base de datos.

Eché un vistazo a la pestaña "Securables" en la ventana de propiedades de los usuarios en Management Studio 2008, se ve así:

Entrada que bloquea la selección de sys.tables

Esquema: sys, Nombre: tablas, Tipo: Vista

Permisos para sys.tables: Permiso: Seleccionar, Concedente: dbo, Denegar está marcado

Entrada que no bloquea ninguna selección

Esquema :, Nombre: INFORMATION_SCHEMA, Tipo: Esquema

Permisos para INFORMATION_SCHEMA: Permiso: Seleccionar, Concedente: dbo, Denegar NO está marcado (Traté de verificarlo, pero no hay posibilidad ...)

Permiso: Seleccionar, Concedente: INFORMATION_SCHEMA, Denegar está marcado


Intenté establecer los permisos a través de la GUI, pero luego recibí el mismo error de que establecer permisos solo sería posible en la base de datos maestra. Pero no tengo el usuario / inicio de sesión agregado a la seguridad de las bases de datos maestras.

Solución:

La única forma en que podía hacer el denytrabajo para el information_schemaera agregar el usuario al master-db y ejecutar el deny selecten el maestro:

DENY SELECT ON [sys].[tables] TO reducedDBO
GO
DENY SELECT ON INFORMATION_SCHEMA.TABLES To reducedDBO
GO

Y como en este código, solo se puede ejecutar para tablas individuales.

SwissCoder
fuente
1
También revise esta pregunta de dba.se y su respuesta por Remus Rusanu - más o menos cubre el mismo tema
marc_s
si gracias. En realidad, la diferencia entre negar las [information_schema] -views y las [sys] -views es que la [information_schema] debe deshabilitarse en el maestro (y afectará a todos los DB) mientras que la vista [sys] debe deshabilitarse en cada db en sí mismo, e incluso si está deshabilitado en el maestro, el usuario aún podrá seleccionar desde la vista, si no está deshabilitado también en el db actual.
SwissCoder

Respuestas:

10

Debería poder denegar los permisos en todo el esquema sysy information_schemaen su conjunto:

DENY SELECT On SCHEMA::sys To [user_name]
DENY SELECT On SCHEMA::INFORMATION_SCHEMA To [user_name]

Básicamente, eso debería evitar que ese usuario realice selecciones en esos dos esquemas.

marc_s
fuente
marcado como respuesta, pero el problema es que SCHEMA :: no ayudó, mejor quítelo nuevamente. La solución es agregar al usuario a la base de datos maestra y luego ejecutar el script de denegación en el maestro. ¡Gracias por tu ayuda!
SwissCoder
Ah, y en realidad tampoco es posible deshabilitar todo el SCHEMA, solo el acceso a tablas individuales se puede deshabilitar de esta manera.
SwissCoder
5

En primer lugar, tiene razón en que la forma (ligeramente contraintuitiva) de evitar el acceso a los esquemas [sys] y [INFORMATION_SCHEMA] es primero asegurarse de que el inicio de sesión (bueno, principal a nivel de servidor) exista como usuario (erm, principal de nivel de base de datos) en la base de datos maestra.

Suponga que tiene un inicio de sesión SQL para simplificar:

CREATE LOGIN [testy] WITH PASSWORD=N'SCoBIqlJELGzrY9zYsKWC5z3kHtMsyCAP6yBHLUYQ0w='
go

Ahora cree un usuario correspondiente en la base de datos maestra:

use [master]
go
CREATE USER [testy] FOR LOGIN [testy]
go

Ahora desea evitar que este inicio de sesión acceda a cualquiera de las tablas en los esquemas proporcionados por el sistema: [sys] y [INFORMATION_SCHEMA].

Parece que hubo un cambio de comportamiento entre SQL Server 2008 R2 y SQL Server 2012:

En SQL Server 2012 (y presumiblemente versiones posteriores), ejecutar lo siguiente en la base de datos [maestra] hace lo que cabría esperar:

DENY SELECT, VIEW DEFINITION ON SCHEMA::[sys] to [testy];
GO
DENY SELECT, VIEW DEFINITION ON SCHEMA::[INFORMATION_SCHEMA] to [testy];
GO

Sin embargo, en SQL Server 2008 R2 (y presumiblemente versiones anteriores), las declaraciones de concesión de acciones que dan acceso a los objetos en estos esquemas a miembros de [public] parecen anular las declaraciones DENY anteriores, lo que me parece un gran montón de fallas. Por lo tanto, en 2008 R2 necesita NEGAR explícitamente para cada CONCESIÓN a [público]. Aquí hay un script para hacer eso:

declare
    @database_principal sysname,
    @cur cursor,
    @sql nvarchar( 4000 );

set @database_principal = 'testy';

set @cur = cursor local forward_only static for
    select 
        'DENY ' +
        permission_name + ' on ' +
        case class 
            when 1 then
                case minor_id
                    when 0 then 'OBJECT'
                    else 'COLUMN'
                end
            else
                class_desc
        end + '::' +
        case class
            when 0 then db_name()
            when 1 then quotename( OBJECT_SCHEMA_NAME(major_id) ) + '.' + quotename( object_name( major_id ) ) + case minor_id when 0 then '' else ( select '.' + quotename( name ) collate database_default from sys.columns where column_id=minor_id) end
            when 3 then schema_name( major_id )
        end + ' to ' +
        quotename( @database_principal )
    from
        sys.database_permissions
    where
        [grantee_principal_id] = 0 -- public
        and
        [state_desc] = 'GRANT'
        and
        [permission_name] = 'SELECT'
;

open @cur;

while
    1 = 1
begin
    fetch @cur into @sql;
    if @@fetch_status <> 0 break;

    print @sql;
    exec sys.sp_executesql @sql;
end;

close @cur;

deallocate @cur;

Ejecute lo anterior en la base de datos maestra y habrá eliminado el acceso al contenido de esos esquemas.

Notas:

  1. Debido a que estas son declaraciones DENY explícitas, son correctas en el momento en que se ejecuta el script. Si posteriormente alguien modifica los permisos otorgados al público (por ejemplo, un paquete de servicio crea una nueva tabla del sistema), eso quedará expuesto al usuario denegado.
  2. Es una buena idea utilizar un rol de base de datos como objetivo de las declaraciones DENY y colocar a los usuarios denegados en ese rol.
  3. Puede deshacer esto cambiando el DENY a un REVOKE
  4. Si comenta las siguientes dos líneas en el script anterior:

        and
        [permission_name] = 'SELECT'

    Tendrá el efecto de deshacer TODAS las CONCESIONES predeterminadas para público. Esto impedirá el acceso a, por ejemplo, sys.sp_tables y, por lo tanto, interrumpirá, por ejemplo, la capacidad de Microsoft Access de enumerar las tablas, pero es útil en escenarios de alta seguridad para hacer esto, de modo que los usuarios obtengan acceso solo donde se haya otorgado explícitamente eso.

Alasdair CS
fuente
3

No estoy seguro de cuándo estuvo disponible este truco, ya que nadie lo ha mencionado, pero parece que funciona al menos desde SQL Server 2008.

DENY VIEW DEFINITION to [database-role / database-user];

Lo anterior funciona sin tener que agregar al usuario a la masterbase de datos como se menciona en algunas de las otras respuestas.

Jesse
fuente
Excelente respuesta! Por technet.microsoft.com/en-us/library/ms175808(v=sql.105).aspx "niega el acceso a metadatos basado en permisos para el concesionario en la base de datos especificada"
Chris Anton