Obter o acesso é metade do trabalho; a outra metade consiste em não o perder. Por isso quase todo o software malicioso automatizado trata antes de mais de voltar a ser iniciado: depois de um reinício, depois de o ficheiro ser apagado, depois de uma mudança de palavra-passe. Daí a história conhecida: «limpámos e dois dias depois voltou».

Os sítios onde isso se organiza não são muitos, e todos se verificam em poucos minutos. Segue-se a ronda completa, por ordem.

1. As chaves SSH

O regresso mais simples: uma linha no authorized_keys sobrevive a uma mudança de palavra-passe, a uma atualização do sistema e a um reinício.

sudo find /home /root -name authorized_keys -exec ls -l {} \; -exec cat {} \;

Cada linha é o acesso permanente de alguém. Se não consegue dizer de quem, considere-a alheia. Repare também no comentário no fim da linha: é texto livre, e coincidir com o seu nome nada prova.

2. As tarefas de cron de todos os utilizadores

Não é só a sua crontab que tem de ser verificada:

for u in $(cut -f1 -d: /etc/passwd); do echo "== $u"; sudo crontab -u "$u" -l 2>/dev/null; done
sudo ls -la /etc/cron.d/ /etc/cron.hourly/ /etc/cron.daily/
sudo cat /etc/crontab

O que procurar: linhas com @reboot, comandos longos codificados, chamadas a curl ou wget encaminhadas para um interpretador, tudo o que arranque de /tmp, /dev/shm ou /var/tmp. Dessas pastas não corre nada de regular.

3. Temporizadores e serviços do systemd

O equivalente moderno do cron, e é verificado bastante menos:

systemctl list-timers --all
systemctl list-units --type=service --state=running
sudo ls -la /etc/systemd/system/ /run/systemd/system/

À parte, os serviços de utilizador, que correm sem privilégios de root e não aparecem na lista geral:

systemctl --user list-units --type=service
sudo ls -la /home/*/.config/systemd/user/

Mais um pormenor: se para um utilizador estiver ativada a persistência (loginctl enable-linger), os seus serviços correm sem sessão ativa. Verifica-se com loginctl list-users.

4. Os ficheiros de arranque da shell

O código acrescentado ao fim de um ficheiro de arranque da shell é executado em cada acesso:

sudo tail -5 /root/.bashrc /root/.profile /home/*/.bashrc /home/*/.profile
sudo ls -la /etc/profile.d/

Veja precisamente o fim do ficheiro: é lá que se acrescenta para não dar nas vistas numa olhadela rápida.

5. ld.so.preload

Um ficheiro que obriga o sistema a carregar uma dada biblioteca em cada processo iniciado. Em condições normais nunca é criado:

ls -l /etc/ld.so.preload

A sua presença é praticamente um sinal inequívoco de comprometimento grave, e uma biblioteca dessas costuma esconder tanto ficheiros como processos e ligações de rede. Nada do que vir depois nessa máquina merece confiança.

6. Os ganchos do gestor de pacotes

Um método raramente considerado: o apt pode executar comandos antes e depois de cada operação com pacotes.

sudo ls -la /etc/apt/apt.conf.d/
sudo grep -r 'DPkg::Pre-Invoke\|DPkg::Post-Invoke\|APT::Update' /etc/apt/apt.conf.d/

Um gancho desses dispara em cada instalação de atualizações, ou seja, com regularidade e como root.

7. A mensagem do dia no Ubuntu

A pasta /etc/update-motd.d/ contém scripts executáveis que correm em cada acesso SSH e compõem o texto de boas-vindas. O sítio é cómodo precisamente por parecer parte do sistema:

sudo ls -la /etc/update-motd.d/

8. As tarefas diferidas do at

sudo atq
sudo ls -la /var/spool/cron/atjobs/ 2>/dev/null

Um mecanismo antigo e pouco usado, e por isso o menos verificado de todos.

O que fazer se aparecer alguma coisa

O primeiro impulso é apagar o achado de imediato. É um erro: com ele desaparece a informação sobre como chegou ali, e sem resposta a essa pergunta tudo se repetirá.

  1. Guardar uma cópia do ficheiro ou da tarefa e a sua hora de modificação.
  2. Com essa hora, ver nos registos do servidor web e no auth.log o que se passava no mesmo minuto. É aí que costuma estar o ponto de entrada.
  3. Verificar os oito sítios da lista, e não apenas aquele onde apareceu alguma coisa. Uma porta traseira quase nunca é deixada num único exemplar.
  4. Só depois limpar e fechar a própria vulnerabilidade.

Saber como é a normalidade

A dificuldade principal desta verificação não são os comandos, mas o facto de uma linha desconhecida numa lista de tarefas não parecer suspeita se não se lembrar de como a lista era antes. Num servidor configurado por outra pessoa, ou configurado há um ano, distinguir o seu do alheio é quase impossível.

Daí a conclusão prática: tirar hoje um instantâneo do estado atual faz sentido, enquanto o servidor está em ordem. A lista de tarefas de cron, temporizadores, chaves e serviços de uma máquina sã é a referência com que se comparará depois. Recolhida e conservada com histórico, transforma a procura de uma porta traseira de um exercício de várias horas numa comparação de duas listas. Como fica mostram-no as páginas de demonstração abaixo.