TokenGroup und MemberOf
Verschiedene Programme arbeiten mit Gruppenmitgliedschaften, um z.B. abhängig davon entsprechende Aktionen auszulösen. Über den Eintrag "MemberOf" eines Benutzers kann ein Programm aber nur die direkten Mitgliedschaften ermitteln. Oft ist es aber erforderlich die rekursive Mitgliedschaft zu ermitteln. Ein Programm könnte nun rekursiv die Mitgliedschaften durchlaufen, was aber lange dauert und viele LDAP-Anfragen liefert. Der DC selbst kann diese Funktion aber schon übernehmen und muss dies sowieso z.B.: für die Ermittlung von Berechtigungen machen. Und es ist bedeutend schneller diese Liste zu nutzen und bei Bedarf die SID auf den Namen aufzulösen als selbst rekursiv die Gruppenzugehörigkeit zu ermitteln.
Funktion von TokenGroup
Das LDAP-Feld "TokenGroup" kann wie jedes andere LDAP-Feld einfach gelesen werden. Da es aber normalerweise nicht in einer Standard Antwort enthalten ist, muss man dieses Feld explizit mit einem "GetEx" anfordern. Vorher macht sich der DC nicht die Mühe das Feld zu ermitteln. Als errechnetes Systemfeld kann es zudem nicht geschrieben werden. Die Basisfunktion unter VBScript könnte wie folgt aussehen:
Function GetTokenGroups(strdn) Dim adsObject Set adsObject = GetObject(strdn) adsObject.GetInfoEx Array("tokenGroups"), 0 GetTokenGroups = adsObject.GetEx("tokenGroups") End Function
Die gleiche Funktion in PowerShell sieht sehr ähnlich aus. Hier noch erweitert um die Ausgabe der Gruppen
$UserAccount = [ADSI]"LDAP://$Account" $UserAccount.GetInfoEx(@("tokengroups"),0) $groups = $UserAccount.Get("tokengroups") write-host "Anzahl der Gruppen" $groups.count
Achtung:
Die Ausgaben sind nur dann akkurat, wenn Sie einen DC der Domäne nutzen,
in der das Objekt angelegt ist. Dazu müssen Sie sich per LDAP verbinden.
Wer einfach eine Suche per "GC" macht, erhält keine komplette Liste der
Gruppen.
Will man noch mehr Details über die Gruppen selbst ermitteln, muss man aus der SID natürlich wieder eine Gruppe ableiten. Aber auch das ist recht einfach:
foreach($group in $groups) { $ID = New-Object System.Security.Principal.SecurityIdentifier($group,0) if($ID) { $groupname = $ID.Translate([System.Security.Principal.NTAccount]) $groupname.Value } }
Für die Tokengröße geht es aber auch einfacher, indem man die SID, welche man schon über die "Groups"-Auflistung erhält, zum Binden an den DC verwendet.
foreach($group in $groups) { $strSID = [System.BitConverter]::ToString($group).replace("-","") $grp = [ADSI]"LDAP://<SID=$strSID>" Write-Host "Group: " $grp.sAMAccountName }
Achtung:
Wer in seinen AD-Konten noch SID-History-Einträge von vergangenen
Migrationen hat, kann durchaus hier noch SIDs finden, die per LDAP nicht
mehr aufzulösen sind.
Über das Property Grouptype der Gruppe bekommt man dann schnell heraus, ob es sich um eine lokale, globale oder universeller Gruppe handelt.
if ($grp.groupType.psbase.value -band 1){ Write-Host " BuildIn" -NoNewline } if ($grp.groupType.psbase.value -band 2){ Write-Host " Global" -NoNewline } if ($grp.groupType.psbase.value -band 4){ Write-Host " Local" -NoNewline } if ($grp.groupType.psbase.value -band 8){ Write-Host " universal" -NoNewline } if ($grp.groupType.psbase.value -band 0x80000000){ Write-Host " Securitygroup" -NoNewline } else { Write-Host " Distributiongroup" -NoNewline }
Dann muss man nur noch anhand der Tabelle die Token-Größe aufaddieren.
1200 für die Verwaltungsinformation
+ 40 * Anzahl der Mitgliedschaften in Domainlokalen Gruppen
+ 40 * Anzahl der Mitgliedschaften in universellen Gruppen anderer Domains + 40 * Anzahl der SIDs in der SIDHistory
+ 8 * Anzahl der Mitgliedschaften in globalen Securitygruppen
+ 8 * Anzahl der Mitgliedschaften in universellen Gruppen der eigenen Domain
=======================
Gesamtgröße des Tokens
Das bedeutet, dass man für universelle Gruppen der gleichen Domain oder globale Gruppen nur 8 Byte addieren muss und ansonsten immer 40 Bytes addiert. Das ganze dann in ein einfaches PowerShell-Skript verpackt finden Sie hier zum Download.
Dump-Ticketsize
PowerShell-Script zum Auslesen der Gruppenmitgliedschaften und Kerberos
Ticketgröße
Sie können es einfach in einer PowerShell aufrufen. Wenn Sie die Ausgabe als CSV-Datei haben wollen, dann sind sie nur einen Export-CSV davon entfernt.
[PS]C:\>.\dumptokensize.ps1 | export-csv -path tokensize.csv
Welche Größe Sie als "kritisch" ansehen, hängt natürlich davon ab, an welche Stellen Sie schon verschiedene Grenzen angehoben haben. Details hierzu finden Sie auf Kerberos Ticketsize.
Limits mit Windows 2008
Als weiteren Schutz gegen DoS Attacken sind in Windows 2008 und 2008R2 einige Grenzwerte "hard" einprogrammiert, mit denen eine Software bei der Abfrage umgehen muss
- 2009267 Windows Server 2008 R2 or Windows Server 2008
domain controller returns only 5000 attributes in a LDAP
response
Dies ist z.B. für automatische Prozesse erforderlich, die große Datenmengen abfragen oder z.B. Gruppen mit mehr als 5000 Mitgliedern verarbeiten wollen. - Range Retrieval of Attribute Values
http://msdn.microsoft.com/en-us/library/cc223242(PROT.10).aspx - Example Code für Ranging with IDirectoryObject
http://msdn.microsoft.com/en-us/library/aa705923(VS.85).aspx - Example Code für Ranging with IDirectorySearch
http://msdn.microsoft.com/en-us/library/aa705924(VS.85).aspx - Paging Search Results
http://msdn.microsoft.com/en-us/library/aa367011(VS.85).aspx - LDAP Policies
http://msdn.microsoft.com/en-us/library/cc223376(PROT.10).aspx - Sharepoint 2013: 5000 Mitglieder
Number of SharePoint 2013 groups a User can belong to = 5000
Quelle: http://technet.microsoft.com/en-us/library/cc262787.aspx
Alternative mit LDAP_MATCHING_RULE_IN_CHAIN
Die Nutzung der TokenGroup liefert natürlich alle Sicherheitsgruppen, da nur diese eine SID haben. Einfache "Verteiler" sind nicht erfasst und fehlen daher in der Liste der Mitglieder. Über eine besondere Option bei der Suche können Sie zwar nicht die Liste Gruppen ermitteln, in der ihr Objekt enthalten ist, aber Sie können sehr wohl prüfen, ob jemand in einer Gruppe enthalten ist. Dazu gibt man den Wert ":1.2.840.113556.1.4.1941:" in der LDAP-Suche hinter dem Feld an, welches für das explizit angegebene Objekt gelesen werden soll.
$objDomain = New-Object System.DirectoryServices.DirectoryEntry("LDAP://rootDSE") $objSearcher = New-Object System.DirectoryServices.DirectorySearcher $objSearcher.SearchRoot = "LDAP://$($objDomain.rootDomainNamingContext)" $objSearcher.PageSize = 1000 $objSearcher.Filter = "(memberof:1.2.840.113556.1.4.1941:=cn=User1,dc=msxfaq,dc=net)" $objSearcher.SearchScope = "Subtree" $objSearcher.PropertiesToLoad.Add("Name") | out-null $colResults = $objSearcher.FindAll() foreach ($objResult in $colResults) { $objItem = $objResult.Properties $objItem.name }
Allerdings ist diese LDAP-Operation für einen Domain Controller sehr aufwändig. Wenn Sie nun also für jedes Objekte nacheinander so die Mitgliedschaften ermitteln wollen, dann sollten Sie besser den umgekehrten Weg gehen und die Mitgliedschaften der Gruppen selbst auslesen und aufaddieren. Um aber mal schnell ein einzelnes Objekte zu prüfen, kann man diesen einfacheren Weg nutzen.
- Search Filter Syntax
http://msdn.microsoft.com/en-us/library/windows/desktop/aa746475(v=vs.85).aspx - Active Directory: LDAP Syntax Filters
https://social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx - Active Directory Week: Explore Group
Membership with PowerShell
https://blogs.technet.microsoft.com/heyscriptingguy/2014/11/25/active-directory-week-explore-group-membership-with-powershell/ - Active Directory User filter does not
search nested groups
https://confluence.atlassian.com/crowdkb/active-directory-User-filter-does-not-search-nested-groups-715130424.html - A hotfix is available that improves the
performance of programs that query Active
Directory for group memberships in Windows
Server 2003
https://support.microsoft.com/en-us/help/914828/a-hotfix-is-available-that-improves-the-performance-of-programs-that-q
Weitere Links
- Kerberos Ticketsize
- Dump-Ticketsize
- Getting Users group membership (tokengroups)
http://bsonposh.com/archives/541 - http://www.rlmueller.net/Programs/IsMember8.txt
- How to Query Active Directory Security Group
Membership
http://explodingcoder.com/cms/content/how-query-active-directory-security-group-membership - MSDN: GetInfoEx
http://msdn.microsoft.com/en-us/library/aa746350(VS.85).aspx - MSDN: Token-Groups Attribute
http://msdn.microsoft.com/en-us/library/ms680275(VS.85).aspx - List Forest-wide Active Directory Group Memberships using PowerShell
http://www.itadmintools.com/2011/08/list-forest-wide-active-directory-group.html - Script Name: Get-TokenSizeReport.ps1
http://www.jhouseconsulting.com/jhouseconsulting/wp-content/uploads/2013/12/Get-TokenSizeReport.ps1_.txt - CheckMaxTokenSize.ps1
http://gallery.technet.microsoft.com/scriptcenter/Check-for-MaxTokenSize-520e51e5 - Alle Mitglieder einer Gruppe in eine neue Gruppe
kopieren
http://blog.dikmenoglu.de/2010/08/alle-mitglieder-einer-gruppe-in-eine-neue-gruppe-kopieren/