Viele Zufälle führen fast zu einer „Endlos“-Schleife bei forest-weiter Gruppenauswertung

Servus Beianand.

Ich hatte vor einiger Zeit eine recht kuriose Anfrage mit unangenehmen „Nebenwirkungen“, sprich Symptomen.

Darauf gestoßen sind wir, weil einzelne wechselnde DCs immer wieder mal hohe CPU-Last, scheinbar verursacht durch LSASS, zeigten.

Wir haben dann herausgefunden, daß der Auslöser die SMS Hardware Inventur war, die beim Erstellen der Inventur auch Infos über die Eventlogs sammelt, z.B. wer Zugriff auf die einzelnen Eventlogdateien hat. Dazu ermittelt WMI die effektive Berechtigung auf diese Dateien. Die hohe Last beobachteten wir vor allem, wenn die Inventur auf etlichen Client-Rechnern gleichzeitig ausgeführt wurde. Allerdings war die Inventur nur das unschuldige Opfer in diesem Fall.

Die Win32 NTEventlogFile WMI Klasse benutzt für die Auswertung der Berechtigungen GetEffectiveRightsFromAcl.

GetEffectiveRightsFromAcl wandert dann durch die ACL (Zugriffsliste) der Datei und überprüft, ob der aufrufende Benutzer in einer der Gruppen der ACL oder direkt in der ACL ist. Also z.B.:

ACL is: ->Ace[0]: ->AceType: ACCESS_ALLOWED_ACE_TYPE
ACL is: ->Ace[0]: ->AceFlags: 0x10
ACL is: ->Ace[0]: INHERITED_ACE
ACL is: ->Ace[0]: ->AceSize: 0x18
ACL is: ->Ace[0]: ->Mask : 0x001f01ff
ACL is: ->Ace[0]: ->SID: S-1-5-32-544

S-1-5-32-544 ist die Gruppe der lokalen Administratoren auf der Maschine.

Usw. für alle Gruppen, die in der ACL direkt aufgelistet sind. Anschließend fragt die API rekursiv die Mitglieder dieser Gruppen ab (die ja auch wieder Gruppen sein können - Stichwort group nesting) und überprüft wieder , ob der Benutzer in einer der Gruppen ist, indem es die SID des Benutzers mit den Mitgliedern der Gruppen vergleicht. Die API imitiert sozusagen eine Anmeldung des aufrufenden Benutzers.

Dieses rekursive Vorgehen kann schon zu einer relativ hohen Last auf DCs führen, wenn wir hier die entsprechende Anzahl solcher Abfragen gleichzeitig haben.

Hinzu kam nun folgendes: Mit Windows 2000 wurden Universal Groups (Universale Gruppen) eingeführt. Intern werden sie von den NT4 APIs (die u.a. GetEffectiveRightsFromAcl verwendet) wie Globale Gruppen behandelt. Zwischen Universalen und Globalen Gruppen gibt es aber einen bedeutenden Unterschied: Universale Gruppen können Mitglieder aus allen Domänen der Gesamtstruktur (des Forests) enthalten, Globale Gruppen können nur Mitglieder aus der eigenen Domäne haben.

In der Security Accounts Manager API wird von Mitgliedern von Globalen (und Universalen) Gruppen lediglich die RID (Relative ID) zurückgegeben.

Jedem Benutzer einer Domäne wird seit Windows NT eine SID (Security ID) zugewiesen, die je Domäne eindeutig ist. Sie setzt sich aus einem Domänenteil, der für alle Objekte der Domäne gleich ist, und der RID zusammen, die quasi eine fortlaufende Numerierung ist. Durch diese Konstellation – Domänenteil + RID – ist die SID dann eindeutig.

Ein Beispiel:
S-1-5-21-112233445-2233445566-3344556677-98765
Hier ist „98765“ die RID
und S-1-5-21-112233445-2233445566-3344556677 der Domänenteil.

Das bedeutet aber nun für uns, daß in der Security Accounts Manager API für Universale Gruppen die Information der domänenübergreifenden Mitgliedschaften verloren geht, weil nur die RID zurückgegeben wird. Wenn es nun in der Domäne des Benutzers, der die Abfrage aufgerufen hat, ein Objekt mit dieser RID gibt, so hat sie dort eine völlig andere Bedeutung. Ist ja auch ein anderes Objekt.

In unserm konkreten Fall war es so, daß die RID einem Benutzer einer anderen Domäne zugeordnet war und die gleiche RID in der Domäne des aufrufenden Benutzers einer Gruppe gehörte. Und diese Gruppe wiederum war zufällig auch in der Gruppenliste des aufrufenden Benutzers.

Dadurch lief die Abfrage in eine Schleife, die nur deshalb nicht wirklich endlos war, weil irgendwann der Zähler zuschlug, der die Verschachtelungstiefe der Rekursion zählt.

Gruß

Barbara