Skip to content

csreq-Code-Anforderungen in TCC.db dekodieren

So lesen Sie die Blobs csreq und indirect_object_code_identity in TCC.db: kompilierte Code-Anforderungen, anchor, identifier und ad hoc signierte Clients.

Veröffentlicht am 6 Min. Lesezeit

Kurz gesagt. Die Spalte csreq einer Zeile in TCC.db ist eine kompilierte Code-Anforderung: ein kleiner Binär-Blob, der mit dem Magic 0xFADE0C00 beginnt und eine Regel in Apples Code Signing Requirement Language kodiert, etwa identifier "com.apple.Terminal" and anchor apple. tccd lässt die Zeile für jeden Code gelten, der diese Regel erfüllt. indirect_object_code_identity enthält die gleiche Art von Blob für das Ziel einer Automation-Freigabe. Eine Anforderung, die nur aus cdhash H"..." besteht, bindet die Zeile an genau einen Build und ist typisch für ad hoc signierten Code. Auf einem Mac dekodiert csreq -r- -t einen Blob; TCC Parser dekodiert beide Spalten im Browser zu Text.

Warum die Anforderung mehr zählt als der Name

Die Spalte client sagt, für wen die Zeile gilt: eine Bundle-ID wie com.example.app oder ein absoluter Pfad wie /usr/local/bin/tool. Ein Name lässt sich aber leicht wiederverwenden. Jeder kann eine App bauen, die die Bundle-ID com.example.app für sich beansprucht. Was diesen Hochstapler daran hindert, die Berechtigungen der echten App zu erben, ist die gespeicherte Anforderung: Fordert ein Programm mit dieser Kennung den Dienst an, prüft tccd, ob die Code-Signatur des Programms csreq erfüllt.

Für Ermittler hat das zwei Folgen:

  • Eine Zeile mit Bundle-ID gilt für jeden Code, der die Anforderung erfüllt. Ist die Anforderung streng (Apple-Anker oder eine bestimmte Team-ID), kommen nur ordnungsgemäß signierte Builds dieses Entwicklers infrage. Ist sie locker oder fehlt sie, ist der Schutz schwächer.
  • Das heutige Binärprogramm auf der Platte ist womöglich nicht das freigegebene. Updates, Austausch und gelöschte Werkzeuge trennen die Verbindung zwischen „Zeile“ und „Datei“. Die Anforderung ist das Beweisstück, das beschreibt, was freigegeben wurde.

Das Blob-Format

Eine kompilierte Anforderung, wie sie in csreq gespeichert ist, ist eine Big-Endian-Struktur:

TeilInhalt
Magic0xFADE0C00 (Anforderung)
LängeGesamtlänge des Blobs
Art1: Ausdrucksform
AusdruckEin Ausdruck in Präfixnotation: ein Operator, gefolgt von seinen Operanden (Zeichenketten, Hashes, Zertifikatsfelder, verschachtelte Ausdrücke)

Den Ausdruck müssen Sie selten von Hand durchgehen. Das Layout zu kennen hilft, den Blob zu erkennen (in einer Hex-Ansicht beginnt er mit FA DE 0C 00) und der Textausgabe eines Decoders erst zu vertrauen, wenn Sie geprüft haben, dass er den gesamten Blob verarbeitet hat.

Dekodieren auf einem Mac

Der native Weg unter macOS ist das Werkzeug csreq. Extrahieren Sie den Blob als Bytes und übergeben Sie ihn über die Standardeingabe:

sqlite3 TCC.db "SELECT hex(csreq) FROM access
                WHERE client = 'com.apple.Terminal'
                  AND service = 'kTCCServiceSystemPolicyAllFiles';" \
  | xxd -r -p | csreq -r- -t

Zum Vergleich mit einem Binärprogramm auf der Platte geben Sie dessen Designated Requirement aus:

codesign -d -r- /System/Applications/Utilities/Terminal.app

Arbeiten Sie nicht auf einem Mac oder haben Sie Hunderte Zeilen, dekodiert TCC Parser jeden Blob in csreq und indirect_object_code_identity zu Anforderungstext und zeigt ihn neben der Zeile an.

Den dekodierten Text lesen

Anforderungen sind boolesche Ausdrücke. Die häufigsten Klauseln:

KlauselBedeutung
identifier "com.apple.Terminal"Die Signaturkennung des Codes muss genau diese sein
anchor appleVon Apple selbst signiert (Apples eigene Software)
anchor apple genericKette bis zu Apples Root, einschließlich Developer-ID- und App-Store-Signaturen
certificate leaf[subject.OU] = TEAMIDDas Signaturzertifikat gehört zu dieser Team-ID
cdhash H"..."Der Hash des Code Directory muss genau diesem Wert entsprechen: ein bestimmter Build
and, or, KlammernVerknüpfen Klauseln

Drei Muster decken die meisten Zeilen ab:

Apple-Software. identifier "com.apple.Terminal" and anchor apple. Nur von Apple signierter Code mit dieser Kennung kommt infrage.

Signierte Software von Drittanbietern. anchor apple generic and identifier "com.example.app" and certificate leaf[subject.OU] = TEAMID, oft mit weiteren Klauseln zu Zertifikatsfeldern. Nur von dieser Team-ID signierte Builds kommen infrage. Die Team-ID ist ein guter Ansatzpunkt für weitere Suchen: in Ihrer Flotte, in anderen TCC-Zeilen und in den Code-Signing-Daten von Binärprogrammen auf der Platte.

