Certificados, Cross Database Ownership Chaining e Segurança

Boa Tarde Pessoal,

No último artigo, demonstrei a utilização do recurso Cross Database Ownership Chaining para criar aplicações que acessam recursos de múltiplos bancos de dados de forma simultânea. Esse recurso permite a centralização da segurança ainda que os recursos (Securables) extrapolem o escopo de um único banco de dados. Sim, esse é o seu ponto positivo, mas o uso desse recurso é definido em nível de banco de dados. Isso significa que outros objetos com a capacidade de acessar recursos de outros bancos de dados podem vir a ser criados também representando riscos a segurança. No SQL Server 2000 não havia muitas alternativas, mas o 2005 e o 2008 com os novos recursos de segurança fornecem alternativas que desincentivam o uso do Cross Database Ownership Chaining. A propriedade Trustworthy já torna alguns controles mais interessantes que o Cross Database Ownership Chaining, mas o uso de certificados definitivamente é uma melhor opção. Nesse artigo, demonstrei como a utilização de certificados pode ser interessante para aplicações que acessem recursos de múltiplos bancos de dados entre si.

O que são certificados ?

Uma das necessidades comuns em um banco de dados é a necessidade de criptografar dados sigilosos. As versões anteriores do SQL Server davam um suporte mínimo à criptografia de dados e ficava a cargo da aplicação a tarefa de criptografar e descriptografar dados enquanto o SQL Server apenas servia como repositório para dados criptografados.

A partir do SQL Server 2005, a Microsoft disponibilizou funcionalidades para tratar a criptografia diretamente na camada de dados possibilitando que o próprio SQL Server criptografe e descriptografe dados de caráter sigiloso (senha, saldos bancários, renda, cartões de crédito, etc).

Os principais recursos de criptografia em nível de coluna incluem a utilização de um texto (código) de criptografia, chaves simétricas, chaves assimétricas e certificados. Todos esses recursos possuem seus pontos fortes e fracos e flutuam na relação segurança vs processamento. Alguns são mais seguros, mas exigem mais processamento enquanto que outros são menos seguros, mas em contrapartida provocam menos overhead para os processadores.

Um certificado é um recurso em nível de banco de dados para criptografar dados com base na utilização de chaves públicas e privadas. Além de representar uma forma de criptografar dados, o seu uso também possibilita a autenticação de usuários em banco de dados. A possibilidade do certificado ter um backup próprio permite que ele seja utilizado em múltiplos bancos de dados como forma de criptografia e autenticação. Essa capacidade que pretendo explorar nesse artigo.

O exemplo

Esse exemplo irá criar dois bancos de dados chamados BD1 e BD2. No banco BD1 existirá uma tabela chamada Departamentos e no banco BD2 existirá uma stored procedure chamada pDepartamentos que busca dados da tabela de departamentos (mas apenas o ID e o nome já que a verba mensal é sigilosa). Posteriormente será criado um usuário para o Login UsrApp em BD2 somente e os direitos de execução na Stored Procedure pDepartamentos.

— Cria um login
CREATE LOGIN UsrApp WITH PASSWORD = ‘UsrApp’, CHECK_POLICY = OFF

— Cria os bancos de dados
CREATE DATABASE BD1
CREATE DATABASE BD2

— Cria os objetos
USE BD1;
CREATE TABLE Departamentos (
    DeptoID INT NOT NULL,
    DeptoNome VARCHAR(50) NOT NULL,
    VerbaMensal MONEY NULL,
    CONSTRAINT PK_Depto PRIMARY KEY (DeptoID))

INSERT INTO Departamentos VALUES (1,‘RH’,15465.50)
INSERT INTO Departamentos VALUES (2,‘Marketing’,32745.59)
INSERT INTO Departamentos VALUES (3,‘Finanças’,43156.30)
INSERT INTO Departamentos VALUES (4,‘TI’,57982.10)

USE BD2;
GO
CREATE PROCEDURE pDepartamentos
AS
    SELECT
DeptoID, DeptoNome FROM
    BD1.dbo.Departamentos

— Concede permissões na SP para o usuário UsrApp
CREATE USER UsrApp FROM Login UsrApp
GRANT EXECUTE ON pDepartamentos TO UsrApp

Se uma nova janela for aberta no SQL Server Management Studio com o usuário UsrApp, ao tentar executar a stored procedure pDepartamentos, um erro é exibido:

