Have you ever tried to use PowerShell (or .NET) to mess with file or folder permissions and wondered what the ‘Synchronize’ right means? It pops up all over the place, like on existing ACEs:
And on new ACEs that you create (even if you don’t include it):
If you try to check permissions using the ACL Editor, you won’t see it anywhere. Here’s the ACE for ‘Users’ from the ‘C:\powershell’ folder shown in the first screenshot above:
So, what is this mysterious right, and why does PowerShell/.NET insist on showing it everywhere? Let’s start with the definition from MSDN:
The right to use the object for synchronization. This enables a thread to wait until the object is in the signaled state. Some object types do not support this access right.
The first time I read that, I didn’t think it sounded all that important. It turns out, though, that it’s critical for working with files and folders.
Before I explain a little bit more about why that right shows up, let’s briefly cover what makes up an access control entry’s access mask. It’s a 32-bit integer, which means that, theoretically, there are 32 different rights that can be controlled (32 bits means 32 different on/off switches). In practice, you don’t get that many rights, though. No matter what type of object you’re working with (file, folder, registry key, printer, service, AD object, etc), those 32-bits are broken down like this:
- Bits 0-15 are used for object specific rights. These rights differ between object types, e.g., bit 1 for a file means ‘CreateFiles’, for a registry key means ‘SetValue’, and for an AD object means ‘DeleteChild’.
- Bits 16-23 are used for “Standard access rights”. These rights are shared among the different types of securable objects, e.g., bit 16 corresponds to the right to delete the object, and it means the same thing for files, folders, registry keys, etc. As far as I know, only bits 16-20 in this range do anything.
- Bit 24 controls access to the SACL.
- Bits 25-27 are reserved and not currently used.
- Bits 28-31 are “Generic access rights”. They are a shorthand way of specifying four common access masks: read, write, execute, and all (full control). These bits are translated into a combination of object specific and standard access rights, and the translation differs depending on the type of object the ACE belongs to.
The ‘Synchronize’ right is controlled by bit 20, so it’s one of the standard access rights:
PS> [math]::Log([System.Security.AccessControl.FileSystemRights]::Synchronize, 2)
20
If you manage to remove the right (or if you explicitly deny it), bad things will happen. For folders, you won’t be able to see child items. For files, you won’t be able to view the contents. It turns out some very important Win32 APIs require that right to be granted, at least for file and folder objects. You get a hint of it from this MSDN page:
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.
I couldn’t do a good job of translating the actual definition of ‘Synchronize’ earlier, but I think I can translate this paragraph. It’s saying that you can’t create an access denied ACE for just GENERIC_READ or just GENERIC_WRITE as they are defined, because each of those sets of rights include ‘Synchronize’, and you’d effectively be denying both sets of rights. GENERIC_READ (bit 31) and GENERIC_WRITE (bit 30) are two of the four “Generic access rights” mentioned above. When they’re translated/mapped to their object-specific rights, they make up a combination of bits 0-20 of the access mask (object specific and standard rights).
Once translated, GENERIC_READ is very similar to [FileSystemRights]::Read, and GENERIC_WRITE is very similar to [FileSystemRights]::Write. From the same MSDN page, here’s a list of the object specific and standard rights that make up the generic rights (the [FileSystemRights] equivalents are listed in parenthesis):
- GENERIC_READ
- FILE_READ_ATTRIBUTES (ReadAttributes)
- FILE_READ_DATA (ReadData)
- FILE_READ_EA (ReadExtendedAttributes)
- STANDARD_RIGHTS_READ (ReadPermissions)
- SYNCHRONIZE (Synchronize)
- GENERIC_WRITE
- FILE_APPEND_DATA (AppendData)
- FILE_WRITE_ATTRIBUTES (WriteAttributes)
- FILE_WRITE_DATA (WriteData)
- FILE_WRITE_EA (WriteExtendedAttributes)
- STANDARD_RIGHTS_WRITE (ReadPermissions)
- SYNCHRONIZE (Synchronize)
The [FileSystemRights] enumeration has values for Read and Write that almost match what is defined above. Since PowerShell coerces strings into enumerations, and enumerations will attempt to show you combined flags where possible, let’s take a look at how those rights are seen when they’re cast as a FileSystemRights enumeration:
Hopefully that makes sense. It’s showing that GENERIC_READ in [FileSystemRights] translates to ‘Read, Synchronize’, which means that GENERIC_READ is not the same as [FileSystemRights]::Read since ‘Read’ doesn’t include ‘Synchronize’. GENERIC_WRITE and [FileSystemRights]::Write are almost the same, except [FileSystemRights]::Write is also missing ‘ReadPermissions’ in addition to ‘Synchronize’.
So, why don’t the generic rights translate to the same numeric values for [FileSystemRights]? It goes back to the warning from the MSDN page above: if you want to deny ‘Read’ or ‘Write’ only, you have to remove the ‘Synchronize’ right first. The ACL editor does this, and it doesn’t give you any control over the ‘Synchronize’ right: if you create a new ACE it will determine whether or not the right is added, and it never shows it to you. The creators of the file/folder access control .NET classes didn’t get that luxury. Each ACE has a numeric access mask, and that access mask needs to be translated with a flags enumeration. If the ‘Synchronize’ bit is set, then the flags enumeration string is going to show it, and vice versa. So, they did the next best thing: they pulled ‘Synchronize’ from the combined ‘Read’ and ‘Write’ rights in the [FileSystemRights] enumeration, and made sure that creating a new allow ACE or audit rule automatically adds the ‘Synchronize’ right, and creating a new deny ACE removes it. If an application wants to hide the ‘Synchronize’ right from the end user, that’s fine, but the underlying .NET object will show it if it’s present.
I hope that makes sense and clears that up. If not, please leave a comment where something needs to be explained a little better, and I’ll try to expand on it some more.
Hi Rohn,
Thank you for the wonderful article. Could you explain what would be the permission for Create Folder/ Append Data. I don’t see in Get-ACL cmdlet.
See below output.
AccessToString : Everyone Allow ReadData, AppendData, ExecuteFile, ReadAttributes, Synchronize
CREATOR OWNER Allow FullControl
NT AUTHORITY\SYSTEM Allow FullControl
IE\Domain Admins Allow FullControl
I have configured Everyone to create folder/append data permission, but do not see it and they are getting access denied
Regards,
Gurpinder Singh
CreateFolder and AppendData have the same numeric access right (4), it just depends on whether or not the ACE applies to a folder or a file. Your AccessToString above is showing ‘AppendData’, so that right is granted (if you look at the Access property instead of AccessToString, you can see the inheritance and propagation flags to see what the ACEs apply to).
What are you doing that’s giving you the access denied error? Are you trying to read or modify the files? You might have a little trouble reading the contents of files w/o ‘ReadExtendedAttributes’ granted as well. Also, I’m having trouble appending data to a file with just AppendData granted (I tried using Out-File -Append and notepad) w/o the WriteData, WriteAttributes, and WriteExtendedAttributes added in (the ‘Write’ permission takes care of all of those).
so, how can we report security ntfs permissions to our Director, is there any possibility to use any tools (for example Get_NTFSAccess) and show the same values as with GUI?
Getting the same view as the GUI requires a lot of steps, for instance, you sometimes have to translate generic rights into object specific rights, and that may lead to needing to combine ACEs after doing the translation. I have a module, PowerShellAccessControl (you want the version 4.0 download), that does just this. It sounds like you’re looking for the Get-PacAccessControlEntry command. While the module hasn’t had any updates in a while, and it still hasn’t been completed, I feel that it still does a great job of viewing the DACL and SACL on objects (for AD objects, I think it’s even better than the GUI). If you want to save the results, Get-PacAccessControl entry can be sent straight to Export-CSV. Try it out and let me know if you find somewhere where the module disagrees with what the GUI says.
Thanks for the great article! I always wondered what the SYNCHRONIZE flag means when I developed my permission reporting tool Parks Authorization Manager.
Great article – really helpful in understanding something our devs and I were trying to understand.