„Persistenz“ ist der Sicherheitsbegriff für ein ganz bestimmtes Problem: Wie sorgt Code, der einmal lief, dafür, automatisch erneut zu laufen, nach einem Neustart oder einer Anmeldung, ohne dass ihn jemand von Hand erneut startet? macOS gibt legitimer Software viele zugelassene Wege, genau das zu tun — ein Update-Prüfer, ein Menüleisten-Sync-Client, der Helfer eines Druckertreibers —, und jeder dieser Mechanismen steht genauso etwas zur Verfügung, das man lieber gar nicht laufen sehen würde. Das hier ist eine Tour durch die tatsächlichen Orte, an denen man nachsehen sollte, mit den echten Befehlen, und eine ehrliche Einordnung, wo ein netzwerkfokussiertes Werkzeug wie FireAI in dieses Bild passt und wo nicht.
LaunchAgents und LaunchDaemons: die beiden großen
macOS startet fast alles über launchd, gesteuert durch Property-List-Dateien (.plist) in einer kleinen Zahl bekannter Verzeichnisse. MITRE ATT&CKs Technik T1543.001 beschreibt den Mechanismus unumwunden: Bei der Anmeldung lädt ein prozessbezogener launchd-Prozess pro Nutzer Plists aus den LaunchAgents-Verzeichnissen von Nutzer und System, und eine Plist mit RunAtLoad auf true wird automatisch ausgeführt, sobald sie geladen wird — ohne dass diejenige oder derjenige, die sie dort platziert hat, noch etwas tun muss. Die Technik listet die drei relevanten Orte: /System/Library/LaunchAgents, /Library/LaunchAgents und ~/Library/LaunchAgents. MITRE merkt etwas an, das man sich merken sollte, während man eine Liste solcher Dateien durchscrollt: Für Persistenz installierte Agenten werden oft „getarnt … mit Namen, die legitimen Betriebssystem- oder Softwarekomponenten ähneln“ — die Datei, die wie com.apple.something.plist aussieht, ist gerade deshalb einen zweiten Blick wert, weil sie versucht, keinen zu bekommen.
LaunchDaemons, behandelt von der verwandten Technik T1543.004, sind die systemweite Version ohne Anmeldung: Sie laufen als root, gestartet beim Boot, aus /System/Library/LaunchDaemons/ oder /Library/LaunchDaemons/. Weil die Installation dort von vornherein administrative Rechte erfordert, beschreibt MITRE den Daemon-Weg als eine Möglichkeit, einen anfänglichen privilegierten Fuß in der Tür in etwas zu verwandeln, das einen Neustart übersteht und ab dann mit Root-Zugriff läuft — auch deshalb ist eine neue, unbekannte Datei in /Library/LaunchDaemons ein gewichtigeres Signal als eine, die im eigenen LaunchAgents-Ordner eines Nutzers auftaucht.
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.plistOb eine Datei auf der Festplatte existiert und ob ein Job tatsächlich geladen ist, sind zwei verschiedene Fragen, und launchctl print beantwortet die zweite. Die Manpage beschreibt es so, dass es „Informationen über den angegebenen Dienst oder Domain“ ausgibt — richtet man es auf eine Domain wie system/ oder gui/501/ (501 ist die UID eines Nutzers), listet es jeden derzeit in diesem Kontext geladenen Dienst und Endpunkt samt Status auf:
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
}Login-Elemente und Background Task Management
Die für Nutzer sichtbare Oberfläche für vieles davon ist der Bereich Login-Elemente in den Systemeinstellungen, und es lohnt sich, ihn mit den eigenen Augen zu prüfen, nicht nur über die Kommandozeile. Apples Support-Leitfaden beschreibt es direkt: Sie können „Login-Elemente auswählen, die sich automatisch öffnen, wenn Sie sich anmelden“, sie dort hinzufügen oder entfernen, und separat Apps erlauben oder verweigern, die „Aufgaben ausführen, wenn die App nicht geöffnet ist, etwa nach Software-Updates suchen oder Daten synchronisieren“ — diese zweite Kategorie umfasst Hintergrundhelfer, die keine vollständigen Login-Elemente sind, aber trotzdem unbeaufsichtigt laufen.
Seit macOS Ventura wird das System hinter diesem Einstellungsbereich in der Sicherheitscommunity meist Background Task Management (BTM) genannt: ein Dienst, der jeden Launch Agent, Launch Daemon und jedes Login-Element verfolgt, sobald es sich registriert — das ist es, was den Systemeinstellungen erlaubt, Ihnen eine live aktualisierte, zentrale Liste zu zeigen, statt dass Sie von Hand durch drei Plist-Verzeichnisse suchen müssen. Es gibt ein undokumentiertes Kommandozeilen-Werkzeug, sfltool, das manche Forscher nutzen, um diese Datenbank direkter mit sfltool dumpbtm abzufragen — Apple liefert dafür keine Manpage, und das Ausgabeformat ist nicht garantiert stabil, behandeln Sie es also eher als Forschungskuriosität, die man auf der eigenen Maschine ausprobiert, statt als etwas, um darauf einen Workflow aufzubauen. Der unterstützte, stabile Weg, dieselben Informationen zu sehen, bleibt der Bereich Login-Elemente in den Systemeinstellungen, oder launchctl print für den Live-Status eines bestimmten Jobs.
cron: älter, leiser, immer noch da
launchd ist schon lange Apples bevorzugter Scheduler, aber der ältere Unix-Daemon cron wird weiterhin ausgeliefert und führt weiterhin alles aus, was darin geplant ist. Die crontab-Manpage beschreibt das Dateiformat direkt: Jede Zeile hat fünf Zeit-/Datumsfelder — Minute, Stunde, Tag des Monats, Monat, Wochentag — gefolgt vom auszuführenden Befehl, wobei @reboot und ähnliche Kurzschreibweisen auf manchen Systemen anstelle der fünf Felder verfügbar sind. crontab -l wird laut der Manpage crontab(1) „die aktuelle Crontab auf der Standardausgabe anzeigen“ für den aktuellen Nutzer:
crontab -l
sudo crontab -l -u rootEin leeres Ergebnis für beide ist auf den meisten Macs heute normal — genau deshalb verdient alles, was dort steht, Aufmerksamkeit. cron ist unspektakulär und wird selten geprüft, und genau deshalb taucht es in Vorfallsberichten immer noch als Ausweich-Persistenzort auf.
Konfigurationsprofile: Persistenz mit Papierspur
Ein Konfigurationsprofil kann einen LaunchDaemon installieren, Datenschutzberechtigungen erteilen oder Einstellungen über eine ganze Flotte von Macs verteilen — legitim ist genau das die Funktionsweise von MDM (Mobile Device Management). Illegitim eingesetzt ist ein Profil ein dokumentierter Weg, Änderungen dauerhaft zu machen, ohne direkt eine Plist-Datei anzufassen. Das Kommandozeilen-Werkzeug profiles listet auf, was installiert ist: profiles list zeigt installierte Profile, und, wie die Manpage anmerkt, wird es als root mit -all ausgeführt „alle Konfigurationsprofile auf dem System auflisten“, statt nur die des aktuellen Nutzers.
sudo profiles list -all
sudo profiles show -allEin persönlicher Mac ohne MDM-Einschreibung sollte in der Regel keines haben, oder nur solche, die Sie absichtlich installiert haben (eine VPN-Konfiguration, ein Arbeitsprofil). Ein Profil, an dessen Installation Sie sich nicht erinnern, ist es wert, vor dem Entfernen untersucht zu werden, da profiles für genau diesen Schritt auch das Entfernen mit Passwortschutz unterstützt.
Autorisierungs-Plugins und der lange Schwanz
Über die großen vier oben hinaus gibt es einen langen Schwanz kleinerer, älterer Mechanismen: Directory-Service- und Autorisierungs-Plugins, Spotlight-Importer, QuickLook-Generatoren, Dock-Tile-Plugins und Shell-Startdateien, die bei jeder neu geöffneten Terminal-Sitzung laufen. Hier zahlt sich ein zweckgebautes Werkzeug gegenüber manueller Prüfung aus. Objective-Sees KnockKnock etwa zählt in einem Durchgang mehr als zwanzig Kategorien von Persistenzorten auf — darunter Launch Agents und Daemons, Login-Elemente, Browser-Erweiterungen, Cron-Jobs, Kernel- und System-Erweiterungen sowie Autorisierungs- und Directory-Service-Plugins — und zeigt den Code-Signatur-Status dessen, was es in jedem findet. Sein Begleitprogramm BlockBlock nimmt dieselbe Liste von Orten und überwacht sie fortlaufend, mit einer Warnung in dem Moment, in dem sich etwas Neues registriert; laut eigener Beschreibung „überwacht es gängige Persistenzorte und warnt, wann immer eine neue persistente Komponente hinzugefügt wird“, zeigt den verantwortlichen Prozess, dessen Signaturstatus, und lässt Sie direkt zulassen oder blockieren.
Shell-Startdateien: der stille Auffangort
Noch ein Ort, der einen direkten Blick wert ist, da er weder eine Plist noch eine privilegierte Installation braucht: Shell-Konfigurationsdateien. ~/.zshrc, ~/.zprofile und ~/.bash_profile laufen jedes Mal, wenn eine passende neue Terminal-Sitzung geöffnet wird, und eine einzige angehängte Zeile — eine Weiterleitung an ein Skript, das Exportieren eines gekaperten PATH, das Starten eines Hintergrundprozesses — genügt, um bei jedem Öffnen von Terminal erneut einen Fuß in der Tür zu haben, ohne dass irgendetwas in launchd geladen wird oder launchctl print etwas zeigen könnte. Objective-Sees KnockKnock nimmt genau diese Kategorie in seinen Scan auf, gelistet neben Launch Agents und Login-Elementen als Shell-Konfigurationsdateien, aus demselben Grund, aus dem sie in diesen Artikel gehört: Sie ist verbreitet genug und unspektakulär genug, um geprüft statt einfach angenommen zu werden.
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-screenWo FireAI passt — und wo bewusst nicht
Um es direkt zu sagen: FireAI scannt nicht /Library/LaunchDaemons, liest keine Plist-Dateien und unternimmt keinen Versuch, ein neues Login-Element oder Konfigurationsprofil zu erkennen. Das ist eine andere Disziplin als das, was FireAI tut, und eigens dafür gebaute Werkzeuge — darunter KnockKnock und BlockBlock — erledigen diese Aufgabe bereits gut. Was FireAI beobachtet, ist der Schritt, der nach der Persistenz kommt und den letztlich jeder dieser Mechanismen braucht, wenn er demjenigen nützen soll, der ihn installiert hat: eine Netzwerkverbindung. Ein LaunchAgent, der bei jeder Anmeldung still läuft, aber nie mit dem Netzwerk spricht, ist aus Sicht einer Netzwerk-Firewall unsichtbar — und in der Praxis auch für einen Angreifer weit weniger nützlich. In dem Moment, in dem er einen Socket öffnet, gelten für ihn FireAIs Regeln pro App wie für jeden anderen Prozess: Eine unbekannte, signierte oder unsignierte Binärdatei, die ihre erste Verbindung aufbaut, löst eine Abfrage aus, mit der Begründung des On-Device-Modells in einfacher Sprache, und jede Entscheidung ist sichtbar, rückgängig zu machen und im Nachhinein als Textregel exportierbar.
Der ehrliche Weg, die beiden Disziplinen zusammenzubringen: Prüfen Sie die Orte in diesem Artikel in einem Rhythmus, der zu Ihrer Risikobereitschaft passt — monatlich ist für die meisten Menschen angemessen, wöchentlich, wenn Sie viel Software von Drittanbietern installieren —, und lassen Sie dazwischen ein Netzwerkwerkzeug die Last tragen, unter der Annahme, dass alles, was sich still eingenistet hat, irgendwann sprechen muss, um denjenigen zu erreichen, dem es Rechenschaft ablegt.
Wo FireAI und HisnLabs ins Spiel kommen
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 ist das eigene Produkt von HisnLabs: eine KI-Firewall für den Mac, die direkt auf dem Gerät läuft. Sie zeigt jede Verbindung Ihrer Apps in verständlicher Sprache und lässt Sie entscheiden, was Ihren Mac verlässt — die KI arbeitet lokal, Ihr Datenverkehr wird also nie an uns oder irgendjemand anderen gesendet. Das Sicherheitsforschungsteam von HisnLabs sorgt dafür, dass diese Entscheidungen verlässlich bleiben: Es katalogisiert, welche Domains gewöhnliche Telemetrie und welche ein echter Dienst sind, verfolgt Land und Netzwerk hinter einer Verbindung und trainiert das lokale Modell (die Autopilot-Funktion) mit echten Verkehrsmustern — ohne dass irgendetwas davon Ihren Mac verlässt.
Die technischen Entscheidungen dahinter können Sie nachlesen — oder FireAI 17 Tage lang ausprobieren — unter FireAI, von HisnLabs.
