Yuval Gordon Sicherheitsforscher | Microsoft

Wie potenzielle Angreifer über DnsAdmins eine privilegierte Persistenz auf einem DC erreichen können

Das Semperis-Forschungsteam hat vor kurzem frühere Untersuchungen erweitert, die einen Funktionsmissbrauch in der Windows Active Directory (AD)-Umgebung zeigten, bei dem Benutzer der Gruppe DnsAdmins eine beliebige DLL in einen DNS-Dienst laden konnten, der auf einem Domänencontroller läuft. Yuval Gordon vom Semperis-Forschungsteam erweiterte diese Forschung, um zu zeigen, wie ein Problem mit der vorherigen Technik überwunden werden kann und dass ein Angreifer diese Taktik nutzen könnte, um eine unentdeckte Hintertür in das Active Directory eines Unternehmens zu hinterlassen - ein erhebliches Sicherheitsrisiko.

In einem Beitrag auf Medium aus dem Jahr 2017 zeigten Sicherheitsforscher, wie Benutzer aus der Gruppe DnsAdmins eine "Funktion" im Microsoft DNS-Verwaltungsprotokoll nutzen konnten, um den DNS-Dienst dazu zu bringen, eine beliebige DLL zu laden. Dieser Dienst läuft auf Domain Controllern als NT AuthoritySystem, was es DnsSAdmins ermöglicht, die Privilegien auf dem DC auf SYSTEM zu erweitern (mit Berechtigungen, die mindestens denen von Domain Admins entsprechen). Dieser "nette Trick", wie ihn der ursprüngliche Forscher, Shay Ber, nannte, kann für Red Teams, die eine AD-Privilegienerweiterung erforschen, nützlich sein und stellt für Angreifer eine potenzielle Hintertür zum Domain Controller dar.

Verwandte Lektüre

In diesem Beitrag erweitere ich Shay Ber's Forschung, indem ich zeige, wie man ein Problem mit der vorherigen Technik überwindet und wie man sie unauffälliger macht. Außerdem gehe ich auf die erforderlichen Berechtigungen ein, um zu zeigen, dass ein Angreifer diese Taktik nutzen könnte, um eine Hintertür zu DC zu hinterlassen, die wahrscheinlich nicht bemerkt würde und einige Tools umgehen könnte.

Shay Ber und Nikhil Mittal haben gezeigt, dass es möglich ist, eine beliebige DLL in einen DNS-Dienst zu laden, der auf einem Domain Controller läuft:

  1. Der Angreifer muss Mitglied der Gruppe DnsAdmins sein, um dnscmd auszuführen und den Dienst auf eine DLL in einem UNC-Pfad zu verweisen.
  2. Der Angreifer startet den DNS-Dienst mit "sc.exe stop/start dns" neu. Dies ist eine Einschränkung, da die Standardkonfigurationen es DnsAdmins-Benutzern nicht erlauben, Dienste anzuhalten und zu starten.

Meine Forschung erweitert das Verständnis für diese Angriffsmöglichkeit auf folgende Weise:

  1. Es ist nicht unbedingt erforderlich, Teil von DnsAdmins zu sein, um diesen Angriff auszuführen, sondern nur Lese-/Schreibzugriff auf den MicrosoftDNS-Container und RPC-Zugriff auf den DC zu haben.
  2. Es ist möglich, den DNS-Dienst nur mit den unter 1. aufgeführten Berechtigungen neu zu starten.

Es ist daher für einen Angreifer mit ausreichenden Rechten möglich, einen Benutzer mit minimalen Berechtigungen und nur direktem Lese-/Schreibzugriff auf den MicrosoftDNS-Container zu erstellen/aktualisieren. Dieser Benutzer würde in den meisten Fällen "unter dem Radar" fliegen, da die Container-Berechtigungen nur selten überwacht werden. Dieser Benutzer könnte unentdeckt bleiben und dazu benutzt werden, beliebige Befehle mit DC SYSTEM-Rechten auszuführen, indem er eine DLL in den DNS-Prozess lädt.

Hintergrund der Forschung

Vor drei Jahren schrieb Shay Ber in dem Medium-Beitrag "Feature, not bug: DnsAdmin to DC compromise in one line" (DnsAdmin zu DC Kompromiss in einer Zeile), bemerkte Shay Ber, dass jedes Mitglied der DnsAdmins Gruppe den DNS Server Dienst dazu bringen kann, beim nächsten Neustart des Dienstes eine DLL als NT AuthoritySystem auf dem DC zu laden.

