Printout Header
RSS Feed

Microsoft Security Identifier (SID) Attribute


Auf dieser Webseite wollen wir einen Blick auf diejenigen Verzeichnis-Attribute werfen, die von Microsoft dazu verwendet werden, um die so genannten Security Identifiers (SID) zu speichern. SIDs spielen eine wichtige Rolle bei der Vergabe und Zuweisung von Berechtigungen und bei der Identifikation von Rechteinhabern gegenüber dem System. Beispiele für derartige Attribute:

objectSid
User objects
Computer objects
Group objects
Die Sicherheits ID, die den betreffenden Security Principal (=potentieller Rechte-Inhaber) eindeutig identifiziert.
sIDHistory
User objects
Computer objects
Goup objects
Existiert nur für migrierte Obekte, die z.B. mittels ADMT aus einer fremden Domäe übernommmen wurden. Die Liste der Security IDs im sIDHistory Attribut ermöglicht es, dass der betreffende Account oder die betreffende Gruppe mit der alten Identität auf Ressourcen zugreift und damit alle ehemaligen Berechtigungen erhalten bleiben.
tokenGroups
User objects
Computer objects
Die SIDs aller Gruppen innerhalb des gleichen AD Forests, in denen der Benutzer enthalten ist. Dabei werden auch Gruppenverschachtelungen beachtet, d.h. diese Liste enthält sowohl die direkten als auch indirekten Gruppenmitgliedschaften.

Ein sehr interessantes Attribut, nach dem leider nicht in LDAP-Filtern gesucht werden kann, weil es sich hier um ein Constructed Attribut handelt.
tokenGroupsGlobalAndUniversal
User objects
Computer objects
Eine Untermenge des tokenGroups Attributes. Es werden hier lediglich die SIDs von globalen und universellen Gruppen in die Liste aufgenommen.
tokenGroupsNoGCAcceptable
User objects
Computer objects
Eine Untermenge des tokenGroups Attributes. Es werden alle Gruppen-SIDs aufgenommen, für deren Auswertung man keinen Global Catalog benötigt.

Der grundlegende LDAP Attribut-Datentyp für derartige Attribute ist eine Microsoft-proprietäre LDAP attribut syntax, die String(Sid) genannt wird - grundsätzlich handelt es sich dabei um binäre Daten, mit denen man schon beim Auslesen im Script speziell umgehen muß. Nähere Details hierzu kann man im SelfADSI Tutorial-Artikel Objekt-Attribute des Typs "Octet String" nachlesen.

Die interne Struktur eines SID Wertes wird in diesem Micrsoft Dokument beschrieben: Microsoft Data Type Reference [MSDTY].

Struktur einer Microsoft SID

1-Byte Revision: Eine 8-bit Unsigned Integer Zahl, die das Revisionslevel der SID Struktur angibt. Dieser Wert ist stets = 1.

1-Byte SubAuthority Count: Eine 8-bit Unsigned Integer Zahl, die die Nummer der Sub-Authority-Elemente (dies sind sozusagen die Sub-IDs innerhalb der SID) angibt. Es kann maximal 15 dieser Sub-Authorities geben.

6-Byte IdentifierAuthority: Diese 6 Bytes stellen den so genannten Authority Identifier dar, der anzeigt unter welcher Authorität die betreffende SID erzeugt wurde. Folgende Werte sind bisher definiert:
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00 : NULL_SID_AUTHORITY
      0x00, 0x00, 0x00, 0x00, 0x00, 0x01 : WORLD_SID_AUTHORITY
      0x00, 0x00, 0x00, 0x00, 0x00, 0x02 : LOCAL_SID_AUTHORITY
      0x00, 0x00, 0x00, 0x00, 0x00, 0x03 : CREATOR_SID_AUTHORITY
      0x00, 0x00, 0x00, 0x00, 0x00, 0x04 : NON_UNIQUE_AUTHORITY
      0x00, 0x00, 0x00, 0x00, 0x00, 0x05 : NT_AUTHORITY
      0x00, 0x00, 0x00, 0x00, 0x00, 0x06 : SECURITY_MANDATORY_LABEL_AUTHORITY

