Fala, meus queridos leitores!
Nesse artigo, eu gostaria de estender um pouco o tema sobre segurança e compartilhar com vocês como desativar o login “sa” minimizando impactos. Como eu já havia comentado no artigo SQL Server – Como ativar/habilitar o usuário sa, é uma boa prática de segurança manter o usuário “sa” desativado e renomeado, uma vez que esse usuário está na role sysadmin (não pode ser removido), não pode ser apagado da instância e é um usuário padrão, ou seja, está presente em qualquer instância do SQL Server, o que torna esse usuário o alvo preferido de possíveis invasores. Inclusive, esse é um dos ítens de segurança do Check-up GRATUITO do SQL Server que a Fabrício Lima está oferecendo para quiser conhecer a empresa.
Durante alguns dias eu deixei público para a Web, uma instância do SQL Server e do Power BI Report Server para realizar alguns testes. Após alguns dias, vi no error log do SQL Server que já estavam tentando invadir a minha base. Imaginem qual o usuário que mais tentaram utilizar para acessar o meu banco ?
Quer consultar como estão essas estatísticas na sua instância? Basta executar o script abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
DECLARE @ArquivosLog TABLE ( LogNumber INT, StartDate DATETIME, SizeInBytes INT ) DECLARE @Dados TABLE ( [LogDate] datetime, [ProcessInfo] nvarchar(12), [Text] nvarchar(3999) ) INSERT INTO @ArquivosLog EXEC sys.xp_enumerrorlogs 1 DECLARE @Contador INT = 0, @Total INT = (SELECT COUNT(*) FROM @ArquivosLog) WHILE(@Contador < @Total) BEGIN INSERT INTO @Dados EXEC sys.sp_readerrorlog @Contador, 1, 'login failed' SET @Contador += 1 END SELECT MIN(LogDate) AS Dt_Menor_Ocorrencia, MAX(LogDate) AS Dt_Maior_Ocorrencia, SUBSTRING([Text], 1, IIF(CHARINDEX('[', [Text]) = 0, LEN([Text]), CHARINDEX('[', [Text]) - 1)) AS Texto, COUNT(DISTINCT [Text]) AS Quantidade FROM @Dados GROUP BY SUBSTRING([Text], 1, IIF(CHARINDEX('[', [Text]) = 0, LEN([Text]), CHARINDEX('[', [Text]) - 1)) ORDER BY 4 DESC |
Agora que já fiz um breve resumo do porque esse usuário deve ser desativado e renomeado, vou explicar como podemos fazer isso no seu banco de dados. Em teoria, é algo extremamente simples:
1 2 3 4 5 6 7 8 |
USE [master] GO ALTER LOGIN [sa] DISABLE GO ALTER LOGIN [sa] WITH NAME = [sa_DESATIVADO] GO |
Ou até mesmo, pela interface do Management Studio (SSMS):
O problema é que muita gente fica insegura de fazer essa operação no seu banco de dados e acabar gerando impactos no ambiente. A minha ideia nesse post, é te ajudar a identificar e minimizar esses possíveis impactos para que você possa aplicar essas configurações de segurança em todos os seus ambientes.
Aplicação utilizando SA
O primeiro ítem que deve ser verificado é se existe alguma aplicação que utiliza o usuário “sa” para se conectar no banco de dados (acreditem, isso existe). A forma mais fácil de identificar isso é questionando o fornecedor da aplicação ou o time de desenvolvimento.
Uma forma que pode te ajudar a validar essas informações e até mesmo já conseguir identificar se esse cenário está ocorrendo no seu ambiente, é consultando a DMV sys.dm_exec_sessions:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
SELECT session_id, login_time, login_name, [program_name], [host_name], client_interface_name, [status], nt_domain, nt_user_name, original_login_name FROM sys.dm_exec_sessions WHERE session_id > 50 AND security_id = 0x01 |
Databases onde o usuário SA é owner
Essa é uma preocupação muito comum entre os DBA’s que se desativar o usuário SA e renomeá-lo, pode ocorrer algum problema nos databases onde o usuário SA é o owner. Entretanto, podem ficar tranquilos que não ocorre problema algum ao fazer isso. Já fiz vários testes em vários ambientes, tanto de testes quanto de produção e você desativar o usuário SA não causa nenhum impacto em relação à isso.
Para comprovar o que eu estou afirmando, segue uma demonstração:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
SELECT A.database_id, A.[name], B.[name] AS [owner], A.create_date, A.state_desc, A.[compatibility_level], A.collation_name FROM sys.databases A JOIN sys.server_principals B ON A.owner_sid = B.[sid] SELECT [name], is_disabled FROM sys.server_principals WHERE principal_id = 1 -- sa |
Jobs onde o usuário SA é owner
Assim como ocorre quando o usuário SA é owner de um database, não há impacto algum referente à execução dos Jobs do SQL Agent ao renomear e desativar o login “sa”. Podem ficar despreocupados e não precisam sair alterando o owner de todos os jobs para renomear/desativar o sa.
Consulta utilizada para demonstração:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
SELECT A.[name] AS Ds_Job, B.[name] AS Ds_Owner, msdb.dbo.agent_datetime(C.run_date, C.run_time) AS Dt_Execucao, (CASE C.run_status WHEN 0 THEN '0 - Falha' WHEN 1 THEN '1 - Sucesso' WHEN 2 THEN '2 - Retry' WHEN 3 THEN '3 - Cancelado' WHEN 4 THEN '4 - Executando' END) AS Ds_Status, C.[message] FROM msdb.dbo.sysjobs A JOIN sys.server_principals B ON A.owner_sid = B.[sid] JOIN msdb.dbo.sysjobhistory C ON C.job_id = A.job_id WHERE C.step_id = 0 -- Geral |
Linked Server
Essa é provavelmente a validação mais difícil de se fazer no ambiente, embora também seja bem incomum. Se existir algum Linked Server que aponte para sua instância, onde a conexão ao banco é feita utilizando o usuário “sa”, fixo no LS, você poderá ter problemas ao desativar e renomear esse usuário.
É difícil validar isso, porque você tem que entrar em todas as instâncias do seu ambiente que podem ter algum linked server apontado para essa instância específica e validar se esse cenário está ocorrendo:
Não é muito comum o uso de Linked Server com usuário fixo na conexão, já que qualquer usuário na instância remota poderia executar QUALQUER COMANDO na instância destino, já que a conexão está chegando como “sa”, que é sysadmin, mas é uma validação que deve ser feita para garantir que a alteração não irá gerar impactos.
Você pode utilizar essa consulta para facilitar essa verificação:
1 2 3 4 5 6 7 8 9 10 11 12 |
SELECT B.[name], B.product, B.[provider], B.[data_source], A.remote_name FROM sys.linked_logins A JOIN sys.servers B ON B.server_id = A.server_id WHERE A.server_id > 0 AND A.local_principal_id = 0 -- SA |
Objetos com IMPERSONATE utilizando o SA
É um tanto comum ver procedures e objetos que utilizem o comando EXECUTE AS para executar tarefas como se fossem outros usuário, especialmente para permitir que um usuário com poucos privilégios possa executar rotinas e comandos que exigiriam mais privilégios que ele possui, fazendo assim, uma elevação de privilégio. Caso você queira se aprofundar mais sobre o IMPERSONATE e elevação de privilégios, recomendo a leitura do meu artigo SQL Server – Como utilizar o EXECUTE AS para executar comandos como outro usuário (Impersonate login e user).
Para tranquilizar você, saiba que não é possível utilizar o EXECUTE AS USER e personificar o usuário “sa”, pois ele é um usuário “especial”, ou seja, menos uma preocupação para você.
Outros serviços
E por fim, para que você possa fazer sua alteração com toda a tranquilidade, recomendo que você valide se existe algum serviço do Windows, relatório do Reporting Services, alguma rotina Power Shell, ferramenta de monitoramento ou algum processo externo ao SQL Server que possa estar utilizando o usuário sa no seu ambiente.
Como são processos externos e podem ser específicos da sua empresa, não tem muita “receita de bolo” para tratar essas situações, mas não é nada comum um DBA permitir que um serviço utilize o usuário “sa” para tal operações, então deve ser muito difícil encontrar esse cenário.
Fique tranquilo e confiante ao desativar e renomear o usuário “sa”, pois essa é uma boa prática de segurança para o seu ambiente. Lembre-se de monitorar o log do SQL Server após essa alteração para consultar se estão ocorrendo mensagens de falha de login utilizando o “sa”. Disponibilizei uma consulta que dá até pra automatizar isso lá no começo desse post 😉
Caso você identifique algum problema, você pode ter descoberto alguma tentativa de invasão ou um processo na sua empresa fora do padrão, que deve ser alterado urgentemente para utilizar outro usuário para a conexão com o banco de dados.
Bom pessoal, é isso aí!
Espero que tenham gostado dessa dica, renomeiem e desativem o usuário “sa” em seus ambientes e até a próxima!
Excelente conteúdo! Obrigado e Parabéns!
Boa noite, tenho uma dúvida, pois sou novo nesse mundo SQL. Tem como criar um usuário somente para o software acessa o banco de dados? E caso esse usuário tente acessar o Management do SQL o mesmo não consiga acessa?