Correção da falta de variação de sal criptográfico no SQL Server sa hash de logon

No Microsoft SQL Server 2005 e em versões posteriores, várias instâncias do SQL Server usam o mesmo salt criptográfico para o logon SA interno. Como o sal é o mesmo para todas as instalações, certos tipos de ataques de força bruta se tornam mais práticos se o invasor puder primeiro obter acesso à senha com hash. As senhas com hash estão disponíveis apenas para os administradores do SQL Server.

Sintomas

No SQL Server 2005 e em versões posteriores, o sal criptográfico é gerado junto com o logon sa. Se CHECK_POLICY estiver habilitado, o sal criptográfico não será regenerado quando o usuário alterar a senha para ser consistente com o histórico de senhas. Por padrão, o CHECK_POLICY está habilitado para o SQL Server 2005. Quando a CHECK_POLICY é desabilitada, a consistência salt não é mais necessária para o logon sa e um novo salt é regenerado na próxima alteração de senha.

Embora isso seja verdadeiro para todas as contas, a conta de logon sa é gerada durante o processo de compilação. Portanto, seu salt é criado durante o mesmo processo de compilação e é mantido durante uma instância da instalação do SQL Server.

Observação Para o SQL Server 2008, esse problema também afeta os logons padrão usados pelo recurso Gerenciamento Baseado em Política, mas o risco é reduzido. Por padrão, esses logons estão desabilitados.

Mitigações

Mesmo que o sal criptográfico permaneça o mesmo em várias instalações, isso não será suficiente para comprometer o hash da senha. Para explorar esse comportamento, o usuário mal-intencionado teria que ter acesso administrativo a uma instância do SQL Server para obter o hash de senha. Se as práticas recomendadas forem seguidas, os usuários comuns não poderão recuperar o hash de senha. Portanto, eles seriam incapazes de explorar a falta de variação criptográfica de sal.

Causa

Informações sobre o service pack do SQL Server 2005

Para resolver esse problema, obtenha o service pack mais recente do SQL Server 2005. Para obter mais informações, clique no número abaixo para ler o artigo da Base de Dados de Conhecimento Microsoft:

913089 Como obter o service pack mais recente do SQL Server 2005

Informações sobre o service pack do SQL Server 2008

Para resolver esse problema, obtenha o service pack mais recente do SQL Server 2008. Para obter mais informações, clique no número abaixo para ler o artigo da Base de Dados de Conhecimento Microsoft:

968382 Como obter o service pack mais recente do SQL Server 2008

Resolução

Para o SQL Server 2005 Service Pack 2 ou versões posteriores, você pode executar o script a seguir para redefinir o salt criptográfico da conta de logon sa. Para executar o script, você deve estar conectado com uma conta que tenha permissões de SERVIDOR DE CONTROLE ou a conta deve ser membro da função de servidor sysadmin. Você deve estar ciente de que, depois de redefinir o sal criptográfico, o histórico de senhas do login sa também será redefinido.

-- Work around for SQL Server 2005 SP2+
--
-- Sets the password policy check off for [sa]
-- Replaces [sa] password with a random byte array
-- NOTE: This effectively replaces the sa password hash with 
-- a random bag of bytes, including the salt,
-- and finally sets the password policy check on again
--
-- After resetting the salt, 
-- it is necessary to set the sa password,
-- or if preferred, disable sa
--
CREATE PROC #sp_set_new_password_and_set_for_sa(@new_password sysname, @print_only int = null)
AS
DECLARE @reset_salt_pswdhash nvarchar(max)
DECLARE @random_data varbinary(24)
DECLARE @hexstring nvarchar(max)
DECLARE @i int
DECLARE @sa_name sysname;

SET @sa_name = suser_sname(0x01);
SET @random_data = convert(varbinary(16), newid()) + convert(varbinary(8), newid())
SET @hexstring = N'0123456789abcdef'
SET @reset_salt_pswdhash = N'0x0100'
SET @i = 1
WHILE @i <= 24
BEGIN
declare @tempint int
declare @firstint int
declare @secondint int

select @tempint = convert(int, substring(@random_data,@i,1))
select @firstint = floor(@tempint/16)
select @secondint = @tempint - (@firstint*16)

select @reset_salt_pswdhash = @reset_salt_pswdhash +
substring(@hexstring, @firstint+1, 1) +
substring(@hexstring, @secondint+1, 1)

set @i = @i+1
END

DECLARE @sql_cmd nvarchar(max)