Variable-Length SubAuthority: Ein Feld von variabler Länge, das aus einem oder mehreren (die Anzahl steht weiter vorn in der SID) Sub-Authority-Elementen besteht. Eine Sub-Authority wird durch eine 32-Bit Integers Nummer repräsntiert, die in umgekehrter Byte-Order (LittleEndian) gespeichert werden. Die SID eines normalen Active Direcory Accounts besteht hier aus 5 solcher Sub-Authorities, die erste hat stets den Wert 21, die nächsten drei stellen den SID-"Grundstock" der Domäne dar, und der letzte Authority-Wert it schließlich die relative ID (RID) des Objektes in seiner Domäne. Ein Beispiel für eine normale Account-SID:

Eine Active Directory Account SID


Obwohl SIDs binäre Werte mit einer variablen Länge sind(normale Active Directory SIDs haben eine Länge von 28 Byte), werden sie für gewöhnlich als Zeichenkette mit einer ganz bestimmten Syntax dargestellt, z.B. wie diese hier:

S-1-5-7   (Wellknown SID for 'Anonymous Logon')
S-1-5-21-1621763826-2590103247-2238570322-1113

Diese Darstellungsform wird SDDL (Security Descriptor Definition Language) genannt. Die Regel für die SDDL-Schreibweise einer SID lautet

S-1-IdentifierAuthority-SubAuthority1-SubAuthority2-...-SubAuthorityn

Jede Active Directory Configuration Partition speichert Informationen über die so genannten wellknown standard SIDs die in dem betreffenden System verwendet werden können. Solche Daten werden in der OU CN=WellKnown Security Principals,CN=Configuration,DC=.... gespeichert. Dies ist der Aufbau der Wellknown SID "Everyone" (S-1-1-0):

Wellknown SID - EveryOne


Und dies ist der Aufbau der Wellknown SID "System" (S-1-5-18):

Wellknown SID - System


Binäre SID Daten umwandeln in lesbare SDDL Strings

Wenn man SIDs mit einem LDAP Script aus dem Verzeichnis lesen will, stellt sich die Frage: Wie wandelt man die binären Daten in einen lesbaren SDDL-String um?

Wie wir bei der Besprechung der Datenstruktur eines SID-Attributes gelernt haben, müssen wir beim Auslesen und Darstellen der Daten zwei Hürden überwinden. Zuerst müssen die puren Binärdaten in einen Hex-String umgewandelt werden: Dies erledigt die Funktion OctetToHexStr. Danach können wir die Daten in eine SDDL-Schreibweise umwandeln, wenn wir die einzelnen Bytes der Authority-Blöcke jeweils gemäß der richtigen Byte-Order in Long-Zahlen umwandeln. Dies macht die Funktion HexStrToSID. Dabei brauchen wir ein paar Hilfsfunktionen, die weiter unten im Beispielscript aufgeführt werden:

'Sie müssen hier andere Namen und Anmeldedaten aus Ihrer eigene Umgebung angeben! Set obj = GetObject("LDAP://cn=Foeckeler,cn=Users,dc=cerrotorre,dc=de") pureSidData = OctetToHexStr(obj.objectSid) sDDLSidStr = HexStrToSID(pureSidData) WScript.Echo obj.cn WScript.Echo pureSidData WScript.Echo sDDLSidStr Function HexStrToSID(strSid) 'wandelt einen SID Hex String in Rohform in den entsprechenden SID String (SDDL) um Dim i, data, offset ReDim data(Len(strSid)/2 - 1) For i = 0 To UBound(data) data(i) = CInt("&H" & Mid(strSid, 2*i + 1, 2)) Next HexStrToSID = "S-" & data(0) & "-" & Byte6ToLong(data(2), data(3), data(4), data(5), data(6), data(7)) blockCount = data(1) For i = 0 To blockCount - 1 offset = 8 + 4*i HexStrToSID = HexStrToSID & "-" & Byte4ToLong(data(offset+3), data(offset+2), data(offset+1), data(offset)) Next End Function '_________________________________________________________________________________________ Hilfsfunktionen Function OctetToHexStr(var_octet) 'wandelt reine Binärdaten (Byte-Array) in einen String mit den Hexadezimalwerten um. Dim n OctetToHexStr = "" For n = 1 To lenb(var_octet) OctetToHexStr = OctetToHexStr & Right("0" & hex(ascb(midb(var_octet, n, 1))), 2) Next End Function Function Byte4ToLong(ByVal b1, ByVal b2, ByVal b3, ByVal b4) 'wandelt 4 Bytes in den entsprechenden Long-Wert um Dim n Byte4ToLong = b1 Byte4ToLong = Byte4ToLong * 256 + b2 Byte4ToLong = Byte4ToLong * 256 + b3 Byte4ToLong = Byte4ToLong * 256 + b4 End Function Function Byte6ToLong(ByVal b1, ByVal b2, ByVal b3, ByVal b4, ByVal b5, ByVal b6) 'wandelt 6 Bytes in den entsprechenden Long-Wert um Dim n Byte6ToLong = b1 Byte6ToLong = Byte6ToLong * 256 + b2 Byte6ToLong = Byte6ToLong * 256 + b3 Byte6ToLong = Byte6ToLong * 256 + b4 Byte6ToLong = Byte6ToLong * 256 + b5 Byte6ToLong = Byte6ToLong * 256 + b6 End Function

Lesbare SID Strings umwandeln in den entsprechenden Hex String

Nun zum umgekehrten Problem: Wie kann ich aus einem gegebenen SID String (in lesbarer SDDL Form) die entsprechenden Binärdaten (als Hex-String) ermitteln. Diese Rohdaten braucht man z.B., wenn man einen LDAP-Filter bauen möchte, der nach einem bestimmten SID-Attribut suchen soll, oder wenn man die Berechtigungen mit ACLs direkt bearbeiten möchte.

Wir benötigen dabei Funktionen, die aus Long Integer Werten entsprechende Hexadezimal-Darstellungen bilden können. Diese Funktionen werden dann in SIDToHexStr aufgerufen:

wellKnownSIDEveryOne = "S-1-1-0" wellKnownSIDCreatorOwner = "S-1-3-0" wellKnownSIDAnonymous = "S-1-5-7" wellKnownSIDAuthenticatedUsers= "S-1-5-11" wellKnownSIDSystem = "S-1-5-18" wellKnownSIDExampleUser = "S-1-5-21-120346000-1731507311-1141323324-1104" WScript.Echo wellKnownSIDEveryOne & " : " & SIDToHexStr(wellKnownSIDEveryOne) WScript.Echo wellKnownSIDCreatorOwner & " : " & SIDToHexStr(wellKnownSIDCreatorOwner) WScript.Echo wellKnownSIDAnonymous & " : " & SIDToHexStr(wellKnownSIDAnonymous) WScript.Echo wellKnownSIDAuthenticatedUsers & " : " & SIDToHexStr(wellKnownSIDAuthenticatedUsers) WScript.Echo wellKnownSIDSystem & " : " & SIDToHexStr(wellKnownSIDSystem) WScript.Echo wellKnownSIDExampleUser & " : " & SIDToHexStr(wellKnownSIDExampleUser) Function SIDToHexStr(ByVal strSID) 'convert SID string value (SSDL) to hex string Dim subStrings Dim i subStrings = Split(strSID, "-") SIDToHexStr = IntToHex1(subStrings(1)) SIDToHexStr = SIDToHexStr & IntToHex1(UBound(subStrings) - 2) SIDToHexStr = SIDToHexStr & LongToHex6(subStrings(2)) For e = 3 To UBound(subStrings) SIDToHexStr = SIDToHexStr & LongToReverseHex4(subStrings(i)) Next End Function '________________________________________________________________________________ Hilfsfunktionen Function IntToHex1(ByVal intVar) 'wandelt einen Unsigned Integer Wert in den entsprechenden HEX String um IntToHex1 = Right("0" & Hex(intVar), 2) End Function Function LongToHex6(ByVal longVar) 'wandelt einen Unsigned Long Wert in den entsprechenden HEX String um If (longVar > &H7FFFFFFF) Then longVar = longVar - 4294967296 LongToHex6 = Right("00000000000" & Hex(longVar), 12) End Function Function LongToHex4(ByVal longVar) 'wandelt einen Unsigned Long Wert in den entsprechenden HEX String um If (longVar > &H7FFFFFFF) Then longVar = longVar - 4294967296 LongToHex4 = Right("0000000" & Hex(longVar), 8) End Function Function LongToReverseHex4(ByVal longVar) 'wandelt einen Unsigned Long Wert in den entsprechenden HEX String um (umgekehrte Byte-Order) Dim i longHex = LongToHex4(longVar) LongToReverseHex4 = "" For i = 0 To Len(longHex)/2 - 1 LongToReverseHex4 = Mid(longHex, 2*i + 1, 2) & LongToReverseHex4 Next End Function

