FireAIs säkerhetsblogg

Av FireAI Security & Research Team · Publicerad

Hunting Persistence på macOS: LaunchAgents, inloggningsobjekt och bakgrundsuppgifter

Hunting Persistence på macOS: LaunchAgents, inloggningsobjekt och bakgrundsuppgifter

"Persistens" är säkerhetstermen för ett specifikt problem: hur fungerar kod som kördes en gång att köras igen, automatiskt, efter en omstart eller en inloggning, utan att någon återstartar den för hand? macOS ger legitim programvara en mängd sanktionerade sätt att göra just det - en uppdateringskontroll, en menyradssynkroniseringsklient, en skrivardrivrutinshjälp - och var och en av dessa mekanismer är lika tillgängliga för något du helst inte skulle köra alls. Det här är en rundtur i de faktiska platserna att titta på, med de verkliga kommandona, och en ärlig redogörelse för var ett nätverksfokuserat verktyg som FireAI gör och inte hör hemma i den bilden.

LaunchAgents och LaunchDaemons: de två stora

macOS startar nästan allt genom launchd, driven av egenskapslistfiler (.plist) i ett litet antal kända kataloger. MITER ATT&CK:s teknik T1543.001 beskriver mekanismen tydligt: ​​vid inloggning, en per-användare launchd-process laddar plists från användar- och system LaunchAgents-kataloger, och en plist med RunAtLoad inställd på sant körs automatiskt i samma ögonblick som den laddas - ingen ytterligare åtgärd behövs från den som lägger den där. Tekniken listar de tre platserna som är viktiga: /System/Library/LaunchAgents, /Library/LaunchAgents och ~/Library/LaunchAgents. MITER noterar något som är värt att komma ihåg när du bläddrar igenom en lista med dessa filer: agenter som är installerade för beständighet är ofta "förklädnad[d]... med namn som liknar legitima OS- eller programvarukomponenter" — filen som ser ut som com.apple.something.plist är värd en andra titt just för att den försöker att inte skaffa en.

LaunchDaemons, som täcks av den relaterade tekniken T1543.004, är den systemomfattande versionen utan inloggning som krävs: de körs som root, med start vid uppstart, från /System/Library/LaunchDaemons/ eller /Library/LaunchDaemons/. Eftersom att installera en där kräver administrativa privilegier till att börja med, ramar MITER in demonrutten som ett sätt att konvertera ett initialt privilegierat fotfäste till något som överlever en omstart, som körs med rotnivååtkomst från och med då - vilket också är anledningen till att en ny, obekant fil som visas i /Library/LaunchDaemons är en tyngre signal än en som visas i en användares egen LaunchAgent-mapp.

Terminal — listar vad som faktiskt är registrerat
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

En fil som finns på disken och ett jobb som faktiskt laddas är två olika frågor, och launchctl print svarar på den andra. Dess man-sida beskriver det som att det skriver ut "information om den angivna tjänsten eller domänen" - pekade på en domän som system/ eller gui/501/ (501 är en användares UID), den listar alla tjänster och slutpunkter som för närvarande laddas i det sammanhanget, plus var och ens tillstånd:

Terminal — vad som faktiskt är laddat just nu
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
	}

Inloggningsobjekt och Background Task Management

Den användarvända ytan för mycket av detta är Systeminställningars ruta för inloggningsobjekt, och det är värt att kolla med dina egna ögon, inte bara med kommandoraden. Apples supportguide beskriver det direkt: du kan "välja inloggningsobjekt som öppnas automatiskt när du loggar in", lägga till eller ta bort dem där och separat tillåta eller neka appar som "utför uppgifter när appen inte är öppen, som att söka efter programuppdateringar eller synkronisera data" - den andra kategorin täcker bakgrundshjälpmedel som inte är fullständiga inloggningsobjekt men som fortfarande körs obevakade.

Sedan macOS Ventura kallas systemet under den inställningsrutan vanligtvis för Background Task Management (BTM) i säkerhetscommunityt: en tjänst som spårar varje startagent, startdemon och inloggningsobjekt när det registrerar sig, vilket är det som låter systeminställningarna visa dig en levande, centraliserad lista istället för att du behöver gå igenom tre plist-kataloger för hand. Det finns ett odokumenterat kommandoradsverktyg, sfltool, som vissa forskare använder för att fråga den databasen mer direkt med sfltool dumpbtm — Apple skickar ingen man-sida för den och dess utdataformat är inte garanterat stabilt, så behandla det som en forskningsnyfikenhet att prova på din egen maskin snarare än något att bygga ett arbetsflöde runt. Det stabila sättet som stöds för att se samma information är fortfarande rutan Inloggningsobjekt i Systeminställningar, eller launchctl print för det aktuella tillståndet för ett specifikt jobb.

cron: äldre, tystare, fortfarande där

launchd har varit Apples föredragna schemaläggare under lång tid, men den äldre Unix cron-demonen skickas fortfarande och kör fortfarande allt som är schemalagt i den. Crontab-mansidan beskriver filformatet direkt: varje rad har fem tid-/datumfält — minut, timme, månad, månad, veckodag — följt av kommandot att köra, med @reboot och liknande förkortningssträngar tillgängliga i stället för de fem fälten på vissa system. crontab -l, enligt crontab(1) direkthjälpen, kommer "Visa aktuell crontab på standardutdata" för den aktuella användaren:

Terminal - kontrollera din egen och roots crontab
crontab -l
sudo crontab -l -u root

Ett tomt resultat för båda är normalt på de flesta Mac-datorer idag - det är precis därför allt därinne förtjänar uppmärksamhet. cron är oglamoröst och kontrolleras sällan, vilket är just därför det fortfarande dyker upp som en reservplats för beständighet i incidentskrivningar.

