Introdução

Este artigo apresenta como restringir os acessos de um novo "login" para uma instância do SQL Server, demonstrando que alguns acessos podem ser "negados", aumentando a segurança de seu servidor SQL Server ao reduzir as condições de obtenção de informações em diferentes níveis e objetos.

A utilização destas restrições é apenas uma parte de tudo o que pode ser implementado para a segurança de seus dados, com o intuito de ajudar a compreender como aplicar acessos adequadamente, que é importante para manter dados críticos e/ou sigilosos disponibilizados apenas àqueles que realmente devem ter direito de consultar e manipular.

Hierarquia de Permissões no SQL Server

O SQL Server possui uma coleção de Permissões que são estruturadas de forma hierárquia, de modo que podem refletir acessos em amplos contextos de uma instância SQL até um único objeto criado em um banco de dados.

Estas coleções nós conhecemos como "Protegíveis" e sua estrutura é muito complexa. Para facilitar a compreensão, vamos destacar os Protegíveis: "Server", "Database" e "Schema" (e seus objetos), como indicado no gráfico abaixo:


Caso tenha interesse em aprofundar seu conhecimento dentro destes Protegíveis, então consulte SQL Server Database Engine Permission Posters onde você poderá obter uma estrutura completa, diagramada para as últimas versões do SQL Server.

Nós manipulamos estas coleções de Permissões, utilizando as instruções: GRANT, DENY ou REVOKE. Utilizando o SQL Server 2014 é possível modificar as permissões através da linguagem T-SQL (Transact-SQL) ou então com a IDE SSMS (SQL Server Management Studio).

Criando um novo LOGIN e USER

Planejar o acesso de um ou mais usuários no SQL Server exige uma análise sobre como este acesso poderá ser realizado e quem serão os responsáveis por sua manutenção sempre que houver a necessidade de conceder ou revogar permissões.

O método mais seguro para acessar uma instância SQL é utilizando o método de autenticação Windows Authentication, que é recomendável para a maioria dos Casos de Uso por utilizar o protocolo de segurança Kerberos, fornecendo uma imposição de Políticas de Senha únicas que são relacionados a Validações de Complexidade controladas por seu Domínio

Como nem sempre é possível utilizar somente este método de autenticação, então o SQL Authentication é uma boa alternativa.

O uso desta autenticação é recomendado principalmente para:
  • Aplicações de diferentes Tecnologias(ASP.Net, Windows Forms,...) que dependem de terceiros para implantar ou conceder acessos;
  • Redes que não oferecem autenticação por Domínio;
  • Aplicações Web onde os usuários criam suas próprias identidades;
  • OS "Software de Prateleira", onde um pacote de instalação é criado com todas as configurações e acessos definidos previamente;
  • Aplicações antigas que exigem o acesso por este método de autenticação;

Abaixo é possível ver um script T-SQL para criação de um "login" à uma instância SQL. Para facilitar a manutenção de diversos "logins" que devem possuir um mesmo perfil de acesso, podemos utilizar a função SERVER ROLE que atuará refletindo as permissões para o Protegível "Server".

USE master;
GO

--CRIANDO UM "SERVER ROLE" AUTORIZADO POR "sa"
CREATE SERVER ROLE applications AUTHORIZATION sa;
GO

--CRIANDO UM "LOGIN" PARA ESTA INSTÂNCIA SQL
CREATE LOGIN [durval.ramos] WITH PASSWORD = '!@#456S';
GO

--ADICIONANDO O NOVO LOGIN SQL PARA O "SERVER ROLE" CHAMADO "applications"
ALTER SERVER ROLE applications ADD MEMBER [durval.ramos];
GO



O novo "login" criado com o nome "durval.ramos" foi adicionado como membro do SERVER ROLE "applications", mantendo as configurações padrão do SQL Server, por este motivo o script é mais simples e principalmente seguro (mantendo sua senha forte).

Ao criar o "login" é possível acessar uma instância SQL, mas você poderá ter diferentes restrições de acesso de acordo com as configurações previamente estabelecidas entre os Protegíveis "Server" e "Database".

