Menor privilégio possível. Mas nem sempre.

Deixar o usuário ver apenas o que lhe interessa e nada mais

Boa noite =)
Hoje um amigo tinha uma dúvida, que também já tive, sobre visualizações de bases desnecessárias. Achei um bom assunto pra postar, pois gosto da temática segurança e apesar de parecer óbvio, nem sempre o SQL Server oferece um dos seus princípios básicos, o princípio do menor privilégio. Vamos conversar sobre isso?

Bem, nada melhor do que um case pra passar a ideia…

1 – A demanda

Você é o DBA de uma única instância SQL Server chamada NINJACORP.
Existem várias bases confidenciais em tal instância, e você é um DBA vigilante por default, pra combinar com o ambiente. Preza muito pela segurança. E essa é sua filosofia de vida.

Segue a lei da segurança máxima e menor privilégio como se fosse uma rígida religião.

Em um belo dia, com sol brilhando, umidade do ar agradável e pássaros cantando no céu, chega uma demanda pra inclusão de login de um desenvolvedor em produção. Seu coração pulsa de forma desequilibrada quando lê que, por A mais B, será necessário criar um sql login.

O chamado em resumo:

“Solicito a inclusão de login sql chamado servidorPublico, senha p@ssw0rd134#@3_2 e que tenha acesso de leitura ao banco DbInformacoesSagradas”

O DBA, relutante, faz a criação do sql login (e queria mesmo usar o Windows Authentication, mas não teve jeito) e do usuário sem maiores problemas.

–> Cria login do sujeito

CREATE LOGIN servidorPublico WITH PASSWORD = ‘p@ssw0rd134#@3_2’ , CHECK_POLICY = OFF

–> Cria usuário para a base

USE [DbInformacoesSagradas]
GO
CREATE USER usrServidorPublico FOR LOGIN [servidorPublico] WITH DEFAULT_SCHEMA = dbo

–> Adiciona o usuário para permissão de leitura (Role datareader)

EXEC sp_addrolemember ‘db_datareader’,’usrServidorPublico’

Passada a dor… Tá na hora do teste..

2 – A descoberta

Até que você, DBA terminou a tarefa e concluiu a demanda. Mas… curioso,pela primeira vez na vida, pois foi um DBA que sempre trabalhou com Windows Authentication (eu sei, muito difícil, mas vamos imaginar!), resolveu logar com o login recém criado, o ServidorPublico.

isNotAccessible

Olha só! Apesar do usuário ter apenas uma base como leitura, ele consegue visualizar os demais bancos. Vale ressaltar: ele consegue visualizar os bancos mas não possui acesso aos mesmos, sendo que uma expansão de qualquer banco resulta em erro (vide imagem acima).

Você precisa garantir de qualquer modo que o login consiga visualizar apenas o banco de dados que possui algum vínculo. Você quer manter o nome das bases em segredo. Quer seguir sua segurança instintiva. Mas como fazer? Bem, pausa pro café e vamos falar agora sobre a ponta do iceberg.

3 – Mínimo privilégio mas nem sempre

O que é mínimo privilégio possível? Bem, em suma, é oferecer o mínimo de permissão possível para que determinada conta/usuário consiga realizar, sem maiores problemas, sua atividade fim.

Você, pra matar uma barata, precisa de um chinelo ou de um fuzil?

Isso deveria ser sagrado em nosso trabalho, e não é só na área de Administração de Banco de Dados, mas em toda a nossa vida, em suas devidas proporções e sem radicalismos.  Tenho uma vontade enorme de falar sobre esse princípio e do “Security by default”, mas vamos nos limitar à definição dada acima pra não esfriar o pão de queijo (no caso, o código).

O SQL Server no geral segue tal princípio na parte de segurança, mas, curiosamente, no caso de visualizar bases de dados desnecessariamente, parece não ser uma preocupação tão crítica, observado que  isso já foi motivo de reclamação (antiga, inclusive) no Microsoft Connect e os caras não ligaram tanto assim.

Seguindo este mesmo princípio ainda, e lembrando do exemplo da barata:

Se o usuário deve ter disponível apenas o que é necessário, qual seria a razão de enxergar qualquer base que não tenha relação com ele?

Parando pra pensar, nenhuma.

