Programação Por Equipe DevBras

Capa do artigo: phpMyAdmin exposto na internet: tire da URL pública e acesse por túnel SSH

phpMyAdmin exposto na internet: tire da URL pública e acesse por túnel SSH

Descubra se o seu phpMyAdmin responde para qualquer um, restrinja ao próprio servidor, entre por túnel SSH e tire do painel o login de root e o usuário com poder demais.

Abra o log de acesso de qualquer servidor web com IP público e procure por phpmyadmin. Na VPS da Casa Pinho foram 640 pedidos num único dia, vindos de dezenas de IPs, testando /phpmyadmin/, /pma/, /myadmin/ e variações. Ninguém da loja acessou o painel nesse dia. A resposta curta: o phpMyAdmin não deve responder para a internet. Restrinja o acesso ao próprio servidor e entre por túnel SSH; se ninguém usa, remova. Além disso, proíba o login de root no painel e use um usuário de banco com privilégios só no banco certo.

O painel é uma interface completa para o banco. Quem passa pela tela de login pode ler, alterar e apagar tudo que o usuário logado alcança, e com root isso é o servidor de banco inteiro.

Por que o painel aberto atrai tanto ataque

Robôs varrem faixas inteiras de IP procurando caminhos conhecidos. O phpMyAdmin é um dos alvos favoritos por três motivos: o caminho padrão é previsível, muitas instalações vêm de pacotes que sugerem usuário root, e o prêmio é o banco inteiro. Cada pedido é uma tentativa de senha ou um teste de vulnerabilidade da versão instalada.

Trocar o caminho para algo como /painel-banco-7x/ reduz o barulho no log, mas não protege. O nome vaza em histórico, em print, em documentação. A proteção real é o painel não responder para quem não está no servidor. Se a página nem carrega, senha fraca e falha de versão deixam de ser urgentes.

Primeiro, descubra se o seu está exposto

Teste de fora da sua rede, por exemplo pelo celular no 4G, para não confundir com alguma liberação do escritório:

curl -sI https://loja.exemplo.com.br/phpmyadmin/ | head -n 1

Se a primeira linha for HTTP/1.1 200 OK ou um redirecionamento para a tela de login, o painel está público. Confira também o tamanho do interesse alheio no log:

sudo grep -ci "phpmyadmin" /var/log/apache2/access.log

O caminho do log varia por distribuição e servidor web. No nginx costuma ser /var/log/nginx/access.log.

Como restringir o painel ao próprio servidor

  1. Pergunte se alguém realmente usa o painel. Se a resposta for não, remova o pacote e pare por aqui.
  2. Restrinja o acesso ao endereço local do servidor.
  3. Recarregue o servidor web e confirme, de fora, que a resposta virou 403.
  4. Acesse por túnel SSH a partir da sua máquina.
  5. Endureça a configuração do phpMyAdmin e os usuários do MySQL.
  6. Mantenha o pacote atualizado junto com o resto do sistema.

Apache: só o próprio servidor entra

No Debian e no Ubuntu, o pacote do phpMyAdmin instala um arquivo de configuração do Apache com um bloco Directory apontando para /usr/share/phpmyadmin. Dentro desse bloco, acrescente a regra de acesso:

<Directory /usr/share/phpmyadmin>
    Require local
    # ... o restante da configuração do pacote continua igual
</Directory>
sudo apachectl configtest && sudo systemctl reload apache2

O Require local do Apache 2.4 libera só conexões vindas do próprio servidor. De fora, a resposta passa a ser 403. Se aparecer 403 também onde você não esperava, o guia sobre erro 403 no Apache ajuda a achar qual regra está recusando.

No nginx, o equivalente é colocar allow 127.0.0.1; e deny all; no bloco location do painel.

O túnel SSH até o painel

Com o painel restrito ao servidor, você leva o navegador até lá pelo SSH. Na sua máquina:

ssh -N -L 8081:127.0.0.1:80 deploy@203.0.113.10

