O blog de segurança da FireAI

Por FireAI Security & Research Team · Publicado

Caçando persistência no macOS: LaunchAgents, itens de login e tarefas em segundo plano

Caçando persistência no macOS: LaunchAgents, itens de login e tarefas em segundo plano

"Persistência" é o termo de segurança para um problema específico: como um código que já rodou uma vez se organiza para rodar de novo, automaticamente, depois de uma reinicialização ou de um login, sem que ninguém precise executá-lo de novo manualmente? O macOS dá ao software legítimo muitas formas sancionadas de fazer exatamente isso — um verificador de atualizações, um cliente de sincronização na barra de menus, o auxiliar de um driver de impressora — e cada um desses mecanismos está igualmente disponível para algo que você preferiria que não estivesse rodando de jeito nenhum. Este é um tour pelos locais reais a examinar, com os comandos de fato, e um relato honesto de onde uma ferramenta focada em rede como o FireAI se encaixa nesse quadro, e onde não se encaixa.

LaunchAgents e LaunchDaemons: os dois grandes

O macOS inicia quase tudo por meio do launchd, dirigido por arquivos property list (.plist) em um pequeno número de diretórios conhecidos. A técnica T1543.001 da MITRE ATT&CK descreve o mecanismo com clareza: no login, um processo launchd por usuário carrega plists dos diretórios de LaunchAgents do usuário e do sistema, e um plist com RunAtLoad definido como true executa automaticamente no momento em que é carregado — sem nenhuma ação adicional de quem o colocou ali. A técnica lista os três locais que importam: /System/Library/LaunchAgents, /Library/LaunchAgents e ~/Library/LaunchAgents. A MITRE observa algo que vale a pena lembrar enquanto você rola por uma lista desses arquivos: agentes instalados para persistência costumam ser "disfarçados... usando nomes parecidos com componentes legítimos do sistema operacional ou de software" — o arquivo que se parece com com.apple.something.plist merece uma segunda olhada exatamente por estar tentando não chamar atenção.

Os LaunchDaemons, cobertos pela técnica relacionada T1543.004, são a versão em nível de sistema, que não exige login: rodam como root, começando na inicialização, a partir de /System/Library/LaunchDaemons/ ou /Library/LaunchDaemons/. Como instalar um ali já exige privilégios administrativos de início, a MITRE apresenta a rota do daemon como uma forma de converter um ponto de apoio privilegiado inicial em algo que sobrevive a uma reinicialização, rodando com acesso de nível root a partir de então — o que também explica por que um arquivo novo e desconhecido aparecendo em /Library/LaunchDaemons é um sinal mais forte do que um aparecendo na pasta LaunchAgents de um usuário.

Terminal — listando o que está de fato registrado
ls -la ~/Library/LaunchAgents /Library/LaunchAgents /Library/LaunchDaemons
# compare this list against what you remember installing; anything you don't
# recognise is worth reading with: plutil -p /path/to/the.plist

Um arquivo existir no disco e uma tarefa estar de fato carregada são duas perguntas diferentes, e o launchctl print responde à segunda. Sua página de manual o descreve como algo que imprime "informações sobre o serviço ou domínio especificado" — apontado para um domínio como system/ ou gui/501/ (501 sendo o UID de um usuário), ele lista todo serviço e endpoint carregado atualmente nesse contexto, além do estado de cada um:

Terminal — o que está de fato carregado agora
launchctl print gui/$(id -u)
# example output, trimmed — a real run lists every loaded agent for your session
	"com.apple.someAgent" => {
		active count = 1
		path = /Library/LaunchAgents/com.apple.someAgent.plist
		state = running
	}

Itens de login e o Gerenciamento de Tarefas em Segundo Plano

A superfície voltada ao usuário para boa parte disso é o painel Itens de Login dos Ajustes do Sistema, e vale a pena checá-lo com os próprios olhos, não só pela linha de comando. O guia de suporte da Apple o descreve diretamente: você pode "escolher itens de login que abrem automaticamente quando você faz login", adicioná-los ou removê-los ali, e separadamente permitir ou negar aplicativos que "realizam tarefas quando o aplicativo não está aberto, como verificar atualizações de software ou sincronizar dados" — essa segunda categoria cobre auxiliares em segundo plano que não são itens de login completos, mas ainda assim rodam sem supervisão.