SIDs in LDAP Filtern

Wenn Sie mit einer LDAP Search Operation nach einem Objekt mit einem bestimmten SID-Wert in einem Attribut suchen wollen, so müssen Sie dazu einen speziellen LDAP Filter bauen. Dieser Filter muss die reinen Binärdaten der gesuchten SID enthalten, dazu werden die einzelnen Bytes in hexadezimaler Schreibweise durch Backslashes (\) getrennt. Als Basis wird also wieder die Funktion SIDToHexStr benötigt, jedoch müssen hier zusätzlich die Backslahses eingefügt werden, um einen gültigen LDAP Filterstring zu erhalten.

Das Beispiel basiert auf der einer ADO-LDAP-Suche, wie sie im SelfADSI Tutorial-Artikel "Objekte suchen nach bestimmten Kriterien" gezeigt wird. Wir lesen das tokenGroups Attribut eines Benutzers aus und suchen nach den entsprechenden Gruppenobjekten (im Global Catalog). Damit lassen sich alle Gruppen ermittlen, in denen der betreffende Account direkt oder indirek enthalten ist:

'Sie müssen hier andere Namen und Anmeldedaten aus Ihrer eigene Umgebung angeben! Set obj = GetObject("LDAP://cn=Foeckeler,cn=Users,dc=cerrotorre,dc=de") obj.GetInfoEx Array("tokenGroups"), 0 'tokenGroups ist ein Operational Attribut und muß extra angefordert werden groupListRaw = obj.GetEx("tokenGroups") Set ado = CreateObject("ADODB.Connection") 'Neue ADO Connection erzeugen ado.Provider = "ADSDSOObject" 'Die ADSI-Schnittstelle verwenden ado.Open "ADS-Search" 'Beliebigen Namen für die Connection vergeben Set gcContainer = GetObject("GC:") 'Global Catalog Search Base ermitteln For Each gcObj In gcContainer gcBase = gcObj.ADsPath Next WScript.Echo obj.cn For i = 0 To UBound(groupListRaw) filterStr = "(objectSid=" & OctetToFilterStr(groupListRaw(i)) & ")" Set adoCmd = CreateObject("ADODB.Command") 'Neues ADO-Kommando erzeugen adoCmd.ActiveConnection = ado 'Zuordnung zur bestehenden ADO-Connection adoCmd.CommandText = "<" & gcBase & ">;" & filterStr & ";distinguishedName;subtree" Set objectList = adoCmd.Execute 'Suche durchführen If (objectList.RecordCount = 1) Then WScript.Echo "---> "& objectList.Fields("distinguishedName") Else WScript.Echo "???? " & HexStrToSID(OctetToHexStr(groupListRaw(i))) End If Next Function OctetToFilterStr(var_octet) 'wandelt reine Binärdaten (Byte-Array) in den entsprechenden LDAP Filter String um. Dim n OctetToFilterStr = "" For n = 1 To lenb(var_octet) OctetToFilterStr = OctetToFilterStr & "\" & Right("0" &hex(ascb(midb(var_octet, n, 1))), 2) Next OctetToFilterStr = Mid(OctetToFilterStr, 1) End Function '_________________________________________________________________________________________ Hilfsfunktionen Function HexStrToSID(strSid) 'wandelt einen SID Hex String in Rohform in den entsprechenden SID String (SDDL) um Dim data, i, offset ReDim data(Len(strSid)/2 - 1) For i = 0 To UBound(data) data(i) = CInt("&H" & Mid(strSid, 2*i + 1, 2)) Next HexStrToSID = "S-" & data(0) & "-" & Byte6ToLong(data(2), data(3), data(4), data(5), data(6), data(7)) blockCount = data(1) For i = 0 To blockCount - 1 offset = 8 + 4*i HexStrToSID = HexStrToSID & "-" & Byte4ToLong(data(offset+3), data(offset+2), data(offset+1), data(offset)) Next End Function Function OctetToHexStr(var_octet) 'wandelt reine Binärdaten (Byte-Array) in einen String mit den Hexadezimalwerten um. Dim n OctetToHexStr = "" For n = 1 To lenb(var_octet) OctetToHexStr = OctetToHexStr & Right("0" & hex(ascb(midb(var_octet, n, 1))), 2) Next End Function Function Byte4ToLong(ByVal b1, ByVal b2, ByVal b3, ByVal b4) 'wandelt 4 Bytes in den entsprechenden Long-Wert um Byte4ToLong = b1 Byte4ToLong = Byte4ToLong * 256 + b2 Byte4ToLong = Byte4ToLong * 256 + b3 Byte4ToLong = Byte4ToLong * 256 + b4 End Function Function Byte6ToLong(ByVal b1, ByVal b2, ByVal b3, ByVal b4, ByVal b5, ByVal b6) 'wandelt 6 Bytes in den entsprechenden Long-Wert um Byte6ToLong = b1 Byte6ToLong = Byte6ToLong * 256 + b2 Byte6ToLong = Byte6ToLong * 256 + b3 Byte6ToLong = Byte6ToLong * 256 + b4 Byte6ToLong = Byte6ToLong * 256 + b5 Byte6ToLong = Byte6ToLong * 256 + b6 End Function

