November 18th, 2019

I set the same ACL with the GUI and with icacls, yet the results are different

A customer found that if they used the GUI and the icacls program to deny Delete permission to a folder, the results were different, even though the resulting ACLs are the same.

Create a user, say, Bob, and create a folder, say, C:\test.

With the GUI

  • Right-click the folder and select Properties.
  • Go the Security tab, click Advanced.
  • Click the Add button to add a new ACE.
  • Select Bob as the Principal.
  • Set the Type to Deny.
  • Click Show advanced permissions.
  • Check Delete and uncheck everything else.
  • Click OK a bunch of times to save the changes.

With icacls

  • From a command prompt, type icacls C:\test /deny Bob:D

If you followed the GUI steps, then Bob can open the directory in Explorer. On the other hand, if you followed the icacls steps, then Bob cannot open the directory in Explorer.

In both cases, running icacls to view the permissions report the same results:

C:\> icacls c:\test
test THISPC\Bob:(DENY)(D)
     BUILTIN\Administrators:(I)(OI)(CI)(F)
     NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
     BUILTIN\Users:(I)(OI)(CI)(RX)
     NT AUTHORITY\Authenticated Users:(I)(M)
     NT AUTHORITY\Authenticated Users:(I)(OI)(CI)(IO)(M)

How is it possible that the permissions are identical, yet the results are different depending on how you set the permissions?

The problem is that your tools are lying to you. The Deny ACE on the directory is not what icacls reports.

If you change the security with the GUI, then the Deny ACE is 0x00010000 = DELETE. But if you change it with the icacls program, then the Deny ACE is is 0x00110000 = DELETE | SYNCHRONIZE.

So the icacls program is lying when it says that it denied Delete (D) permission. It actually denied both Delete and Synchronize.

And then on top of that, the icacls program is lying when it says that the actual ACE is a Deny D. It’s hiding the denied SYNCHRONIZE access.

And it’s that denied SYNCHRONIZE access which is the difference. Explorer cannot open a folder where SYNCHRONIZE is denied. (And the command prompt cannot chdir into such a directory either.)

I’m guessing that the icacls is doing this extra work as a courtesy, but it also makes diagnosing problems more difficult.

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

10 comments

Discussion is closed. Login to edit/delete existing comments.

  • Ian Yates

    Synchronise is new to me… Off to do some reading. Thanks!

  • Torrin

    Powershell appears to show everything. I’m guessing that’s best bet if this matters to you.

    PS C:\>get-acl C:\test | select -expand access
    . . .
    FileSystemRights : Delete, Synchronize
    AccessControlType : Deny
    IdentityReference : Bob
    . . .

    • Mystery Man

      Not everything. For example:


      Get-Acl C:\Windows\system32 | Select-Object -ExpandProperty Access

      FileSystemRights : 268435456
      AccessControlType : Allow
      IdentityReference : CREATOR OWNER
      IsInherited : False
      InheritanceFlags : ContainerInherit, ObjectInherit
      PropagationFlags : InheritOnly

      FileSystemRights : 268435456
      AccessControlType : Allow
      IdentityReference : NT AUTHORITY\SYSTEM
      IsInherited : False
      InheritanceFlags : ContainerInherit, ObjectInherit
      PropagationFlags : InheritOnly

      ...

      Update: 268435456, I believe is “Generic_ALL” or “Full control”

  • Ben Voigt

    I would definitely call this a bug. "(D)" is the friendly shorthand for a group of rights (0x00110000) The indicator for Delete alone (0x00010000), without the rest of the group, is "(DE)".

    icacls should be showing "(D)" for the file it acted on, where both Delete and Synchronize are in the ACE. And it should be showing "(DE)" for the permissions as set by the GUI, where only Delete appears in the ACE.

    From...

    Read more
    • Stefan Kanthak

      It’s not a bug, it’s PEBKAC: the correct command is “icacls C:\test /deny Bob:DE”

      • Ben Voigt

        It’s a bug that “/deny Bob:DE” results in “(D)” on inspection.

      • Stefan Kanthak

        Still PEBKAC, or "you too, Brutus": you use the wrong tool for "inspection"!
        Both CACLS.exe C:\test /S and CACLS.exe C:\test show the correct ACE set by ICACLS.exe C:\test /Deny Bob:(D) as well as ICACLS.exe C:\test /Deny Bob:(DE)
        I recommend to read the title of Raymond's post, CAREFUL!
        Also ignore the wrong part "even though the resulting ACLs are the same" of his first sentence: the ACLs differ.

        Read more
      • cheong00

        “This command has been deprecated. Please use icacls instead.”

        Btw, that doesn’t change the idea that apparently this is a bug in ICACLS command for displaying information inaccurately.

    • Dave Bacher

      https://docs.microsoft.com/en-us/windows/win32/fileio/file-security-and-access-rights

      Note: the NTFS.com description of the flag is much better than the Microsoft description, in my opinion. But that's just my opinion.

      "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,...

      Read more
  • Alex Martin

    But I suppose the icacls behavior is a compatibility constraint now and can’t be fixed.