Melhores Práticas para Reforçar as Configurações de Segurança do Servidor MySQL

Reforce o MySQL com usuários de privilégios mínimos, restrições de host, TLS, configurações mais seguras do my.cnf, aplicação de patches e auditoria básica.

Melhores Práticas para Reforçar as Configurações de Segurança do Servidor MySQL

O reforço do MySQL começa com uma pergunta simples: o que um invasor ganharia se uma senha de aplicação vazasse? Se a resposta for "todos os bancos de dados de qualquer lugar", seu servidor precisa de usuários, regras de rede e configurações mais restritivas.

Use estas práticas para reduzir o raio de explosão de uma violação sem tornar a administração diária dolorosa.

1. Gerenciamento de Usuários e Acesso: O Princípio do Menor Privilégio

Um gerenciamento eficaz de usuários é fundamental para a segurança do MySQL. Conceder aos usuários apenas as permissões que eles absolutamente precisam é primordial.

Crie Usuários Específicos para Aplicações Específicas

Evite usar o usuário root para conexões de aplicação. Em vez disso, crie usuários dedicados com permissões granulares.

CREATE USER 'meu_usuario_app'@'localhost' IDENTIFIED BY 'SenhaForte123!';
GRANT SELECT, INSERT, UPDATE, DELETE ON `seu_banco`.* TO 'meu_usuario_app'@'localhost';

Imponha Senhas Fortes

Senhas fortes e únicas são sua primeira linha de defesa. Utilize o plugin de validação de senha embutido do MySQL, se disponível.

  • Complexidade: Misture maiúsculas, minúsculas, números e símbolos.
  • Comprimento: Mire em pelo menos 12-16 caracteres.
  • Unicidade: Nunca reutilize senhas.
  • Rotação: Implemente uma política de troca regular de senhas.

Você pode habilitar o componente validate_password (MySQL 8.0+) ou plugin (MySQL 5.7+):

INSTALL COMPONENT 'file://component_validate_password';
-- OU para versões mais antigas
INSTALL PLUGIN validate_password SONAME 'validate_password.so';

-- Configure a política de força (ex.: MEDIUM para 8+ caracteres, misturar maiúsculas, números, especiais)
SET GLOBAL validate_password.policy = MEDIUM;
SET GLOBAL validate_password.length = 12;

Remova Usuários Padrão e Não Utilizados

O MySQL pode incluir contas administrativas e internas. Mantenha contas de sistema necessárias como mysql.session e mysql.sys intactas, mas remova contas anônimas e quaisquer contas humanas ou de aplicação que você não usa mais.

-- Para identificar usuários anônimos:
SELECT user, host FROM mysql.user WHERE user = '';
-- Para remover um usuário anônimo (se encontrado):
DROP USER ''@'localhost';

-- Para remover bancos de dados de teste (se existirem):
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\_%';
FLUSH PRIVILEGES;

Restrinja o Acesso por Host

Limite as contas de usuário para conectar apenas de endereços IP ou nomes de host específicos. Evite usar % como curinga para host, a menos que seja absolutamente necessário e combinado com outros controles de segurança fortes.

-- Usuário só pode conectar do localhost
CREATE USER 'admin'@'localhost' IDENTIFIED BY 'OutraSenhaForte!';

-- Usuário só pode conectar de um endereço IP específico
CREATE USER 'usuario_backup'@'192.168.1.100' IDENTIFIED BY 'SenhaBackup!';

Seja Cauteloso com GRANT OPTION

A cláusula WITH GRANT OPTION permite que um usuário conceda seus próprios privilégios a outros usuários. Isso pode ser um risco de segurança significativo se concedido a usuários não confiáveis. Use-a com moderação e apenas para contas administrativas que realmente precisam dessa capacidade.

-- Um usuário com capacidade de conceder privilégios (use com extrema cautela)
CREATE USER 'superadmin'@'localhost' IDENTIFIED BY 'SenhaSuperAdmin!';
GRANT ALL PRIVILEGES ON *.* TO 'superadmin'@'localhost' WITH GRANT OPTION;

2. Segurança de Rede: Isolando seu Banco de Dados

Controles em nível de rede são críticos para evitar acesso externo não autorizado ao seu servidor MySQL.

Configure Firewalls

Permita conexões à porta padrão do MySQL (3306) apenas de endereços IP ou redes confiáveis. Bloqueie todas as outras conexões de entrada para esta porta.

Exemplo (UFW no Linux):

sudo ufw enable
sudo ufw allow from 192.168.1.0/24 to any port 3306
sudo ufw deny 3306
sudo ufw status

Exemplo (CentOS/RHEL com firewalld):

sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="3306" protocol="tcp" accept'
sudo firewall-cmd --permanent --remove-port=3306/tcp --zone=public # Garanta que não esteja aberto globalmente
sudo firewall-cmd --reload

Proteja Conexões com SSL/TLS

Criptografe todo o tráfego entre clientes e o servidor MySQL usando SSL/TLS para evitar espionagem e ataques Man-in-the-Middle (MitM). Isso é especialmente crucial para conexões em redes não confiáveis.

