Quo Vadis AccessFlags?
Introduction
When IIS is configured as an Application Server it executes scripts like ASP and ASP.NET, CGI programs and other dynamic content. But in other scenarios IIS is supposed to only allow the download of html files and other static content like html pages, music or video files. With the accessFlags setting in IIS 6.0 administrators were able to lock down the IIS execution permissions to prevent dynamic content from executing.
accessFlags in IIS 6.0
The configuration property that allows or prevents execution of dynamic content is called accessFlags in IIS 6.0. Here a link to the IIS 6.0 metabase reference documentation: http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/e9b6d626-9583-4d59-b7f7-a079ec47461c.mspx?mfr=true
Here is a brief overview of the three most important settings. These are also the only one’s show in the User Interface shown above.
“Read”
Setting a site, virtual directory or web application to “Read” has the effect that no dynamic content gets executed. If you have any kind of script content, for example ASP pages, ASP.NET pages, PHP or Perl scripts in this location they will generate a 403 Forbidden error.
“Script Execution”
If you set your site, virtual directory or web application to “Script Execution” only URLs that are mapped to script engines get executed. The most popular script engines on IIS are ASP, ASP.NET, Cold Fusion, PHP or Perl. To find out what script engines you have installed you have to look into the scriptmaps. The scriptmaps is another configuration property in IIS 6.0. It is there to register the script engine but also contains a mapping between a file extension and a DLL or executable.
“Script and Executable Content”
If you want to allow the execution of an ISAPI extension or CGI program you have to enable “Script and Executable content”. If you don't do this you get a HTTP Error 403.1 - Forbidden error.
Note: all executable programs also have to be registered in the Web Service Extension Restriction List before they can be executed otherwise you will see a 404.2 error in you log files!
Changes in IIS7
There are several changes that got introduced in IIS 7. Scriptmaps are not called scriptmaps anymore. The configuration section is called “handlers” now. And accessflags is not called accessflags anymore. It’s name is now accessPolicy and it lives in the handlers configuration section. Let’s have a look at the handlers section in %windir%\system32\inetsrv\config\applicationhost.config:
<handlers accessPolicy="Script, Read">
<add name="TRACEVerbHandler" path="*" verb="TRACE" modules="ProtocolSupportModule" requireAccess="None" />
<add name="OPTIONSVerbHandler" path="*" verb="OPTIONS" modules="ProtocolSupportModule" requireAccess="None" />
<add name="ISAPI-dll" path="*.dll" verb="*" modules="IsapiModule" resourceType="File" requireAccess="Execute" allowPathInfo="true" />
<add name="AXD-ISAPI-2.0" path="*.axd" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" />
<add name="PageHandlerFactory-ISAPI-2.0" path="*.aspx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" />
<add name="SimpleHandlerFactory-ISAPI-2.0" path="*.ashx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" />
<add name="WebServiceHandlerFactory-ISAPI-2.0" path="*.asmx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" />
<add name="HttpRemotingHandlerFactory-rem-ISAPI-2.0" path="*.rem" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" />
<add name="HttpRemotingHandlerFactory-soap-ISAPI-2.0" path="*.soap" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" />
<add name="AXD-ISAPI-1.1" path="*.axd" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.Net\Framework\v1.1.4322\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv1.1,bitness32" responseBufferLimit="0" />
<add name="PageHandlerFactory-ISAPI-1.1" path="*.aspx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.Net\Framework\v1.1.4322\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv1.1,bitness32" responseBufferLimit="0" />
<add name="SimpleHandlerFactory-ISAPI-1.1" path="*.ashx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.Net\Framework\v1.1.4322\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv1.1,bitness32" responseBufferLimit="0" />
<add name="WebServiceHandlerFactory-ISAPI-1.1" path="*.asmx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.Net\Framework\v1.1.4322\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv1.1,bitness32" responseBufferLimit="0" />
<add name="HttpRemotingHandlerFactory-rem-ISAPI-1.1" path="*.rem" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.Net\Framework\v1.1.4322\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv1.1,bitness32" responseBufferLimit="0" />
<add name="HttpRemotingHandlerFactory-soap-ISAPI-1.1" path="*.soap" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.Net\Framework\v1.1.4322\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv1.1,bitness32" responseBufferLimit="0" />
<add name="TraceHandler-Integrated" path="trace.axd" verb="GET,HEAD,POST,DEBUG" type="System.Web.Handlers.TraceHandler" preCondition="integratedMode" />
<add name="WebAdminHandler-Integrated" path="WebAdmin.axd" verb="GET,DEBUG" type="System.Web.Handlers.WebAdminHandler" preCondition="integratedMode" />
<add name="AssemblyResourceLoader-Integrated" path="WebResource.axd" verb="GET,DEBUG" type="System.Web.Handlers.AssemblyResourceLoader" preCondition="integratedMode" />
<add name="PageHandlerFactory-Integrated" path="*.aspx" verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.PageHandlerFactory" preCondition="integratedMode" />
<add name="SimpleHandlerFactory-Integrated" path="*.ashx" verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.SimpleHandlerFactory" preCondition="integratedMode" />
<add name="WebServiceHandlerFactory-Integrated" path="*.asmx" verb="GET,HEAD,POST,DEBUG" type="System.Web.Services.Protocols.WebServiceHandlerFactory, System.Web.Services, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" preCondition="integratedMode" />
<add name="HttpRemotingHandlerFactory-rem-Integrated" path="*.rem" verb="GET,HEAD,POST,DEBUG" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode" />
<add name="HttpRemotingHandlerFactory-soap-Integrated" path="*.soap" verb="GET,HEAD,POST,DEBUG" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode" />
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" />
</handlers>
There are two interesting settings in this section from an execution policy point of view.
1) accessPolicy and
2) requiredAccess
As you can see the accessPolicy setting is set for the whole handlers collection. In our case it is set to “Read” and “Script”. This means that only handlers that require “Read” or “Script” access will execute. Every handler that requires “Execute” access will not run with this setting. A ??? error will be generated. For example: Only if you extend the accessPolicy to “Read”, “Script” and “Execute” you will be able to execute an unmapped ISAPI extension (ISAPI-dll). The requireAccess property in for ISAPI extensions requires “Execute” access, see below:
<add name="ISAPI-dll" path="*.dll" verb="*" modules="IsapiModule" resourceType="File" requireAccess="Execute" allowPathInfo="true" />
The accessPolicy entry to enable unmapped ISAPI extensions would look like this:
<handlers accessPolicy="Script, Read, Execute">
If you don’t want to allow any dynamic content you would set the accessPolicy to
<handlers accessPolicy="Read">
Only the following handlers would remain in the list.
<handlers accessPolicy="Script, Read">
<add name="TRACEVerbHandler" path="*" verb="TRACE" modules="ProtocolSupportModule" requireAccess="None" />
<add name="OPTIONSVerbHandler" path="*" verb="OPTIONS" modules="ProtocolSupportModule" requireAccess="None" />
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" />
</handlers>
Note: Every handler without the requiredAccess property set will use the default. The default for requiredAccess is “Script”.
Controlling accessPolicy via the User Interface
Access policy can still be controlled on a granular level . To change the access policy: navigate to your site, virtual directory or web application and click the “Handler Mappings” icon.
You will see an entry called “Edit Handler Permissions…” in the Actions menueon the right hand side.
<I will add pictures how the UI looks soon - promise!>
If you click this entry you will get a dialog that allows you to control the access policy for the location you selected.
Summary
IIS7 introduced several changes to the way IIS7 controls execution permissions to web content. The new handlers configuration section now contains all settings necessary to set the policy for web content. These permissions can be controlled on a granular level and let Administrators determine what can be executed on their servers and what’s forbidden.