SET @sql_cmd = N'ALTER LOGIN ' + quotename(@sa_name) + N' WITH CHECK_POLICY = OFF;
ALTER LOGIN ' + quotename(@sa_name) + N' WITH PASSWORD = ' + @reset_salt_pswdhash + N' HASHED;
ALTER LOGIN ' + quotename(@sa_name) + N' WITH CHECK_POLICY = ON;
ALTER LOGIN ' + quotename(@sa_name) + N' WITH PASSWORD = ' + quotename(@new_password, '''') + ';'

IF( @print_only is not null AND @print_only = 1 )
print @sql_cmd
ELSE
EXEC( @sql_cmd )
go

---------------------------------------------------------------------------------------
-- Usage example:
--
DECLARE @new_password sysname 

-- Use tracing obfuscation in order to filter the new password from SQL traces
-- http://blogs.msdn.com/sqlsecurity/archive/2009/06/10/filtering-obfuscating-sensitive-text-in-sql-server.aspx
--
SELECT @new_password = CASE WHEN 1=1 THEN 
    -- TODO: replace password placeholder below with a strong password
    --
   ##[MUST_CHANGE: replace this placehoder with a new password]##:
   ELSE EncryptByPassphrase('','') END
EXEC #sp_set_new_password_and_set_for_sa @new_password
go

DROP PROC #sp_set_new_password_and_set_for_sa 
go

Para o SQL Server 2008, você pode executar o script a seguir. Para executar o script, você deve estar conectado com uma conta que tenha permissões de SERVIDOR DE CONTROLE ou a conta deve ser membro da função de servidor sysadmin.

-- Work around for SQL Server 2008
--

------------------------------------------------------------------------
-- Set the password policy check off for [sa]
-- Reset the password
-- Set the password policy check on for [sa] once again
-- 
-- NOTE: The password history will be deleted
--
CREATE PROC #sp_set_new_password_and_set_for_sa(@new_password sysname, @print_only int = null) 
AS
DECLARE @sql_cmd nvarchar(max);

DECLARE @sa_name sysname;

-- Get the current name for SID 0x01. 
-- By default the name should be "sa", but the actual name may have been chnaged by the system administrator
--
SELECT @sa_name = suser_sname(0x01);

-- NOTE: This password will not be subject to password policy or complexity checks
-- if desired, this step can be replaced with a "throw away" password for 
-- and set the real password after the check policy setting has been set
--
SELECT @sql_cmd = 'ALTER LOGIN ' + quotename(@sa_name) + ' WITH CHECK_POLICY = OFF;
ALTER LOGIN ' + quotename(@sa_name) + ' WITH PASSWORD = ' + quotename(@new_password, '''') + ';
ALTER LOGIN ' + quotename(@sa_name) + ' WITH CHECK_POLICY = ON;'

IF( @print_only is not null AND @print_only = 1 )
print @sql_cmd
ELSE
EXEC( @sql_cmd )
go

---------------------------------------------------------------------------------------
-- Usage example:
--
DECLARE @new_password sysname

-- Use tracing obfuscation in order to filter the new password from SQL traces
-- http://blogs.msdn.com/sqlsecurity/archive/2009/06/10/filtering-obfuscating-sensitive-text-in-sql-server.aspx
--
SELECT @new_password = CASE WHEN 1=1 THEN 
    -- TODO: replace password placeholder below with a strong password
    --
   ##[MUST_CHANGE: replace this placehoder with a new password]##:
   ELSE EncryptByPassphrase('','') END
EXEC #sp_set_new_password_and_set_for_sa @new_password
go

DROP PROC #sp_set_new_password_and_set_for_sa 
go

No SQL Server 2008, o salt criptográfico para os logons de Gerenciamento Baseado em Política pode ser redefinido usando o script a seguir. Para executar o script, você deve estar conectado com uma conta que tenha permissões de SERVIDOR DE CONTROLE ou a conta deve ser membro da função de servidor sysadmin.

------------------------------------------------------------------------
-- Set the password policy check off for the Policy principals
-- Reset the password
-- Set the password policy check on for them once again
--
-- NOTE: 
-- These principals are not intended to establish connections to SQL Server
-- So this SP will also make sure they are disabled
--
CREATE PROC #sp_reset_password_and_disable(@principal_name sysname, @print_only int = null) 
AS
DECLARE @random_password nvarchar(max)

SET @random_password = convert(nvarchar(max), newid()) + convert(nvarchar(max), newid())
DECLARE @sql_cmd nvarchar(max)

SET @sql_cmd = N'ALTER LOGIN ' + quotename(@principal_name) + N' WITH CHECK_POLICY = OFF;
ALTER LOGIN ' + quotename(@principal_name) + N' WITH PASSWORD = ''' + replace(@random_password, '''', '''''') + N''';
ALTER LOGIN ' + quotename(@principal_name) + N' WITH CHECK_POLICY = ON;
ALTER LOGIN ' + quotename(@principal_name) + N' DISABLE;'

IF( @print_only is not null AND @print_only = 1 )
print @sql_cmd
ELSE
EXEC( @sql_cmd )
go

EXEC #sp_reset_password_and_disable '##MS_PolicyEventProcessingLogin##';
EXEC #sp_reset_password_and_disable '##MS_PolicyTsqlExecutionLogin##';
go

SELECT name, password_hash, is_disabled FROM sys.sql_logins
go

Solução alternativa

A Microsoft confirmou que este é um problema nos produtos da Microsoft listados na seção "Aplica-se a".
Esse problema foi corrigido pela primeira vez no SQL Server 2005 Service Pack 4 para SQL Server 2005.
Esse problema foi corrigido pela primeira vez no SQL Server 2008 Service Pack 2 para SQL Server 2008.

Status

A Microsoft agradece aos seguintes por trabalharem conosco para ajudar a proteger os clientes:

Mais informações