A imagem abaixo mostra o acesso local a uma instância nomeada do SQL Server, utilizando o método SQL Authentication.




As próximas seções vão demonstrar como fazer este "login" acessar um banco de dados e a seguir, restringir seu acesso a apenas determinadas colunas de uma tabela. Para isso precisamos criar um "user" para este banco de dados, vinculando ao "login".

Abaixo é possível ver na janela "Object Explorer" do SSMS o novo "login" criado e também um banco de dados em destaque, chamado "DBSecurity".




É necessário informar o "login" recém-criado para que seja vinculado no momento que criar o seu "user", não necessariamente eles precisam possuir o mesmo nome, use as denominações para facilitar seu uso (como padrão, o Assistente do SQL Server mantém o mesmo nome). Caso exista mais de um schema neste banco de dados, é recomendado também informar qual será o schema padrão para utilização deste "user".

As propriedades do "login" são complementadas pelas propriedades do "user", ampliando as possibilidades de acesso do usuário que possuir esta conta do SQL Authentication.

Com a mesma finalidade da função SERVER ROLE, também criamos o DATABASE ROLE para facilitar a manipulação de acessos e restrições dentro dos Protegíveis "Database", onde adicionamos o "user" durval.ramos.

A primeira restrição aplicada a este DATABASE ROLE chamado de "db_app" é relacionada à um "user" ou outra função que é vinculada como proprietária desta nova função. Neste caso, aplicamos como proprietário o user "dbo" e desta forma, seus acessos e restrições passam a ser herdadas para "db_app", agora ampliar ou reduzir estes acessos podem ser realizados diretamente neste DATABASE ROLE.

  Aseguir, adicionamos nosso DATABASE ROLE "db_app" como membro de outras funções padrões do SQL Server: "db_datareader" e "db_datawriter", o que vai permitir que nosso "user" durval.ramos possa consultar e manipular (INSERT, UPDATE, DELETE) todos os dados de User Databases que possuir permissão de acesso.

O script abaixo cria e permite estes acessos:


USE DBSecurity;
GO

--CRIANDO UM "USER" E VINCULANDO AO "LOGIN" (COM MESMO NOME)
CREATE USER [durval.ramos] FOR LOGIN [durval.ramos] WITH DEFAULT_SCHEMA=dbo;
GO

--CRIANDO UM "DATABASE ROLE" AUTORIZADO POR "dbo" CHAMADO "db_app"
CREATE ROLE db_app AUTHORIZATION dbo;
GO

--ADICIONANDO O "USER" COMO MEMBRO DO DATABASE ROLE "db_app"
ALTER ROLE db_app ADD MEMBER [durval.ramos];
GO

--ADICIONANDO O DATABASE ROLE "db_app" COMO MEMBRO
--DOS DATABASE ROLE "db_datareader" E "db_datawriter"
ALTER ROLE db_datareader   ADD MEMBER db_app;
GO

ALTER ROLE db_datawriter   ADD MEMBER db_app;
GO



Na imagem abaixo podemos ver no SSMS que o "login" e o "user" estão disponíveis no escopo dos Protegíveis "Server" e "Database":





Restringindo Acesso para sua Instância SQL

Você poderá acessar e manipular todos os objetos disponíveis na Instância do SQL Server acessando através do SSMS e por outro provedor de acesso, por exemplo utilizando uma linguagem de programação como C# ou VB.Net.

Inicialmente é necessário levantar os requisitos necessários para o que cada "login" realmente necessita manipular nesta instância SQL, assim você poderá conceder apenas as permissões adequadas para que seja possível atender a demanda de uso.

Abaixo temos um script para conceder alguns acessos de manipulação aos Protegíveis no nível "Server". Também podemos ver na sequência deste script que alguns foram explícitamente "negados" para evitar que uma função proprietária possa conceder acessos a recursos que não pretendemos disponibilizar a um ou mais usuários que utilizarem este "login".


USE master
GO