Aqui existe uma óbvia contradição no princípio de mínimo privilégio. Pra quê visualizar bases que não são necessárias? Pode parecer bobo, mas isso abre brechas diversas que enfraquecem a segurança. Uma delas, é que, pra um desenvolvedor, realmente interessa saber que naquela instância existe um banco do RH? Bem, não vou entrar no campo ético da coisa, mas já imagina-se as possíveis situações em que algo aparentemente bobo pode se tornar… Basta um pouco de engenharia social, criatividade e um pouco de atitude…

Existe uma forma  de contornar essa situação de ocultar a visualização das bases (que deveria ser default, na minha opinião, segundo motivos já explicados do menor privilégio). Não resolve 100%, mas quase. Infelizmente, a solução a seguir oculta todas as bases, inclusive as que se tem algum vínculo.

4 – A forma mais aproximada de se resolver o problema

Existe uma permissão à nível de servidor chamada VIEW ANY DATABASE, que possibilita o usuário ver metadados relacionados aos bancos de dados, o que inclui suas visualizações na:

a) sys.databases

b) sys.sysdatabases

c) sp_helpdb

E afeta também o modo visual do Management Studio (ssms), o que é extremamente importante.

Em suma: mesmo o usuário servidorPublico tendo acesso a um só banco, ele consegue, utilizando esses três itens mencionados acima, enxergar alguns metadados de outros bancos.

O legal dessa história é que essa permissão VIEW ANY DATABASE é automaticamente concedida ao Public, ou seja, todo usuário ou conta que se conecta no SQL Server automaticamente ganha as permissões adquiridas desta role. Tecnicamente, isso equivale a dizer que, a menos que você negue tal permissão pro public, todas as contas/usuários do banco podem enxergar metadados que não são de seu interesse (acredita-se) por padrão.

Mas como contornar o problema?

Sabendo que todo login (inclusive o que acabamos de criar) pertence a uma role public (que é default), temos duas possibilidades:

1) Alterar o login desejado;

USE MASTER
GO
DENY VIEW ANY DATABASE TO servidorPublico

É uma solução interessante. O usuário não enxerga banco nenhum no modo visual mas consegue acessar a base (que possui permissão) normalmente através de T-SQL. Aqui cabe uma observação minha… Seria extremamente desejável que ele pudesse enxergar as bases na qual possui vínculo. Ou seja, seria interessante aqui termos uma permissão a mais (no final do artigo eu chego nesse ponto).

2) Alterando a role public

USE MASTER
GO
DENY VIEW ANY DATABASE TO PUBLIC

É uma solução “broadcast”, hehe . Lembre-se que TODOS os usuário criados são atribuidos ao public, e qualquer efeito sobre o mesmo pode afetar permissões de todo mundo que está interligado. Lembrando que poucas roles escapam da  restrição deste método, como por exemplo, os sysadmins.

TRIVIA: de todas as server roles, PUBLIC é a única que pode sofrer operações de DCL. Tente dar DENY em outras server roles, como por exemplo, no securityadmin.

5 – O fim

Você, DBA grilado, implementa a primeira solução logado em sua conta de sysadmin, volta pro login criado e percebe que agora, apesar do login não conseguir nem ver a base descrita no client do ssms, consegue ler (intenção desejada) os dados e só consegue enxergar na tempdb e na master informações relacionadas às suas permissões. Independente do método utilizado acima, o resultado é:

(Clique na imagem para ampliar)

p2

Pra testar a sp_helpdb, você  resolve testar com nome de outro banco qualquer:

SP_HELPDB ‘DbFinanceiro’

E recebe o seguinte erro (Totalmente justificável):

Msg 15010, Level 16, State 1, Procedure sp_helpdb, Line 45

The database ‘DbFinanceiro’ does not exist. Supply a valid database name. To see available databases, use sys.databases.

Antigamente sem o DENY na ALTER VIEW ANY DATABASES, o usuário conseguiria enxergar alguns metadados relacionados aos bancos sem maiores dificuldades. Agora não mais.

E lá vai você, o DBA ninja, tomar um café pra encerrar essa empreitada aqui narrada.

6 – Considerações finais

A parte ruim dessa história toda é que não existe essa permissão de visualizar por banco. Seria legal que pudéssemos setar um ‘VIEW DATABASE’ (Se existissse) pra apenas as bases que gostaria, porém, isso não seria possível. Ou seja, seria desejável que o SQL Server permitisse a visualização de bancos que fossem interessantes ao login/user em específico. Imagino esse recurso voltado para os desenvolvedores.

Espero que tenha passado informações úteis.

Se você tiver alguma crítica, sugestão, correção, adendo, proposta de emprego ou comentário, fique à vontade também. Esse blog é nosso 😉