As contas de usuários do MySQL estão lisatadas na tabela
user
do banco de dados
mysql
. Para cada conta do MySQL é definida
uma senha, no entanto o que está armazenado na coluna
Password
da tabela user
não seja uma versão da senha em texto puro, mas um valor hash
computado para ela. Valores hash de senha são calculados pela
função PASSWORD()
.
O MySQL usa senhas em duas fases da comunicação cliente/servidor:
Primeiro, quando um cliente tenta se conectar ao servidor, existe uma etapa de autenticação inicial na qual o cliente deve apresentar uma senha que combina com o valor hash armazenado na tabela de usuários para a conta que aquele cliente deseja usar.
Em segundo lugar, depois que o cliente conecta, ele pode configurar ou alterar o hash da senha para as contas listadas na tabela de usuário (se ele tiver privilégios suficientes).O cliente pode fazer isto usando a função PASSWORD() para gerar uma hash da senha ou usando as instruções GRANT ou SET PASSWORD.
Em outra palavras, o servidor usa valores
hash durante a autenticação quando um cliente tenta a primeira
conexão. O servidor gera os valores hash
se um cliente conectado chama a função
PASSWORD()
ou usa uma instrução
GRANT
ou SET PASSWORD
para
definir ou alterar uma senha.
O mecanismo de hash da senha foi atualizado no MySQL 4.1 para
fornecer melhor segurança e reduzir os riscos de senhas serem
roubadas. No entanto, Este novo mecanismo só é interpretado
pelo servidor 4.1 e clientes 4.1, que podem resultar em alguns
problemas de compatibilidade. Um cliente 4.1 pode conectar a um
servidor pre-4.1, porque o cliente entende tanto o antigo quanto
o novo mecanismo hash de senha. No entanto, um cliente pre-4.1
que tentar se conectar a um servidor 4.1 pode encontrar
dificuldades. Por exemplo, um cliente mysql
4.0 que tentar se conectar a um servidor 4.1 pode falhar com a
seguinte mensagem de erro:
shell> mysql
Client does not support authentication protocol requested
by server; consider upgrading MySQL client
A seguinte discussão descreve a diferença entre o antigo e o novo mecanismo de senha, e o que você deve fazer se você atualizar o seu servidor para a versão 4.1 mas precizar de manter compatibilidade com clientes pre-4.1.
Nota: Esta discussão contrasta no comportamento da versão 4.1 com o comportamento da pre-4.1, mas o da versão 4.1 descrito aqui começa relamente na versão 4.1.1. O MySQL é uma distribuição ``disferente'' porque ela tem um mecanismo um pouco diferente daquele implementado na 4.1.1 e acima. Diferenças entre a versão 4.1.0 e as versões mais recentes são descritas posteriormente.
Antes do MySQL 4.1, o hash de senha calculado pela função
PASSWORD()
tem tamanho de 16 bytes. Este hash
se parece com:
mysql> SELECT PASSWORD('mypass');
+--------------------+
| PASSWORD('mypass') |
+--------------------+
| 6f8c114b58f2ce9e |
+--------------------+
A coluna Password
da tabela
user
(na qual estes hashes são armazenados)
também têm 16 bytes de tamanho antes do MySQL 4.1.
A partir do MySQL 4.1, a função PASSWORD()
foi modificada para produzir um valor hash de 41 bytes.
mysql> SELECT PASSWORD('mypass');
+-----------------------------------------------+
| PASSWORD('mypass') |
+-----------------------------------------------+
| *43c8aa34cdc98eddd3de1fe9a9c2c2a9f92bb2098d75 |
+-----------------------------------------------+
De acordo com o mostrado, a coluna Password
na tabela user
também deve ter 41 bytes para
armazeanar estes valores.
Se você realiza uma nova instalação do MySQL 4.1, a
coluna Password
será convertida para o
tamanho de 41 bytes automaticamente.
Se você atualizar uma instalação mais antiga para a
versão 4.1, você executar o script
mysql_fix_privilege_tables
para atualizar
o tamanho da coluna Password
de 16 para
41 bytes. (O script não altera valores de senhas
existentes, que continuam com 16 bytes.)
Uma coluna Password
mais larga pode armazenar
hashes de senha no formato novo e no antigo. O formato de
qualquer valor de hash de senha dado podeser determinado de dois
modos:
A diferença óbvia é o tamanho (16 bytes versus 41 bytes)
A segunda diferença é que os hashes de senha no novo
formato sempre começam com um caracter
‘*
’, que as senhas no formato
antigo nunca faziam.
O formato maior do hash de senha tetm melhores propriedades criptográficas, e a autenticação do cliente baseada em hashs mais longos é mais segura que aquela baseada nos antigos hashes menores.
A diferença entre os hashs de senhas menores e maiores são relevantes em como o servidor usa as senhas durante a autenticação e como ela gera hash de senhas para clientes conectados que realizam operações de alteração de senha.
O modo no qual o servidor usa o hash de senha durante a autenticação é afetada pela largura da coluna Password:
Se a coluna não for larga, apenas a autenticação de hash curto é usada.
Se a coluna é larga, ela pode guardar tanto hash curtas quanto hashs longas, e o servidor pode usar ambos os formatos:
Clientes pre-4.1 podem conectar, mas como els só conhecem o mecanismo hash antigo, eles só podem se conectar pelas contas com hashes curtos.
Clientes 4.1 podem autenticar contas com hashes longos ou curtos.
Para contas com o hash curto, o processo de autenticação é na verdade um pouco mais seguro para clientes 4.1 que para clientes mais antigos. Em termos de segurança, o gradiente do menos para o mais seguro é:
Clientes pre-4.1 autenticando em contas com hash de senha curto
Clientes 4.1 autenticando em contas com hash de senha curto
Clientes 4.1 autenticando em contas com hash de senha longo
O modo no qual o servidor gera hashes de senhas para clientes
conectados é afetado pela largura da coluna
Password
e pela opção
--old-passwords
. Um servidor 4.1 gera hashes
longos apenas se certas condicões forem encontradas: A coluna
Password
deve ser grande o suficiente para
armazenar valores longos e a opção
--old-passwords
não deve ser dada. Estas
condições se aplicam da seguinte forma:
A coluna Password
deve ser grande o
suficiente para armazenar hashes longos (41 bytes). Se a
coluna não foi atualizada e ainda tem a largura de 16 bytes
(antes da 4.1), o servidor avisa que o hash não pode caber
nela e gera apenas hashes curtos quando um cliente realiza a
operação de troca de senha usando
PASSWORD()
, GRANT
, ou
SET PASSWORD
. (Este comportamento ocoree
se você tiver atualizado para a versão 4.1 mas não
executou o script
mysql_fix_privilege_tables
para aumentar
a coluna Password
.)
Se a coluna Password
for larga, ela
poderá aramazenar tanto os hashes de senha curtos quanto os
longos. Neste caso, PASSWORD()
,
GRANT
, e SET PASSWORD
irão gerar hashes longos a menos que o servidor tenha sido
iniciado com a opção --old-passwords
.
Esta opção força o servidor a gerar hashes de senha
curtos.
O propósito da opção --old-passwords
é
permitir que você mantenha compatibilidade com clientes com
versões anteriores à 4.1 sob circunstâncias nas quais os
servidores gerariam hashes de senha longos. Ele não afeta a
autenticação (clientes 4.1 podem ainda usar contas que possuem
hash de senha longo), mas ele não previne a criaçõa de um
hash de senha longo na tabela user
como
resultado de uma operação de troca de senha. Onde isto
ocorrer, a conta não mais poderá ser usada por clientes
pré-4.1. Se a opção --old-passwords
, o
seguinte cenário é possível:
Um cliente antigo conecta a uma conta que têm um hash de senha curto.
O cliente altera a senha das contas. Sem
--old-passwords
, isto resulta na conta que
têm um hash de senha longo.
A próxima vez que o cliente antigo tentar se conectar à conta, ele não conseguirá, porque a conta agora exige o novo mecanismo de hash durante a autenticação. (Uma vez que uma conta tem um hash de senha longo na tabela de usuário, apenas os clientes 4.1 poderão ser autenticados, porque clientes de versões anteriores a 4.1 não entendem o hash longo.)
Este cenário mostra que é perigoso executar um servidor 4.1
sem usar a opção --old-passwords
, operações
de alteração de senha não irão gerar hashes de senha longos
e assim não faz com que as contas se tornem inacessíveis para
clientes mais antigos. (Estes clientes não podem bloquear eles
mesmos inadivertidamente alterando suas senhas e ficando com um
hash de senha longo.
A desvantagem da opção --old-passwords
é que
qualquer senha que você criar ou alterar usará hashes curtos,
mesmo para clientes 4.1. Assim, você perde a segurança
adicional fornecida pelos hashes de senha longos. Se você
quiser criar uma conta qye tenha um hash longo (por exemplom
parr uso pelos clientes 4.1), você deve fazê-lo enquanto
executa o servidor sem a opção
--old-passwords
.
Os seguintes cenários são possíveis para executar um servidor 4.1:
Cenario 1) Coluna Password
menor na tabela de
usuários
Apenas hashes curtos podem ser armazenados na coluna
Password
.
O servidor usa apenas hasghes curtos durante a autenticação do cliente.
Para clientes conectados, operações de geração de hash
de senha envolvendo PASSWORD()
,
GRANT
ou SET PASSWORD
usa hashes curtos exclusivamebnte. Qualquer alteração a
senha de uma conta faz com que a conta tenha um hash de
senha curto.
A opção --old-passwords
pode ser usada
mas é superflua porque com uma coluna
Password
menor, o servidor irá gerar
hashes de senha curtos de qualquer forma.
Cenário 2) Colunas Password
longas; servidor
não iniciado com a opção --old-passwords
Hashes de senha longos e curtos podem ser armazenados na
coluna Password
.
Clientes 4.1 podem autenticar contas com hashes curtos ou longos.
Clientes anteioriores ao 4.1 só podem autenticar contas com hash curto.
Para clientes conectados, operações de geração de hash
de senha envolvendo PASSWORD()
,
GRANT
, ou SET PASSWORD
usam hashes longos exclusivamente. Qualquer mudança na
senha de uma conta fará com que ela possua um hash de senha
longo.
OLD_PASSWORD()
pode ser usado para gerar
explicitamente um hash curto. Por exemplo, para atribuir uma
senha curta a uma conta, use UPDATE
da
seguinte forma:
mysql>UPDATE user SET Password = OLD_PASSWORD('mypass')
->WHERE Host = 'some_host' AND User = 'some_user';
mysql>FLUSH PRIVILEGES;
Como indicado anteriormente, o perigoso neste cenário é que é
possível que contas com hashes de senha curtos se tornem
inacessíveis para cliente anteriores ao 4.1. Qualquer
alteração a senha de uma conta feita via
GRANT
, SET PASSWORD
, ou
PASSWORD()
faz com que a conta tenha um hash
de senha longo, e a partir deste ponto, nenhum cliente anterior
ao 4.1 poderá autenticar esta conta até que ele seja
atualizado para a versão 4.1.
Cenário 3) Coluna Password
longa; servidor
iniciado com a opção --old-passwords
Hashes longos e curtos podem ser armazenados na coluna
Password
.
Clientes 4.1 podem autenticar contas que tenham hashes
longos ou curtos (mas note que é possível criar hashes
longos apenas quando o servidor é iniciado sem
--old-passwords
).
Clientes anteriores ao 4.1 podem autentticar apenas contas com hashes curtos.
Para clientes conectados, operações de geração de hash
de senha envolvendo PASSWORD()
,
GRANT
, ou SET PASSWORD
usa hashes curtos exclusivamente. Qualquer alteração em
uma senha de conta faz com que a conta tenha um hash de
senha curto.
Neste cenário, você não pode criar contas que tenham hashes
de senha longo, porque --old-passwords
previne
a criação de hashes longos. Também, se você criar uma conta
com um hash longo antes de usar a opção
--old-passwords
, alterar a senha da conta
enquanto --old-passwords
está funcionando faz
com que seja dada a conta uma sena curta, fazendo com que ela
perca os benefícios de segurança de um hash longo.
As disvantagens para este cenário pode ser resumido como a seguir:
Cenário 1) Você não pode tirar vantagem do hash longo que fornece mais autenticação segura.
Cenário 2) Contas com hashes curtos tornam clientes anteriores
ao 4.1 inacessíveis se você alterar a senha deles sem usar
OLD_PASSWORD()
explicitamente.
Cenário 3) --old-passwords
evita que as contas
com hashes curtos se tornem inacessíveis, mas operações de
alteração de senhas fazem com que as contas com hashes longos
seja revertida para hashes curtos, e você não pode alterá-las
de volta para hashes longos enquanto
--old-passwords
está em efeito.
Implicações de Alteração de Hashes de Senha para Aplicativos
Um atualização para o MySQL 4.1 para trazer problemas de
compatibilidade para aplicações que usam
PASSWORD()
para gerar senha para os seus
próprios propósitos. (Aplicativos não devem fazer isto,
porque PASSWORD()
deve ser usado paenas para
gerenciar contas do MySQL. Mas algumas aplicações usam
PASSWORD()
para seus próprios propósitos.)
Se você atualizar para o MySQL 4.1 e executar o servidor sob
condições onde ele gera hashes de senha longo, uma aplicação
que usa PASSWORD()
para as suas próprias
senhas irá falhar. O curso de ação recomendado é modificar o
aplicativo para usar outras funções como
SHA1()
ou MD5()
para
produzir valores de hash. Se isto não for possível você pode
utilizar a função OLD_PASSWORD()
, que é
fornecida para gerar hashes curtos no formato antigo. (Mas note
que OLD_PASSWORD()
pode vir a não ser mais
suportado.)
Se o servidor está rodando sob circuntâncias onde ele gera
hashes de senha curtos, OLD_PASSWORD()
está
disponível mas é equivalente a PASSWORD()
.
Hash de senhas no MySQL 4.1.0 difere do hash no 4.1.1 e acima. As diferenças da versão 4.1.0 são as seguintes:
Hashes de senhas de 45 bytes em vez de 41 bytes.
A função PASSWORD()
não é
repetitível. Isto é, com um dado argumento
X
, successivas chamadas a
PASSWORD(X)
geram diferentes resultados.
This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.