Essencial de macOS e Linux · Aula 4 de 5
Logs do Linux: journald, logs de autenticação, wtmp e btmp
13 min de leitura
Em um servidor Linux, a pergunta "quem fez login, de onde, quando e o que fez como root" é respondida por logs de texto, pelo journal do systemd e por pequenos registros binários de login. Esta aula mostra onde cada um fica em sistemas das famílias Debian e Red Hat, como lê-los offline, como converter seus carimbos de data/hora em valores UTC exatos e como corroborar um login SSH em todos eles.
Logs de texto em /var/log
Os logs de texto são gravados por um daemon syslog, geralmente o rsyslog, seguindo regras em /etc/rsyslog.conf e /etc/rsyslog.d/. Leia esses arquivos na imagem: eles mostram qual arquivo recebeu quais mensagens e se as mensagens foram encaminhadas para um servidor remoto de logs que o invasor não conseguia acessar.
| Conteúdo | Debian e Ubuntu | Família RHEL (RHEL, Rocky, Alma, Fedora) |
|---|---|---|
| Autenticação, sudo, su, alterações de contas | /var/log/auth.log | /var/log/secure |
| Mensagens gerais do sistema | /var/log/syslog | /var/log/messages |
| Mensagens do kernel | /var/log/kern.log | em messages |
| Tarefas agendadas | em syslog (a menos que cron.log esteja habilitado) | /var/log/cron |
| Serviços | diretórios próprios, por exemplo, /var/log/apache2/, /var/log/nginx/ | diretórios próprios, por exemplo, /var/log/httpd/ |
Configurações mais antigas do Debian também gravavam daemon.log e user.log. Os padrões mudam, portanto relate o que a imagem contém. Em particular, novas instalações do Debian 12 e posteriores não incluem necessariamente o rsyslog; quando ele está ausente, /var/log/auth.log não existe e o journal é o único registro de logins.
Rotação
O logrotate (configurado em /etc/logrotate.conf e /etc/logrotate.d/) renomeia os logs conforme um agendamento. No Debian, os arquivos do rsyslog normalmente passam por rotação semanal, com quatro cópias antigas mantidas e compressão adiada, resultando em auth.log, auth.log.1, auth.log.2.gz, auth.log.3.gz e auth.log.4.gz. Sistemas da família RHEL geralmente acrescentam uma data em vez de um número (secure-20260308). Colete todos os arquivos da rotação, pesquise nos arquivos comprimidos com zgrep e ordene-os pelo conteúdo, não pelo nome.
Carimbos de data/hora
O formato clássico do syslog (estilo RFC 3164) inicia cada linha com Mar 14 14:20:31: sem ano e sem fuso horário. A hora é a hora local do sistema no momento em que a linha foi gravada. Para convertê-la, você deve estabelecer:
- Ano: a partir da hora de modificação do arquivo, da sequência de rotação e de fontes datadas, como o journal ou o wtmp. Fique atento a linhas de dezembro em um arquivo fechado em janeiro.
- Fuso horário: a partir de
/etc/localtimena imagem (geralmente um link simbólico para/usr/share/zoneinfo/; resolva-o dentro da imagem, não na sua máquina de análise) e, no Debian, de/etc/timezone.
O rsyslog pode, em vez disso, gravar carimbos de data/hora RFC 3339, e os pacotes do rsyslog do Debian 12 e do Ubuntu 24.04 fazem isso por padrão, com microssegundos e um deslocamento de fuso horário, por exemplo, 2026-03-14T10:43:52.104312-03:00. Esse formato inclui o ano e o deslocamento, portanto pode ser convertido sem suposições.
O journal do systemd
O systemd-journald armazena logs em um formato binário indexado. Os arquivos persistentes ficam em /var/log/journal/<machine-id>/, em que o ID da máquina é o valor de 32 dígitos hexadecimais em /etc/machine-id. Os arquivos voláteis ficam em /run/log/journal/, armazenados em RAM, perdidos na reinicialização e ausentes de uma imagem de disco. A configuração Storage= em /etc/systemd/journald.conf determina esse comportamento; seu padrão auto armazena de forma persistente somente se /var/log/journal existir.
O arquivo ativo é system.journal (mais user-<UID>.journal para sessões de usuários). Os arquivos arquivados recebem o nome system@….journal. Um arquivo que não foi fechado corretamente, por exemplo, após uma falha, é renomeado para system@….journal~; esses arquivos muitas vezes ainda podem ser lidos e também devem ser coletados.
Cada entrada é um conjunto de campos. Campos com um sublinhado inicial são adicionados pelo journald, de modo que o programa que registra o log não pode falsificá-los; dois sublinhados indicam metadados de endereçamento.
| Campo | Significado |
|---|---|
MESSAGE | O texto do log, por exemplo, a linha do sshd |
SYSLOG_IDENTIFIER | Identificador do programa, por exemplo, sshd, sudo |
_PID, _UID, _COMM | ID do processo, ID do usuário e nome do comando do remetente |
_SYSTEMD_UNIT | Unidade de serviço, por exemplo, ssh.service |
_BOOT_ID | Identificador de 128 bits da inicialização em que a entrada foi gravada |
__REALTIME_TIMESTAMP | Microssegundos desde 1970-01-01 00:00:00 UTC no momento em que o journald recebeu a entrada |
Leia um journal offline com journalctl -D /case/var/log/journal (um diretório) ou journalctl --file '/case/var/log/journal/<machine-id>/system@*.journal'. Use uma versão recente do journalctl; uma versão mais antiga pode rejeitar arquivos com recursos de formato mais novos. Opções úteis:
--utcpara exibir em UTC; forneça--since "2026-03-14 13:00:00 UTC"e--untilcom um sufixoUTCexplícito.-u sshpara a unidade do OpenSSH no Debian e no Ubuntu (-u sshdno RHEL), ou_COMM=sshd. A partir do OpenSSH 9.8, o trabalho por conexão é realizado porsshd-session, portanto as linhas podem trazer esse nome em vez disso.-o jsonou-o verbosepara mostrar todos os campos, incluindo__REALTIME_TIMESTAMP;-o short-iso-precisepara horários legíveis com precisão de microssegundos.--list-bootspara listar os IDs de inicialização com suas primeiras e últimas entradas, depois-b <boot ID>;--verifypara verificar a consistência dos arquivos.
O que significam as linhas de autenticação
As mesmas linhas aparecem no journal e, quando o rsyslog está em execução, em auth.log ou secure.
| Linha (processo) | Significado |
|---|---|
Accepted password for alice from 198.51.100.23 port 51744 ssh2 (sshd) | Login com senha bem-sucedido: conta, IP de origem, porta de origem |
Accepted publickey for root from 198.51.100.23 port 51790 ssh2: ED25519 SHA256:<fingerprint> (sshd) | Login com chave; a impressão digital identifica a chave |
Failed password for root from 203.0.113.77 port 40210 ssh2 (sshd) | Senha incorreta para uma conta existente |
Invalid user admin from 203.0.113.77 port 40212 e Failed password for invalid user admin from … (sshd) | A conta não existe neste sistema |
Disconnected from user alice 198.51.100.23 port 51744 (sshd) | Fim da conexão SSH |
pam_unix(sshd:session): session opened for user alice(uid=1001) by (uid=0) | Início de sessão PAM (versões mais antigas omitem o UID após o nome); session closed marca o fim |
alice : TTY=pts/0 ; PWD=/home/alice ; USER=root ; COMMAND=/usr/bin/tar czf /tmp/h.tgz /home (sudo) | Comando executado como root: quem, de qual terminal e diretório, como qual usuário e exatamente o quê |
(to root) alice on pts/0 (su) | Troca para outra conta com su |
new user: name=svc-upd, UID=1002, …, add 'svc-upd' to group 'sudo', password changed for svc-upd (useradd, usermod, passwd) | Criação e alterações de contas, registradas pelo shadow-utils e pelo PAM |
Para vincular um login por chave pública a uma chave, execute ssh-keygen -lf no arquivo ~/.ssh/authorized_keys da conta na imagem; ele exibe a impressão digital SHA256 de cada chave, e o campo de comentário da linha correspondente frequentemente indica seu proprietário.
Registros binários de login
| Arquivo | Conteúdo | Comando offline |
|---|---|---|
/var/run/utmp | Sessões atuais; armazenado em RAM, portanto disponível apenas em coletas ao vivo | who /path/to/utmp |
/var/log/wtmp | Histórico de logins e logouts, reinicializações e desligamentos, com host ou IP de origem | TZ=UTC last -f wtmp -i -x --time-format iso |
/var/log/btmp | Logins malsucedidos, um registro por tentativa, incluindo nomes de usuários inexistentes | TZ=UTC lastb -f btmp -i --time-format iso |
/var/log/lastlog | Último login por UID: hora, terminal, host | analisar diretamente (veja abaixo) |
last e lastb exibem os horários no fuso horário da máquina de análise, daí o uso de TZ=UTC; -i exibe ut_addr_v6 numericamente; utmpdump wtmp exibe todos os campos com microssegundos.
utmp, wtmp e btmp compartilham a struct utmp da glibc, com 384 bytes por registro no Linux x86-64: ut_type no offset 0 (7 USER_PROCESS login, 8 DEAD_PROCESS logout, 2 BOOT_TIME reinicialização), ut_pid em 4, ut_line (32 bytes, por exemplo, pts/0) em 8, ut_user (32 bytes) em 44, ut_host (256 bytes) em 76, ut_tv (segundos e microssegundos de 32 bits desde a época Unix, UTC) em 340 e ut_addr_v6 (16 bytes) em 348. O tamanho de um arquivo íntegro é múltiplo de 384. O last associa um login ao próximo logout no mesmo ut_line. O campo de segundos de 32 bits sofre estouro em janeiro de 2038, portanto distribuições recentes estão abandonando esses arquivos. O Debian 13 não inclui mais last, lastb ou lastlog: os logins vão para o wtmpdb (/var/lib/wtmpdb/wtmp.db, lido com wtmpdb last) e o lastlog2 (/var/lib/lastlog/lastlog2.db) quando instalados, e os logins malsucedidos podem existir apenas no journal. Verifique quais arquivos a imagem realmente contém e, em um host de análise Debian 13, analise wtmp/btmp com utmpdump ou um script.
O lastlog contém registros de 292 bytes (ll_time com 4 bytes, ll_line com 32, ll_host com 256), indexados por UID no offset UID × 292. É um arquivo esparso: um UID grande torna seu tamanho aparente enorme, embora pouco espaço em disco seja usado. O comando lastlog lê por padrão o arquivo do sistema em execução, portanto, em uma imagem, leia o registro no offset calculado.
Força bruta e adulteração
A força bruta se manifesta como centenas de linhas Failed password e Invalid user e registros btmp de um único IP em poucos minutos, frequentemente alternando entre nomes como root, admin e test. A constatação decisiva é uma linha Accepted posterior do mesmo IP. A pulverização de senhas tem uma aparência diferente: poucas tentativas por conta a partir de muitos IPs. O rsyslog pode condensar linhas consecutivas idênticas em message repeated N times, portanto conte os registros btmp além das linhas de texto.
Os indicadores de adulteração incluem lacunas durante atividade conhecida, um log atual vazio ao lado de arquivos de rotação cheios, números de rotação ausentes, registros wtmp inteiramente zerados, tamanhos que não são múltiplos de 384 e divergências entre o journal e o auth.log; o Módulo 7 aborda a limpeza de logs.
Exemplo resolvido: reconstrução de uma intrusão SSH
Um servidor Debian cujo /etc/localtime aponta para America/Sao_Paulo (UTC−3, sem horário de verão em 2026) tem rsyslog com o formato tradicional e um journal persistente.
- Falhas.
TZ=UTC lastb -f btmp -i --time-format iso | grep -c 203.0.113.77retorna 1.240 registros, o primeiro em 2026-03-14T13:02:15Z e o último em 13:39:48Z. Duração: 37 min 33 s = 2.253 s, portanto 1.240 / 2.253 ≈ 0,55 tentativas por segundo. Se o btmp contiver apenas esses registros, seu tamanho deverá ser 1.240 × 384 = 476.160 bytes. - Sucesso.
journalctl -D /case/var/log/journal _COMM=sshd -o jsonmostraAccepted password for backup from 203.0.113.77 port 40122 ssh2com__REALTIME_TIMESTAMP1773495667482913. Decomposição: 1.773.495.667 segundos e 482.913 microssegundos. 1.773.495.667 / 86.400 = 20.526 dias com resto de 49.267 s; 49.267 s = 13 h 41 min 7 s; o dia 20.526 após 1970-01-01 é 2026-03-14. Resultado: 2026-03-14T13:41:07.482913Z, confirmado compython3 -c "import datetime as d; print(d.datetime(1970,1,1,tzinfo=d.timezone.utc)+d.timedelta(microseconds=1773495667482913))". - Uso de privilégios.
auth.log.1contémMar 14 10:43:52 srv01 sudo: backup : TTY=pts/0 ; PWD=/var/backups ; USER=root ; COMMAND=/usr/bin/tar czf /tmp/.c.tgz /etc /home. Suposições: ano 2026 (a hora de modificação do arquivo e o journal), hora local UTC−3 de/etc/localtimee um relógio correto (aula 3.5). 10:43:52 + 3 h = 2026-03-14T13:43:52Z, correspondendo à entrada do journal para a mesma linha. - Sessão.
TZ=UTC last -f wtmp -i --time-format isomostrabackup pts/0 203.0.113.77 2026-03-14T13:41:07+00:00 - 2026-03-14T14:12:40+00:00 (00:31), correspondendo aDisconnected from user backup 203.0.113.77 port 40122às 14:12:40Z no journal. - Último login. No Debian,
backupé uma conta de sistema com UID 34, portanto seu registro lastlog está em 34 × 292 = 9.928 bytes:ll_timeé decodificado como 13:41:07Z, ell_hosté203.0.113.77. Comobackupnormalmente tem uma senha bloqueada e o shell/usr/sbin/nologin, verifique/etc/passwd,/etc/shadowe sudoers (aula 6.3) para determinar como a conta obteve uma senha, um shell e permissões de sudo.
Pergunta → log → comando
| Pergunta | Log | Comando (offline) |
|---|---|---|
| Quem fez login, de qual IP e quando? | wtmp; journal; auth.log/secure | TZ=UTC last -f wtmp -i --time-format iso; journalctl -D … --utc -u ssh |
| Quantas tentativas malsucedidas e de onde? | btmp; auth.log | TZ=UTC lastb -f btmp -i; zgrep "Failed password" auth.log* |
| Qual chave foi usada? | auth.log/journal; authorized_keys | ssh-keygen -lf authorized_keys |
| O que foi executado como root? | linhas do sudo | journalctl -D … _COMM=sudo |
| Contas foram criadas ou alteradas? | auth.log/journal | zgrep -e "new user" -e usermod -e "password changed" auth.log* |
| Hora exata com precisão de microssegundos? | journal | journalctl -D … -o json (__REALTIME_TIMESTAMP) |
| Quando o sistema foi inicializado? | journal; wtmp | journalctl -D … --list-boots; last -f wtmp -x reboot |
Foco no exame: Espere ter de informar um IP de origem de login ou um horário UTC obtido de logs do Linux e converter corretamente um valor__REALTIME_TIMESTAMPou uma linha syslog sem ano. Saiba qual arquivo contém os logins malsucedidos (btmp), o histórico de logins (wtmp) e o nome do log de autenticação no RHEL (secure). Esteja preparado para declarar as suposições por trás de uma conversão de syslog: ano, fuso horário e relógio.
Pontos principais
- Os eventos de autenticação vão para
auth.log(Debian/Ubuntu) ousecure(família RHEL); colete todas as cópias da rotação, incluindo arquivos.gz. - Os horários do syslog clássico não têm ano nem fuso horário; versões recentes do Debian e do Ubuntu gravam horários RFC 3339 com um deslocamento, e novos sistemas Debian 12+ podem ter apenas o journal.
- O journal fica em
/var/log/journal/<machine-id>/(persistente) ou/run/log/journal(perdido na reinicialização); leia-o comjournalctl -De--utc;__REALTIME_TIMESTAMPrepresenta microssegundos desde a época Unix, em UTC. - utmp, wtmp e btmp usam registros de 384 bytes com horários desde a época Unix em UTC; execute
lastelastbcomTZ=UTC. - lastlog é indexado por UID em UID × 292 bytes; analise-o diretamente a partir de uma imagem.
- Corrobore um login entre btmp, a linha do sshd, wtmp, lastlog e as linhas do sudo.