Para habilitar SSL/TLS, você normalmente precisa gerar certificados e chaves SSL, então configurar seu my.cnf:

# my.cnf
[mysqld]
ssl_ca=/etc/mysql/certs/ca.pem
ssl_cert=/etc/mysql/certs/server-cert.pem
ssl_key=/etc/mysql/certs/server-key.pem

Os clientes devem então ser configurados para conectar usando SSL/TLS, frequentemente com REQUIRE SSL na declaração GRANT do usuário:

CREATE USER 'usuario_ssl'@'%' IDENTIFIED BY 'SenhaUsuarioSSL!';
GRANT SELECT ON `seu_banco`.* TO 'usuario_ssl'@'%' REQUIRE SSL;

Vincule a Endereços IP Específicos

Por padrão, o MySQL pode escutar em todas as interfaces de rede disponíveis (0.0.0.0). Restrinja-o para escutar apenas nas interfaces que precisam aceitar conexões (ex.: localhost para aplicações locais, ou um IP de rede privada para conexões internas).

# my.cnf
[mysqld]
bind-address = 127.0.0.1  # Apenas para conexões locais
# OU
bind-address = 192.168.1.10  # Para um IP interno específico

Dica: Se sua aplicação e servidor MySQL estão na mesma máquina, bind-address = 127.0.0.1 (localhost) é a opção mais segura, pois impede completamente qualquer conexão externa.

3. Reforço do Arquivo de Configuração (my.cnf / my.ini)

O arquivo de configuração do MySQL (my.cnf no Linux, my.ini no Windows) oferece inúmeros parâmetros para melhorar a segurança.

Desabilite Funcionalidades Não Utilizadas

Minimize a superfície de ataque desabilitando funcionalidades não necessárias para sua implantação.

  • local_infile = 0: Desabilita LOAD DATA LOCAL INFILE, que pode, de outra forma, ler arquivos do host cliente quando tanto o cliente quanto o servidor permitem.
    [mysqld]
    local_infile = 0
    
  • skip-networking: Se seu banco de dados é acessado apenas por aplicações no mesmo servidor, desabilite a rede completamente. Isso força todas as conexões a usar o socket Unix ou pipes nomeados.
    [mysqld]
    skip-networking
    
  • symbolic-links = 0: Impede o uso de links simbólicos para tablespaces do banco de dados, que podem ser explorados para acessar arquivos fora do diretório de dados do MySQL.
    [mysqld]
    symbolic-links = 0
    
  • secure_file_priv: Restringe o diretório usado por operações de importação e exportação de arquivos, como LOAD DATA INFILE e SELECT ... INTO OUTFILE.
    [mysqld]
    secure_file_priv = /var/lib/mysql-files
    

Defina secure_file_priv para um diretório dedicado de propriedade da conta de serviço do MySQL. Não aponte para /tmp, um diretório de upload de aplicação ou um caminho onde usuários não confiáveis possam escrever.

Evite Segredos em Texto Simples em Arquivos de Opções

Arquivos de opções do cliente podem expor acidentalmente senhas de banco de dados para qualquer um que possa lê-los. Se você precisar armazenar credenciais para automação, restrinja as permissões do arquivo e use uma conta dedicada de baixo privilégio.

chmod 600 /home/backup/.my.cnf
chown backup:backup /home/backup/.my.cnf

Para administração interativa, prefira solicitar a senha:

mysql -u admin -p

4. Aplique Patches e Verifique o Servidor

A configuração de segurança não salvará um servidor sem patches. Mantenha o MySQL, as bibliotecas cliente e o sistema operacional atualizados através do seu processo normal de pacotes ou atualizações do fornecedor.

Após alterar o my.cnf, valide e reinicie durante uma janela de manutenção:

mysqld --validate-config
sudo systemctl restart mysql
sudo systemctl status mysql

Os nomes dos pacotes e serviços variam conforme a distribuição. Alguns sistemas usam mysqld em vez de mysql.

5. Monitore o Acesso e Revise Privilégios

O reforço não termina após a primeira passagem. Revise contas e concessões regularmente, especialmente após mudanças na aplicação ou rotatividade de pessoal.

SELECT user, host, account_locked FROM mysql.user ORDER BY user, host;
SHOW GRANTS FOR 'meu_usuario_app'@'localhost';

Fique atento a contas que usam hosts %, privilégios amplos *.*, FILE, SUPER, SYSTEM_USER ou WITH GRANT OPTION. Esses privilégios podem ser válidos para um pequeno número de contas administrativas, mas nunca devem aparecer em usuários de aplicação rotineiros.

Conclusão

Reforce o MySQL em camadas. Comece com usuários dedicados de privilégios mínimos, restrinja de onde eles podem conectar, criptografe o tráfego quando ele cruzar uma rede, desabilite funcionalidades arriscadas que você não usa e mantenha o servidor atualizado. Em seguida, agende revisões de privilégios para que acessos antigos não se tornem silenciosamente seu próximo incidente.