This script uses WMI to enumerate each access control entry in an NTFS access control list, looking for explicit entries, that is, entries that are not inherited.

If SECURITY_PRINCIPAL is blank the script will return all explicit rights beneath granted from base path down. The script attempts to provide a summary for common rights.

The PowerShell version of this script is considerably better for granular reporting of rights assigned. This one is more of a demonstration of security descriptor enumeration.

Option Explicit

' Looks for a Trustee containing the SECURITY_PRINCIPAL string on
' the file system. Recurses from BASE_PATH down (file and folders).

' Set these values for the search.

Const BASE_PATH = "C:\"
Const SECURITY_PRINCIPAL = "Chris"

Sub FSRecurse(strPath)
  ' Simple FS recursion

  Dim objFolder, objFile, objSubFolder

  Set objFolder = objFileSystem.GetFolder(strPath)

  For Each objFile in objFolder.Files
    CheckDescriptor objFile.Path
  Next
  For Each objSubFolder in objFolder.SubFolders
    CheckDescriptor objSubFolder.Path

    FSRecurse objSubFolder.Path
  Next

  Set objFolder = Nothing
End Sub

Sub CheckDescriptor(strPath)
  ' Look for the Trustee in the Security Descriptor and filter out
  ' inherited ACEs

  Const ACE_FLAG_INHERITED = &H10 ' 16

  Dim objSecuritySettings, objSecurityDescriptor, objACE, objTrustee

  Set objSecuritySettings = objWMIService.Get _
    ("Win32_LogicalFileSecuritySetting.Path='" & strPath & "'")
  objSecuritySettings.GetSecurityDescriptor objSecurityDescriptor

  For Each objACE in objSecurityDescriptor.dACL
    If InStr(1, objACE.Trustee.Name, _
        SECURITY_PRINCIPAL, VbTextCompare) > 0 Then

      ' ACEFlags is binary. Must perform binary comparison.
      If objACE.ACEFlags And ACE_FLAG_INHERITED Then
        ' Problems with negation of the above.
        ' This is just easier.
      Else
        EnumAccess strPath, objACE
      End If
    End If
  Next
End Sub

Sub EnumAccess(strPath, objACE)
  ' Most access mask values have matching Folder versions. These are not
  ' numerically different, they only differ when interpreted.

  ' ACE Type

  Const ACCESS_ALLOWED_ACE_TYPE = &h0
  Const ACCESS_DENIED_ACE_TYPE  = &h1

  ' Base Access Mask values

  Const FILE_READ_DATA = &h1
  Const FILE_WRITE_DATA = &h2
  Const FILE_APPEND_DATA = &h4
  Const FILE_READ_EA = &h8
  Const FILE_WRITE_EA = &h10
  Const FILE_EXECUTE = &h20
  Const FILE_DELETE_CHILD = &h40
  Const FILE_READ_ATTRIBUTES = &h80
  Const FILE_WRITE_ATTRIBUTES = &h100
  Const FOLDER_DELETE = &h10000
  Const READ_CONTROL = &h20000
  Const WRITE_DAC = &h40000
  Const WRITE_OWNER = &h80000
  Const SYNCHRONIZE = &h100000

  ' Constructed Access Masks

  Dim FULL_CONTROL
  FULL_CONTROL = FILE_READ_DATA + FILE_WRITE_DATA + FILE_APPEND_DATA + _
    FILE_READ_EA + FILE_WRITE_EA + FILE_EXECUTE + FILE_DELETE_CHILD + _
    FILE_READ_ATTRIBUTES + FILE_WRITE_ATTRIBUTES + FOLDER_DELETE + _
    READ_CONTROL + WRITE_DAC + WRITE_OWNER + SYNCHRONIZE

  Dim READ_ONLY
  READ_ONLY = FILE_READ_DATA + FILE_READ_EA + FILE_EXECUTE + _
    FILE_READ_ATTRIBUTES + READ_CONTROL + SYNCHRONIZE

  Dim MODIFY
  MODIFY = FILE_READ_DATA + FILE_WRITE_DATA + FILE_APPEND_DATA + _
    FILE_READ_EA + FILE_WRITE_EA + FILE_EXECUTE + _
    FILE_READ_ATTRIBUTES + _
    FILE_WRITE_ATTRIBUTES + FOLDER_DELETE + READ_CONTROL + SYNCHRONIZE

  Dim strRights
  Dim intAccessMask

  WScript.Echo "Path: " & strPath
  WScript.Echo "Username: " & objACE.Trustee.Name
  WScript.Echo "Domain: " & objACE.Trustee.Domain
  WScript.Echo "ACE Flags (Decimal): " & objACE.ACEFlags

  ' ACE Type

  If objACE.ACEType = ACCESS_ALLOWED_ACE_TYPE Then
    WScript.Echo "ACE Type: Allow"
  Else
    WScript.Echo "ACE Type: Deny"
  End If

  ' Attempt to generate a basic summary of access rights

  strRights = ""
  intAccessMask = objACE.AccessMask

  If intAccessMask = FULL_CONTROL Then
    strRights = " (FullControl)"
  ElseIf intAccessMask = MODIFY Then

    strRights = " (Modify)"
  ElseIf intAccessMask = READ_ONLY Then
    strRights = " (ReadOnly)"
  End If

  ' Echo the decimal mask with any summarised rights

  WScript.Echo "Access Mask (Decimal): " & intAccessMask & strRights

  WScript.Echo
End Sub

'
' Main code block
'

Dim objFileSystem, objWMIService

Set objFileSystem = CreateObject("Scripting.FileSystemObject")
' WMI Connection to the local machine
Set objWMIService = GetObject("winmgmts:\\.")

FSRecurse BASE_PATH

Set objWMIService = Nothing
Set objFileSystem = Nothing

No related posts.

Related posts brought to you by Yet Another Related Posts Plugin.

Leave a Reply