' DACL2.vbs ' VBScript program to document object security. ' ' ---------------------------------------------------------------------- ' Copyright (c) 2002-2016 Richard L. Mueller ' Hilltop Lab web site - http://www.rlmueller.net ' Version 1.0 - November 10, 2002 ' Version 1.1 - February 19, 2003 - Standardize Hungarian notation. ' Version 1.2 - March 30, 2007 - Document owner of Security Descriptor. ' Version 1.3 - November 6, 2010 - No need to set objects to Nothing. ' Version 2.0 - November 18, 2016 - Prompt for object to document. ' Version 2.1 - January 10, 2016 - Determine if inheritance enabled. ' Version 2.2 - January 12, 2016 - Use disconnected recordset to sort. ' ' Program enumerates the ACE's within an Active Directory ACL for a ' specified object. The Program either accepts the distinguished name of ' the object as a command line parameter, or prompts for the distinguished ' name. The output is written to a text file in the current folder. The ' name of the output file is the Relative Distinguish Name of the object, ' with commas, spaces, and periods removed, followed by the string ' "Report", and with extension "txt". ' Based in part on a program (pg. 425-431) in the text "Windows NT/2000 ' ADSI Scripting for System Administration", by Thomas Eck, MacMillan ' Technical Publishing, 2000. ' ' You have a royalty-free right to use, modify, reproduce, and ' distribute this script file in any way you find useful, provided that ' you agree that the copyright owner above has no warranty, obligations, ' or liability for such use. Option Explicit Dim objADObject, objACE, objDiscretionaryACL, objSecurityDescriptor Dim strDistinguishedName, objFSO, objReport Dim strName, strDN, strInheritance, adoACEList Dim strTrustee, intAccessMask, strObjectType, intAceFlags Dim intAceType, intFlags, strInheritedObjectType ' Define constants. Const ADS_RIGHT_DELETE = &H10000 Const ADS_RIGHT_READ_CONTROL = &H20000 Const ADS_RIGHT_WRITE_DAC = &H40000 Const ADS_RIGHT_OWNER = &H80000 Const ADS_RIGHT_SYNCHRONIZE = &H100000 Const ADS_RIGHT_ACCESS_SYSTEM_SECURITY = &H1000000 Const ADS_RIGHT_GENERIC_READ = &H80000000 Const ADS_RIGHT_GENERIC_WRITE = &H40000000 Const ADS_RIGHT_GENERIC_EXECUTE = &H20000000 Const ADS_RIGHT_GENERIC_ALL = &H10000000 Const ADS_RIGHT_DS_CREATE_CHILD = &H1 Const ADS_RIGHT_DS_DELETE_CHILD = &H2 Const ADS_RIGHT_ACTRL_DS_LIST = &H4 Const ADS_RIGHT_DS_SELF = &H8 Const ADS_RIGHT_DS_READ_PROP = &H10 Const ADS_RIGHT_DS_WRITE_PROP = &H20 Const ADS_RIGHT_DS_DELETE_TREE = &H40 Const ADS_RIGHT_DS_LIST_OBJECT = &H80 Const ADS_RIGHT_DS_CONTROL_ACCESS = &H100 Const SE_DACL_PROTECTED = 4096 Const ForAppending = 8 Const CreateIfNotExist = True Const OpenAsASCII = 0 Const adVarChar = 200 Const MaxCharacters = 255 Const adInteger = 3 ' Retrieve DN or prompt for DN of object to document. If (Wscript.Arguments.Count = 1) Then strDistinguishedName = Wscript.Arguments(0) Else strDistinguishedName = InputBox("Enter distinguishedName of object", "DACL") End If ' Bind to the object in Active Directory with the LDAP provider. On Error Resume Next Set objADObject = GetObject("LDAP://" & strDistinguishedName) If (Err.Number <> 0) Then Wscript.Echo "Unable to bind to object " & strDistinguishedName Wscript.Echo "Program Aborted" Wscript.Quit End If On Error GoTo 0 ' Remove any escaped commas. strDN = Replace(strDistinguishedName, "\,", "") ' Parse for the Relative Distiguished Name of the object. strName = Mid(strDN, InStr(strDN, "=") + 1) strName = Mid(strName, 1, InStr(strName, ",") -1) ' Remove any spaces or periods. strName = Replace(strName, " ", "") strName = Replace(strName, ".", "") strName = strName & "Report.txt" ' Open output text file with append access. Set objFSO = CreateObject("Scripting.FileSystemObject") On Error Resume Next Set objReport = objFSO.OpenTextFile(strName, ForAppending, _ CreateIfNotExist, OpenAsASCII) If (Err.Number <> 0) Then Wscript.Echo "Unable to open report file " & strName Wscript.Echo "Program Aborted" Wscript.Quit End If On Error GoTo 0 ' Setup disconnected recordset. ' This will be used to track the ACE's and sort them before display. ' This allows permissions to be more easily compared between objects. Set adoACEList = CreateObject("ADODB.Recordset") adoACEList.Fields.Append "Trustee", adVarChar, MaxCharacters adoACEList.Fields.Append "AccessMask", adInteger adoACEList.Fields.Append "ObjectType", adVarChar, MaxCharacters adoACEList.Fields.Append "AceFlags", adInteger adoACEList.Fields.Append "AceType", adInteger adoACEList.Fields.Append "Flags", adInteger adoACEList.Fields.Append "InheritedObjectType", adVarChar, MaxCharacters adoACEList.Open ' Bind to the security objects. Set objSecurityDescriptor = objADObject.Get("ntSecurityDescriptor") Set objDiscretionaryACL = objSecurityDescriptor.discretionaryACL ' Determine if inheritance enabled. If (objSecurityDescriptor.Control And SE_DACL_PROTECTED) Then strInheritance = "False" Else strInheritance = "True" End If ' Write header information to the output file. objReport.WriteLine "Active Directory Object: " & objADObject.Name objReport.WriteLine "Distinguished Name: " & strDistinguishedName objReport.WriteLine "Security Descriptor Owner: " _ & objSecurityDescriptor.Owner objReport.WriteLine "Inheritance Enabled: " & strInheritance objReport.WriteLine "---------------------------" ' Enumerate each ACE in the DACL. For Each objACE In objDiscretionaryACL adoACEList.AddNew adoACEList("Trustee") = objACE.Trustee adoACEList("AccessMask") = objACE.AccessMask adoACEList("ObjectType") = objACE.ObjectType adoACEList("AceFlags") = objACE.AceFlags adoACEList("AceType") = objACE.AceType adoACEList("Flags") = objACE.Flags adoACEList("InheritedObjectType") = objACE.InheritedObjectType adoACEList.Update Next ' Sort the list of ACEs. adoACEList.Sort = "Trustee, AccessMask, ObjectType" ' Enumerate the sorted list of ACEs and display. adoACEList.MoveFirst Do Until adoACEList.EOF strTrustee = adoACEList.Fields.Item("Trustee") intAccessMask = adoACEList.Fields.Item("AccessMask") strObjectType = adoACEList.Fields.Item("ObjectType") intAceFlags = adoACEList.Fields.Item("AceFlags") intAceType = adoACEList.Fields.Item("AceType") intFlags = adoACEList.Fields.Item("Flags") strInheritedObjectType = adoACEList.Fields.Item("InheritedObjectType") objReport.WriteLine "Trustee: " & strTrustee objReport.WriteLine " AceFlags : " & intAceFlags objReport.WriteLine " AceType : " & intAceType objReport.WriteLine " Flags : " & intFlags objReport.WriteLine " ObjectType: " & strObjectType objReport.WriteLine " AccessMask: " & intAccessMask ' Delete right. ' Grants the right to delete the object. Call ListRights(ADS_RIGHT_DELETE, intAccessMask, strObjectType, _ strInheritedObjectType, "ADS_RIGHT_DELETE") ' Read Control right. ' Grants the right to read the object's security descriptor. Call ListRights(ADS_RIGHT_READ_CONTROL, intAccessMask, strObjectType, _ strInheritedObjectType, "ADS_RIGHT_READ_CONTROL") ' Write DAC right. ' Grants the right to modify the descretionary access control list. Call ListRights(ADS_RIGHT_WRITE_DAC, intAccessMask, strObjectType, _ strInheritedObjectType, "ADS_RIGHT_WRITE_DAC") ' Right owner. ' Grants the right to take ownership of the object. Call ListRights(ADS_RIGHT_OWNER, intAccessMask, strObjectType, _ strInheritedObjectType, "ADS_RIGHT_OWNER") ' Synchronize right. ' Enables the object to be used for synchronization. Call ListRights(ADS_RIGHT_SYNCHRONIZE, intAccessMask, strObjectType, _ strInheritedObjectType, "ADS_RIGHT_SYNCHRONIZE") ' Access System Security right. ' Grants the right to manipulate the object's SACL. Call ListRights(ADS_RIGHT_ACCESS_SYSTEM_SECURITY, intAccessMask, strObjectType, _ strInheritedObjectType, "ADS_RIGHT_ACCESS_SYSTEM_SECURITY") ' Generic Read right. ' Grants the right to read the security descriptor, all properties, and ' any children of the object. Call ListRights(ADS_RIGHT_GENERIC_READ, intAccessMask, strObjectType, _ strInheritedObjectType, "ADS_RIGHT_GENERIC_READ") ' Generic write right. ' Grants the right to write to the DACL and all properties, as well as ' to remove the object from the directory. Call ListRights(ADS_RIGHT_GENERIC_WRITE, intAccessMask, strObjectType, _ strInheritedObjectType, "ADS_RIGHT_GENERIC_WRITE") ' Generic Execute right. ' Grants the ability to list the object's children. Call ListRights(ADS_RIGHT_GENERIC_EXECUTE, intAccessMask, strObjectType, _ strInheritedObjectType, "ADS_RIGHT_GENERIC_EXECUTE") ' Generic All right. ' Grants the right to create or delete child objects and subtrees, ' read and write all properties, and add or remove the object. Call ListRights(ADS_RIGHT_GENERIC_ALL, intAccessMask, strObjectType, _ strInheritedObjectType, "ADS_RIGHT_GENERIC_ALL") ' DS Create Child right. ' Grants the ability to create child objects. ' If ObjectType is set to the schemaIDGuid of an object class, the right ' is restricted to that object class. Call ListRights(ADS_RIGHT_DS_CREATE_CHILD, intAccessMask, strObjectType, _ strInheritedObjectType, "ADS_RIGHT_DS_CREATE_CHILD") ' DS Delete Child right. ' Grants the ability to delete child objects. ' If ObjectType is set to the schemaIDGuid of an object class, the right ' is restricted to that object class. Call ListRights(ADS_RIGHT_DS_DELETE_CHILD, intAccessMask, strObjectType, _ strInheritedObjectType, "ADS_RIGHT_DS_DELETE_CHILD") ' Access Control DS List right. ' Grants the ability to list all child objects. Call ListRights(ADS_RIGHT_ACTRL_DS_LIST, intAccessMask, strObjectType, _ strInheritedObjectType, "ADS_RIGHT_ACTRL_DS_LIST") ' DS Self right. ' Grants the ability to list the object itself. Call ListRights(ADS_RIGHT_DS_SELF, intAccessMask, strObjectType, _ strInheritedObjectType, "ADS_RIGHT_DS_SELF") ' DS Read Property right. ' Grants the ability to read object properties. ' If ObjectType is set to the GUID of a property or property set, the ' right is restricted to that property or property set. Call ListRights(ADS_RIGHT_DS_READ_PROP, intAccessMask, strObjectType, _ strInheritedObjectType, "ADS_RIGHT_DS_READ_PROP") ' DS Write Property right. ' Grants the ability to write object properties. ' If ObjectType is set to the GUID of a property or property set, the ' right is restricted to that property or property set. Call ListRights(ADS_RIGHT_DS_WRITE_PROP, intAccessMask, strObjectType, _ strInheritedObjectType, "ADS_RIGHT_DS_WRITE_PROP") ' DS Delete Tree right. ' Grants the ability to delete the object and all associated child ' objects. Call ListRights(ADS_RIGHT_DS_DELETE_TREE, intAccessMask, strObjectType, _ strInheritedObjectType, "ADS_RIGHT_DS_DELETE_TREE") ' DS List Object right. ' Used to show or hide an object from user view. Call ListRights(ADS_RIGHT_DS_LIST_OBJECT, intAccessMask, strObjectType, _ strInheritedObjectType, "ADS_RIGHT_DS_LIST_OBJECT") ' DS Control Access right. ' Grants the ability to to perform an operation restricted by an ' extended access right. Must specify a rights GUID identifying a ' controlAccessRight object in the Extended-Rights container in the ' configuration partition. Call ListRights(ADS_RIGHT_DS_CONTROL_ACCESS, intAccessMask, strObjectType, _ strInheritedObjectType, "ADS_RIGHT_DS_CONTROL_ACCESS") objReport.WriteLine "" adoACEList.MoveNext Loop adoACEList.Close ' Clean up. objReport.Close Wscript.Echo "Done" Wscript.Echo "See report in file: " & strName Sub ListRights(intConstant, intMask, strObjType, strInherited, strRight) ' Subroutine to document rights to text file. ' objReport is the output file object, with global scope. If ((intMask And intConstant) <> 0) Then If (strObjType = "") _ And (strInherited = "") Then objReport.WriteLine " " & strRight Else If (strInherited = "") Then objReport.WriteLine " " & strRight & " for SchemaIDGuid: " _ & strObjType Else objReport.WriteLine " Inherited " & strRight _ & " for SchemaIDGuid: " & strInherited End If End If End If End Sub