Como encontrar e remover um crypto miner do servidor
Última atualização:
Um minerador de criptomoedas é o que mais se encontra num servidor Linux comprometido. Ele usa toda a CPU que consegue para minerar Monero ou outra moeda para outra pessoa, e o primeiro sinal costuma ser um site lento, a ventoinha no máximo, uma cobrança de créditos de CPU ou um e-mail de abuso do provedor.
O minerador em si é a parte fácil. O que importa é o que deixou ele entrar e o que faz ele voltar: um cron, uma unidade systemd, uma chave SSH, uma biblioteca pré-carregada em todos os processos. Siga esta ordem: encontrar, conter, remover, achar o ponto de entrada, reforçar. Os comandos são para Debian e Ubuntu e para a família RHEL; PID é o ID do processo que você encontrar no passo 1.
Identifique o minerador
Comece pelo que está usando a CPU. Um minerador normalmente ocupa um processo a 100% por núcleo, rodando há dias.
ps -eo pid,user,%cpu,etime,args --sort=-%cpu | head -n 15- Nomes:
xmrige suas variantes, ou nomes escolhidos para parecer inofensivos:kdevtmpfsi,kinsing,kworkerds, um[kthreadd]escrito à mão, uma sequência aleatória de caracteres. - Uma thread do kernel aparece entre colchetes e não tem binário: um nome entre colchetes com um caminho por trás é falso.
- O usuário: um minerador rodando como
www-data,apache,nginx,redisoupostgresentrou por esse serviço.
Para um PID suspeito, veja o binário, o diretório de trabalho, a linha de comando completa e qual unidade systemd o iniciou:
sudo ls -l /proc/PID/exe /proc/PID/cwd
sudo tr '\0' ' ' < /proc/PID/cmdline; echo
systemctl status PIDUm binário que aparece como (deleted), ou que roda a partir de /tmp, /var/tmp ou /dev/shm, é um sinal forte. Este comando lista todos esses processos de uma vez:
sudo ls -l /proc/[0-9]*/exe 2>/dev/null | grep -E '\(deleted\)|/tmp/|/var/tmp/|/dev/shm/'Quando o top não mostra nada: ld.so.preload
Se a carga está alta mas nenhum processo explica isso, o minerador pode estar escondido atrás de uma biblioteca carregada em todos os programas pelo /etc/ld.so.preload. Esse arquivo normalmente não existe. Se ele existe e aponta para uma biblioteca que você não conhece, o ps e o top estão mentindo para você.
ls -l /etc/ld.so.preload 2>/dev/null && cat /etc/ld.so.preload
sudo grep -l LD_PRELOAD /proc/[0-9]*/environ 2>/dev/nullConexões com um pool de mineração
Os mineradores falam com um pool pelo protocolo stratum. Portas como 3333, 4444, 5555, 7777 e 14444 são típicas, mas os pools também escutam na 443 e na 80, então olhe também as conexões do próprio processo:
sudo ss -tnp state established '( dport = :3333 or dport = :4444 or dport = :5555 or dport = :7777 or dport = :14444 )'
sudo ss -tnp state established | grep PIDOs arquivos de configuração dos mineradores costumam ter a URL de um pool. Este comando procura por elas nos lugares de sempre:
sudo grep -rIl -E 'stratum\+(tcp|ssl)://|"pools"|donate-level' /tmp /var/tmp /dev/shm /root /home /var/www /etc 2>/dev/nullO que faz ele voltar
Procure a persistência antes de matar qualquer coisa, para saber o que remover. Primeiro o cron: linhas que baixam algo com curl ou wget, decodificam base64 ou rodam a partir de /tmp.
sudo cat /etc/crontab
sudo ls -la /etc/cron.d /etc/cron.hourly /etc/cron.daily /var/spool/cron 2>/dev/null
for u in $(cut -d: -f1 /etc/passwd); do sudo crontab -l -u "$u" 2>/dev/null | sed "s/^/$u: /"; done
sudo grep -rE 'curl|wget|base64|/tmp/|/dev/shm' /etc/crontab /etc/cron.* /var/spool/cron 2>/dev/nullDepois os timers do systemd e os arquivos de unidade alterados nos últimos 30 dias:
systemctl list-timers --all
sudo sh -c "find /etc/systemd/system /usr/lib/systemd/system /lib/systemd/system /root/.config/systemd /home/*/.config/systemd \
-type f \( -name '*.service' -o -name '*.timer' \) -mtime -30 2>/dev/null"Depois as chaves SSH que você não adicionou, o rc.local, os arquivos de inicialização do shell e as contas que você não criou:
sudo sh -c 'cat /root/.ssh/authorized_keys /home/*/.ssh/authorized_keys 2>/dev/null'
ls -l /etc/rc.local 2>/dev/null
sudo sh -c "grep -lE 'curl|wget|/tmp/|/dev/shm' /etc/profile.d/* /etc/bash.bashrc /etc/bashrc /root/.bashrc /root/.profile /home/*/.bashrc 2>/dev/null"
awk -F: '$3 == 0 || $3 >= 1000 {print $1, $3, $7}' /etc/passwdPor fim, confira se os binários do próprio sistema não foram substituídos. A saída lista os arquivos de pacotes cujo conteúdo mudou; os arquivos de configuração ficam de fora.
sudo dpkg --verify | grep -v ' c /'sudo rpm -Va 2>/dev/null | grep -E '^..5' | grep -v ' c /'Contenha o minerador
Se o seu provedor permite tirar um snapshot do disco, tire agora: ele guarda as evidências e um caminho de volta. Depois corte a ligação do minerador com o pool. Troque 198.51.100.23 pelo endereço do pool encontrado no passo 1. Esta tabela nftables funciona no Debian, no Ubuntu e na família RHEL junto com o ufw ou o firewalld, e some depois de um reboot.
sudo nft add table inet quarantine
sudo nft 'add chain inet quarantine out { type filter hook output priority 0; policy accept; }'
sudo nft add rule inet quarantine out ip daddr 198.51.100.23 dropGuarde uma cópia do binário e da linha de comando antes que sejam apagados. O /proc/PID/exe funciona mesmo quando o arquivo no disco já foi removido. O SHA-256 pode ser consultado em bases públicas de malware.
sudo mkdir -p /root/evidence
sudo cp /proc/PID/exe /root/evidence/miner.bin
sudo tr '\0' ' ' < /proc/PID/cmdline | sudo tee /root/evidence/cmdline.txt
sudo sha256sum /root/evidence/miner.binPrimeiro congele o processo, para que um watchdog não perceba que ele morreu e o reinicie na hora, veja o processo pai e só então mate o processo. Se o pai for um script ou um segundo processo minerador, cuide dele também.
sudo kill -STOP PID
ps -o pid,ppid,user,args -p PID
sudo kill -9 PIDAtenção: Considere que todos os segredos do servidor são conhecidos: chaves SSH, senhas, as senhas de banco de dados e as chaves de API no .env e nos arquivos de configuração. Troque tudo a partir de uma máquina limpa, começando pelas contas que dão acesso a outros servidores.
Remova o minerador e tudo o que faz ele voltar
Remova cada peça de persistência encontrada no passo 1 e depois os binários. Para uma unidade systemd (troque NAME):
sudo systemctl disable --now NAME.service
sudo rm /etc/systemd/system/NAME.service
sudo systemctl daemon-reload- Cron: apague as linhas com
sudo crontab -e -u USERe os arquivos em/etc/cron.dque você não criou. - SSH: apague de cada
authorized_keysas chaves que você não reconhece. - Contas: bloqueie ou apague os usuários que você não criou (
sudo usermod -L NAME) e confira o/etc/sudoerse o/etc/sudoers.d/. - Binários e arquivos de configuração do minerador, onde quer que o passo 1 os tenha encontrado.
Os mineradores muitas vezes deixam seus arquivos imutáveis, para que o rm falhe com Operation not permitted mesmo como root. Verifique e remova os atributos primeiro:
sudo lsattr /path/to/file
sudo chattr -i -a /path/to/file
sudo rm /path/to/fileSe o /etc/ld.so.preload aponta para uma biblioteca que você não conhece, tire o arquivo do lugar (é raro um software legítimo usá-lo) e apague a biblioteca indicada:
sudo mv /etc/ld.so.preload /root/evidence/ld.so.preload
sudo ldconfigReinicie, depois confira a CPU de novo após uma hora e no dia seguinte: um minerador que volta significa que ainda sobrou uma peça de persistência ou o ponto de entrada continua aberto.
Atenção: Se o minerador rodou como root, se binários do sistema foram alterados ou se o ld.so.preload foi usado, não dá para ter certeza de que o servidor está limpo. Reconstrua a partir de uma imagem nova e restaure os dados de um backup feito antes da infecção, depois de conferi-lo. Limpar no lugar só é razoável quando o minerador rodou como um usuário sem privilégios e nada fora dos arquivos desse usuário mudou.
Descubra como ele entrou
Se você não fechar a porta de entrada, o minerador volta em poucos dias. O usuário com que o minerador rodava e a data de criação dos arquivos dele apontam o caminho:
ps -o user,pid,lstart,args -p PID
sudo stat /path/to/miner- Rodando como o usuário do servidor web: um plugin, tema ou aplicação vulnerável, ou um formulário de upload. Olhe os logs web perto do horário em que o arquivo apareceu.
- Rodando como
redis, ou com arquivos criados por ele: Redis aberto para a internet sem senha. - Iniciado por um contêiner ou pelo
dockerd: a API do Docker exposta na 2375 ou na 2376. - Rodando como root ou como um usuário comum com um login logo antes: uma senha fraca ou uma chave SSH roubada.
last -i -n 50
sudo journalctl --since "14 days ago" | grep -E "Accepted (password|publickey)"sudo grep -hE 'wget|curl|base64|%2Fbin%2Fsh|/bin/sh' \
/var/log/nginx/access.log* /var/log/apache2/access.log* /var/log/httpd/access_log* 2>/dev/null | tail -n 50E os serviços que costumam servir de porta de entrada quando escutam em todas as interfaces: a API do Docker, Redis, consoles web na 8080, Elasticsearch, MongoDB, Memcached.
sudo ss -tlnp | grep -E ':(2375|2376|6379|8080|9200|27017|11211)\b'Reforce o servidor depois
- Feche o ponto de entrada que você encontrou: atualize ou remova a aplicação, deixe o Redis e os bancos de dados escutando só em localhost e com senha, nunca exponha a API do Docker.
- SSH só com chaves e sem login de root: veja Como parar ataques de força bruta no SSH.
- Instale as atualizações, ative as atualizações automáticas de segurança e o firewall: veja Proteger uma VPS nova: o checklist.
- Limite o tráfego de saída onde puder: um servidor web raramente precisa abrir conexões para portas quaisquer.
- A partir de agora, monitore o uso de CPU, as conexões de saída e as alterações no cron, no systemd e nas chaves SSH, para que o próximo seja pego em minutos e não em semanas.
Como o InfraFence detecta um minerador de criptomoedas
Vários detectores do InfraFence cobrem os passos acima, cada um por um lado diferente:
- Detecção de processos: um processo em execução cujo nome ou linha de comando corresponde a um minerador conhecido (xmrig, minerd, cpuminer e outros), a uma URL stratum ou a um pool conhecido é reportado como crítico, com o PID e a linha de comando. Reverse shells e scripts rodando a partir de
/tmptambém são reportados. - Varredura de malware: assinaturas de mineradores de criptomoedas, web shells e backdoors nos seus sites, regras YARA atualizadas diariamente e os binários do sistema conferidos com a base de dados de pacotes (
dpkg -V/rpm -Va). - Saída e DNS: conexões para endereços em listas públicas de inteligência de ameaças, e cada consulta DNS ligada ao programa que a fez.
- Integridade de arquivos: o
/etc/ld.so.preload, as crontabs, as unidades systemd e cadaauthorized_keystêm hash calculado e são monitorados, e qualquer alteração gera um alerta na hora. - Verificações de hardening que apontam os caminhos de entrada mais comuns: bancos de dados abertos para a internet, software desatualizado, SSH com senha.
A verificação de processos compara nomes e linhas de comando: um minerador renomeado que lê o pool de um arquivo de configuração não corresponde a ela, e fica a cargo dos outros detectores. A limpeza descrita neste guia continua sendo tarefa sua.
Perguntas
- Posso simplesmente matar o processo?
- Ele vai voltar. Os mineradores instalam um cron, uma unidade systemd ou uma chave SSH para reiniciar, e a brecha por onde entraram continua aberta. Remova a persistência e feche o ponto de entrada.
- Preciso reinstalar o servidor?
- Se o minerador rodou como root, se binários do sistema foram alterados ou se o
/etc/ld.so.preloadfoi usado, sim: não dá para provar que o servidor está limpo. Se rodou como um usuário sem privilégios e nada mais mudou, uma limpeza cuidadosa pode bastar. - Meu provedor diz que o servidor está minerando, mas eu não vejo nada. Por quê?
- O minerador pode estar escondido com o
/etc/ld.so.preload, rodar num contêiner ou iniciar só em certos horários pelo cron. Confira o arquivo de preload, odocker pse as conexões que o servidor abre ao longo do tempo.
Teste grátis em 1 servidor
O Starter é gratuito para um servidor, com proteção completa e bloqueio automático. Sem cartão de crédito.
Instale o agente como root, com o seu token no lugar de <TOKEN>:
curl -fsSL https://github.com/infrafence/infrafence-agent/releases/latest/download/install.sh | sudo bash -s -- --token <TOKEN>O token é criado no painel, em Servidores › Adicionar servidor.
