4

I have the following scenario where I (admin) applied the (DE,W) deny permissions to the following folder test_folder for test_user who already has inherited modify permissions from parent folder:

B:\>icacls test_folder
test_folder     test_user:(I)(OI)(CI)(M)
                admin:(I)(OI)(CI)(M)

B:>icacls test_folder /deny test_user:(DE,W)

B:>icacls test_folder test_folder test_user:(DENY)(W,D) test_user:(I)(OI)(CI)(M) admin:(I)(OI)(CI)(M)

The end result I would expected is test_user being able to have read/execute access to test_folder without being able to delete/rename the folder and add folders/files to it.

However, the result was test_folder not being visible to test_user at all. The test_folder is still visible to me (admin).

While I deny only DE however:

B:\>icacls test_folder
test_folder     test_user:(I)(OI)(CI)(M)
                admin:(I)(OI)(CI)(M)

B:>icacls test_folder /deny test_user:(DE)

B:>icacls test_folder test_folder test_user:(DENY)(D) test_user:(I)(OI)(CI)(M) admin:(I)(OI)(CI)(M)

test_user was able to see test_folder. So somehow W is causing an issue.

Any idea why this is happening?

Robotnik
  • 2,645

1 Answers1

3

Both (W) and (M) are macros; they expand to multiple actual access flags.

In particular, (W) like FILE_GENERIC_WRITE grants these rights:

  • "Synchronize" (S)
  • "Write data" (WD)
  • "Append data" (AD)
  • "Write EAs" (WEA)
  • "Write attributes" (WA)

The "Synchronize" right is rather obscure (and not even shown in the GUI), but it – as a comment points out – it happens to be included in both "(R)" and "(W)" sets. So when you deny (W) access, you end up denying (S) and that means programs can no longer request the full (R) group of access rights – even if they technically still have specific (RD) access.

Microsoft's file access documentation also notes this:

Note that you cannot use an access-denied ACE to deny only GENERIC_READ or only GENERIC_WRITE access to a file. This is because for file objects, the generic mappings for both GENERIC_READ or GENERIC_WRITE include the SYNCHRONIZE access right. If an ACE denies GENERIC_WRITE access to a trustee, and the trustee requests GENERIC_READ access, the request will fail because the request implicitly includes SYNCHRONIZE access which is implicitly denied by the ACE, and vice versa. Instead of using access-denied ACEs, use access-allowed ACEs to explicitly allow the permitted access rights.

If you must use a "deny" ACE, you'll need to individually deny the four other rights that (W) includes, i.e. (WD,AD,WEA,WA), but note that such an ACE tends to confuse ACL editing tools a little. (Many will still collapse it to a generic "Write" and you won't be able to tell the difference.)

The older cacls tool is particularly useful here, as it doesn't know many new macros/aliases and as a result shows you all the individual access rights. Alternatively, PowerShell's Get-Acl is normally too fine-grained to be useful, but in this case it's fine-grained just enough to be useful:

PS C:\> icacls test /grant "user:(OI)(CI)(R,X)"
PS C:\> icacls test /deny "user:(OI)(CI)(W)"

PS C:> Get-Acl test | fl Access : FOO\user Deny Write, Synchronize NT AUTHORITY\SYSTEM Allow FullControl BUILTIN\Administrators Allow FullControl FOO\user Allow ReadAndExecute, Synchronize

PS C:> cacls test
C:\test FOO\user (OI)(CI)(DENY)(special access:) SYNCHRONIZE FILE_WRITE_DATA FILE_APPEND_DATA FILE_WRITE_EA FILE_WRITE_ATTRIBUTES FOO\user:(OI)(CI)(DENY)(special access:) DELETE SYNCHRONIZE BUILTIN\Administrators:(OI)(CI)F NT AUTHORITY\SYSTEM:(OI)(CI)F

grawity
  • 501,077