DnsAdmins verfügt standardmäßig nicht über die erforderliche Berechtigung, den Dienst auf dem DC aus der Ferne neu zu starten. Das bedeutet, dass Angreifer, die die Funktion missbrauchen wollen, warten müssen (oder andere Methoden verwenden), bis der Server oder Dienst neu gestartet wird, um ihre Nutzlast auszuführen.

Meine Aufgabe war es, nach einer Möglichkeit zu suchen, den Neustart des Dienstes zu erzwingen oder die DLL sofort zu laden, und zwar so unauffällig wie möglich. (Selbst wenn ich die Berechtigungen für einen Neustart mit sc.exe hätte, würde dies zahlreiche Protokolle erzeugen und wahrscheinlich entdeckt werden). Dieser Ansatz erwies sich als überraschend einfach, hatte aber einige unerwartete Konsequenzen. Bevor Sie weiter lesen, empfehle ich Ihnen, zuerst Ber's ursprüngliche Forschung zu lesen.

Ein Neustart
Ich begann damit, die MS-DNSP-Spezifikationen zu überprüfen und suchte nach einer Erwähnung des Wortes Neustart, als ich auf Folgendes stieß:

pszOperation neu starten
Abbildung 1: Neustart pszOperation

Diese Zeile zeigt an, dass einer der Befehle, die der Server (pszOperation) in R_DnssrvOperation akzeptiert, restart ist, was (wenig überraschend) den DNS-Serverprozess neu starten wird. Klingt perfekt!

Um mir das Leben leichter zu machen, habe ich mir die Dokumentation des Tools dnscmd (CLI-Tool für die Verwaltung von DNS-Servern) angesehen und nach einer Möglichkeit gesucht, damit einen Neustartbefehl an den DNS-Server zu senden, aber nichts gefunden.

Ich dachte, ich sollte mir die Zeichenketten des Tools für "Neustart" ansehen und (überraschenderweise) war es da:

Abbildung 2 Neustart-Zeichenfolge in den Zeichenfolgen von dnscmd
Abbildung 2: Neustart-Zeichenfolge in den Zeichenfolgen von dnscmd

Obwohl es weder in der Microsoft-Dokumentation noch in der Hilfe des Tools erwähnt wird, gibt es einen Schalter "/Restart", den Sie in dnscmd verwenden können, um den Neustart eines DNS-Servers auszulösen.

Abbildung 3 Erfolgreicher Aufruf des Neustart-Befehls
Abbildung 3: Erfolgreicher Aufruf des Neustart-Befehls

Der Dienst löste einen internen Neustart aus, indem er eine interne Funktion namens "reloadShutdown" aufrief und dann alles neu startete, ohne den Prozess zu beenden, im Gegensatz zu einem normalen Neustart des Dienstes.

Jetzt wusste ich also, wie ich einen Reload auslösen und die DLL sofort laden konnte, aber was waren die erforderlichen Berechtigungen?

Wie in der Dokumentation beschrieben, besteht die erste Prüfung jeder DNS-Operation darin, die Anmeldeinformationen des Clients auf Leseberechtigung für den MicrosoftDNS-Container zu testen. Für unsere spezifischen Operationen (Neustart und ServerLevelPluginDll) ist auch eine Schreibberechtigung für dasselbe Objekt erforderlich.

Inzwischen hatte ich einen Reload ausgelöst, der den Dienst dazu brachte, die zuvor gesendete DLL zu laden (der im Szenario-Abschnitt gezeigte Befehl) und weniger Spuren zu hinterlassen, da keine Protokolle über den Neustart des Dienstes oder die Erstellung von Prozessen erstellt wurden.

Die Protokolle, die beide im DNS-Server-Protokoll erstellt wurden, waren Ereignis-ID 770 (eine Plugin-DLL auf Serverebene wurde geladen) und Ereignis-ID 140:

Abbildung 4: DNS-Server-Protokolleinträge

Im nächsten Abschnitt gehe ich darauf ein, warum dieser Fehler erzeugt wird. Wenn Sie die Details überspringen möchten, können Sie zum Abschnitt "Mögliche Auswirkungen" springen.

Der Fehler
Beim Ausführen des Neustart-Befehls ist etwas Unerwartetes passiert: Die DLL wurde geladen (wie erwartet), und der Dienst lief weiter, aber im DNS Server-Protokoll wurde folgendes Protokoll erstellt:

Abbildung 5: Nach dem Neustart erzeugtes Fehlerprotokoll
Abbildung 5: Nach dem Neustart erzeugtes Fehlerprotokoll

