16

I have a user in a domain who has access to multiple subfolders in multiple folders. His rights were defined pretty granularly. Now he's leaving the company but will continue to work for a firm as a contracted resource.

I need to find all folders he had access to and revoke his permissions, then set him up with a different set of access permissions.

Is there any tool (freeware, preferably) that lists all NTFS permissions for a given user? I've tried with AccessEnum from Sysinternals, but the list cannot be filtered by username and is useless for me. I've looked at CACLS, too, but as far as I can tell it displays permissions ordered by file, not by user.

Any ideas?

3
  • 1
    This is why you should always grant membership based on groups, even if there is only one user in the group. You could have just removed him from the group. In the meantime while you wait for an answer, you can just disable his account in AD.
    – MDMarra
    Aug 17, 2010 at 14:15
  • Did you try this tool: AccessChk v5.0 ? As a part of ensuring that they've created a secure environment Windows administrators often need to know what kind of accesses specific users or groups have to resources including files, directories, Registry keys, global objects and Windows services. AccessChk quickly answers these questions with an intuitive interface and output. Found here: technet.microsoft.com/en-us/sysinternals/bb664922.aspx
    – Luke99
    Aug 17, 2010 at 23:05
  • @MarkM: So true... It's just that when user needs an access to a single folder, you add him. Then in few months he needs another access on completely different share. And in few months again on 2 or 3 folders. How do you create a group with meaningful name for such user? "Username_granular_access_group"? This would probably do the trick. @Luke99: Interesting tool from Sysinternals. How could I miss it. Anyway, I see it displays all folders user has direct or indirect access to. Is there a way to display only folders where user is explicitly listed in ACL (excluding acces via groups)?
    – imagodei
    Aug 18, 2010 at 13:20

3 Answers 3

17

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.

4
  • 1
    Seems like it should be obvious, but bears pointing out: Searching for *. does NOT equal searching directories only, or all directories. Directory names can have extensions and files don't have to have extensions. If you want to be thorough let it search everything.
    – Scott E
    Mar 22, 2018 at 21:02
  • This is such an amazing answer because this subtle hint does not exist anywhere else on the entire web. I unknowingly found it for the second time today after several years and noticed that I have already upvoted it, even though I don't recall doing so. In my case I was auditing for specific modify access, so I actually ended up with ICACLS "C:\*." /T /C 2>nul: | findstr "BUILTIN\Users:(M)". One observation I have is that findsid only finds the existence of an ACL for the SID, which may not necessarily mean that the SID "has access". Although rare, a hit could be an explicit deny ACL too.
    – Amit Naidu
    Sep 19, 2022 at 23:07
  • Thanks, @AmitNaidu. Can you clarify what you refer to as "this subtle hint"? I only ask as some readers may wonder. Sep 21, 2022 at 3:15
  • And thanks also to @ScottE for the observation about my example not ensuring it lists ONLY folders (the OP's request), as well as AmitNaidu for the observation about the risk that my result could list ACLs giving the SID--even if it may be a deny. Both are great points, and I'd said I was open to feedback to improve my answer. I hope someone reading along may share at some point how to solve either problem. Sep 21, 2022 at 3:19
7

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.

2
  • 1
    Would it also be possible to "exclude" inherited Permissions? (i.e. searching every Folder, where "DOMAIN\Username" has been added in an explicit way?
    – dognose
    Feb 27, 2016 at 15:22
  • 2
    Yes, you can: if ($ACL.IdentityReference -like $ReferenceAccountName -and !$ACL.IsInherited){
    – dognose
    Feb 27, 2016 at 15:31
4

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .