InfraFenceInfraFence

Live Security Operations

Começar

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.

Qualquer distribuição
ps -eo pid,user,%cpu,etime,args --sort=-%cpu | head -n 15
  • Nomes: xmrig e 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, redis ou postgres entrou 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:

Qualquer distribuição
sudo ls -l /proc/PID/exe /proc/PID/cwd
sudo tr '\0' ' ' < /proc/PID/cmdline; echo
systemctl status PID

Um 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:

Qualquer distribuição
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ê.

Qualquer distribuição
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/null

Conexõ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:

Qualquer distribuição
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 PID

Os arquivos de configuração dos mineradores costumam ter a URL de um pool. Este comando procura por elas nos lugares de sempre:

Qualquer distribuição
sudo grep -rIl -E 'stratum\+(tcp|ssl)://|"pools"|donate-level' /tmp /var/tmp /dev/shm /root /home /var/www /etc 2>/dev/null

O 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.

Qualquer distribuição
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/null

Depois os timers do systemd e os arquivos de unidade alterados nos últimos 30 dias:

Qualquer distribuição
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:

Qualquer distribuição
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/passwd

Por 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.

Debian / Ubuntu
sudo dpkg --verify | grep -v ' c /'
RHEL, Rocky Linux, AlmaLinux, Oracle Linux, Fedora
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.

Qualquer distribuição com nftables
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 drop

Guarde 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.

Qualquer distribuição
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.bin

Primeiro 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.

Qualquer distribuição
sudo kill -STOP PID
ps -o pid,ppid,user,args -p PID
sudo kill -9 PID

Atençã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):

Qualquer distribuição
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 USER e os arquivos em /etc/cron.d que você não criou.
  • SSH: apague de cada authorized_keys as 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/sudoers e 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:

Qualquer distribuição
sudo lsattr /path/to/file
sudo chattr -i -a /path/to/file
sudo rm /path/to/file

Se 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:

Qualquer distribuição
sudo mv /etc/ld.so.preload /root/evidence/ld.so.preload
sudo ldconfig

Reinicie, 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:

Qualquer distribuição
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.
Logins SSH
last -i -n 50
sudo journalctl --since "14 days ago" | grep -E "Accepted (password|publickey)"
Logs do servidor web
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 50

E 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.

Qualquer distribuição
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 /tmp també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 cada authorized_keys tê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.preload foi 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, o docker ps e 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.