Die Überprüfung des Fehlercodes ergab, dass es ein Problem mit dem RPC-Endpunkt gab (0x6cc - Der Endpunkt ist ein Duplikat.).

Als ich versuchte, mit dnscmd einen anderen Befehl an denselben DNS-Server zu senden, funktionierte plötzlich nichts mehr:

Abbildung 6 Nichts funktioniert
Abbildung 6: Nichts funktioniert

Auch die DNS-Verwaltungskonsole funktionierte nicht mehr:

Abbildung 7 Weitere Fehler
Abbildung 7: Weitere Fehler

Um zu verstehen, woran es lag, habe ich ApiMonitor verwendet und gesehen, dass es ein Problem mit der Registrierung des Endpunkts nach dem Neustart gab.

Wenn Sie den DNS-Serverdienst auf die übliche Weise neu starten (z.B. services.msc), wird der Dienst angehalten und gestartet, ohne dass ein Fehler auftritt. Daher habe ich als Nächstes nachgesehen, warum hier kein Fehler ausgelöst wird, im Gegensatz zu einem Neustart mit dem Befehl /restart, der an den Server übermittelt wird.

Es ist jedoch etwas Interessantes passiert. Sowohl der Neustart des Dienstes als auch das Neuladen des Dienstes schlugen bei demselben API-Aufruf fehl.

Bei dieser Meldung klingelt es bei Ihnen, nicht wahr? Der Dienst konnte die Registrierung des RPC-Endpunkts nicht aufheben und hat dann beim Versuch, den Endpunkt zu verwenden, einen doppelten Fehler erzeugt.

Die Erklärung für die Tatsache, dass nach einem Neustart des Dienstes keine weiteren Fehler auftraten, ist, dass beim Neustart des Dienstes der Prozess beendet wird, wodurch der Endpunkt automatisch deregistriert wird. Dies geschieht nicht, wenn Sie einen Dienstneustart auslösen (der Prozess wird nicht wirklich neu gestartet, daher kein Prozessausgang).

Mögliche Auswirkungen

Mit diesen Methoden kann ein Angreifer beliebige DLLs innerhalb des Sicherheitskontextes des DNS-Dienstes ausführen.

Da der DNS-Dienst häufig auf Domänencontrollern ausgeführt wird, bietet diese Schwachstelle Angreifern die Möglichkeit, die Privilegien für jeden Benutzer in der Domäne, der unter ihrer Kontrolle steht, zu erweitern. Wie im nächsten Abschnitt beschrieben, bieten die Besonderheiten der Active Director-Container-ACLs Angreifern nicht nur die Möglichkeit, ihren aktuellen Angriff voranzutreiben, sondern auch "Schläfer-Admins" und nicht privilegierte Benutzer zu schaffen, die ihre Privilegien nach Belieben erweitern können.

Damit diese Angriffe funktionieren, muss ein Angreifer über Folgendes verfügen:

  • Dnscmd (nicht notwendig, spart aber Zeit und Mühe)
  • RPC offen für DC
  • Lese- und Schreibberechtigungen für den MicrosoftDNS-Container (im Systemcontainer)

Beispiel-Szenario

Angreifer, denen es gelingt, einen Benutzer in der DnsAdmin-Gruppe zu kompromittieren, können ihre Position auf verschiedene Weise ausbauen. Neben der sofortigen Ausweitung der Privilegien auf SYSTEM-Benutzer auf einem DC (wodurch sie Domänen-Admin-Benutzer hinzufügen oder sogar einen Skeleton Key erhalten können), können sie auch einem Benutzer mit geringen Privilegien die Möglichkeit geben, seine Privilegien zu erhöhen, indem sie ihm im Rahmen ihres ersten Angriffs Lese-/Schreibzugriff auf den MicrosoftDNS-Container zuweisen.

Dieser Benutzer könnte vom Angreifer oder von einem bestehenden Benutzer mit einem kompromittierten Passwort oder einem bekannten SPN für späteres Kerberoasting erstellt werden. Während privilegierte AD-Gruppen wie z.B. Domänenadministratoren oft genau überwacht werden, ist es bekanntermaßen schwierig, genaue Objekt-ACLs effektiv zu überwachen. Dies führt zu einer Situation, in der Benutzer scheinbar unprivilegiert sind, in Wirklichkeit aber den DNS-Dienst neu starten und DLLs injizieren können, um wieder privilegierten Zugriff zu erhalten, was eine dauerhafte Hintertür in die Umgebung darstellt.

