The Request Filtering feature is an improved version
of the UrlScan tool available for previous versions of IIS. The Request
Filtering feature enforces limitations on the format of the request URL
and its contents to protect the application from possible exploits that
may arise from exceeding these limits. With IIS 6.0 and previous
versions of IIS, these limits have thwarted the majority of known Web
application exploits, such as application-specific buffer overruns
resulting from long malicious URLs and query strings. Though the Web
server itself, starting with IIS 6.0, has been engineered to not be
vulnerable to these attacks, these limits remain valuable in preventing
both known and unknown future exploits for the Web server and
applications running on it.
In addition to
enforcing request limits, the Request Filtering feature also serves to
deny access to certain application resources that are not meant to be
served to Web clients, but are located in the servable namespace for an
application. These files include the web.config configuration files for
IIS and ASP.NET, as well as contents of the /BIN and /App_Code
directories for ASP.NET applications.
You can use Request Filtering to do the following:
Set request limits
Configure limits on the length and encoding of the URL, the length of
the query string, the length of the request POST entity body, allowed
request verbs, and maximum lengths of individual request headers.
Configure allowed extensions Configure which file extensions are allowed or rejected, regardless of the selected handler mapping.
Configure hidden URL segments Configure which URL segments are not served, to hide parts of your URL hierarchy.
Configure denied URL sequences Configure which URL patterns are not allowed, possibly to prevent known exploits that use specific URL patterns.
IIS 7.0 depends
on request filtering by default to reject requests that may contain
malicious payloads and to protect certain content from being served by
the Web server. You can also use it to further restrict the input to
your application, or to protect additional URLs, directories, and files
or file extensions from being served by the Web server.
Caution
Request
filtering is a critical security component and should not be removed
unless it is absolutely clear that it is not needed. Always prefer to
relax request filtering limits by setting the configuration rather than
uninstalling or removing the Request Filtering module. |
The request
filtering configuration does not have an associated IIS Manager page, so
these settings cannot be set through IIS Manager. To set them, you can
configure the system.webServer/security/requestFiltering configuration section directly at the command line by using Appcmd.exe or other configuration APIs. The requestFiltering
section is unlocked by default, so you can set request filtering
configuration in web.config files at the site, application, or URL
level.
The remainder of this section will illustrate how to modify common request filtering configuration tasks.
Setting Request Limits
You can use Request
Filtering to configure even tighter request limits if allowable in your
application’s usage to further reduce attackers’ ability to exploit your
application with malicious
input. At other times, you may need to relax the default request limits
to allow your application to function correctly, for example, if your
application uses long query strings that may exceed the default limit of
2048 characters.
You may need to modify
request limits applied by request filtering if any of the default
limits interfere with your application usage.
You can use Appcmd to set request filtering limits as follows.
%systemroot%\system32\inetsrv\Appcmd set config [ConfigurationPath]
/section:system.webServer/security/requestFiltering
[/allowDoubleEscaping:bool] [/allowHighBitCharacters:bool]
[/requestLimits.maxAllowedContentLength:uint] [/requestLimits.maxUrl:uint]
[/requestLimits.maxQueryString:uint]
This command uses the parameters in Table 1.
Table 1. Parameters for Requesting Filtering Limits
Parameter | Description |
---|
ConfigurationPath | The configuration path at which to set this configuration. |
allowDoubleEscaping | Whether
or not request URLs that contain double-encoded characters are allowed.
Attackers sometimes use double-encoded URLs to exploit canonicalization
vulnerabilities in authorization code. After two normalization
attempts, if the URL is not the same as it was after one, the request is
rejected with the 404.11 response status code. The default is false. |
allowHighBitCharacters | Whether
or not non-ASCII characters are allowed in the URL. If a high bit
character is encountered in the URL, the request is rejected with the
404.12 response status code. The default is true. |
requestLimits.maxAllowedContentLength | The
maximum length of the request entity body (in bytes). If this limit is
exceeded, the request is rejected with the 404.13 response status code.
The default is 30000000 bytes (approximately 28 megabytes). |
requestLimits.maxUrl | The
maximum length of the request URL’s absolute path (in characters). If
this limit is exceeded, the request is rejected with the 404.14 response
status code. The default is 4096 characters. |
requestLimits.maxQueryString | The
maximum length of the query string (in characters). If this limit is
exceeded, the request is rejected with the 404.15 response status code.
The default is 2048 characters. |
Note
You can also configure the request header length limits for each header by adding header limits in the headerLimits collection in the system.webServer/security/requestFiltering
section. If the request exceeds a configured header limit, it will be
rejected with a 404.10 response status code. Additionally, you can
configure which verbs are allowed by adding those verbs to the verbs collection. If the request specifies a verb that is not allowed, it is rejected with a 404.6 response status code. |
Configuring Allowed Extensions
By
default, the Web server will process only extensions for which a
handler mapping exists. By default, StaticFileModule processes all
unmapped extensions. StaticFileModule serves only extensions listed in
the system.webServer/staticContent
configuration section (known as Mimemaps in IIS 6.0 and previous
versions of IIS). Therefore, the handler mapping configuration and the
static content configuration serves as the two-level mechanism for
controlling which extensions can be served for a particular URL.
However, as a defense in
depth measure, you may still want to use Request Filtering to deny
requests to a particular extension, after making sure that it is not
configured in the IIS handler mappings and the static content list. This
makes sure that requests to this extension are rejected very early in
the request processing pipeline, much before they otherwise would be
rejected by the configuration mentioned earlier.
To add a prohibited or explicitly allowed extension by using Appcmd, use the following syntax.
%systemroot%\system32\inetsrv\Appcmd set config [ConfigurationPath]
/section:system.webServer/security/requestFiltering
/+fileExtensions.[fileExtension='string',allowed='bool']
The fileExtension string is in the format of .extension.
To delete a prohibited extension by using Appcmd, use the following syntax.
%systemroot%\system32\inetsrv\Appcmd set config [ConfigurationPath]
/section:system.webServer/security/requestFiltering
/-fileExtensions.[fileExtension='string']
These commands use the parameters in Table 2.
Table 2. Parameters for Deleting Prohibited Extension
Parameter | Description |
---|
ConfigurationPath | The configuration path at which to set this configuration. |
fileExtension | The extension, in the format of .extension, that should be allowed or denied. |
allowed | Whether or not the extension is allowed or denied. |
You can set this
configuration for a particular site, application, or URL by specifying
the configuration path with commands shown earlier in this section.
Note
Alternatively, you can configure the fileExtensions
collection to deny all unlisted extensions, explicitly enabling the
extensions that are allowed. This may be a more effective practice for
reducing surface area than prohibiting specific extensions. However, it
requires you to know and maintain the exhaustive list of all allowed
extensions necessary for your application. To do this, set the allowUnlisted attribute on the fileExtensions collection at the desired configuration path to false. |
Configuring Hidden URL Segments
You
may also want to prohibit a URL segment from being servable. ASP.NET
uses this technique to prohibit requests to the /BIN, /App_Code, and
other special /App_xxx directories that contain ASP.NET application
resources that the application is not to serve. You can create your own
special directories that contain nonservable content and protect them
with URL segments. For example, to prevent content from being served
from all directories named data, you can create a hidden segment named
data.
The
debate on how to protect special directories containing application
content not meant to be served directly, such as the ASP.NET /BIN
directory, dates back to IIS 5.0 days. The ASP.NET team has gone through
multiple attempts at achieving this, starting with the explicit removal
of Read permissions from the /BIN directory on IIS 5.0 during ASP.NET
application startup, to adding the code that prohibited requests
containing the /BIN segment to the ASP.NET ISAPI filter.
During the
development of ASP.NET 2.0, I had the opportunity to guide the solution
to this problem for the several new directories introduced by ASP.NET
2.0, such as the new App_Code directory. Unfortunately, removing the
Read permissions from these directories was no longer an option, because
on IIS 6.0, ASP.NET no longer had Write access to the IIS metabase. In
the absence of a general Web server feature to protect special
directories, we had no better option than to add blocking support for
all new directories to the ISAPI filter. Arguably, the most painful part
of the project was the decision to ask the community for the preferred
naming of these special directories, which resulted in much debate and
the changing of the directory names from Application_Code, to App$_Code,
and finally to App_Code. At the end, we were so fed up with changing
the names that the development manager ordered hats for all of us that
were printed with “App$.”
IIS 7.0 finally
provides a general solution for protecting special directories, a
solution that ASP.NET leverages to protect its special directories when
installed. Therefore, it no longer relies on the ISAPI filter for this
support. Additionally, hidden URL segments provide a general mechanism
for anyone to configure protected directories as appropriate for their
applications, without writing special code to perform the blocking.
Mike Volodarsky
IIS Core Program Manager, Microsoft
|
To add a hidden URL segment by using Appcmd, use the following syntax.
%systemroot%\system32\inetsrv\Appcmd set config [ConfigurationPath]
/section:system.webServer/security/requestFiltering
/+hiddenSegments.[segment='string']
The segment string is the segment to protect.
To delete a hidden URL segment by using Appcmd, use the following syntax.
%systemroot%\system32\inetsrv\Appcmd set config [ConfigurationPath]
/section:system.webServer/security/requestFiltering
/-hiddenSegments.[segment='string']
Note
Unlike
file extensions, there is no way to prohibit all segments other than
the ones configured. You can only deny specific segments by adding them
using the preceding command. |
You can target
configuration for a particular site, application, or URL by specifying
the configuration path with the preceding commands.
Configuring Denied URL Sequences
In some cases, you may
want to reject requests that contain specific sequences in the URL,
whether or not they are a complete segment. If it is not possible to fix
the application itself, this may be an effective way to protect an
application from certain URL patterns that are known to cause issues.
To add a denied URL sequence by using Appcmd, use the following syntax.
%systemroot%\system32\inetsrv\Appcmd set config [ConfigurationPath]
/section:system.webServer/security/requestFiltering
/+denyURLSequences.[sequence='string']
The sequence string is the sequence to reject.
To delete a denied URL sequence by using Appcmd, use the following syntax.
%systemroot%\system32\inetsrv\Appcmd set config [ConfigurationPath]
/section:system.webServer/security/requestFiltering
/-denyURLSequences.[sequence='string']
Note
Unlike
file extensions, there is no way to prohibit all URL sequences other
than the ones configured. You can only deny specific sequences by adding
them using the preceding command. |
You can set
this configuration for a particular site, application, or URL by
specifying the configuration path with the preceding commands.