Auditing NTFS Permissions

Recently I’ve wanted to review the account per­mis­sions on my home server that I use for backup. It has some­times served as a sand­box of sorts; not best prac­tice, but real­ity for hardware/monetary lim­its. Rather than spend the time right-clicking and check­ing the per­mis­sions on each folder I thought it’d be nice to write a WMI script to gen­er­ate a report.

I knew this had to have been done before, and after some quick googlefu I can across this script by Amine Abdelka­der that basi­cally did every­thing I wanted.

I didn’t like the HTML out­put though, I want CSV so that it can be eas­ily sorted, fil­tered, manip­u­lated in Excel. I also wanted to con­trol the depth of the search into sub­fold­ers and the total num­ber of fold­ers it would report on.

The script, mod­i­fied for these changes, is listed below:

‘========================================================================================
’ Orig­i­nal Author:  Abdelka­der, Amine
’ Orig­i­nal Date: 10/03/2006
’ Orig­i­nal Ouput: HTML File

’ Mod­i­fied by: Randy Armknecht
’ Mod­i­fied Date: 2009-11-05
’ Mod­i­fied Out­put:  CSV File, with abil­ity to con­trol depth of sub­folder search (depth)
’           and abil­ity to con­trol total num­ber of fold­ers reported on (max_seen)
’          
’========================================================================================
Const For­Read­ing = 1, For­Writ­ing = 2, ForAp­pend­ing = 8

Const Ful­lAc­cess­Mask = 2032127, Mod­i­fy­Ac­cess­Mask = 1245631, WriteAc­cess­Mask = 118009
Const ROAc­cess­Mask = 1179817



str­Com­puter = “.“
sPar­ent­Folder = Input­Box(“Please Enter folder to gather infor­ma­tion on”, “Par­ent Folder”)
SParentFoldern=replace(sParentFolder,”\”,””)
SParentFoldern=replace(sParentFoldern,”:”,””)

max_seen = 1000
depth = 1
count = 0


Set fso = Cre­ateOb­ject(“Scripting.FileSystemObject”)
’File name Same As Folder Name with­out spe­cial Car­ac­teres
fullfilename=SParentFoldern&”.csv“
’WScript.echo full­file­name

Set fsOut = fso.OpenTextFile(fullfilename, ForAp­pend­ing, True)

On Error Resume Next

    fsOut.Writeline “Folder, User Name, Per­mis­sion“

fsOut.Close



Show­Sub­Fold­ers FSO.GetFolder(sParentFolder),fullfilename

Out­put­Folder­Info sPar­ent­Folder, full­file­name

Set fsOut = fso.OpenTextFile(fullfilename, ForAp­pend­ing, True)
fsOut.Writeline strTable­Foot
fsOut.Close
Msg­Box “Done “
WScript.Quit

Pub­lic Sub OutputFolderInfo(FolderName , sOut­file)
    Const Ful­lAc­cess­Mask = 2032127, Mod­i­fy­Ac­cess­Mask = 1245631, WriteAc­cess­Mask = 1180095
    Const ROAc­cess­Mask = 1179817
    Const For­Read­ing = 1, For­Writ­ing = 2, ForAp­pend­ing = 8
   
    str­Com­puter = “.“

    ‘Build the path to the folder because it requites 2 back­slashes
    fold­er­path = Replace(FolderName, “\”, “\\”)

    object­path = “winmgmts:Win32_LogicalFileSecuritySetting.path=’” & fold­er­path & “‘“

    ‘Get the secu­rity set for the object
    Set wmi­FileSec­Set­ting = GetO­b­ject(object­path)

    ‘ver­ify that the get was suc­cess­ful
    Ret­Val = wmiFileSecSetting.GetSecurityDescriptor(wmiSecurityDescriptor)
    If Err Then
        ‘Msg­Box (“Get­Se­cu­ri­ty­De­scrip­tor failed” & vbCrLf & Err.Number & vbCrLf & Err.Description)
        Err.Clear
    End If

    Set objWMIS­er­vice = GetO­b­ject(“win­mgmts:” & “{impersonationLevel=impersonate}!\\” & str­Com­puter & “\root\cimv2”)
    Set col­Fold­ers = objWMIService.ExecQuery(“SELECT * FROM Win32_Directory WHERE Name =’” & fold­er­path & “‘”)

    For Each obj­Folder In col­Fold­ers
        ’ Retrieve the DACL array of Win32_ACE objects.
        DACL = wmiSecurityDescriptor.DACL

        Set fso = Cre­ateOb­ject(“Scripting.FileSystemObject”)
        Set fsOut = fso.OpenTextFile(sOutfile, ForAp­pend­ing, True)
   

        For Each wmi­Ace In DACL
            ’ Get Win32_Trustee object from ACE
            Set Trustee = wmiAce.Trustee
           
            fsOut.Write objFolder.Name&”,”&Trustee.Domain&”\”&Trustee.Name&”,“

            FoundAc­cess­Mask = False
            Cus­tom­Ac­cess­Mask = Flase
           
            While Not FoundAc­cess­Mask And Not Cus­tom­Ac­cess­Mask
                If wmiAce.AccessMask = Ful­lAc­cess­Mask Then
                    AccessType = “Full Con­trol“
                    FoundAc­cess­Mask = True
                End If
                If wmiAce.AccessMask = Mod­i­fy­Ac­cess­Mask Then
                    AccessType = “Mod­ify“
                    FoundAc­cess­Mask = True
                End If
                If wmiAce.AccessMask = WriteAc­cess­Mask Then
                    AccessType = “Read/Write Con­trol“
                    FoundAc­cess­Mask = True
                End If
                If wmiAce.AccessMask = ROAc­cess­Mask Then
                    AccessType = “Read Only“
                    FoundAc­cess­Mask = True
                Else
                    Cus­tom­Ac­cess­Mask = True
                End If
            Wend
     
            If FoundAc­cess­Mask Then
                fsOut.Write AccessType&vbCrLf
            Else
                fsOut.Write “Cus­tom”&vbCrLf
            End If
        Next

        Set fsOut = Noth­ing
        Set fso = Noth­ing
    Next

    Set fsOut = Noth­ing
    Set fso = Noth­ing
end Sub

Sub Show­Sub­Fold­ers (Folder,fname)
    On Error Resume Next
        If count < depth then
            count = count + 1
            total_seen = 0
            For Each Sub­folder in Folder.SubFolders
            if total_seen < max_seen then
                total_seen = total_seen + 1
                Call OutputFolderInfo(Subfolder.Path,fname)
                ‘Wscript.Echo Subfolder.Path
                call Show­Sub­Fold­ers (Subfolder,fname)
            end if
            Next
        end if
End Sub

Leave a Reply