LDAP Bind zu Objekten mit SIDs anstatt mit dem Distinguished Name

Eine interessante Variation der Suche nach Objekten mit einer vorgegebenen SID: Man kann beim Verbinden mit  Objekten (LDAP Bind) auch einfach deren SID verwenden, wenn man folgende Syntax einhält

<SID=S-1-5-21-34672221-56910222-80333210-57321189-511>                              (Beispiel)

Sogar die puren HexStrings der SIDs lassen sich hier zum BIND benutzen:

<SID=0105000000000005150000001b0e683dbf16479eb5a59ec158040000>          (Beispiel)

Diese Technik können wir verwenden, um die Liste der direkten und indirekten Gruppenmitgliedschaften viel eleganter als im letzten Beispiel zu erhalten:

'Sie müssen hier andere Namen und Anmeldedaten aus Ihrer eigene Umgebung angeben! Set obj = GetObject("LDAP://cn=Foeckeler,cn=Users,dc=cerrotorre,dc=de") obj.GetInfoEx Array("tokenGroups"), 0 'tokenGroups ist ein Operational Attribut und muß extra angefordert werden groupListRaw = obj.GetEx("tokenGroups") WScript.Echo obj.cn For i = 0 To UBound(groupListRaw) sidHex = OctetToHexStr(groupListRaw(i)) Set obj = GetObject("LDAP://<SID=" & sidHex &">") WScript.Echo "---> " & obj.distinguishedName Next Function OctetToHexStr(var_octet) 'wandelt reine Binärdaten (Byte-Array) in einen String mit den Hexadezimalwerten um. Dim n OctetToHexStr = "" For n = 1 To lenb(var_octet) OctetToHexStr = OctetToHexStr & Right("0" & hex(ascb(midb(var_octet, n, 1))), 2) Next End Function

Werkzeuge für die Anzeige und Konvertierung von SIDs

Es gibt mehrere andere Werkzeuge für die Anzeige eines Microsoft String(SID) Attributes und dessen Umwandlung in einen lesbaren SDDL-SID-String.

LEX - The LDAP Explorer

LEX - The LDAP Explorer (ein leistungsfähiger kommerzieller LDAP Browser, den ich entwickelt habe) hat spezielle Attribut-Editoren für Microsoft SID Attribute und kann diese sowohl als SDDL als auch als binäre Rohdaten anzeigen:

Screenshot: Integer8 Attributes in the LEX LDAP Browser

LEX Editor für Microsoft SID Attributes:

Screenshots: Integer8 Attribute Editors for timestamps in LEX - The LDAP Explorer


PSGETSID


Diese Tool ist in der bekannten SysInternals PSTools Sammlung enthalten und kann kostenlos bei Microsoft heruntergeladen werden. Sie können damit auf der Kommandozeile SIDs in Usernamen auflösen und andersherum:

Screenshot: Integer8 Attribute Conversion with W32TM