When configuring folder permissions for IIS7 applications, many administrators encounter this puzzling scenario: Even after granting Read/Write access to the IIS_IUSRS group, operations fail when using IUSR for anonymous authentication. Process Monitor reveals the access attempts show:
Event: File System > CreateFile Result: ACCESS DENIED User: NT AUTHORITY\NETWORK SERVICE (impersonating: IUSR_MACHINENAME)
Contrary to common assumptions, IUSR is not automatically a member of IIS_IUSRS. These are distinct security principals:
- IIS_IUSRS: Contains Application Pool identities (Network Service, ApplicationPoolIdentity, or custom accounts)
- IUSR: Standalone account specifically for anonymous authentication
The impersonation chain explains why simply adding IIS_IUSRS isn't sufficient:
- Application Pool identity (member of IIS_IUSRS) launches worker process
- For anonymous requests, IIS impersonates IUSR account
- Access checks now evaluate against IUSR's permissions, not the App Pool identity
For a folder requiring both application and anonymous access:
Option 1: Explicit Permissions
icacls "C:\webcontent\uploads" /grant "IUSR":(OI)(CI)(M) icacls "C:\webcontent\uploads" /grant "IIS_IUSRS":(OI)(CI)(M)
Option 2: Permission Inheritance
Configure parent folder with both permissions, then inherit:
icacls "C:\webcontent" /grant "IUSR":(OI)(CI)(M) icacls "C:\webcontent" /grant "IIS_IUSRS":(OI)(CI)(M) icacls "C:\webcontent\uploads" /inheritance:e
For applications creating files that need subsequent anonymous access:
// C# example for setting permissions programmatically FileSystemAccessRule iusrRule = new FileSystemAccessRule( @"IUSR_MACHINENAME", FileSystemRights.Modify, InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, PropagationFlags.None, AccessControlType.Allow); DirectorySecurity sec = Directory.GetAccessControl(folderPath); sec.AddAccessRule(iusrRule); Directory.SetAccessControl(folderPath, sec);
For most production scenarios, we recommend:
- Maintain separate permissions for IIS_IUSRS (App Pool) and IUSR (Anonymous)
- Audit permissions using
icacls
or PowerShell'sGet-Acl
- Consider using ApplicationPoolIdentity instead of Network Service for better isolation
When configuring folder permissions for IIS applications, I discovered a critical nuance: granting RW (Read/Write) access to the IIS_IUSRS group doesn't automatically extend those permissions to the IUSR account. This creates confusion because:
// Typical permission assignment that WON'T work for anonymous auth: icacls "C:\\webcontent\\uploads" /grant "IIS_IUSRS":(OI)(CI)(M)
The misconception stems from how IIS handles impersonation:
- Application Pool Identity (e.g., NetworkService) runs worker processes
- IUSR handles anonymous authentication requests
- IIS_IUSRS contains worker process identities, NOT authentication identities
Using Sysinternals Process Monitor confirms the actual access pattern:
Process: w3wp.exe User: NETWORK SERVICE (impersonating IUSR) Path: C:\webcontent\uploads\test.txt Result: ACCESS DENIED
IIS_IUSRS and IUSR serve fundamentally different purposes in the security model:
Security Principal | Purpose | Membership |
---|---|---|
IIS_IUSRS | Worker process group | App Pool identities |
IUSR | Anonymous auth identity | Not in IIS_IUSRS |
For anonymous authentication scenarios, you must explicitly grant IUSR permissions:
// Correct permission assignment: icacls "C:\\webcontent\\uploads" /grant "IUSR":(OI)(CI)(M)
Alternatively, modify the application to run under the application pool identity:
<configuration> <system.web> <identity impersonate="false"/> </system.web> </configuration>
For complex scenarios, consider these approaches:
- Create a custom domain account for both application pool and anonymous auth
- Use Windows Authentication instead of anonymous
- Configure inheritance with careful ACE ordering
For production environments, I recommend:
# PowerShell script for secure permission setup $folder = "C:\webcontent\uploads" $rule1 = New-Object System.Security.AccessControl.FileSystemAccessRule( "IUSR","Modify","ContainerInherit,ObjectInherit","None","Allow") $rule2 = New-Object System.Security.AccessControl.FileSystemAccessRule( "IIS_IUSRS","ReadAndExecute","ContainerInherit,ObjectInherit","None","Allow") $acl = Get-Acl $folder $acl.SetAccessRule($rule1) $acl.SetAccessRule($rule2) Set-Acl $folder -AclObject $acl