--CONCEDENDO PERMISSÕES PARA ESTA INSTANCIA AO LOGIN "durval.ramos"
GRANT
       ALTER ANY DATABASE,
       VIEW  ANY DATABASE,
       VIEW  ANY DEFINITION,
       CONNECT ANY DATABASE,
       AUTHENTICATE SERVER,
       VIEW SERVER STATE,
       SELECT ALL USER SECURABLES
TO [durval.ramos];
GO

--RESTRINGINDO PERMISSÕES PARA ESTA INSTANCIA AO LOGIN "durval.ramos"
DENY
       ADMINISTER BULK OPERATIONS,
       ALTER ANY LINKED SERVER,
       ALTER ANY LOGIN,
       CREATE ANY DATABASE,
       CREATE SERVER ROLE
TO [durval.ramos];
GO



Dependendo das suas necessidades de uso e da manutenção utilizada para seus dados é recomendável que o "login" utilizado por suas aplicações seja diferente (e com mais restrições) do que o "login" disponibilizado para outras equipes de desenvolvedores tenham que utilizar esta mesma instância SQL.

Uma restrição útil para evitar tentativas de acesso não permitidas é inibindo a visualização dos "User Databases" vinculados à sua instância SQL. Veja na imagem abaixo a visão do "login" durval.ramos no SSMS:



Este "login" pode ver todos os bancos de dados de sistema e de usuários, incentivando pessoas não autorizadas à fazer "tentativas" de acesso não autorizadas. A mesma permissão garante que este "login" possa fazer uma consulta simples no banco de dados "master", consultando todos os bancos de dados vinculados à esta instância SQL, com suas configurações e seus status. Veja na imagem abaixo:



Se este "login" for disponibilizado para uso de uma aplicação, sua vulnerabilidade poderá aumentar ainda mais se não for restringido este acesso.  Para isso, basta executar o script:

USE master
GO

DENY VIEW ANY DATABASE
TO [durval.ramos]
GO



Após executar o script podemos executar a mesma consulta e teremos disponível para visualização apenas os bancos de dados de sistema: "master" e "tempdb", como indicado na imagem abaixo:



Essa simples restrição também reflete imediatamente no SSMS, ocultando os demais bancos de dados. O acesso continua disponível, desde que este usuário utilize a instrução "USE <NomeDoBanco>".



Para evitar o uso de pessoas não autorizadas visualizando seus objetos, e posteriormente procurando alternativas para manipular o conteúdo dentro de sua instância SQL, é fundamental ocultar seus objetos e suas estruturas.

Você poderá ver que alguns DMV's podem fornecer também informações sobre o sistema operacional e as condições de uso de seu hardware, então é importante também restringir o acesso para quem não tem necessidade de obter estes dados.

Veja na imagem abaixo a consulta de alguns contadores de desempenhos obtidas através de dm_os_performance_counters:



É possível efetuar uma restrição simples para evitar a disponibilização destes dados para este "user":

USE master
GO

DENY
       VIEW ANY DEFINITION,
       VIEW SERVER STATE
TO [durval.ramos]
GO



Após aplicar este restrição ao Protegível "Server", é disparado a mensagem de erro abaixo:




Restringindo Acesso para Bancos de Dados

Você poderá acessar e manipular todos os objetos disponíveis em seu banco de dados SQL Server, acessando através do SSMS ou de um provedor de dados que habilite uma conexão com sua instância SQL.

Definir explicitamente os acessos de seu "user" e suas principalmente suas restrições para cada banco de dados é algo fundamental para evitar perda de dados e/ou expor informações sigilosas.


USE DBSecurity;
GO

GRANT
       ALTER,
       ALTER ANY ASSEMBLY,
       AUTHENTICATE,
       CONNECT,
       CREATE AGGREGATE,
       CREATE ASSEMBLY,
       CREATE DEFAULT,
       CREATE FUNCTION,
       CREATE PROCEDURE,
       CREATE SYNONYM,
       CREATE TABLE,
       CREATE VIEW,
       DELETE,
       EXECUTE,
       INSERT,
       REFERENCES,
       SELECT,
       SHOWPLAN,
       UPDATE,
       VIEW DATABASE STATE,
       VIEW DEFINITION
