Conhecendo um pouco sobre o Dynamic Data Masking no SQL Server
Fala galerinha,
Espero que estejam todos bem ?
Hoje falaremos um pouco sobre a feature Dinamyc Data Masking, já ouviu falar?
Tentarei ser o mais breve e claro possível.
O Dynamic Data Masking (Mascaramento de dados dinâmico) também chamado de DDM. É um recurso de segurança que foi adicionado no SQL Server 2016. O DDM ajuda a impedir que usuários não autorizados façam o acesso a dados considerados sensíveis. É importante frisarmos que estamos falando de uma tecnologia de mascaramento de dados e não de uma criptografia diretamente, OK? Como a máscara é incorporada ao esquema da tabela o DDM acaba sendo totalmente transparente para a aplicação e não requer nenhum tipo de alteração (Muito bom e prático né?? ?. No entanto, nem tudo são flores. A segurança também é um fator importante e esse recurso não impede que os usuários mal-intencionados possam tentar usar técnicas de inferência ou força bruta para desmascarar os dados.
Falando em segurança, para que se tenha sucesso na implementação dessa funcionalidade o controle de acessos da sua instância é primordial. Caso contrário usuários com permissões elevadas poderão facilmente desmascarar os dados, tornando ineficiente o uso deste recurso, falaremos mais a frente sobre isso.
Tome muito cuidado ao utilizar essa funcionalidade como a sua principal camada de segurança.
Recomendo fortemente algumas ações antes de pensar em implementar o DDM, dentre elas estão :
- Faça a revisão da permissão de todos os usuários da instância. Se estiver dentro de um domínio, de preferencia para a criação de grupos, separando por departamentos, funções, etc, isso te ajudará na manutenção e a manter a rastreabilidade dos usuários e também permitirá que esteja tudo interligado em um lugar só, caso um usuário saia da empresa, basta exclui-lo no AD (Active Directory) que ele já não terá mais acesso ao banco;
- Se possível retire todos os usuários com acesso sysadmin da instância (de preferência centralizando essa elevação em poucas pessoas como um DBA ou alguma pessoa especializada dentro da organização);
- Faça a criação de um usuário especifico com permissões limitadas para a aplicação;
O DDM suporta os seguintes tipos de máscaras:
- Partial (Cadeia de caracteres personalizada) : Um método de mascaramento que mostra a primeira e a última letra e adiciona uma sequência de preenchimento personalizada no meio.
- Default (Padrão) : Mascaramento completo dependendo do tipo de dados do campo:
- Para tipos binários de dados, é utilizado um único byte de valor ASCII 0 (binary, varbinary,image).
- Para os tipos de dados de data e hora, é utilizado 01.01.1900 00:00:00.0000000 (date,datetime2,datetime,datetimeoffset,smalldatetime,time).
- Para tipos de dados numéricos, é utilizado o valor zero (bigint,bit,decimal,int,money,numeric,smalltint,smallint,smallmoney,tinyint,float,real).
- Para tipos de dados de texto, é utilizado XXXX e se o tamanho do valor arquivado for inferior a 4 caracteres, o SQL também irá mostrar XXXX (char,nchar,varchar,nvarchar,text,ntext).
- E-mail : Mascara endereços de e-mail mostrando apenas a primeira letra e o sufixo de .com constante no seguinte formato [email protected].
- Random (Aleatório) : Um método de mascaramento que substituirá um valor aleatório dentro do intervalo especificado para um tipo numérico.
Faremos alguns exemplos práticos disso mais adiante.
Para maiores detalhes, consulte a documentação:
As regras de mascaramento NÃO podem ser definidas para o seguinte contexto:
- Colunas criptografadas com Always Encrypted.
- Colunas do tipo Column_Set.
- Colunas do tipo Filestream.
- Colunas do tipo Computada.
- Se uma coluna computada depender de uma coluna mascarada, a coluna computada retornará os dados mascarados.
- Uma coluna com mascaramento de dados não pode ser uma chave para um índice FULLTEXT.
Bom, chega de teoria… Vamos praticar um pouco?
Laboratório :
Usarei nessa demonstração a base AdventureWorks2016 que você pode baixar no seu ambiente neste link :
Temos a seguinte consulta :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | SELECT TOP 10 P.BusinessEntityID, P.FirstName, P.LastName, E1.EmailAddress, PP.PhoneNumber, PA.AddressLine1, PA.StateProvinceID FROM [Person].[Person] AS P LEFT JOIN [HumanResources].[Employee] AS E ON E.BusinessEntityID = P.BusinessEntityID LEFT JOIN [Person].BusinessEntity B ON P.BusinessEntityID = B.BusinessEntityID LEFT JOIN Person.EmailAddress E1 ON E1.BusinessEntityID = P.BusinessEntityID LEFT JOIN Person.PersonPhone PP ON PP.BusinessEntityID = P.BusinessEntityID LEFT JOIN person.BusinessEntityAddress BE ON BE.BusinessEntityID = P.BusinessEntityID LEFT JOIN person.Address PA ON PA.AddressID = BE.AddressID WHERE PA.AddressLine1 IS NOT null |
Suponhamos que os dados de e-mail, telefone, endereço e estado foram considerados sensíveis pela sua organização e queremos aplicar o DDM neles. Para aplicar as funções de mascaramento, é muito simples, você pode “criar” uma tabela já aplicando a função desejada nos campos desejados ou alterar uma existente. No mundo real geralmente as bases já estão criadas e você na maioria das vezes precisará alterar algo já previamente criado, então focarei os exemplos desta demonstração apenas nas alterações (Mas tenha ciência que é a mesma coisa na criação, basta adicionar a função na frente do campo) :
Exemplo : Aplicando a função de mascaramento E-mail().
1 2 | --MASCARANDO A COLUNA DE ENDEREÇO DE E-MAIL UTILIZANDO A FUNÇÃO DE MASCARAMENTO EMAIL() ALTER TABLE Person.EmailAddress ALTER COLUMN EmailAddress ADD MASKED WITH (FUNCTION ='email()') |
Exemplo : Aplicando a função de mascaramento Default().
1 2 | --MASCARANDO A COLUNA DE ENDEREÇO UTILIZANDO A FUNÇÃO DE MASCARAMENTO DEFAULT() ALTER TABLE person.Address ALTER COLUMN AddressLine1 ADD MASKED WITH (FUNCTION ='default()') |
Exemplo : Aplicando a função de mascaramento Partial().
1 2 | --MASCARANDO A COLUNA DE TELEFONE UTILIZANDO A FUNÇÃO DE MASCARAMENTO PARTIAL() ALTER TABLE Person.PersonPhone ALTER COLUMN PhoneNumber ADD MASKED WITH (FUNCTION ='PARTIAL(0,"XXX-XXX-",4)') |
Exemplo : Função de mascaramento Random().
1 2 | --MASCARANDO A COLUNA DE ID DO ESTADO UTILIZANDO A FUNÇÃO DE MASCARAMENTO RANDOM() ALTER TABLE person.Address ALTER COLUMN StateProvinceID ADD MASKED WITH (FUNCTION ='RANDOM(10,30)') |
Para testar o que acabamos de fazer, iremos criar um usuário no SQL Server com a permissão de somente leitura (“db_datareader”)
1 2 3 4 5 6 7 8 9 10 11 | USE [master] GO CREATE LOGIN [user_ddm] WITH PASSWORD=N'teste', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF GO USE [AdventureWorks2016] GO CREATE USER [user_ddm] FOR LOGIN [user_ddm] GO USE [AdventureWorks2016] GO ALTER ROLE [db_datareader] ADD MEMBER [user_ddm] |
Vamos fazer o login com esse usuário na nossa instância.
Agora vamos executar a nossa consulta novamente (com o usuário user_ddm) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | SELECT TOP 10 P.BusinessEntityID, P.FirstName, P.LastName, E1.EmailAddress, PP.PhoneNumber, PA.AddressLine1, PA.StateProvinceID FROM [Person].[Person] AS P LEFT JOIN [HumanResources].[Employee] AS E ON E.BusinessEntityID = P.BusinessEntityID LEFT JOIN [Person].BusinessEntity B ON P.BusinessEntityID = B.BusinessEntityID LEFT JOIN Person.EmailAddress E1 ON E1.BusinessEntityID = P.BusinessEntityID LEFT JOIN Person.PersonPhone PP ON PP.BusinessEntityID = P.BusinessEntityID LEFT JOIN person.BusinessEntityAddress BE ON BE.BusinessEntityID = P.BusinessEntityID LEFT JOIN person.Address PA ON PA.AddressID = BE.AddressID WHERE PA.AddressLine1 IS NOT null |
Show!! Os dados foram mascarados com sucesso!!
Com essa permissão que foi aplicada neste usuário de somente leitura ele não conseguirá fazer nada em relação a segurança do nosso mascaramento, mas e se fosse um “db_owner”?
1 2 3 4 5 6 7 8 9 10 11 12 | USE [master] GO CREATE LOGIN [user_ddm2] WITH PASSWORD=N'teste', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF GO USE [AdventureWorks2016] GO CREATE USER [user_ddm2] FOR LOGIN [user_ddm2] GO USE [AdventureWorks2016] GO ALTER ROLE [db_owner] ADD MEMBER [user_ddm2] GO |
Vamos logar nele e rodar a consulta novamente.
Eita, o que aconteceu? Com a permissão db_owner o usuário em questão já tem as permissões necessárias para visualizar o dado real.
Portanto, tome muito cuidado!!
Se o usuário fizer parte do grupo sysadmin ele poderá também conceder ou revogar a permissão de outros usuários da sua instância.
Lembra do nosso usuário “user_ddm” com permissão somente leitura membro da role “db_datareader”? Vamos conceder permissão pra ele visualizar os dados desmascarados a partir de um usuário sysadmin.
1 | GRANT UNMASK TO [user_ddm] |
Agora executando a nossa consulta com o usuário “user_ddm”, ele também pode visualizar os dados “desmascarados”.
Conclusão :
A solução funciona bem e é de fácil implementação .No entanto, o controle de acessos passa a ser um fator chave para se ter sucesso no uso deste recurso.
É isso ai pessoal, espero que tenham gostado!
Qualquer dúvida deixe nos comentários.
Um grande abraço!
Gustavo Larocca
Consultor SQL Server
Um comentário
Recurso muito legal! Com certeza há muita aplicabilidade.