EXEC BD2.dbo.pDepartamentos

Msg 916, Level 14, State 1, Procedure pDepartamentos, Line 3
The server principal "UsrApp" is not able to access the database "BD1" under the current security context.

Embora o usuário UsrApp em BD2 tenha acesso de execução na stored procedure, como ela acessa dados em BD1 e o usuário UsrApp não possui acesso a esses dados, o erro é gerado, pois, nesse caso, o Owner da stored procedure não é o Owner dos dados solicitados e UsrApp necessitaria de acesso nesses dados para que pudesse executar a stored procedure. Conceder acesso direto representa uma brecha na segurança, pois, uma vez que o usuário possua acesso direto, ele pode optar por não executar a stored procedure. No artigo anterior, foi demonstrado como resolver esse problema com o uso do Cross Database Ownership Chaining. Ainda assim, esse recurso abre outras brechas relacionadas a segurança. O uso de certificados elimina esses problemas.

— Cria um certificado em BD2
USE BD2;
CREATE CERTIFICATE cAcessoBD ENCRYPTION BY PASSWORD = ‘?!@fhcu#$’
WITH SUBJECT = ‘Permitir Acesso para pDepartamentos’

— Assina a procedure pDepartamentos com o certificado cAcessoBD
ADD SIGNATURE TO dbo.pDepartamentos BY CERTIFICATE cAcessoBD
WITH PASSWORD = ‘?!@fhcu#$’

— Faz uma cópia do certificado
BACKUP CERTIFICATE cAcessoBD TO FILE = ‘C:\TEMP\cAcessoMultiBanco.CER’

O script acima cria um certificado chamado cAcessoBD cuja a chave privada foi criptografada com a senha ?!@fhcu#$. Não há nenhuma obrigatoriedade em criptografar a chave privada do certificado com uma senha, mas é que se ela fosse criptografada pela MASTER KEY do banco, outros usuários que participassem da role db_owner teriam direito a utilizar esse certificado. A segunda linha do código assina a stored procedure com base no certificado e isso confere a essa stored procedure o direito de se autenticar através do certificado cAcessoBD. Como o chave privada do certificado está criptografada com base em uma senha, é necessário especificar a senha no momento de adicionar a assinatura à stored procedure. A última linha do código faz uma cópia do certificado para um arquivo a ser utilizada posteriormente.

— Restaura o certificado em BD1
USE BD1;
CREATE CERTIFICATE cAcessoBD FROM FILE = ‘C:\TEMP\cAcessoMultiBanco.CER’

CREATE USER uAcessoBD FROM CERTIFICATE cAcessoBD
GRANT SELECT ON Departamentos TO uAcessoBD

O script acima cria o mesmo certificado em BD1 a partir do arquivo gerado anteriormente. Apenas a chave pública está disponível no arquivo, pois, não foi especificada a opção "WITH PRIVATE KEY". Após o certificado estar disponível em BD1, o arquivo pode inclusive ser excluído se necessário. Um usuário chamado uAcessoBD é criado não a partir de um login, mas a partir do próprio certificado. A esse usuário uAcessoBD é concedida a permissão de SELECT na tabela Departamentos.

Se uma nova janela for aberta no SQL Server Management Studio com o usuário UsrApp, ao tentar executar a stored procedure pDepartamentos o resultado é retornado corretamente.

EXEC BD2.dbo.pDepartamentos

DeptoID DeptoNome
1 RH
2 Marketing
3 Finanças
4 TI

Se o usuário UsrApp tentar o acesso direto através de uma query, o mesmo não conseguirá visualizar as informações de departamento

SELECT DeptoID, DeptoNome, VerbaMensal FROM BD1.dbo.Departamentos

Msg 916, Level 14, State 1, Line 1
The server principal "UsrApp" is not able to access the database "BD1" under the current security context.

Essa é a prova real de que realmente o acesso aos dados está sendo feito de forma segura, pois, os mesmos só podem ser visualizados através da stored procedure pDepartamentos e que o acesso direto não é permitido.

A explicação

