Criptografando a comunicação do SQL Server com SSL

Para aqueles que ficaram meio que ‘sem chão’ quando viram que com um Sniffer é possível obter informações dos dados que transitam entre as aplicações clientes e SQL Server na rede (ver artigo sobre sniffer no SQL Server), vou apresentar a solução.

A solução que trabalharemos é semelhante à utilização do SSL para comunicação HTTP (HTTPS), mas sobre o protocolo TDS.

Com o SDK da .NET Framework, criaremos um certificado por meio do makecert via prompt de comando:

#Caso estiver com um Windows x64:
cd C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin

#Caso estiver com um Windows x86:
cd C:\Program Files\Microsoft SDKs\Windows\v7.0A\Bin

#Criando o certificado:
makecert -r -pe -n "CN=NomeDoComputador" -b 01/01/2000 -e 01/01/2036 -eku 1.3.6.1.5.5.7.3.1 -ss my -sr localMachine -sky exchange -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12

Abrimos o Microsoft Management Console (mmc):

Em “File\Add or Remove Snap-ins…”, adicionamos o Snap-in de certificados:

Informamos que gerenciaremos os certificados da conta do computador:

E no caminho “Personal\Certificates”, encontramos o certificado que acabamos de criar:

Por fim, copiamos o certificado para o caminho “Trusted Root Certification Authorities\Certificates”:

Em seguida, pelo SQL Server Configuration Manager (SSCM), acessamos as propriedades da configuração de rede da nossa instância do SQL Server:

Exigimos que a comunicação entre os clientes e o SQL Server seja criptografada:

E selecionamos o nosso certificado:

Depois de reiniciarmos o SQL Server, com o Microsoft Network Monitor 3.4, onde anteriormente tínhamos a comunicação pelo protocolo TDS, agora teremos somente comunicação criptografada TLS:

Referências:

Configuring Certificate for Use by SSL
http://msdn.microsoft.com/en-us/library/ms186362.aspx

Um sniffer na comunicação do SQL Server

Em qualquer cenário onde há comunicação remota do SQL Server com outros computadores, se torna fácil identificar os dados que são trafegados na rede utilizando um sniffer, principalmente quando não há muita dificuldade em uma máquina entrar na rede onde esta o SQL Server.

Para mostrar que a comunicação entre máquinas clientes e o SQL Server não é muito segura se não há utilização de criptografia, utilizarei o Microsoft Network Monitor 3.4 com um parse específico para obter informações do SQL Server, mostrando os dados trafegando pela rede.

Iniciando o Network Monitor, criaremos uma nova aba de capturada (New capture tab):

Definindo em ‘Tools\Options’ o parse do SQL Server:

Iniciaremos a captura e executando algumas consultas em um SQL Server, já teremos informações para analisar:

Basicamente teremos informações sobre qual protocolo utilizando (TCP, TDS…), qual a ação realizada (SQLBatch, Response, Flags, Prelogin…) e o SPID da conexão (ex.: 52):

Como exemplo de um TDS:SQLBatch, no qual executei o comando “SELECT name FROM sys.tables” no SQL Server Management Studio (SSMS), será fácil encontrar o comando nos detalhes da comunicação:

E um TDS:Response, no qual tive o seguinte retorno no SSMS:

E no Network Monitor, também é possível visualizar os dados trafegados:

Fiquem tranquilos, próxima semana publico a solução para este cenário! (ver artigo sobre SSL no SQL Server)

Programas utilizados:

Microsoft Network Monitor 3.4
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=983b941d-06cb-4658-b7f6-3088333d062f&displaylang=en

Network Monitor Open Source Parsers (NetworkMonitor Parsers forSQLServer)
http://nmparsers.codeplex.com/releases/view/64054

Utilizando certificados para autenticação entre bancos de dados no SQL Server

Uma alternativa mais saudável para cenários onde é necessário executar stored procedures, funções, triggers e assemblies que requerem utilizar objetos de outros bancos de dados, é a utilização de certificados, ao invés da já conhecida configuração de Cross DB Ownership Chaining.

A desvantagem dos certificados se dá a complexidade na utilização dos mesmos, mas com a demonstração a seguir, acredito que vocês terão poucas dúvidas.

Para o início da demonstração, temos dois bancos de dados com Cross DB Ownership Chaining desabilitado (configuração padrão em muitos cenários), onde teremos uma stored procedure em um banco tentando acessar uma tabela de outro.

-- Criando os bancos de dados
CREATE DATABASE DB01;

ALTER DATABASE DB01 SET DB_CHAINING OFF;

CREATE DATABASE DB02;

ALTER DATABASE DB02 SET DB_CHAINING OFF;
GO

-- Criando a tabela
USE DB01;
GO
CREATE TABLE SuperTabela (Id INT);
GO