Desde o macOS Ventura, o sistema por trás desse painel de ajustes é comumente chamado de Background Task Management (BTM) na comunidade de segurança: um serviço que rastreia todo agente de inicialização, daemon de inicialização e item de login à medida que se registra, o que é o que permite aos Ajustes do Sistema mostrar uma lista centralizada e ao vivo, em vez de você precisar vasculhar três diretórios de plist manualmente. Existe uma ferramenta de linha de comando não documentada, o sfltool, que alguns pesquisadores usam para consultar esse banco de dados de forma mais direta com sfltool dumpbtm — a Apple não distribui nenhuma página de manual para ela, e o formato da sua saída não tem garantia de permanecer estável, então trate-a como uma curiosidade de pesquisa para testar na sua própria máquina, e não como algo para construir um fluxo de trabalho em torno. A forma suportada e estável de ver a mesma informação continua sendo o painel Itens de Login nos Ajustes do Sistema, ou o launchctl print para o estado ao vivo de uma tarefa específica.

cron: mais antigo, mais discreto, ainda presente

O launchd tem sido o agendador preferido da Apple há muito tempo, mas o mais antigo daemon cron do Unix ainda vem incluído e ainda executa tudo que for agendado nele. A página de manual do crontab descreve diretamente o formato do arquivo: cada linha tem cinco campos de hora/data — minuto, hora, dia do mês, mês, dia da semana — seguidos pelo comando a executar, com @reboot e strings abreviadas parecidas disponíveis no lugar dos cinco campos em alguns sistemas. crontab -l, segundo a página de manual do crontab(1), vai "exibir o crontab atual na saída padrão" para o usuário atual:

Terminal — verificando o seu próprio crontab e o do root
crontab -l
sudo crontab -l -u root

Um resultado vazio para os dois é normal na maioria dos Macs hoje — é exatamente por isso que qualquer coisa ali merece atenção. O cron não chama atenção e raramente é verificado, o que é precisamente o motivo pelo qual ainda aparece como um local de persistência de reserva em relatos de incidentes.

Perfis de configuração: persistência com rastro documentado

Um perfil de configuração pode instalar um LaunchDaemon, conceder permissões de privacidade ou distribuir ajustes por uma frota de Macs — de forma legítima, é assim que o MDM (gerenciamento de dispositivos móveis) funciona. De forma ilegítima, um perfil é uma maneira documentada de fazer alterações permanecerem sem tocar diretamente em um arquivo plist. A ferramenta de linha de comando profiles lista o que está instalado: profiles list mostra os perfis instalados, e, como observa sua página de manual, rodá-la como root com -all vai "listar todos os perfis de configuração no sistema", em vez de apenas os do usuário atual.

Terminal — todo perfil de configuração no Mac
sudo profiles list -all
sudo profiles show -all

Um Mac pessoal sem cadastro em MDM geralmente não deveria ter nenhum, ou apenas os que você instalou deliberadamente (uma configuração de VPN, um perfil de trabalho). Um perfil do qual você não se lembra de ter instalado vale a pena investigar antes de remover, já que o profiles também permite remoção protegida por senha exatamente para essa etapa.

Plugins de autorização e a longa cauda

Além dos quatro grandes acima, existe uma longa cauda de mecanismos menores e mais antigos: plugins de Directory Service e de autorização, importadores do Spotlight, geradores do QuickLook, plugins de tile do Dock e arquivos de inicialização de shell que rodam toda vez que uma nova sessão de terminal se abre. É aqui que uma ferramenta feita especificamente para isso justifica seu valor em relação à checagem manual. O KnockKnock, da Objective-See, por exemplo, enumera mais de vinte categorias de locais de persistência em uma única passada — incluindo agentes e daemons de inicialização, itens de login, extensões de navegador, tarefas cron, extensões de kernel e de sistema, e plugins de autorização e de directory service — e mostra o status de assinatura de código do que encontra em cada um. Seu companheiro, o BlockBlock, pega essa mesma lista de locais e os observa continuamente, alertando no instante em que algo novo se registra; segundo sua própria descrição, ele "monitora locais comuns de persistência e alerta sempre que um novo componente persistente é adicionado", mostrando o processo responsável, seu status de assinatura, e permitindo permitir ou bloquear na hora.

