Configuring Applications for Least Privilege
Next to reducing its
surface area, the most effective strategy to reduce the risk of a
successful attack on your Web server is to configure your applications
to run with the least privilege possible. Doing this minimizes the
amount of damage that results if an attacker successfully exploits any
known or future vulnerability. Similar to reducing the surface area,
this technique is
not limited to blocking specific threats—it works well for any threat
that may be present in your application today or that may be found in
the future.
The key to reducing
the privilege of the application code in the IIS environment is to
understand the identity under which the code executes, select the
identity with the minimal number of privileges required, and limit the
rights of the identity to access server resources. To help achieve least
privilege, we will review these techniques:
Use a low privilege application pool identity
Set NTFS file system (NTFS) permissions to grant minimal access
Reduce trust of ASP.NET applications
Isolate applications
These techniques are discussed next in this section.
Use a Low Privilege Application Pool Identity
The majority of code
executed as part of a Web application is executed in the context of the
IIS worker process and typically runs under the identity configured for
the application pool. Therefore, using a least privilege application
pool identity is the primary way to constrain the privileges and rights
granted to the application code.
By default, IIS
application pools are configured to run using the built-in Network
Service account, which has limited rights on the Web server. When each
IIS worker process is started, it also automatically receives membership
in the IIS_IUSRS group. This group replaces the IIS_WPG group used in
IIS 6.0 as the required group identifying all IIS worker processes on
the computer. IIS setup may still create the IIS_WPG group for
backward-compatibility reasons, in which case IIS_IUSRS will be made a
member of this group.
In addition, certain
code in your application may execute with the identity of the
authenticated user associated with each request. Table 1 summarizes the identities that may be used in your application.
Table 1. Application Identities
Identity Type | Used When... | Identities |
---|
Application pool identity | Accessing all files necessary for the execution of the IIS worker process Accessing web.config files Running FastCGI applications (by default) Running ASP.NET applications (by default)
| |
Authenticated user | Accessing static files Running ISAPI extensions Running CGI programs (by default) Running FastCGI applications (if impersonation is enabled) Running ASP.NET applications (if impersonation is enabled)
| |
Virtual directory fixed credentials (when configured) | | |
When
using authentication schemes that produce Windows tokens, such as
Windows Authentication or Basic Authentication, be aware that when
highly privileged users access your application, it will execute with
higher privileges than intended. Therefore, it is recommended that you
do not allow users that have administrative privileges on the server to
access your application.
Caution
When
using authentication schemes that produce Windows identities, your
applications may execute with the identity of the authenticated user. |
Also, when using
anonymous authentication, you may opt for configuring the anonymous user
to be the application pool identity, to ensure that all code always
executes under the application pool identity. This makes it
significantly easier to manage the access rights of the worker process.
Note
To simplify access management, configure the anonymous authentication user to be the application pool identity. |
When selecting
the application pool identity for your applications, use the following
guidelines to maintain or improve the security of your Web server:
Ensure that the application pool identity is not granted sensitive privileges or unnecessary rights to access resources.
Often, in the face of “access denied” errors, administrators tend to
grant the application pool identity full or otherwise unnecessary access
to resources. This increases the privilege of the worker process and
increases the risk of a serious
compromise if the code in the worker process is compromised. Only grant
the worker process the minimal access needed for the application to
work. If this minimal access involves privileges or rights typically
associated with administrative users, you need to re-evaluate your
application’s design.
Do not use highly privileged or administrative identities for IIS application pools. Never use LocalSystem, Administrator, or any other highly privileged account as an application pool identity. Just say no!
Consider using a lower privilege identity.
If your application allows it, consider using a custom low privilege
account for the IIS worker process. Unlike IIS 6.0, IIS 7.0
automatically injects the new IIS_IUSRS group into the worker process,
eliminating the need for you to make the new identity a member of any
group.
Separate code with different privilege requirements into different application pools.
If your server has multiple applications that require different levels
of privilege (for example, one requires the privilege to write to the
Web application, and the other one doesn’t), separate them into two
different application pools.
When using anonymous authentication, configure the anonymous user to be the application pool identity.
This significantly simplifies configuring access rights for your
application by making the application code always execute with the
application pool identity.
Grant minimal access.
When granting access to the application pool identity, grant the
minimal access necessary. You can use this in conjunction with
separating applications into different application pools to maintain
least privilege for your applications. To grant access to a resource for
all IIS application pools, grant it to the IIS_IUSRS group. To grant
access to a resource for a specific application pool, use the unique
application pool identity. Alternatively, use the automatic Application
Pool SID that is named IIS APPPOOL\<ApppoolName>
(the latter does not work for UNC content, only local content). Do not
grant access rights to Network Service because it grants access to all
services running on the server under the Network Service identity.
Set NTFS Permissions to Grant Minimal Access
By default, all files
required for IIS worker processes to function grant access to the
IIS_IUSRS group, which ensures that IIS worker processes can function
regardless of the selected application pool identity. However, it is up
to you to grant access to the application content so that the Web server
and the application can successfully access its resources.
Additionally, it is up to you to grant access to the additional
resources the IIS worker process uses, such as ISAPI extensions, CGI
programs, or custom directories configured for logging or failed request
tracing.
Table 2 indicates the level of access the Web server typically requires for different kinds of resources.
Table 2. Access Levels for Web Server Resources
Resource Type | Identity | Required Access |
---|
Content (virtual directory physical path and below) |
OR
| |
Additional
resources IIS features use: CGI programs, ISAPI extensions, native
module dynamic-link libraries (DLLs), compression directory, failed
request tracing directory, logging directory, and more | | Read Execute, for CGI programs Write, for compression or logging directories, or whenever the Web server needs to write data
|
When granting access to content directories, you can use one of the following techniques:
Grant access to IIS_IUSRS.
This enables all IIS worker processes to access the content when using
the application pool identity, or when using anonymous authentication.
However, this does not enable you to isolate multiple application pools.
If using a Windows-based authentication scheme, you also will need to
grant access to all of the authenticated users that use your
application.
Grant access to the identity of the application’s application pool.
This will enable only the IIS worker processes running in the
application pool with the configured identity to access the content. If
using anonymous authentication, you additionally need to set the
anonymous user to be the application pool identity. If using a
Windows-based authentication scheme, you also will need to grant access
to all of the authenticated users that use your application. This
approach is the basis for application pool isolation.
Configure fixed credentials for the application’s virtual directory and grant access to these credentials.
This will prompt the IIS worker process to access the content by using
the fixed credentials, regardless of the authenticated user identity.
This option is often used when granting access to remote UNC shares to
avoid the difficulties of ensuring that authenticated user identities
can be delegated to access the remote network share. It can also be an
efficient way to manage access to the content for a single identity
regardless of the authenticated user (which can be set to the
application pool identity when using custom application pool
identities). Finally, it can be used to control access to the
application when you host multiple applications inside the same
application pool.
Note
If
you are using IIS Manager to administer the application remotely, you
will also need to grant Read access to the NT Service\WMSvc account.
|
If you are using an
authentication scheme (other than anonymous authentication) that
produces Windows identities for authentication users, such as most of
the IIS authentication schemes, you will also need to make sure that all
authenticated users that require the use of your application have
access to its content. This is because the Web server will use the
authenticated user identity to access application content. Also, many
application frameworks will by default impersonate the authenticated
user when executing application code and accessing application
resources.
When you need to
allow multiple Windows users to use the application, you should add all
of these users to a specific group and grant this group access to the
application content. Alternatively, when using the fixed credentials
model, you do not have to grant access to the authenticated users.
Instead, IIS and application code will always impersonate the fixed
virtual directory credentials.
When your content is on a
UNC share, you will likely need to use the fixed credentials model
because most IIS authentication schemes do not produce Windows tokens
that can be used for remote network shares (with the exception of basic
authentication and IIS client certificate mapping authentication).
Alternatively, you can configure your Web server for Constrained
Delegation and Protocol Transition to allow the authenticated user
tokens to be used against the remote share. However, using the fixed
credentials for virtual directories on UNC shares is significantly
easier to configure, so it is recommended over setting up delegation.
Unlike
in IIS 6.0, in which the authenticated user having access to the
content directory is typically sufficient (except for ASP.NET
applications), IIS 7.0 also requires the IIS worker process identity to
have access to the content directories before they can read the
web.config configuration files. This happens before IIS determines the
authenticated user. |
Reduce Trust of ASP.NET Applications
In addition to
constraining the execution rights of the application by using a low
privilege application pool identity, you can further sandbox the .NET
parts of your application by using the ASP.NET trust levels. The ASP.NET
parts of the application include the ASP.NET applications themselves,
as well as managed modules that provide services for any application in
ASP.NET Integrated mode applications.
ASP.NET
trust levels use the Code Access Security (CAS) infrastructure in the
.NET Framework to limit the execution of the application code, by
defining a set of code permissions that control what application code
can and cannot do. By default, ASP.NET applications and managed modules
execute using the Full trust level, which does not limit their
execution. In this trust level, the application can perform any action
that is allowed by the Windows privileges and resource access rights.
You can reduce the trust
level of ASP.NET applications to limit their execution further. This
can be an effective way to achieve lower privilege for your application.
By default, you have options described in Table 3, which are defined by the ASP.NET trust policy files.
Table 3. Default Trust Level Options
.NET Trust Level | Execution Limits | Rights |
---|
Full (internal) | None | All |
High (web_hightrust.config) | None/.NET | Can do anything except call native code |
Medium (web_mediumtrust.config) | Application is trusted within its own scope, but should not be able to affect other applications or the rest of the machine | Access files in the application root Connect to SQL and OLEDB databases Connect to Web services on the local machine Manipulate threads and execution for its own requests
|
Low (web_lowtrust.config) | Application is not highly trusted; meant for applications that can use built-in ASP.NET features but do not run custom code | Only read access within application root |
Minimal (web_minimaltrust.config) | Application is untrusted; ability to use built-in ASP.NET features is extremely restricted | Minimal permissions for executing code |
It is recommended that
you run ASP.NET applications by using the Medium trust level. In this
trust level, the application is not able to access resources outside of
itself and cannot perform operations that can compromise the security of
the Web server overall. However, if you do this, you should test the
application to make sure that it does not experience any security
exceptions due to the lack of required permissions. You may also want to
performance test the application to make sure that using the reduced
trust level does not negatively impact your application’s performance.
Note
The
Medium trust level is the recommended trust level to constrain the
execution of ASP.NET applications and managed modules, and to host
multiple applications on a shared Web server. |
You
can use IIS Manager to configure the trust level used for ASP.NET
applications and managed modules by double-clicking .NET Trust Levels.
You can do this for the entire Web server—or for a specific
application—by selecting that application node prior to using the .NET
Trust Levels feature. You can also set the trust level directly by
changing the level attribute in the system.web/trust configuration section.
Caution
The system.web/trust
configuration section is not locked by default, which means that any
application can configure its own trust level. If you don’t want this,
lock the configuration section at the server level. |
Isolating Applications
Application
pools provide a great way to isolate multiple applications running on
the same machine, both in terms of availability and security. This
provides the following benefits:
Failures,
instability, and performance degradation experienced in one application
do not affect the applications in a different application pool.
Applications
running in a different application pool can restrict access to their
resources to that application pool only, preventing other applications
from being able to access their resources.
The
recommended way to configure applications for isolation is to place each
application into a separate application pool. When you do this, IIS 7.0
makes it easy to isolate applications by automatically injecting a
unique application pool security identifier, called the application pool
SID, into the IIS worker process of each application pool. Each
application pool SID is generated based on the application pool name and
has the name IIS APPPOOL\ <ApppoolName>.
The application pool SID makes it possible to quickly isolate
applications by placing NTFS permissions on their content to grant
access only to the application pool SID of the application’s application
pool.
Note
You
can quickly isolate applications by setting permissions on their
content to allow only the Application Pool SID of the corresponding
application pool. |
To make Application Pool SID–based isolation effective, you need to do the following:
1. | Configure anonymous authentication to use the application pool identity.
|
2. | Grant access to the application content for the IIS APPPOOL\ <ApppoolName> SID.
|
3. | Do
not grant access to the application content to IIS_IUSRS, IIS_WPG or
any other application pool identity that may be used by another
application pool.
|
4. | Configure
separate locations for all temporary and utility directories that IIS
and the application use for each application or application pool, and
set permissions on them to allow access only for the IIS APPPOOL\ <ApppoolName> SID.
|
Table 4
shows some of the common directories that IIS and ASP.NET applications
use. The directories must be configured for isolation for each Web site
or application and receive the appropriate permissions to enable access
only by the associated application pool.
Table 4. Common Directories Used by IIS and ASP.NET Applications
Directory | Configured In... |
---|
Content directories | Virtual directory physical path |
Windows TEMP directory (%TEMP% or %TMP%): used by Windows components | Set the loadUserProfile attribute to true in the processModel element of each application pool. This causes the TEMP directory to point to %SystemDrive%\Users\%UserName%\AppData\Local\Temp. |
Web site log file directory | directory attribute of the logFile element for each site. The default is %SystemDrive%\Inetpub\Logs\LogFiles. |
Web site Failed Requests Logs directory | directory attribute of the traceFailedRequestsLogging%SystemDrive%\Inetpub\Logs\FailedReqLogFiles. element of each site. The default is |
IIS Static Compression directory | Isolated
automatically by creating a subdirectory for each application pool and
applying ACLs to each directory for the Application Pool SID. |
ASP.NET Temp directory: used by ASP.NET compilation system | tempDirectory attribute in system.web/compilation%SystemRoot%\Microsoft.NET\Framework\<version>\Temporary ASP.NET Files. section for each application. The default is |
ASP Template Disk Cache directory | Isolated automatically by applying ACLs to each file for the Application Pool SID. |
Note
The
Application Pool SIDs can be used only for isolating local content. If
you are using content located on a UNC share, you need to either use a
custom application pool identity or configure fixed credentials for each
virtual directory. Then you should use that identity to grant access to
the network share. |
IIS 7.0 provides
automatic isolation of the server-level configuration by using
configuration isolation. No action is necessary to enable this, because
it is done by default.
Note
The server-level configuration in applicationHost.config is isolated automatically using configuration isolation. |
However, .NET Framework
configuration in the machine.config and root web.config files—as well as
the configuration in the distributed web.config files that are part of
the Web site’s directory structure—are not isolated. To properly isolate
the distributed web.config files, set the appropriate permissions on
the content directories, as described earlier in this section.