Ad hoc signierter oder fixierter Code. Nur cdhash H"4b6a...". Über den Hash eines Builds hinaus gibt es keine Identität. Das sehen Sie typischerweise bei ad hoc signierten Binärprogrammen (ohne Entwicklerzertifikat) und bei vielen pfadbasierten Clients. Für sich genommen ist das nicht bösartig: Eigene Builds von Entwicklern, manche Open-Source-Werkzeuge und lokal kompilierte Skripte sehen genauso aus. Für einen Dienst mit hoher Tragweite ist es aber ungewöhnlich, und es bedeutet, dass die Freigabe an einen einzigen Build gebunden ist: Hat die Datei auf der Platte einen anderen cdhash, ist sie nicht der freigegebene Build.

Auch eine fehlende Anforderung (csreq ist null oder leer) verdient eine Notiz. Bei manchen vom System gesetzten Zeilen kann das legitim sein, bei einer für den Benutzer sichtbaren Freigabe entfällt damit aber die Identitätsprüfung, die die Zeile normalerweise mitbringt.

indirect_object_code_identity: die andere Seite der Automation

Bei Apple-Events-Automation (kTCCServiceAppleEvents) hat eine Zeile zwei Beteiligte: den client, der Ereignisse sendet, und das Ziel in indirect_object_identifier (zum Beispiel com.apple.finder oder com.apple.systemevents). indirect_object_code_identity ist die kompilierte Anforderung für dieses Ziel, im selben Format wie csreq. Dekodieren Sie sie auf dieselbe Weise. Bei Apple-Zielen erwarten Sie Anforderungen mit anchor apple; alles andere lohnt eine genaue Lektüre.

Ein Beispiel

Im fiktiven Beispiel FIN-MBP-03, das mit TCC Parser ausgeliefert wird, enthält die System-Datenbank eine Zeile für Bedienungshilfen mit einem pfadbasierten Client:

FeldWert
servicekTCCServiceAccessibility
client/Users/dana.whitlock/Library/Caches/.sync/sync-helper
client_type1 (absoluter Pfad)
csreq (dekodiert)nur cdhash H"..."

Zusammen gelesen: ein Binärprogramm in einem versteckten Ordner unter den Caches des Benutzers, über den Pfad statt über eine Bundle-ID identifiziert, mit einer Anforderung, die einen einzigen ad hoc signierten Build fixiert, und im Besitz einer Fähigkeit, mit der sich die Benutzeroberfläche steuern lässt. Jedes Element für sich hat harmlose Erklärungen; zusammen sind sie Grund genug, die Datei zu sichern, ihren Hash zu bilden, ihren cdhash mit der Anforderung zu vergleichen und nachzuvollziehen, wie sie auf das System kam. Vergleichen Sie das mit der Zeile für Festplattenvollzugriff von com.apple.Terminal in derselben Datenbank, deren Anforderung einen Apple-Anker enthält: Die Identität ist in Ordnung, und die Frage lautet nun, wer Terminal genutzt hat und wofür. Darum geht es in Missbrauch von TCC-Berechtigungen untersuchen.

Wie TCC Parser die Anforderung nutzt

Im Tab Permissions (Berechtigungen) sehen Sie nach einem Klick auf eine Zeile ihre dekodierte Anforderung im Detailfenster, und der Tab Findings (Befunde) markiert Zeilen, deren Anforderung ad hoc (nur cdhash) ist oder fehlt. Die Markierung ist ein Anlass hinzusehen, kein Urteil. Derselbe dekodierte Text erscheint im JSON-Export, sodass Sie ihn mit dem Fall aufbewahren können.

Fallstricke

  • Dekodieren ist nicht Verifizieren. Die Anforderung zu lesen sagt Ihnen, was freigegeben wurde. Ob eine bestimmte Datei sie erfüllt, prüfen Sie nur mit der Datei und codesign.
  • Kennungen belegen keine Herkunft. identifier "com.example.app" ohne Klausel für Anker oder Team-ID ist schwach.
  • Updates ändern cdhashes. Eine Zeile, die nur einen cdhash enthält, passt nach einem Neubau nicht mehr, und eine neue Abfrage erzeugt einen neuen Zeilenzustand.
  • Der csreq in expired und MDMOverrides.plist. Abgelaufene Zeilen behalten ihren csreq, und MDM-Einträge tragen CodeRequirement (Text) und CodeRequirementData (Blob). Vergleichen Sie sie mit den aktiven Zeilen.

Verwandte Artikel

Verwandte Artikel

Schritt für Schritt: TCC.db samt WAL in einen kostenlosen Browser-Parser laden, Befunde lesen, Berechtigungen und Verlauf prüfen, Zeitraum setzen, exportieren.
Wie sich die Tabelle access in TCC.db von Mojave über Big Sur bis Sonoma verändert hat: allowed, auth_value, auth_reason, pid, last_reminded und Nebentabellen.
Was die TCC-Datenbank von macOS aufzeichnet, was sie belegt und was nicht, die wichtigsten Dienste und ein wiederholbarer Ablauf für die forensische Analyse.