
Ein Prototyp eines Malware-C2-Kanals, der x509-Zertifikate über mTLS verwendet.
Zuallererst: Warum stelle ich das überhaupt als Open Source bereit?
MITRE ATT&CK erwähnt nur gestohlene oder selbstsignierte Zertifikate, und NDRs (soweit ich das beurteilen kann) schenken dem Inhalt von x509-Zertifikaten abgesehen von der ausstellenden CA nur sehr wenig Aufmerksamkeit. Im Allgemeinen werden x509-Zertifikate als vertrauenswürdig behandelt und dürfen unsere Firewalls ungehindert passieren. Aber im Wesentlichen sind sie nur Dateien, die wie jede andere leicht schädliche Nutzlasten enthalten können. Wir vertrauen ihnen und ignorieren sie, weil sie ein Kernbestandteil eines Verschlüsselungsprozesses sind, den wir als selbstverständlich betrachten. Das Hauptziel dieses Projekts ist es, das Bewusstsein für eine Klasse von Sicherheitsindikatoren zu schärfen, der wir vertrauen gelernt haben, und Methoden aufzuzeigen, mit denen eine böswillige Nutzung erkannt werden kann.
Ich habe mich immer gefragt, ob Bedrohungsakteure jemals x509-Zertifikate als Teil ihrer C2-Kommunikation verwendet haben – nicht um den Netzwerkverkehr zu verschlüsseln, sondern um die C2-Kommunikation tatsächlich im x509-Zertifikat einzubetten. Nachdem ich fünf Jahre lang in freier Wildbahn danach gesucht hatte, habe ich schließlich beschlossen, es einfach selbst zu programmieren, um zu sehen, ob es möglich ist … und es ist möglich.
Jede einzelne verschlüsselte Nachricht, die über HTTPS/TLS gesendet wird, wird durch die Übertragung eines x509-Zertifikats ermöglicht. Beim Aufbau eines TLS-Handshakes (Abbildung unten) sendet der Server im vierten Schritt sein x509-Zertifikat an den Client. Der Client verifiziert das Zertifikat, vergleicht die vom Server unterstützten Verschlüsselungsalgorithmen und wählt aus, welcher Algorithmus für die gesamte weitere Kommunikation verwendet wird.

Wie dieses Diagramm zeigt, handelt es sich hierbei nur um eine Einbahnübertragung des x509-Zertifikats vom Server zum Client. Das eignet sich nicht besonders gut für die C2-Kommunikation, da der Client keine Möglichkeit hat, dem Server zu antworten. Im besten Fall könnte es nur als Einweg-Datenübertragungsmechanismus verwendet werden (siehe Abschnitt „Bekannte Vorarbeiten“ weiter unten).
Es gibt jedoch eine andere Art von TLS-Sitzung, die gegenseitige TLS-Authentifizierung (mTLS) genannt wird, bei der sowohl der Client als auch der Server x509-Zertifikate austauschen, um sich gegenseitig zu authentifizieren.

Wie die obige Abbildung zeigt, wird während der gegenseitigen Authentifizierung zuerst das x509-Zertifikat des Servers an den Client zur Authentifizierung gesendet, und anschließend wird das x509-Zertifikat des Clients an den Server zur Authentifizierung gesendet. Dieser Austausch von Artefakten stellt eine Gelegenheit dar, einen bidirektionalen Kommunikationskanal für C2-Server zu schaffen.
Da die Server- und Client-Zertifikate von der zugrunde liegenden SSL-Bibliothek ausgetauscht werden, gibt es keine Möglichkeit für den Client, die Nachricht aus dem Zertifikat des Servers zu extrahieren, den Befehl auszuführen und ein Antwortzertifikat zu erzeugen – alles innerhalb einer einzigen mTLS-Verbindung. Das bedeutet, dass der C2-Kanal so ausgelegt werden muss, dass der Anfrage-Antwort-Austausch über zwei verschiedene gegenseitige TLS-Verbindungen erfolgt, ähnlich einem Pseudo-Halbduplex-Übertragungsmodus.

Der Anfrage-/Antwortprozess durchläuft die folgenden Schritte:
Nachdem ich das zum Laufen gebracht hatte, war ich ziemlich stolz auf mich, so kreativ und so gewesen zu sein.
Dann stieß ich auf diesen BSides-Vortrag von 2018 von Jason Reaves, der einen Malware-Binary-Dropper mit x509-Zertifikaten über TLS geschrieben hat. Ein Jahr später veröffentlichte Jason dieses Paper, das einen vollwertigen bidirektionalen Kommunikationskanal mit mTLS beschreibt.
mTLS erfordert, dass sowohl die Zertifikate des Clients als auch des Servers von demselben CA-Zertifikat signiert werden. Der erste Schritt besteht also darin, ein eigenes CA-Privatkey-/Zertifikatpaar zu erzeugen.
Root-CA-Privatkey erzeugen:
openssl genrsa -des3 -out hmCA.key 2048
Hinweis: Die Passphrase verhindert, dass jemand, der in den Besitz Ihres privaten Schlüssels gelangt, ein eigenes Root-Zertifikat erzeugen kann.
Root-CA-Zertifikat erzeugen:
openssl req -x509 -new -nodes -key hmCA.key -sha256 -days 1825 -out hmCA.pem
Kopieren Sie die erzeugten Schlüssel- und Zertifikatsdateien in den Ordner certs/ca_certs. Das Projekt enthält ein Demo-Schlüssel-/Zertifikatpaar, diesen Schritt können Sie also überspringen, wenn Sie möchten.
Client starten:
python client.py
Server starten:
python server.py
Ich möchte niemals etwas potenziell Schädliches veröffentlichen, ohne auch zu beschreiben, wie man es in den Netzwerkprotokollen erkennt.
Man würde meinen, diese Art von TLS-Muster sei leicht zu erkennen, aber so einfach ist es nicht. Eines der Hauptmerkmale dieses C2-Kanals ist sein halbduplexer Kommunikationsstil: Es sind zwei gegenseitige Authentifizierungsabläufe nötig, um eine vollständige Anfrage/Antwort zwischen Server und Client abzuschließen. Dies geschieht dann mehrfach, während der Server verschiedene Befehle an den Client sendet.
Das bedeutet, dass Sie nach Folgendem Ausschau halten sollten:
Das klingt nach einer glasklaren Reihe von Erkennungsregeln, aber wie ich bereits sagte, ist es nicht so einfach. Es stellt sich heraus, dass es eine Reihe von Unternehmensdiensten gibt, die ebenfalls ein ähnliches mTLS-Verkehrsmuster aufweisen, darunter:
Einige davon scheinen Asset-/Geräteverwaltungsdienste zu sein. Theoretisch sollten sie also bei jedem Durchlauf durch alle ihre Geräte denselben Satz von Zertifikaten senden. Sie könnten prüfen, ob es Gruppen von mehreren mTLS-Sitzungen gibt, die sich alle N Stunden wiederholen, und dann feststellen, ob die Zertifikats-Hashes zwischen zwei verschiedenen Gruppen von mTLS-Sitzungen übereinstimmen oder größtenteils übereinstimmen. Prüfen Sie außerdem möglicherweise, ob die Client-Zertifikate für jede mTLS-Sitzung unterschiedlich sind, das Server-Zertifikat jedoch über alle Sitzungen hinweg gleich bleibt.
SSL-Inspektion ist eine Möglichkeit, diese Art von C2-Kommunikationskanal potenziell zu blockieren, da der SSL-Inspektionsserver nicht über das bösartige CA-Zertifikat verfügen würde, das zur Authentifizierung des Client-Zertifikats erforderlich ist.