-- Criando a stored procedure
USE DB02;
GO
CREATE PROC SuperProc AS
	SELECT * FROM DB01.dbo.SuperTabela
	WHERE ID > 10;
GO

A nossa usuária Maria somente terá acesso á stored procedure, mas não a tabela, logo numa tentativa de utilizar o usuário dela para executar a stored procecure teremos um erro por falta de permissão:

-- Criando a usuária Maria
USE [master];
GO
CREATE LOGIN Maria WITH PASSWORD = '9455w0rd';
GO

USE DB02;
GO
CREATE USER Maria FOR LOGIN Maria;
GO

-- Permitindo o acesso à stored procedure
USE DB02;
GO
GRANT EXEC ON dbo.SuperProc TO Maria;
GO

-- Executando a stored procedure
USE DB02;
GO
EXECUTE AS LOGIN = 'Maria';
GO
EXEC dbo.SuperProc;
GO
REVERT;
GO

Msg 916, Level 14, State 1, Procedure SuperProc, Line 2
The server principal “Maria” is not able to access the database “DB01” under the current security context.
Ah “Maria” sua n00b!!

Agora para resolver a questão da permissão, criaremos um certificado no banco de dados onde esta a tabela que precisamos de acesso, e permitimos acesso a esta tabela por meio de um usuário criado a partir deste certificado:

USE DB01;
GO

-- Criando o certificado
CREATE CERTIFICATE CERT_DB01
	ENCRYPTION BY PASSWORD = '5up3r53nh4'
	WITH SUBJECT = 'CERT_DB01';

-- Criando um usuário a partir do certificado
CREATE USER USU_CERT_DB01
	FOR CERTIFICATE CERT_DB01;

-- Permitindo acesso do usuário à tabela
GRANT SELECT ON dbo.SuperTabela
	TO USU_CERT_DB01;

Salvamos o certificado para o movimentarmos para o outro banco de dados:

-- Salvando o certificado para movimentar para o outro banco de dados
BACKUP CERTIFICATE CERT_DB01
	TO FILE = 'C:\Projetos\CERT_DB01.cer'
	WITH PRIVATE KEY (
		DECRYPTION BY PASSWORD = '5up3r53nh4',
		FILE = 'C:\Projetos\CERT_DB01.pvk',
		ENCRYPTION BY PASSWORD = '5up3r53nh4-01'
	);

-- Apagando a chave privada do certificado
ALTER CERTIFICATE CERT_DB01
	REMOVE PRIVATE KEY;
GO

Restauramos o certificado onde esta a stored procedure, e assinamos a stored procedure com o certificado:

USE DB02;
GO

-- Restaurando o ceritificado no banco de dados
CREATE CERTIFICATE CERT_DB01
	FROM FILE = 'C:\Projetos\CERT_DB01.cer'
	WITH PRIVATE KEY (
		DECRYPTION BY PASSWORD = '5up3r53nh4-01',
		FILE = 'C:\Projetos\CERT_DB01.pvk',
		ENCRYPTION BY PASSWORD = '5up3r53nh4'
	);
GO

-- Assinando a stored procedure com o certificado
ADD SIGNATURE TO dbo.SuperProc
	BY CERTIFICATE CERT_DB01
	WITH PASSWORD = '5up3r53nh4';
GO

Agora podemos executar a stored procedure com o usuário da Maria sem problemas:

-- Executando a stored procedure
USE DB02;
GO
EXECUTE AS LOGIN = 'Maria';
GO
EXEC dbo.SuperProc;
GO
REVERT;
GO

Por fim, finalizamos o cenário:

-- Finalizando o cenário
USE [master];

DROP DATABASE DB01;

DROP DATABASE DB02;

DROP LOGIN Maria;
GO

Cross DB Ownership Chaining

Uma solução muito comum para situações onde temos um usuário que precisa executar uma procedure ou VIEW que relaciona dados de outro banco de dados, mas este usuário não deve ter acesso direto a este outro banco de dados, é utilizar a opção de Cross DB Ownership Chaining (SQL Server 2005+).

Como exemplo desta funcionalidade, vamos criar no primeiro banco de dados, uma tabela e no segundo banco de dados, uma VIEW que retorna os valores desta tabela do primeiro banco dados:

USE DB01
GO
CREATE TABLE SuperTabela (Id INT)
GO

USE DB02
GO
CREATE VIEW SuperVisao AS
SELECT * FROM DB01.dbo.SuperTabela
WHERE ID > 10
GO

Vamos criar um LOGIN para a Maria e um USER em cada um dos bancos de dados do nosso cenário:

USE [master]
GO
CREATE LOGIN Maria WITH PASSWORD = '9455w0rd'
GO

USE DB01
GO
CREATE USER Maria FOR LOGIN Maria
GO

USE DB02
GO
CREATE USER Maria FOR LOGIN Maria
GO

Em seguida, damos permissão de SELECT na VIEW que criamos ao usuário da Maria:

USE DB02
GO
GRANT SELECT ON dbo.SuperVisao TO Maria
GO

Sem Cross DB Ownership Chaining

Com o Cross DB Ownership Chaining desabilitado nos bancos de dados, primeiramente testamos se ela não tem acesso diretamente à tabela (acesso negado):

-- Desabilitando o Cross DB Ownership Chaining
USE [master]
GO
ALTER DATABASE DB01 SET DB_CHAINING OFF
GO
ALTER DATABASE DB02 SET DB_CHAINING OFF
GO

USE DB02
GO
EXECUTE AS LOGIN = 'Maria';
GO
SELECT * FROM SuperTabela
GO
REVERT
GO

Msg 229, Level 14, State 5, Line 1
The SELECT permission was denied on the object ‘SuperTabela’, database ‘DB01’, schema ‘dbo’.

E testamos o acesso dela na View e teremos como retorno que ela não tem acesso a tabela:

USE DB02
GO
EXECUTE AS LOGIN = 'Maria';
GO
SELECT * FROM SuperVisao
GO
REVERT
GO

Msg 229, Level 14, State 5, Line 1
The SELECT permission was denied on the object ‘SuperTabela’, database ‘DB01’, schema ‘dbo’.

Com Cross DB Ownership Chaining

Habilitamos o Cross DB Ownership Chaining, e testamos o acesso dela à tabela (acesso negado):

-- Habilitando o Cross DB Ownership Chaining
USE [master]
GO
ALTER DATABASE DB01 SET DB_CHAINING OFF
GO
ALTER DATABASE DB02 SET DB_CHAINING OFF
GO

USE DB02
GO
EXECUTE AS LOGIN = 'Maria';
GO
SELECT * FROM SuperTabela
GO
REVERT
GO

Msg 229, Level 14, State 5, Line 1
The SELECT permission was denied on the object ‘SuperTabela’, database ‘DB01’, schema ‘dbo’.

Agora, testamos o acesso á VIEW, e ela terá o acesso sem problemas:

USE DB02
GO
EXECUTE AS LOGIN = 'Maria';
GO
SELECT * FROM SuperVisao
GO
REVERT
GO

Id
———–
(0 row(s) affected)

Caso você dar o acesso da Maria á tabela do primeiro banco de dados, não será necessário utilizar a opção “Cross DB Ownership Chaining”.

Também é possível habilitar esta opção em todo o servidor com o seguinte comando:

sp_configure 'cross db ownership chaining', 1
GO
RECONFIGURE
GO

Referências:
http://msdn.microsoft.com/en-us/library/ms188694.aspx

Ocultando a instância do SQL Server

Nestes dias, me questionaram “como esconder as instâncias do SQL Server” numa rede, mas ainda possibilitando se conectar a elas (mais ou menos igual aos cenários de rede wireless, onde escondem o SSID, nome da rede, para “tentar” evitar invasões), pois o cenário que me foi apresentado, só mudar as portas de conexão do SQL Server não faria o que eles desejavam.

Vamos ao nosso cenário, precisamos esconder uma das instâncias do SQL Server que estão facilmente visíveis para toda rede.

Para isso, precisaremos do “SQL Server Configuration Manager”:

Nas configurações de rede do SQL Server, vamos às propriedades dos protocolos da instância que desejamos “ocultar”:

Alteremos a propriedade “Hide Instance” para “Yes” e em seguida reiniciamos o SQL Server.

Para validar, vamos ao Browser for Servers do SQL Server Management Studio… e onde esta aquela instância?

Pronto! De forma rápida resolvemos este “mini” cenário, fique tranquilo pois ainda é possível se conectar à instância que foi ocultada.

Se alguém esta em um cenário onde existe criptografia em todas conexões com o SQL Server, portas padrões do SQL Server alteradas, instâncias escondidas, autenticação somente por Windows Authentication, bloqueios de MAC e IP, dentre outras estratégias de segurança físicas e/ou lógicas, pode ficar tranquilo, neste mundo há cenários que isso é somente o básico do básico.

Existem vulnerabilidades no seu SGBD?

Para avaliar um software na perspectiva de segurança e vulnerabilidades, temos um site de bastante credibilidade para obter informação nesta prespectiva, o Secunia.com, que possui uma relação de milhares de softwares e quantitativos de vulnerabilidades.

Abaixo alguns SGBDs comuns relacionados por este site:

IBM DB2 9.x
http://secunia.com/advisories/product/13504/

Oracle 11.x
http://secunia.com/advisories/product/18050/

Microsoft SQL Server 2008
http://secunia.com/advisories/product/21744/

MySQL 5.x
http://secunia.com/advisories/product/8355/

PostgreSQL 8.x
http://secunia.com/advisories/product/4587/

E um menos comum, mas que eu já tive oportunidade de trabalhar:

Caché 5.x
http://secunia.com/advisories/product/1808/