Embora tenha funcionado, estou certo que nem todos estão 100% seguros do que aconteceu e nem de todas as implicações e possibilidades implícitas dessa abordagem. O primeiro ponto é que o chave privada do certificado está criptografada com base em uma senha que somente quem criou o certificado conhece. Como o uso de assinaturas depende dessa chave, isso impossibilita que outros usuários utilizem esse certificado para adicionar assinaturas a outros objetos. Mesmo que esses usuários estejam nas roles db_owner e (ou) sysadmin não poderão utilizar o certificado para adicionar assinaturas. Eles podem remover a chave privada, mas nesse caso, as assinaturas já existentes são invalidadas.

Exportar o certificado para um arquivo pode ser feito por outros usuários bem como importá-los para outros bancos também. Só que isso só leva a chave pública do certificado e não possibilita o uso do mesmo para novas assinaturas, pois, para isso é necessário a chave privada do mesmo.

O uso da assinatura permitiu que a stored procedure acessasse os recursos em BD1, pois, a autenticação foi feita em nível de certificado (a assinatura em BD2 e o usuário criado a partir do certificado em BD1). Alguém poderia pensar que há uma falha de segurança, pois, se a autenticação e autorização para execução já estão garantidas, alguém poderia mudar o conteúdo da stored procedure pDepartamentos. Analisemos essa questão mais de perto.

— Muda o contexto do banco de dados
USE BD2;

— Verifica a assinatura
SELECT CRYPT_PROPERTY FROM SYS.CRYPT_PROPERTIES
WHERE MAJOR_ID = OBJECT_ID(‘dbo.pDepartamentos’)
GO

— Altera a Stored Procedure
ALTER PROCEDURE pDepartamentos
AS
    SELECT
DeptoID, DeptoNome, VerbaMensal FROM
    BD1.dbo.Departamentos
GO

— Verifica a assinatura
SELECT CRYPT_PROPERTY FROM SYS.CRYPT_PROPERTIES
WHERE MAJOR_ID = OBJECT_ID(‘dbo.pDepartamentos’)

O primeiro SELECT mostra o binário que representa a assinatura atribuída à stored procedure pDepartamentos.

CRYPT_PROPERTY (Abreviado)
0x26E681B524C94997FAE8A4550CA86C75F43660EDB5DF3153A7627

Após a alteração da Stored Procedure, a mesma perde a assinatura, pois, o seu código foi violado.

CRYPT_PROPERTY (Abreviado)

Se o usuário UsrApp tentar executar a stored procedure novamente, o acesso a tabela de departamentos será negado, pois, sem a assinatura (chave privada do certificado) não é possível autenticar como uAcessoBD em BD1 (chave pública do certificado):

EXEC BD2.dbo.pDepartamentos

Msg 916, Level 14, State 1, Procedure pDepartamentos, Line 4
The server principal "UsrApp" is not able to access the database "BD1" under the current security context.

Para que a stored procedure possa novamente funcionar é necessário adicionar novamente a assinatura e uma vez que apenas o criador do certificado conhece a senha que criptografou sua chave privada, outros usuários não poderão adicionar essa assinatura. O código abaixo adiciona a assinatura para a procedure pDepartamentos com base no certificado cAcessoBD. Não é necessário configurar mais nada, pois, as demais permissões já estavam configuradas previamente.

— Muda o contexto do banco de dados
USE BD2;

— Assina a procedure pDepartamentos com o certificado cAcessoBD
ADD SIGNATURE TO dbo.pDepartamentos BY CERTIFICATE cAcessoBD
WITH PASSWORD = ‘?!@fhcu#$’

Agora se UsrApp tentar a execução da stored procedure pDepartamentos, conseguirá novamente o acesso (dessa vez com a nova coluna).

EXEC BD2.dbo.pDepartamentos

DeptoID DeptoNome VerbaMensal
1 RH 15.465,50
2 Marketing 32.745,59
3 Finanças 43.156,30
4 TI 57.982,10

A stored procedure voltou a ser assinada, mas sua assinatura agora mudou o hash.

CRYPT_PROPERTY (Abreviado)
0xD60FB6F862633160AFC12724E51A3BDCFE3D0D79921EBE493DE63

Podemos ver que dessa forma é possível criar objetos que acessem múltiplos bancos de dados sem soluções como o acesso direto aos objetos e o Cross Database Ownership Chaining. O SQL Server 2005 introduziu a opção Trustworthy que é certamente melhor que as anteriores, mas a utilização de certificados é a opção mais segura dentre as citadas.

[ ]s,

Gustavo

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s