Arquivos de inicialização do shell: o pega-tudo silencioso

Mais um local que vale a pena examinar diretamente, já que não precisa de nenhum plist nem de instalação privilegiada: os arquivos de configuração do shell. ~/.zshrc, ~/.zprofile e ~/.bash_profile rodam toda vez que uma nova sessão de terminal correspondente se abre, e uma única linha acrescentada — encaminhando para um script, exportando um PATH sequestrado, iniciando um processo em segundo plano — basta para restabelecer um ponto de apoio toda vez que você abre o Terminal, sem nada para carregar no launchd e nada para o launchctl print mostrar. O KnockKnock, da Objective-See, inclui exatamente essa categoria em sua varredura, listada ao lado dos agentes de inicialização e itens de login como arquivos de configuração do shell, pelo mesmo motivo que ela pertence a este artigo: é comum o suficiente, e discreta o suficiente, para valer a pena verificar em vez de presumir.

Terminal — uma leitura rápida, não um substituto para de fato ler o arquivo
cat -A ~/.zshrc ~/.zprofile ~/.bash_profile 2>/dev/null | less
# -A shows non-printing characters, which surfaces anything hidden with
# trailing whitespace or a carriage return trying to push it off-screen

Onde o FireAI se encaixa, e onde deliberadamente não se encaixa

Para ser direto sobre isso: o FireAI não varre /Library/LaunchDaemons, não lê arquivos plist e não faz nenhuma tentativa de detectar um novo item de login ou perfil de configuração. Essa é uma disciplina distinta do que o FireAI faz, e ferramentas construídas especificamente para isso — o KnockKnock e o BlockBlock entre elas — já cumprem bem esse papel. O que o FireAI observa é a etapa que vem depois da persistência, e que todos esses mecanismos eventualmente precisam se quiserem ser úteis para quem os instalou: uma conexão de rede. Um LaunchAgent que roda silenciosamente a cada login, mas nunca fala com a rede, é, do ponto de vista de um firewall de rede, invisível — e também, na prática, muito menos útil para um atacante. No momento em que ele de fato abre um socket, as regras por aplicativo do FireAI se aplicam a ele como a qualquer outro processo: um binário desconhecido, assinado ou não, fazendo sua primeira conexão dispara um aviso, com o raciocínio do modelo no dispositivo mostrado em linguagem simples, e toda decisão fica visível, reversível e exportável como uma regra em texto depois.

A forma honesta de juntar as duas disciplinas: verifique os locais deste artigo em uma frequência que corresponda à sua tolerância a risco — mensalmente é razoável para a maioria das pessoas, semanalmente se você instala muito software de terceiros — e deixe uma ferramenta de rede carregar o peso entre uma verificação e outra, partindo do princípio de que qualquer coisa que persistiu silenciosamente eventualmente vai precisar se comunicar para alcançar quem quer que ela responda.

Onde FireAI e HisnLabs entram nessa história

FireAI does not scan for persistence — that is a different job, and tools like KnockKnock and BlockBlock already do it well; what FireAI watches is what that persisted code does the moment it opens a socket, which is the step every one of these mechanisms eventually has to take to be useful to whoever installed it.

O FireAI é o produto da HisnLabs: um firewall com IA que roda direto no seu Mac. Ele mostra, em linguagem simples, cada conexão que seus aplicativos fazem e deixa você decidir o que sai do seu Mac — a IA roda localmente, então seu tráfego nunca é enviado para nós nem para ninguém. A equipe de pesquisa em segurança da HisnLabs é quem mantém essas decisões confiáveis: cataloga quais domínios são telemetria comum e quais são um serviço de verdade, rastreia o país e a rede por trás de uma conexão e treina o modelo local (o recurso Autopilot) com padrões reais de tráfego, sem que nada disso saia do seu Mac.

Você pode ler as decisões técnicas por trás dele, ou testar o FireAI por 17 dias, em FireAI, da HisnLabs.

Fontes