TO [durval.ramos];
GO

DENY
       ALTER ANY APPLICATION ROLE,
       ALTER ANY ASYMMETRIC KEY,
       ALTER ANY CERTIFICATE,
       ALTER ANY DATABASE DDL TRIGGER,
       ALTER ANY ROLE,
       ALTER ANY SCHEMA,
       ALTER ANY SYMMETRIC KEY,
       ALTER ANY USER,
       CHECKPOINT,
       CREATE ASYMMETRIC KEY,
       CREATE CERTIFICATE,
       CREATE CONTRACT,
       CREATE ROLE,
       CREATE SYMMETRIC KEY
TO [durval.ramos];
GO



Evitar que usuários utilizem um "user" com acesso à definições de objetos de seu banco de dados, como: views, procedures, functions ou tabelas; pode possibilitar que um usuário não autorizado modifique a estrutura, o funcionamento e o comportamento de scripts. Uma vulnerabilidade que você poderá inibir também criando um "user" específico para o uso de suas aplicações e com restrições de alteração e visualização apenas no que for necessário.

Abaixo podemos um exemplo de script que exibe a estrutura da tabela "TB_PESSOA":



Para restringir esta permissão de visualização é possível executar o script para modificar o Protegível "Database":


USE DBSecurity
GO

DENY
       VIEW DATABASE STATE,
       VIEW DEFINITION
TO [db_app] AS [dbo]
GO


Quando executamos novamente o script é disparado o erro de acesso como indicado na imagem abaixo:




Neste script, todos os "users" que fazem parte do DATABASE ROLE "db_app" passarão a ter a mesma restrição.


Restringindo Acesso para Objetos (Tabelas)

Você poderá acessar todas as informações disponíveis em uma ou mais tabelas de sua Instância do SQL Server, mas mesmo em um nível tão baixo é possível restringir dados para "users" que não necessitam visualizar todas suas informações armazenadas.

Um recurso para "escapar" destas restrições é o EXECUTE AS, que ao ser executado alterna para o "login" indicado possibilitando utilizar todas as permissões que este "login" e este "user" possuírem no SQL Server.

Veja na imagem abaixo um outro "login" executando a consulta na tabela "TB_PESSOA" com as permissões do "login" durval.ramos:



O script abaixo restringe este acesso para o "login" durval.ramos:


USE master;
GO

DENY IMPERSONATE ANY LOGIN TO [durval.ramos];
GO



Quando aplicamos a restrição para o "login" durval.ramos, nenhum outro "login" poderá executar scripts com suas permissões, inclusive o login "sa". Veja na imagem abaixo:



O ideal é que seja disponibilizadas views específicas para a consulta de dados por usuários que devem apenas realizar consultas pontuais, mas em alguns casos a necessidade de uma demanda exige que seja disponibilizado também o acesso para manipular os dados diretamente em sua tabela.

Você poderá restringir estes acessos para que este "user" tenha acesso apenas às colunas que ele precisa consultar/atualizar. Neste caso, primeiro "negamos" o acesso para consulta na tabela para o DATABASE ROLE "db_app" e logo a seguir é concedido o acesso apenas para às colunas necessárias para atender às suas consultas.

Veja na imagem abaixo:



Assim que é executado o script, o SQL Server dispara o erro para cada coluna que este usuário não possui acesso.

Para que a consulta seja realizada com sucesso, basta especificar as colunas que este "user" pode acessar. Veja na imagem abaixo:





Conclusão

Para manter sua instância SQL e seu claro, seu servidor longe de ataques e acessos indevidos, é necessário estabelecer diversos recursos de segurança.

O acesso aos Protegíveis do SQL Server são um dos meios importantes para evitar estes transtornos. Certamente a utilização destas permissões de acesso são fundamentais para qualquer servidor que esteja exposto a acessos de muitos usuários, principalmente caso esta exposição seja externa, através de aplicações Web.

Lembrando que esta implementação de Protegíveis é apenas um dos fatores que podem garantir a segurança de seu servidor SQL Server e de seus dados.

Referências

Veja Também