List user's folder access permissions

Solution 1:

This seems to do the trick (with perhaps a caveat), to find all folders that user "someuser" has access to, in this example on the C drive, using the built-in Windows icacls command:

icacls c:\*. /findsid someuser /t /c /l

The /t is needed to tell it to recurse directories. The /c is needed to tell it to keep going even if it encounters errors. The /l makes it work with symbolic links (if any). (That last one is an L, and these flags can be upper or lower-case.)

The *. will be recognized by DOS old-timers as the way to say "look for directories, not files". Of course, if you DO want to find files and not folders, change it to *.*, and of course you can point it to any drive, or run it from any folder and leave off the drive/folder path and let it search relative to that folder only.

I sought the same answer as the OP, and found this entry, but was bummed to see only an offer based on a downloadable tool. Like others, I preferred to use something built-in, and I found it, in this icacls tool.

And I have confirmed it works on Windows Server 2012, 2008, and Windows 7, so I suspect it will work as well in Server 2003, Windows 8, and so on.

The resulting list will be folders indicated line after line, such as:

SID Found: c:\somedir\somesubdir.

Note that if you run this as a user who does not itself have permissions to some directories being traversed, you will get errors interleaved in the results such as:

c:\System Volume Information: Access is denied.

And if you may be searching an entire drive, that could result in hundreds of such errors, making it hard to find within them the results.

Some may think the answer is to run the command line as administrator, but that will simply cause far more such errors to appear, as you will now be traversing folders that were previously hidden.

Now, if you were interested in hiding those errors, you won't be able to use a find command to pipe only the results which DO succeed (those which DO refer to "SID found"), because the errors will NOT be filtered out by the pipe to the find command. Instead, if you want to remove all the errors, you need to use the rather obscure trick of redirecting the error stream (stderr) to the "bit bucket" by using 2>nul:. So the example above would become:

icacls c:\*. /findsid someuser /t /c /l 2>nul:

Just do beware that some of the folders which generated such errors, which errors are now hidden, may well be folders that the named "someuser" DOES have access to but which YOU do not. So you may want to think twice about simply ignoring these errors. but if you want to, that's how you can do it.

That possibility does potentially limit the value of this answer, I realize. If anyone with more familiarity with things would like to expand on or correct my answer I'd welcome it.

Solution 2:

You can use PowerShell without needing to download anything else. This will work with v2.0 and later:

$ReferenceAccountName = 'DOMAIN\Username'
[string[]]$SearchDirectories = @('X:\SomeDirectory', 'F:\AnotherDirectory')

foreach ($RootDir in $SearchDirectories) {
    $DirACL = Get-Acl -Path $RootDir
    foreach ($ACL in $DirACL.Access){
        if ($ACL.IdentityReference -like $ReferenceAccountName){
            Write-Output $RootDir
        }
    }
    foreach ($Directory in (Get-ChildItem -Path $RootDir -Recurse | `
                            Where-Object -FilterScript {$_.Attributes `
                            -contains 'Directory'})){
        $DirACL = Get-Acl -Path $Directory.FullName
        foreach ($ACL in $DirACL.Access){
            if ($ACL.IdentityReference -like $ReferenceAccountName){
                Write-Output $Directory.FullName
            }
        }
    }
}

It is not as clean as what is available with PowerShell v3 and on, but it will work. This will output a list of the directories found in string format.

You could easily output them as objects and continue to do work with them (export them to a CSV file, remove the entries as you find them, update a ticket with the information...etc) by manipulating the input object of the Write-Output calls.


Solution 3:

I found a solution to my own question. It is, I believe, very simple and clean. You only have to install subinacl and run one line from the command prompt.

You can download subinacl here. Although it is officially supported only on Windows 2000, Windows XP, and Windows Server 2003, it should work on Windows Vista, Windows Server 2008 and Windows 7 as well.

Next, you run the following from the command prompt:

subinacl /testmode /noverbose /outputlog=c:\TEXTFILENAME.TXT /subdirectories=directoriesonly X:\*.* /findsid=DOMAIN\username

Where X: is the drive you're scanning and username is the user whose permissions you'd like to list. Scanning can take some time and you get the results in TEXTFILENAME.TXT.

If you use the switch /noverbose you get a compact list of access permissions - basically you see which directories the user has access to (with access masks and some other stuff that might come in handy sometimes).

I used OpenOffice Calc to import the list and then applied a Custom Filter and filtered only for those lines starting with +FILE. These lines contain directories the user has access to. This is how using simple tools you end up with only relevant information.

Since inheritance is often enabled on parent directories, the actual number of directories you might need to visit to adjust permissions is usually significantly lower than the list itself.