Abbildung 8: Domänenbenutzer

Im obigen Screenshot sieht der Benutzer "haxer" wie ein nicht privilegierter Benutzer aus, da er nur ein Mitglied der Domänenbenutzer ist. Aber alles, was er braucht, um Domänen-Admin zu werden, ist RPC zum DC und Schreibzugriff auf eine Freigabe, auf die der DC zugreift.

In diesem Beispiel wird die DLL beim Laden eine Shell starten, die Befehle aus einer Datei in einer Freigabe (command.txt) empfängt und die Ausgabe in eine andere Datei in derselben Freigabe (out.txt) schreibt.

Der Angreifer meldet sich als Benutzer "haxer" an, der derzeit kein Mitglied einer privilegierten Gruppe ist, und erstellt eine Freigabe mit Lese-/Schreibzugriff für alle, die seine bösartige DLL enthält:

Abbildung 9: Angreifer meldet sich als "haxer" an

Jetzt muss der Angreifer die DLL nur noch als ServerLevelPluginDll auf dem DC registrieren, einen Dienstneustart auslösen und mit der Datei, die er erstellt, Befehle senden:

Abbildung 10: Registrierung der DLL

Bei diesem Szenario sind zwei Aspekte wichtig:

  1. Wenn der DC nicht auf den als ServerLevelPluginDLL gesendeten Pfad zugreifen kann, führt der Neustart-Auslöser dazu, dass der DNS-Dienst beendet wird und erst wieder gestartet werden kann, wenn der DC auf den Pfad zugreifen kann oder der Pfad aus der Registrierung des DCs entfernt wird. (Und als DnsAdmin werden wir wahrscheinlich nicht in der Lage sein, den Dienst zu starten, wenn er ausgefallen ist).
  2. Aufgrund des oben beschriebenen Fehlers führt das Auslösen eines Neuladens zu Problemen mit der Duplizierung des RPC-Endpunkts, und wir können keine weiteren Befehle senden oder einen weiteren Neustart auslösen:
Abbildung 11: Neustart-Befehl schlägt fehl

Protokollierung und Erkennung

Im Folgenden finden Sie einige Schritte, die Unternehmen unternehmen können, um ein mögliches Eindringen zu protokollieren und zu erkennen. Zunächst ist es wichtig zu wissen, dass ein Neustart des DNS-Server-Prozesses mit dem Befehl restart pszOperation KEIN Protokoll mit der Ereignis-ID 7036 erzeugt, da es sich hierbei nicht um einen Dienstneustart handelt.

1. Die Ereignis-ID 770 wird im Protokoll DNS Server auf dem DC erstellt, wenn er die DLL nach einem Neustart lädt, wobei der DLL-Pfad angegeben wird.

Abbildung 12: Ereignis 770 protokolliert

2. Die Ereignis-ID 140 wird erstellt, wenn ein Neustart mit R_DnssrvOperation ausgelöst wird (nur wegen des Fehlers; idealerweise wird dies in Zukunft nicht mehr passieren).

Abbildung 13: Ereignis 140 protokolliert

3. Überwachen Sie auf ntSecurityDescriptor-Änderungen bei MicrosoftDNS und der DnsAdmins-Gruppe (Ereignis-ID 5136).

4. Überwachen Sie das Hinzufügen von Mitgliedern zur Gruppe DnsAdmins.

5 Behandeln Sie Benutzer und Gruppen, die bereits über diese Berechtigungen verfügen, wie Domänenadmins und überwachen Sie sie entsprechend.

6. Benutzer und Gruppen mit diesen Berechtigungen sollten zum besseren Schutz zur Gruppe Geschützte Benutzer hinzugefügt werden.

7. Mit IPSIDS können Sie R_DnssrvOperation und R_DnssrvOperation2 Anfragen von Nicht-Administrationscomputern an DNS-Server überwachen.

8. Überwachen Sie die Änderungen am Registrierungspfad "HKLMSYSTEMCurrentControlSetServicesDNSParametersServerLevelPluginDLL" auf DNS-Servern.

Schutz für Ihren Microsoft DNS-Dienst

Durch die Implementierung dieser Best Practices für die Protokollierung und Erkennung kann Ihr Unternehmen ein Szenario verhindern, in dem Benutzer, die bereits über die Berechtigung zur Verwaltung des DNS verfügen, diesen für eine Kompromittierung des Domänencontrollers nutzen können - oder eine heimliche Hintertür für unerwünschte Eindringlinge in der Domäne hinterlassen.