Konfigurationsprofiler: uthållighet med ett pappersspår

En konfigurationsprofil kan installera en LaunchDaemon, ge integritetsbehörigheter eller trycka på inställningar över en flotta av Mac-datorer – med rätta är det så här MDM (mobilenhetshantering) fungerar. Olagligt är en profil ett dokumenterat sätt att få ändringar att fastna utan att röra en plist-fil direkt. Kommandoradsverktyget profiles listar vad som är installerat: profiles list visar installerade profiler och, som dess man-sida noterar, kommer att köra det som root med -all att "lista alla konfigurationsprofiler på systemet" snarare än bara den nuvarande användarens.

Terminal — varje konfigurationsprofil på Mac
sudo profiles list -all
sudo profiles show -all

En personlig Mac utan MDM-registrering bör i allmänhet inte ha någon, eller bara de som du installerat medvetet (en VPN-konfiguration, en arbetsprofil). En profil du inte kommer ihåg att ha installerat är värd att undersöka innan du tar bort, eftersom profiles också stöder borttagning med lösenordsskydd för just det steget.

Auktoriseringsplugins och den långa svansen

Utöver de fyra stora ovan finns det en lång svans av mindre, äldre mekanismer: Directory Service och auktoriseringsplugin, Spotlight-importörer, QuickLook-generatorer, Dock-tile-plugins och skalstartfiler som körs varje gång en ny terminalsession öppnas. Det är här ett specialbyggt verktyg tjänar sin behållning över manuell kontroll. Objective-Sees KnockKnock räknar till exempel upp mer än tjugo kategorier av beständighetsplatser i ett pass – inklusive startagenter och demoner, inloggningsobjekt, webbläsartillägg, cron-jobb, kärn- och systemtillägg samt auktoriserings- och katalogtjänstplugin – och visar kodsigneringsstatusen för vad den hittar i var och en. Dess följeslagare, BlockBlock, tar samma lista över platser och tittar på dem kontinuerligt och larmar så fort något nytt registreras; enligt sin egen beskrivning "övervakar den vanliga beständighetsplatser och varnar när en ny beständig komponent läggs till", visar den ansvariga processen, dess signeringsstatus och låter dig tillåta eller blockera på plats.

Shell-startfiler: den tysta catch-all

Ytterligare en plats värd en direkt titt, eftersom den inte behöver någon plist och ingen privilegierad installation alls: skalkonfigurationsfiler. ~/.zshrc, ~/.zprofile och ~/.bash_profile körs varje gång en matchande ny terminalsession öppnas, och en enstaka tillagd rad – koppling till ett skript, export av ett kapat PATH, start av en bakgrundsprocess – räcker för att återupprätta ett fotfäste varje gång du öppnar Terminal, utan att ingenting kan laddas in i @@CODE till @@CODE och @@CODE. Objective-See’s KnockKnock inkluderar exakt denna kategori i sin genomsökning, listad tillsammans med lanseringsagenter och inloggningsobjekt som skalkonfigurationsfiler, av samma anledning som den hör hemma i den här artikeln: den är tillräckligt vanlig och oglamorös nog för att vara värd att kontrollera snarare än att anta.

Terminal — en snabb läsning, inte en ersättning för att faktiskt läsa den
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

Där FireAI passar, och där det medvetet inte gör det

För att vara direkt om det: FireAI skannar inte /Library/LaunchDaemons, läser inte plist-filer och gör inga försök att upptäcka ett nytt inloggningsobjekt eller konfigurationsprofil. Det är en distinkt disciplin från vad FireAI gör, och verktyg byggda specifikt för det - KnockKnock och BlockBlock bland dem - gör redan det jobbet bra. Vad FireAI tittar på är steget som kommer efter uthållighet, och som var och en av dessa mekanismer så småningom behöver om den ska vara användbar för den som installerade den: en nätverksanslutning. En LaunchAgent som körs tyst vid varje inloggning men som aldrig pratar med nätverket är, ur en nätverksbrandväggs synvinkel, osynlig – och även i praktiken mycket mindre användbar för en angripare. I samma ögonblick som den öppnar en socket, gäller FireAI:s per-app-regler på den som vilken annan process som helst: en obekant signerad eller osignerad binär som gör sin första anslutning utlöser en prompt, med enhetens modells resonemang som visas på ett enkelt språk, och varje beslut är synligt, omöjligt och exporterbart som en textregel efteråt.

Det ärliga sättet att sätta samman de två disciplinerna: kontrollera platserna i den här artikeln enligt ett schema som matchar din risktolerans - månadsvis är rimligt för de flesta, varje vecka om du installerar mycket programvara från tredje part - och låt ett nätverksverktyg bära belastningen däremellan, under antagandet att allt som kvarstår tyst så småningom kommer att behöva tala för att nå vem det än svarar till.

Var FireAI och HisnLabs kommer in

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.

FireAI är HisnLabs eget verktyg: en AI-brandvägg som körs direkt på din Mac. Den visar varje anslutning dina appar gör, på klarspråk, och låter dig avgöra vad som lämnar din Mac — AI:n körs lokalt, så din trafik skickas aldrig till oss eller någon annan. HisnLabs säkerhetsforskningsteam är de som håller de bedömningarna tillförlitliga: de katalogiserar vilka domäner som är vanlig telemetri och vilka som är en riktig tjänst, spårar land och nätverk bakom en anslutning och tränar den lokala modellen (Autopilot-funktionen) på verkliga trafikmönster — utan att något av det lämnar din Mac.

Du kan läsa om de tekniska besluten bakom, eller prova FireAI i 17 dagar, på FireAI, från HisnLabs.

Källor