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á.
- Guardar uma cópia do ficheiro ou da tarefa e a sua hora de modificação.
- Com essa hora, ver nos registos do servidor web e no
auth.logo que se passava no mesmo minuto. É aí que costuma estar o ponto de entrada. - 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.
- 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.