On my server I'm running various different types of sites. Static files only, older Web-forms applications and some ASP.NET MVC sites.
I don't use cookie-less sessions, any WCF services, no CGI or COM objects. I also don't use ASP.NET membership services.
So all my application pools are running CLR v4.0 in 64Bit in integrated mode or 'No Managed Code' at all.
Considering this, I can get rid of several built-in modules.
This is to reduce the attack surface but also possibly improve performance.
Before applying any of these changes, make sure you've read IIS Hardening - File Extensions
IIS Components
First, lets review the installed components:
Get-WindowsOptionalFeature -Online | Where {$_.FeatureName -match "^IIS-" -and $_.State -eq "Enabled"} | Sort FeatureName | Select FeatureName
this shows all the components like this:
FeatureName
-----------
IIS-ApplicationDevelopment
IIS-ApplicationInit
IIS-ASPNET45
IIS-BasicAuthentication
IIS-CGI
IIS-CommonHttpFeatures
IIS-DefaultDocument
IIS-HealthAndDiagnostics
IIS-HttpCompressionDynamic
IIS-HttpCompressionStatic
IIS-HttpErrors
...
Review them all and decide whether you need them. In my case I had a few left-overs from old sites, I removed them:
& Disable-WindowsOptionalFeature -Online -FeatureName IIS-CGI
& Disable-WindowsOptionalFeature -Online -FeatureName IIS-IISCertificateMappingAuthentication
& Disable-WindowsOptionalFeature -Online -FeatureName IIS-BasicAuthentication
Handler Mappings on the machine level
I'm not using 32bit AppPools, so I can remove all 32bit mappings
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='xamlx-ISAPI-4.0_32bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='rules-ISAPI-4.0_32bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='xoml-ISAPI-4.0_32bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='svc-ISAPI-4.0_32bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='AXD-ISAPI-4.0_32bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='PageHandlerFactory-ISAPI-4.0_32bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='SimpleHandlerFactory-ISAPI-4.0_32bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='WebServiceHandlerFactory-ISAPI-4.0_32bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='HttpRemotingHandlerFactory-rem-ISAPI-4.0_32bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='HttpRemotingHandlerFactory-soap-ISAPI-4.0_32bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='aspq-ISAPI-4.0_32bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='cshtm-ISAPI-4.0_32bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='cshtml-ISAPI-4.0_32bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='vbhtm-ISAPI-4.0_32bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='vbhtml-ISAPI-4.0_32bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='ExtensionlessUrlHandler-ISAPI-4.0_32bit'}
I'm not using Classic mode, so I can remove all related IASPI mappings:
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='xamlx-ISAPI-4.0_64bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='rules-ISAPI-4.0_64bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='xoml-ISAPI-4.0_64bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='svc-ISAPI-4.0_64bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='AXD-ISAPI-4.0_64bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='PageHandlerFactory-ISAPI-4.0_64bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='SimpleHandlerFactory-ISAPI-4.0_64bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='WebServiceHandlerFactory-ISAPI-4.0_64bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='HttpRemotingHandlerFactory-rem-ISAPI-4.0_64bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='HttpRemotingHandlerFactory-soap-ISAPI-4.0_64bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='aspq-ISAPI-4.0_64bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='cshtm-ISAPI-4.0_64bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='cshtml-ISAPI-4.0_64bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='vbhtm-ISAPI-4.0_64bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='vbhtml-ISAPI-4.0_64bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='ExtensionlessUrlHandler-ISAPI-4.0_64bit'}
I'm not using WFC service or any sort of remoting:
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='xamlx-Integrated-4.0'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='rules-Integrated-4.0'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='xoml-Integrated-4.0'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='svc-Integrated-4.0'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='HttpRemotingHandlerFactory-rem-Integrated-4.0'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='HttpRemotingHandlerFactory-soap-Integrated-4.0'}
I don't need protection for .*html files
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='cshtm-Integrated-4.0'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='cshtml-Integrated-4.0'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='vbhtm-Integrated-4.0'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='vbhtml-Integrated-4.0'}
Other handlers I don't need
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='WebAdminHandler-Integrated-4.0'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='SimpleHandlerFactory-Integrated-4.0'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='aspq-Integrated-4.0'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='ISAPI-dll'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='ScriptHandlerFactoryAppServices-Integrated-4.0'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='ScriptResourceIntegrated-4.0'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='TRACEVerbHandler'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='OPTIONSVerbHandler'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/handlers" -name "." -AtElement @{name='TraceHandler-Integrated-4.0'}
WebAdminHandler
handles WebAdmin.axd to display the ASP.NET Website Administration Toolkit, you can remove this if you don't use that builtin feature.
SimpleHandlerFactory
handles *.asmx and *_AppService.axd to support Web service calls via Ajax.
aspq
- I have no idea what this is. I never used, I don't need it.
ScriptHandlerFactoryAppServices
handles *_AppService.axd for an Application Service within ASP.NET.
ScriptResourceIntegrated
handles ScriptResource.axd which I don't use.
TRACEVerbHandler
and OPTIONSVerbHandler
handle trace and options http requests, I don't support them.
TraceHandler
handles trace.axd which you don't want on a production server.
ISAPI-dll
for old school ISAPI extensions, don't want them.
Handler Mappings I want to keep
After removing all those mappings I'm left with these:
<handlers accessPolicy="Read, Script">
<add name="AssemblyResourceLoader-Integrated-4.0" path="WebResource.axd" verb="GET,DEBUG" type="System.Web.Handlers.AssemblyResourceLoader" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="PageHandlerFactory-Integrated-4.0" path="*.aspx" verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.PageHandlerFactory" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="WebServiceHandlerFactory-Integrated-4.0" path="*.asmx" verb="GET,HEAD,POST,DEBUG" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" responseBufferLimit="0" />
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule" resourceType="Either" requireAccess="Read" />
</handlers>
These are enough to run all my sites, that's 5 out of 87 handler mappings.
Do we really need those ISAPI thingies?
Even though some people, say you need the ISAPI ASP.NET filter and Restrictions, I found that I don't, so lets disable them:
Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/isapiFilters/filter[@name='ASP.Net_4.0_32bit']" -name "enabled" -value "False"
Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/isapiFilters/filter[@name='ASP.Net_4.0_64bit']" -name "enabled" -value "False"
Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/security/isapiCgiRestriction/add[@path='%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll']" -name "allowed" -value "False"
Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/security/isapiCgiRestriction/add[@path='%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll']" -name "allowed" -value "False"
You can also get rid of them completely:
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/isapiFilters" -name "." -AtElement @{name='ASP.Net_4.0_32bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/isapiFilters" -name "." -AtElement @{name='ASP.Net_4.0_64bit'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/security/isapiCgiRestriction" -name "." -AtElement @{path='%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/security/isapiCgiRestriction" -name "." -AtElement @{path='%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll'}
Http Modules on the machine level:
Again depending on your sites and technology there are a bunch of modules you don't need. I don't use most of the ASP.NET features, so in my case I could remove the following:
Managed Modules
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/modules" -name "." -AtElement @{name='WindowsAuthentication'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/modules" -name "." -AtElement @{name='FormsAuthentication'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/modules" -name "." -AtElement @{name='RoleManager'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/modules" -name "." -AtElement @{name='UrlAuthorization'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/modules" -name "." -AtElement @{name='FileAuthorization'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/modules" -name "." -AtElement @{name='AnonymousIdentification'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/modules" -name "." -AtElement @{name='Profile'}
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/modules" -name "." -AtElement @{name='UrlMappingsModule'}
Native Modules
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/modules" -name "." -AtElement @{name='IsapiModule'}