Enquanto esse comando estiver rodando, abra http://localhost:8081/phpmyadmin/. O pedido entra cifrado pelo SSH e chega ao Apache como se viesse do próprio servidor, por isso passa no Require local. Ao fechar o terminal, o acesso acaba. Use chave em vez de senha no SSH, como mostra o guia de chave SSH na VM.

Se você prefere um cliente de desktop como MySQL Workbench ou DBeaver, o mesmo túnel funciona apontando para a porta do MySQL (-L 3307:127.0.0.1:3306), e os dois clientes também têm opção de túnel SSH embutida. Aí o phpMyAdmin pode simplesmente sair do servidor.

Endureça o painel e os usuários do banco

A restrição de rede é a barreira principal. As configurações abaixo valem para o dia em que alguém afrouxar a regra por engano. No Debian e no Ubuntu, o arquivo fica em /etc/phpmyadmin/config.inc.php:

$cfg['Servers'][$i]['AllowRoot'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false;
$cfg['LoginCookieValidity'] = 1800;

A primeira linha impede o login de root pelo painel. A segunda recusa usuários sem senha. A terceira encerra a sessão depois de 30 minutos sem uso, em segundos.

No MySQL, separe os papéis. O usuário da aplicação só precisa ler e gravar no banco da loja. O usuário humano de manutenção pode ter mais, mas só a partir do próprio servidor:

CREATE USER 'loja_app'@'localhost' IDENTIFIED BY 'senha-longa-gerada-para-a-aplicacao';
GRANT SELECT, INSERT, UPDATE, DELETE ON loja.* TO 'loja_app'@'localhost';

CREATE USER 'marco_admin'@'localhost' IDENTIFIED BY 'outra-senha-longa-e-unica';
GRANT ALL PRIVILEGES ON loja.* TO 'marco_admin'@'localhost';

Com isso, mesmo quem descobrir a senha da aplicação não consegue criar usuários nem apagar outros bancos. No Ubuntu, o root do MySQL costuma autenticar pelo usuário do sistema (plugin auth_socket), o que já impede login de root por senha no painel. Confira antes de mudar.

Na hospedagem compartilhada

Painéis de hospedagem costumam oferecer o phpMyAdmin por trás do login do próprio painel, com o usuário do banco já limitado à sua conta. Esse caminho é aceitável, desde que a senha do painel seja forte e tenha segundo fator se a hospedagem oferecer. O perigo é a cópia que alguém instalou à mão dentro de public_html "para facilitar". Procure e apague.

Se o seu banco está num serviço gratuito com painel público, o problema é maior que o phpMyAdmin. O guia sobre MySQL grátis na internet mostra como sair de lá.

Erros comuns

  • Só trocar o caminho do painel: o barulho no log diminui, mas o painel continua respondendo para quem descobrir o endereço.
  • Entrar no painel como root: uma senha vazada entrega todos os bancos do servidor, e não só o da loja.
  • Usar o mesmo usuário para a aplicação e para manutenção: uma injeção de SQL na aplicação ganha o poder de apagar tabelas e criar usuários.
  • Liberar o IP do escritório e esquecer: o IP muda, alguém amplia a regra para "todos" no improviso e ela fica.
  • Deixar o pacote desatualizado: falhas antigas do phpMyAdmin são justamente o que os robôs testam.
  • Abrir a porta 3306 para a internet como alternativa: troca um painel exposto por um banco exposto.

Checklist

  • De fora da sua rede, o caminho do painel responde 403 ou 404.
  • O acesso ao painel, quando existe, passa por túnel SSH com chave.
  • AllowRoot e AllowNoPassword estão desligados.
  • A aplicação usa um usuário com SELECT, INSERT, UPDATE e DELETE só no próprio banco.
  • Nenhuma cópia manual do phpMyAdmin está dentro da raiz pública do site.
  • A porta do MySQL não aceita conexões da internet.
  • O pacote do painel recebe atualização junto com o sistema.

Pegue o celular, desligue o Wi-Fi e abra o endereço do seu site seguido de /phpmyadmin/: aparece uma tela de login ou uma recusa?

Avalie este artigo

Referência: http://eu5org.freewebhostingarea.com/pma/