You are on page 1of 33

http://msdn.microsoft.

com/en-us/library/Aa292118

ASP.NET Impersonation
Visual Studio .NET 2003 Another important security feature is the ability to control the identity under which code is executed. Impersonation is when ASP.NET executes code in the context of an authenticated and authorized client. By default, ASP.NET does not use impersonation and instead executes all code using the same user account as the ASP.NET process, which is typically the ASPNET account. This is contrary to the default behavior of ASP, which uses impersonation by default. In Internet Information Services (IIS) 6, the default identity is the NetworkService account. Note Impersonation can significantly affect performance and scaling. It is generally more expensive to impersonate a client on a call than to make the call directly. Using impersonation, ASP.NET applications can optionally execute the processing thread using the identity of the client on whose behalf they are operating. You usually use impersonation for resource access control. Delegation is a more powerful form of impersonation and makes it possible for the server process to access remote resources while acting as the client. For more information, see ASP.NET Delegation. Note Impersonation is local to a particular thread. When code changes threads, such as when using thread pooling, the new thread executes using the process identity by default. When impersonation is required on the new thread, your application should save the security token (WindowsIdentity.Token Property) from the original thread as part of the state for the completion thread. If you enable impersonation, ASP.NET can either impersonate the authenticated identity received from IIS or one specified in the application's Web.config file. You have the following three options when configuring impersonation:

Impersonation is disabled. This is the default setting. For backward compatibility with ASP, you must enable impersonation and change the ASP.NET process identity to use the Local System account. In this instance, the ASP.NET thread runs using the process token of the application worker process regardless of which combination of IIS and ASP.NET authentication is used. By default, the process identity of the application worker process is the ASPNET account. For more information, see ASP.NET Process Identity.

<identity impersonate="false" />


Impersonation enabled. In this instance, ASP.NET impersonates the token passed to it by IIS, which is either an authenticated user or the anonymous Internet user account (IUSR_machinename).

<identity impersonate="true" />


Impersonation enabled for a specific identity. In this instance, ASP.NET impersonates the token generated using an identity specified in the Web.config file.

<identity impersonate="true" userName="domain\user" password="password" />

If the application resides on a UNC share, ASP.NET always impersonates the IIS UNC token to access that share unless a configured account is used. If you provide an explicitly configured account, ASP.NET uses that account in preference to the IIS UNC token. You should exercise care when using impersonation because it makes it possible for an application to potentially process code using permissions not anticipated by the application designer. For example, if your application impersonates an authenticated intranet user, that application possesses administrative privileges when impersonating a user with those privileges. Likewise, if the impersonated user possesses more restrictive permissions than anticipated, the user may not be able to use the application.

ASP.NET Impersonation
.NET Framework 1.1 Other Versions

When using impersonation, ASP.NET applications can optionally execute with the identity of the client on whose behalf they are operating. The usual reason for doing this is to avoid dealing with authentication and authorization issues in the ASP.NET application code. Instead, you rely on Microsoft Internet Information Services (IIS) to authenticate the user and either pass an authenticated token to the ASP.NET application or, if unable to authenticate the user, pass an unauthenticated token. In either case, the ASP.NET application impersonates whichever token is received if impersonation is enabled. The ASP.NET application, now

impersonating the client, then relies on the settings in the NTFS directories and files to allow it to gain access, or not. Be sure to format the server file space as NTFS, so that access permissions can be set. Impersonation is disabled by default. For ASP compatibility, the user must explicitly enable impersonation. If impersonation is enabled for a given application, ASP.NET always impersonates the access token that IIS provides to ISAPI extensions. That token can be either an authenticated user token, or the token for the anonymous user (such as IUSR_MACHINENAME). The impersonation occurs regardless of the type of authentication being used in the application. Only application code is impersonated; compilation and configuration are read as the process token. The result of the compilation is put in the "Temporary ASP.NET files" directory. The account that is being impersonated needs to have read/write access to this directory. If an application is on a universal naming convention (UNC) share, ASP.NET will always impersonate the token provided to IIS to access that share unless a configured account is used. If an explicit configured account is provided, ASP.NET will use that account in preference to the IIS UNC token. Applications that do want per-request impersonation can simply be configured to impersonate the user making the request. Impersonation is disabled at the computer level by default and, unless overridden, all the application domains inherit this setting. You can enable impersonation by putting a configuration file in the application root directory. For more information about the ASP.NET configuration system, see ASP.NET Configuration. As is the case with other configuration directives, this directive applies hierarchically. It is respected by nested applications in the hierarchy, unless explicitly overridden. The default value for this setting is as follows.

<impersonation enable="false"/>
A minimal configuration file to enable impersonation for an application might look similar to the following example.

<!-- Web.config file. --> <identity impersonate="true"/>


There is also name support for running an application as a configurable identity. For example:

<identity impersonate="true" userName="contoso\Jane" password="pass"/>


This enables the entire application to run as contoso\Jane, regardless of the identity of the request, as long as the password is correct. This type of impersonation can be delegated to another computer. You can programmatically read the identity of the impersonated user, as shown in the following example. VB

Dim username As String = System.Security.Principal.WindowsIdentity.GetCurrent().Name [C#] String username = System.Security.Principal.WindowsIdentity.GetCurrent().Name;


In the preceding example, userName and password are stored in clear text in the configuration file. Although IIS will not transmit .config files in response to a user agent request, configuration files can be read by other means, for instance by an authenticated user with proper credentials on the domain that contains the server. To help increase security, the identity section supports storage of encrypted userName and password attributes in the registry as shown in the following example.

userName="registry:HKLM\Software\AspNetIdentity,Name" password="registry:HKLM\Software\AspNetIdentity,Password"
The portion of the string after the keyword registry and before the comma indicates the name of the registry key that ASP.NET opens. The portion after the comma contains a single string value name from which ASP.NET will read the credentials. The comma is required, and the credentials must be stored in the HKLM hive. If the configuration format is incorrect, ASP.NET will not launch the worker process and the current account creation failure code path will be followed. The credentials must be in REG_BINARY format, containing the output of a call to the Windows API function CryptProtectData. You can create the encrypted credentials and store them in the registry with the ASP.NET Set Registry console application(Aspnet_setreg.exe), which uses CryptProtectData to accomplish the encryption. To download Aspnet_setreg.exe, along with the Visual C++ source code and documentation, visit the Web site www.asp.net and search for "aspnet_setreg". You should configure access to the key storing the encrypted credentials so that access is provided only to Administrators and SYSTEM. Because the key will be read by the ASP.NET process running as SYSTEM, you should set the following permissions: Administrators:F

SYSTEM:F CREATOR OWNER:F ProcessAccount:R This provides two lines of defense to protect the data:

The ACL permissions require the identity accessing the data to be an Administrator. An attacker must run code on the server (CryptUnprotectData) to recover the credentials for the account.

ASP.NET Web Application Security


.NET Framework 1.1 Other Versions

Most Web sites need to selectively restrict access to some portions of the site. You can think of a Web site as somewhat analogous to an art gallery. The gallery is open for the public to come in and browse, but there are certain parts of the facility, such as the business offices, that are accessible only to people with certain credentials, such as employees. When a Web site stores its customers' credit card information in a database, for example, access to the database must be restricted. ASP.NET security features help you address this and many other security issues. ASP.NET, in conjunction with Microsoft Internet Information Services (IIS), can authenticate user credentials such as names and passwords using any of the following authentication methods:

Windows: Basic, digest, or Integrated Windows Authentication (NTLM or Kerberos). Microsoft Passport authentication Forms authentication Client Certificate authentication

ASP.NET controls access to site information by comparing authenticated credentials, or representations of them, to NTFS file system permissions or to an XML file that lists authorized users, authorized roles (groups), or authorized HTTP verbs. This section and the following sections describe the specifics of ASP.NET security. For more information about the types of security attacks Web sites experience and how you can help protect your site from attack, see Security Considerations for ASP.NET Web Applications. In This Section How ASP.NET Security Works Provides an overview of ASP.NET security. ASP.NET Architecture Provides an overview of ASP.NET infrastructure and subsystem relationships, as related to security. ASP.NET Data Flow Describes the security data flow for two common scenarios. ASP.NET Authentication Describes ASP.NET authentication providers. ASP.NET Authorization Describes two fundamental ways to authorize access to a resource. ASP.NET Impersonation Describes how and when to use ASP.NET Impersonation. Designing Secure ASP.NET Applications Describes how to create ASP.NET applications with incorporated security. ASP.NET Application Security in Hosted Environments Describes ASP.NET security features for multi-application Web servers.

How to implement impersonation in an ASP.NET application


View products that this article applies to. This article was previously published under Q306158 This article refers to the following Microsoft .NET Framework Class Library namespaces:


On This Page

System.Web.Security System.Security.Principal System.Runtime.InteropServices

Expand all | Collapse all SUMMARY This article describes different ways to implement impersonation in an ASP.NET application.

Back to the top MORE INFORMATION If you want to impersonate a user on a thread in ASP.NET, you can use one of the following methods, based on your requirments:

Impersonate the IIS authenticated account or user Impersonate a specific user for all the requests of an ASP.NET application Impersonate the authenticating user in code Impersonate a specific user in code

Note You can use the following code to determine what user the thread is executing as:

System.Security.Principal.WindowsIdentity.GetCurrent().Name

Back to the top

Impersonate the IIS Authenticated Account or User


To impersonate the Microsoft Internet Information Services (IIS) authenticating user on every request for every page in an ASP.NET application, you must include an <identity> tag in the Web.config file of this application and set the impersonate attribute to true. For example:

<identity impersonate="true" />

Back to the top

Impersonate a Specific User for All the Requests of an ASP.NET Application


To impersonate a specific user for all the requests on all pages of an ASP.NET application, you can specify theuserName and password attributes in the <identity> tag of the Web.config file for that application. For example:

<identity impersonate="true" userName="accountname" password="password" />

Note The identity of the process that impersonates a specific user on a thread must have the "Act as part of the operating system" privilege. By default, the Aspnet_wp.exe process runs under a computer account named ASPNET. However, this account does not have the required privileges to impersonate a specific user. You receive an error message if you try to impersonate a specific user. This information applies only to the .NET Framework 1.0. This privilege is not required for the .NET Framework 1.1.

To work around this problem, use one of the following methods:

Grant the "Act as part of the operating system" privilege to the ASPNET account (the least privileged account).

Note Although you can use this method to work around the problem, Microsoft does not recommend this method.

Change the account that the Aspnet_wp.exe process runs under to the System account in the <processModel> configuration section of the Machine.config file.

Back to the top

Impersonate the Authenticating User in Code


To impersonate the authenticating user (User.Identity) only when you run a particular section of code, you can use the code to follow. This method requires that the authenticating user identity is of type WindowsIdentity.

Visual Basic .NET

Dim impersonationContext As System.Security.Principal.WindowsImpersonationContext Dim currentWindowsIdentity As System.Security.Principal.WindowsIdentity

currentWindowsIdentity = CType(User.Identity, System.Security.Principal.WindowsIdentity) impersonationContext = currentWindowsIdentity.Impersonate()

'Insert your code that runs under the security context of the authenticating user here.

impersonationContext.Undo()

Visual C# .NET

System.Security.Principal.WindowsImpersonationContext impersonationContext; impersonationContext =

((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();

//Insert your code that runs under the security context of the authenticating user here.

impersonationContext.Undo();

Visual J# .NET

System.Security.Principal.WindowsImpersonationContext impersonationContext; impersonationContext =

((System.Security.Principal.WindowsIdentity)get_User().get_Identity()).Impersonate();

//Insert your code that runs under the security context of the authenticating user here.

impersonationContext.Undo();

Back to the top

Impersonate a Specific User in Code


To impersonate a specific user only when you run a particular section of code, use the following code:

Visual Basic .NET

<%@ Page Language="VB" %> <%@ Import Namespace = "System.Web" %> <%@ Import Namespace = "System.Web.Security" %> <%@ Import Namespace = "System.Security.Principal" %> <%@ Import Namespace = "System.Runtime.InteropServices" %>

<script runat=server> Dim LOGON32_LOGON_INTERACTIVE As Integer = 2 Dim LOGON32_PROVIDER_DEFAULT As Integer = 0

Dim impersonationContext As WindowsImpersonationContext

Declare Function LogonUserA Lib "advapi32.dll" (ByVal lpszUsername As String, _ ByVal lpszDomain As String, _ ByVal lpszPassword As String, _ ByVal dwLogonType As Integer, _ ByVal dwLogonProvider As Integer, _ ByRef phToken As IntPtr) As Integer

Declare Auto Function DuplicateToken Lib "advapi32.dll" ( _ ByVal ExistingTokenHandle As IntPtr, _ ByVal ImpersonationLevel As Integer, _ ByRef DuplicateTokenHandle As IntPtr) As Integer

Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Long Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Long

Public Sub Page_Load(ByVal s As Object, ByVal e As EventArgs) If impersonateValidUser("username", "domain", "password") Then 'Insert your code that runs under the security context of a specific user here. undoImpersonation() Else 'Your impersonation failed. Therefore, include a fail-safe mechanism here. End If End Sub

Private Function impersonateValidUser(ByVal userName As String, _ ByVal domain As String, ByVal password As String) As Boolean

Dim tempWindowsIdentity As WindowsIdentity Dim token As IntPtr = IntPtr.Zero Dim tokenDuplicate As IntPtr = IntPtr.Zero impersonateValidUser = False

If RevertToSelf() Then

If LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, token) <> 0 Then If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then tempWindowsIdentity = New WindowsIdentity(tokenDuplicate) impersonationContext = tempWindowsIdentity.Impersonate() If Not impersonationContext Is Nothing Then impersonateValidUser = True End If End If End If End If If Not tokenDuplicate.Equals(IntPtr.Zero) Then CloseHandle(tokenDuplicate) End If If Not token.Equals(IntPtr.Zero) Then CloseHandle(token) End If End Function

Private Sub undoImpersonation() impersonationContext.Undo() End Sub </script>


Visual C# .NET

<%@ Page Language="C#"%> <%@ Import Namespace = "System.Web" %> <%@ Import Namespace = "System.Web.Security" %> <%@ Import Namespace = "System.Security.Principal" %> <%@ Import Namespace = "System.Runtime.InteropServices" %>

<script runat=server> public const int LOGON32_LOGON_INTERACTIVE = 2; public const int LOGON32_PROVIDER_DEFAULT = 0;

WindowsImpersonationContext impersonationContext;

[DllImport("advapi32.dll")] public static extern int LogonUserA(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] public static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken);

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] public static extern bool RevertToSelf();

[DllImport("kernel32.dll", CharSet=CharSet.Auto)] public static extern bool CloseHandle(IntPtr handle);

public void Page_Load(Object s, EventArgs e) { if(impersonateValidUser("username", "domain", "password")) { //Insert your code that runs under the security context of a specific user here. undoImpersonation(); } else { //Your impersonation failed. Therefore, include a fail-safe mechanism here. } }

private bool impersonateValidUser(String userName, String domain, String password) {

WindowsIdentity tempWindowsIdentity; IntPtr token = IntPtr.Zero; IntPtr tokenDuplicate = IntPtr.Zero;

if(RevertToSelf()) { if(LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0) { if(DuplicateToken(token, 2, ref tokenDuplicate) != 0) { tempWindowsIdentity = new WindowsIdentity(tokenDuplicate); impersonationContext = tempWindowsIdentity.Impersonate(); if (impersonationContext != null) { CloseHandle(token); CloseHandle(tokenDuplicate); return true; } } } } if(token!= IntPtr.Zero) CloseHandle(token); if(tokenDuplicate!=IntPtr.Zero) CloseHandle(tokenDuplicate); return false; }

private void undoImpersonation() { impersonationContext.Undo(); } </script>

Visual J# .NET

<%@ Page language="VJ#" %> <%@ Import Namespace="System.Web" %> <%@ Import Namespace="System.Web.Security" %> <%@ Import Namespace="System.Security.Principal" %> <%@ Import Namespace="System.Runtime.InteropServices" %>

<script runat=server> public static int LOGON32_LOGON_INTERACTIVE = 2; public static int LOGON32_PROVIDER_DEFAULT = 0;

WindowsImpersonationContext impersonationContext;

/** @attribute DllImport("advapi32.dll") */ public static native int LogonUserA(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, System.IntPtr[] phToken);

/** @attribute DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true) */ public static native int DuplicateToken(System.IntPtr hToken, int impersonationLevel, System.IntPtr[] hNewToken);

/** @attribute DllImport("kernel32.dll",CharSet=CharSet.Auto) */ public static native boolean CloseHandle(System.IntPtr[] handle);

/** @attribute DllImport("advapi32.dll", CharSet=CharSet.Auto,SetLastError=true) */ public static native boolean RevertToSelf();

public void Page_Load(Object s, System.EventArgs e) { if(impersonateValidUser("username", "domain", " password")) { //Insert your code that runs under the security context of a specific user here. undoImpersonation(); } else { //Your impersonation failed. Therefore, include a fail-safe mechanism here. } }

private boolean impersonateValidUser(String userName, String domain, String password) { WindowsIdentity tempWindowsIdentity; System.IntPtr[] token = new System.IntPtr[1]; System.IntPtr[] tokenDuplicate = new System.IntPtr[1];

if(RevertToSelf()) { if(LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, token) != 0) { if(DuplicateToken(token[0], 2, tokenDuplicate) != 0) { tempWindowsIdentity = new WindowsIdentity(tokenDuplicate[0]); impersonationContext = tempWindowsIdentity.Impersonate(); if (impersonationContext != null) { CloseHandle(tokenDuplicate); CloseHandle(token);

return true; } } } } if(!token[0].Equals(System.IntPtr.Zero)) CloseHandle(token); if(!tokenDuplicate[0].Equals(System.IntPtr.Zero)) CloseHandle(tokenDuplicate); return false;

private void undoImpersonation() { impersonationContext.Undo(); } </script>

Note The identity of the process that impersonates a specific user on a thread must have the "Act as part of the operating system" privilege if the Aspnet_wp.exe process is running on a Microsoft Windows 2000-based computer. The "Act as part of the operating system" privilege is not required if the Aspnet_wp.exe process is running on a Windows XP-based computer or on a Windows Server 2003-based computer. By default, the Aspnet_wp.exe process runs under a computer account named ASPNET. However, this account does not have the required privileges to impersonate a specific user. You receive an error message if you try to impersonate a specific user. .

To work around this problem, use one of the following methods:

Grant the "Act as part of the operating system" privilege to the ASPNET account.

Note We do not recommend this method to work around the problem.

Change the account that the Aspnet_wp.exe process runs under to the System account in the <processModel> configuration section of the Machine.config file.

http://www.codeproject.com/Articles/107940/Back-to-Basic-ASP-NET-Runtime-Impersonation
Today I got a question from one of the developers at my main customer. The question was how to move an uploaded file from an ASP.NET server to a file server on the network. The answer is of course by impersonating. In this post Ill explain how you can make ASP.NET impersonation and in more details how to make runtime impersonation.

Impersonation in ASP.NET
When we are doing I/O operations, the operation system makes security checks to understand if the user is authorized to do the operation. The same thing happens when you try to do operations on another machine in your network. Impersonation in ASP.NET occurs when ASP.NET executes code in the context of an authenticated and authorized user. By default, ASP.NET run in the ASPNET account. By using impersonation we can impersonate the ASPNET account to another account that has access to resources which arent granted in the internet security permission. One way to impersonate a user is by using the identity element in the web.config. When you use the following code in your web.config, ASP.NET impersonates to the authenticated user or to an anonymous internet user account:
Collapse | Copy Code

<identity impersonate="true" />

If you want to impersonate to a specific user you can use the following configuration:
Collapse | Copy Code

<identity impersonate="true"

userName="domain\username" password=" password"/>

Runtime Impersonation
At my customer the previous configuration examples werent an option. The second way to impose impersonation is by runtime. This option can be achieved by using the System.Security.Principal and the WindowsIdentity class. TheWindowsIdentity class has a method that makes impersonation and returns a WindowsImpersonationContext. The problem with this class is that you need to supply to it an IntPtr which is a security access token of the user that you wish to impersonate to. The solution is to use P/Invoke and call the LogonUser Win32 API. After you get the impersonation context you can run the network operations that you seek to perform. After you finish to do your operations you need to undo the impersonation. The following code shows an example of an impersonation service class:
Collapse | Copy Code

using using using using using

System; System.Collections.Generic; System.Linq; System.Web; System.Runtime.InteropServices;

using System.Security.Principal; namespace WebApplication1 { public class ImpersonationService { #region Consts public const int LOGON32_LOGON_INTERACTIVE = 2; public const int LOGON32_PROVIDER_DEFAULT = 0; #endregion #region External API [DllImport("advapi32.dll", SetLastError = true)] public static extern int LogonUser( string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken ); [DllImport("advapi32.dll", SetLastError = true)] public static extern bool RevertToSelf(); [DllImport("kernel32.dll", SetLastError = true)] public static extern int CloseHandle(IntPtr hObject); #endregion #region Methods public void PerformImpersonatedTask(string username, string domain, string password, int logonType, int logonProvider, Action methodToPerform) { IntPtr token = IntPtr.Zero; if (RevertToSelf()) { if (LogonUser(username, domain, password, logonType, logonProvider, out token) != 0) { var identity = new WindowsIdentity(token); var impersonationContext = identity.Impersonate(); if (impersonationContext != null) { methodToPerform.Invoke(); impersonationContext.Undo(); } } else { // do logging } } if (token != IntPtr.Zero) { CloseHandle(token); } } #endregion } }

Here is an example of how to use the class in your ASP.NET application:


Collapse | Copy Code

using System; using System.IO; namespace WebApplication1 { public partial class _Default : System.Web.UI.Page { #region Page Events private void Page_Load(object sender, System.EventArgs e) { var service = new ImpersonationService(); service.PerformImpersonatedTask("username", "domain", "password", ImpersonationService.LOGON32_LOGON_INTERACTIVE, ImpersonationService.LOGON32_PROVIDER_DEFAULT, new Action(MethodToPerform)); } #endregion #region Methods public void MethodToPerform() { var serverPath = @"\\ServerName\test"; var dirInfo = new DirectoryInfo(serverPath); Response.Write(dirInfo.Exists); } #endregion } }

Summary
In the post I showed a simple way to implement a class that impersonate to a relevant account in order to achieve some functionality that internet security permissions dont allow. You should consider to use the web.config instead since it does all the communication with Win32 API instead of the supplied code. The impersonation isnt limited only to ASP.NET and can be used also in other frameworks.

http://www.west-wind.com/weblog/posts/2005/May/18/Understanding-ASPNET-ImpersonationSecurity
Understanding ASP.NET Impersonation Security
64 comments

May 18, 2005 @ 1:10 am

With ASP.NET applications its usually recommended that you run under the ASP.NET user account without impersonation. The idea is that this account is a low rights account that can do little damage if for some reason the machine is compromised.

I get a lot of questions that are related to access rights for ASP.NET (and classic ASP) applications and 90% of the time the issue is related to the user underlying system account that IIS is running under. There tends to be some confusion in understanding just what account your application runs under and what rights need to be set to access this or that resource on the server. Usually the scenario involves a file on disk that needs to be accessed in read/write format.

First, to find out exactly which account your ASP.NET application runs under you can simply echo back Environment.UserName which is useful if youre not that familiar with IIS or youre running on an ISP box and they failed to provide you this information You can stick:

<%= Environment.UserName %> <%= Environment.UserName %>

into an ASPX page will tell you exactly which account the page is running under.

In all of my applications I tend to add one page in my admin directory that displays a bunch of information about the running environment. This page is fairly generic and its self contained so its easy to copy between projects (although I usually add a few admin functions). The following comes from my West Wind Web Storeapp:

Notice that there are two accounts that are listed: The underlying system account and the logged on user. These are two different things and the underlying system account is what Environment.UserName returns. The Logged on User in turn gets returned by User.Identity.Name which is a much higher level informational abstract that can be used by your application to figure out which user authenticated.

So, Environment.UserName returns to you the current Impersonation of the ASP.NET thread that you are running under. User.Identity.Name only returns you the authentication that ASP.NET has figured out based on the current request. So above I accessed a page with a Windows Login, hence it shows my username rstrahl. If I displayed this on a standard non-logged in Web page it would show the IUSR_ account the Internet Guest account.

What were interested in here is the underlying account which really determines what rights your ASP.NET application has to access system resources. Now, the account that ASP.NET runs under depends on the Windows version, how you have configured your Web server and what settings are configured in your Web.Config file.

Web Server If you are running IIS 5, the default account that IIS runs ASP.NET under is the ASPNET account. The actual account is configurable in machine.config. The ASPNET account is an account that ASP.NET installs and has fairly low rights. One big drawback in IIS 5 is that this account cannot be customized for each application the ProcessModel key that sets this account lives in machine.config and cannot be overridden in web.config, so you basically end up with having the same account run all your ASP.NET applications.

On IIS 6 things are much more configurable. The default account used is NETWORK SERVICE but its actually configurable via a new feature called an Application Pool. With IIS 6 all processing no longer occurs in the INETINFO.EXE process, but rather is offloaded into one or more daemon process (w3wp.exe). You can configure one or more of these processes by adding Application Pools in the IIS management Console. You can then add virtual directories to specific Application Pools. Application Pools are quite configurable and one of the key options is the ability to specify an Identity that this process runs under.

By default this is Network Service, but you can change this to any account you see fit. Network Service is used because like the ASPNET account on IIS 5 its a low rights account which by default has access to next to nothing on your machine.

Web.Config The next level of configuration for your ASP.NET application is web.config which allows you to specify the type of Impersonation is used with your ASP.NET application. By default ASP.NET unlike classic ASP doesnt use any impersonation. Impersonation is the concept of the application pretending to be a different account than the underlying account running the application ie. ASPNET or NETWORK SERVICE. In classic ASP IIS impersonated the logged on user which usually was the Internet Guest Account (IUSR_) or if you were logged in via Windows or Basic or Digest Authentication the user that was actually logged on.

ASP.NET works differently. It runs under the account that the process was started under originally. This means ASPNET or NETWORK SERVICE or if youre using IIS 6 the account you have specifically configured for your Application Pool. So while ASP.NET provides different Authentication models to let you see who logged on to secure areas of your Web site via Forms or Windows Authentication, the underlying account in this scenario never changes. The Authentication is merely a tool for your application, but it doesnt change the underlying security context.

This is a good thing and something that wasnt really easily possible with classic ASP. You can however revert to the Impersonation model that works just like classic ASP by turning Impersonation on in web.config:

<system.web> <location path="admin"> <system.web> <identity impersonate="true" /> <!-- WS: Allow only Authenticated users --> <authorization> <!-- allow users="*"/ --> <deny users="?" /> </authorization> </system.web> </location> </system.web>

This option goes back to setting the underlying system account to the specific account that is logged on: The anonymous Internet Guest account or who ever is logged on. In this mode ASP.NET impersonates the current Web user. It gets this token from IIS which passes this account token on the ISAPI thread that originally fires off this request.

While this is not recommended generally, it can be a useful. I like to use this sort of setup for my Admin directories of an application. This makes it possible for my main application to run under a low privilege account, but allows my Admin paths to elevate the rights for users that have authentication to access a specifc directory of the application. Once the impersonation is in effect I can run under a specific admin account which will have rights for example to write to data in my application directory.

Directory Rights So now we know which account is actually driving the application. The next step is to dole out permissions for your application in such a way that you can access the data you might need without compromising security. Which is not always easy and often means a compromise between security and flexibility.

The most common scenario I see is people needing to write some sort of output to the application directory. Usually people have problems when they need to write or access data in the Web Directory. Once youve figured out which account your application is actually running under you can start adjusting permissions as needed. So if you need to write to a file in your Web directory you need to give NETWORK SERVICE/ASPNET or whatever your app runs under rights to access this file. As always be very careful with this task and think ahead of how any security changes affect your security environment beyond just what you need to accomplish to access the file.

The easy way is to go in and give the required account the appropriate rights give NETWORK SERVICE WRITE access for example in the directory. But again be careful here. General security guidelines would say giving the operating account WRITE access might permit a hacker to upload ASPX pages and execute them. True, but you have to weigh that risk against the need to do what you need to do which might be to write an XML log file or write to web.config etc.

If you do need to open up security try to minimize your surface area. If you need access to a specific file give access only to that file. Even better move any files you are accessing out of the script directories and into a separate folder. Remove anonymous access rights (assuming you dont want Web site users to see the content) and then add read/write access for NETWORK SERVICE.

Heres another little trick in this regard: One thing all my Web applications do is allow configuration settings to be stored in Web.Config using a custom Configuration class that allows reading and writing and serializing configuration data to various output formats. Web.Config lives in the application root of course along with most of the ASPX files. So I need WRITE access for my NETWORK SERVICE account right?

Well, no. <g> I can actually cheat by designing my in such a way that configuration settings are only updated from an Admin directory. I can set up impersonation on the Admin directory, disable access for anonymous users and voila I can now log in and gain elevated rights that do allow me write to the web.config file without changing the permissions (beyond making sure that my user account or group has WRITE access) on the default files. There's more detail about this scenario in this previous entry.

Note that you can restrict access to a directory either declaratively in web.config as a I showed in the previous section, or you can do it explicitly by setting directory permissions on a directory. If you have an Admin directory you can simply remove the Internet Guest account from the file permissions which will disallow all anonymous access to the directory without changing anything in you Web.config. In fact this may be desirable anyway if you store any sensitive data in the directory. The <location> tag only applies to files that ASP.NET processes (ASPX, ASMX etc.) but not static files like HTML, XML etc. So in some cases you may need directory rights anyway.

Programmatic Impersonation? Note that it's also possible to affect the application's security environment programmatically from within your ASP.NET application by using some Windows API calls. There's more info on this topic in this previous entry about Using Programmatic Impersonation from an ASP.NET Page.

http://www.west-wind.com/weblog/posts/2005/Feb/24/Using-programmatic-Impersonation-from-anASPNET-Page
Using programmatic Impersonation from an ASP.NET Page
123 comments

February 24, 2005 @ 8:40 pm

Several times I've heard the following question asked: I have an ASP.NET application and I need access to network resources that my account running ASP.NET does not have. How can I change the permissions at runtime without setting up Impersonation or using a high privilige account for my ASP.NET user account? In short, how can you raise permissions of an ASP.NET request at runtime to perform some task that requires rights that the standard account ASP.NET runs under cannot handle? To accomplish this you can use various system API calls (LogonUser, ImpersonateLoggedOnUser and RevertToSelf) to change the currently active account ASP.NET runs under. This would be Environment.UserName as opposed to Page.User. Environment.UserName returns the threads currently logged on user. Page.User returns the name that ASP.NET verifies through Authentication and this user in most cases is independent of the Windows logon that is running the current thread. For anonymous requests Page.User is blank, while Environment.User will be NETWORK SERVICE (or ASPNET on IIS5). The only time when Page.User reflects Environment.User is when Impersonation is enabled in which case the ASP.NET automatically changes the impersonation on the underlying ASP.NET thread to match of who's logged on. For anonymous users this will be the IUSR_ account or if logged on the user who logged on. With the API calls mentioned above you can change the thread's security environment. The idea is, you can log on as a user, change the impersonation to that environment, do your thing then revert back. Let's look at how to do this first before going over some caveats. Given that you have rights to use PInvoke calls to make these API calls (NETWORK SERVICE generally does have these rights) the following code can be used to accomplish this:

using using using using using using using using using using

System; System.Collections; System.ComponentModel; System.Data; System.Drawing; System.Web; System.Web.SessionState; System.Web.UI; System.Web.UI.WebControls; System.Web.UI.HtmlControls;

using System.Runtime.InteropServices; using System.Text; namespace Westwind.WebStore.Demos { /// <summary> /// Summary description for Test. /// </summary> public class Test : System.Web.UI.Page { const const const const const int int int int int LOGON32_LOGON_INTERACTIVE LOGON32_LOGON_NETWORK LOGON32_LOGON_BATCH LOGON32_LOGON_SERVICE LOGON32_LOGON_UNLOCK = = = = = 2; 3; 4; 5; 7;

const int LOGON32_LOGON_NETWORK_CLEARTEXT = 8; const int LOGON32_LOGON_NEW_CREDENTIALS = 9; const int LOGON32_PROVIDER_DEFAULT = 0; [DllImport("advapi32.dll", SetLastError=true)] public static extern int LogonUser( string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken ); [DllImport("advapi32.dll", SetLastError=true)] public static extern int ImpersonateLoggedOnUser( IntPtr hToken ); [DllImport("advapi32.dll", SetLastError=true)] static extern int RevertToSelf(); [DllImport("kernel32.dll", SetLastError=true)] static extern int CloseHandle(IntPtr hObject); private void Page_Load(object sender, System.EventArgs e) { Response.Write( Environment.UserName + "<hr>"); IntPtr lnToken; int TResult = LogonUser("ricks",".","supersecret", LOGON32_LOGON_NETWORK,LOGON32_PROVIDER_DEFAULT, out lnToken); if ( TResult > 0 ) { ImpersonateLoggedOnUser(lnToken); StringBuilder sb = new StringBuilder(80,80); uint Size = 79; Response.Write( Environment.UserName + " - " + this.User.Identity.Name + "<hr>"); RevertToSelf(); Response.Write("<hr>" + Environment.UserName); CloseHandle(lnToken); } else { Response.Write("Not logged on: " + Environment.UserName); }

return; } }

To use this code change the username and password in the call to LogonUser to a valid local or domain account (see MSDN Docs for exact syntax to use for domain accounts and machine names). When you run this code you should see: NETWORK SERVICE ricks NETWORK SERVICE which corresponds to the original account the page is running under, the Impersonation that I applied, and then after I reverted back to the original account. Note that you should make sure to close the Token handle returned after you are done with your request, preferrably in a Finally section so you don't leak handles. Actually you don't have to revert back - ASP.NET assigns security to the ASP.NET thread before your request starts, so Revert is not really required.

Caveats
Now is this a good idea to do this in your code? Not really, because it's obviously a potential security risk. There are two things that are a problem here. First you need to run under an account that has rights to make PInvoke calls which is by no means guaranteed. Many multi-hosted ISPs will set up very low right accounts for their sites so that you may not be able to actually perform these tasks. OTOH, it's unlikely that in an ISP scenario you would actually need access to additional resources that require impersonation. Second and maybe more importantly using LogonUser requires that you use a password and that password has to come from somewhere. This means somewhere in your system you have to store this password and retrieve that password which can be compromised and then potentially be used to further penetrate security. A fairly far fetched hack scenario that would require somebody pretty damn familiar with your architecture, but still a threat.

You can also impersonation system accounts like SYSTEM and NETWORK SERVICE which don't require passwords (pass "" for the password), but most likely these accounts are not what you need to get your job done - for example access another machine on the network.

Alternatives
Ultimately the solution to this problem is to set up your ASP.NET application with the right account with the exact rights it needs. While I think security is important it's always been my feeling that if someone can penetrate your network and compromise ASP.NET pages - they're in too far already to not be able to do the rest (like changing web.config and stepping down security), so I am usually not opposed to running ASP.NET in slightly elevated security modes to match my needs. Another option for those one off requests is to use Impersonation and Windows Security in a separate directory. I do this in several of my applications where several admin requests require elevated rights. These pages sit off in a seperate directory with anonymous access off and Impersonation enabled in a separate web.config (or a Location section in the main web.config). An example of this is my Configuration class manager which has the capability to write Config changes back into Web.Config. I don't want to give NETWORK SERVICE rights to write any files in my main application directory, so I have my Configuration page off in an Admin directory. Admin requires Windows Security and then uses Impersonation, which means it runs under my Admin account on the server once I've logged in with my username and password. <location path="admin"> <system.web> <identity impersonate="true" /> <!-- WS: Allow only Authenticated users --> <authorization> <!-- allow users="*"/ --> <deny users="?" /> </authorization> </system.web> </location> I can set this up in a couple of ways. Here I do it all through ASP.NET's impersonation and security settings which deny access to non-authenticated users to these Admin pages. I could also set this up with directory security on the Admin directory and simply remove IUSR_ to achieve the same effect although I would still need the impersonate setting in web.config. This works well as long as the requests in question can be easily isolated and users are that are accessing these requests indeed can authenticate, which is not always the case. Use with care... and don't impersonate GrandMa - it ain't nice!

http://odetocode.com/resources/110.aspx
Impersonation in ASP.Net

Posted by ? on Sunday, March 14, 2004


ASP.NET applications can execute with the identity of the client. These articles take a look at different ways to use and troubleshoot impersonation in ASP.NET

By default, ASP.NET executes in the security context of a restricted user account on the local machine. Sometimes you need to access network resources such as a file on a shared drive, which requires additional permissions. One way to overcome this restriction is to use impersonation. With impersonation, ASP.NET can execute the request using the identity of the client who is making the request, or ASP.NET can impersonate a specific account you specify in web.config.

Implementing Impersonation in an ASP.NET Application Choosing Resource Access Identities - Identity Impersonation In ASP.NET MSDN: ASP.NET Impersonation HOW TO: Secure an ASP.NET Application by Using Windows Security On being someone else

http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q306158

http://www.dnzone.com/go?504
Authorization
In ASP.NET, it is possible to allow authorization to the application when you make additional settings available within the Web.config file. You can allow certain users or certain groups access to these additional settings. The following examples describe this capability. To allow access to all users found in the Windows NT Group that is called "Managers," use the following code:

<configuration> <system.web> <authorization> <allow roles="domainname\Managers" /> <deny users="*" /> </authorization> </system.web> </configuration>
To allow access to only certain users, use the following code:

<configuration> <system.web> <authorization> <allow users="domainname\user1,domainname\user2,domainname\user3" /> <deny users="*" /> </authorization> </system.web> </configuration>
Note You can reference multiple roles or users when you use a comma-separated list.

How to Enable Impersonation


In this procedure, you will configure the WindowsSite application to impersonate the Windows user who is accessing it.

1.
2.

In Visual Studio, view the Web.config file for the WindowsSite project. Add the following element after the authentication element:

3. <identity impersonate = "true" />

4. 5.

Save Web.config. Run the project. Confirm that the page is displayed with the following message (note that the ASP.NET execution engine will use your Windows credentials to access resources on your behalf):

You are: Your Windows user name This page runs as: Your Windows user name

6.

Quit Internet Explorer to stop the project.

http://www.dotnet-guide.com/impersonation.html

Understanding Impersonation in ASP.NET


At times users access a resource as though they were someone else. This is known as impersonation. For example, if a web page has no access controls, then any user can access that web page. HTML pages, ASP pages, and components in version 3.0 and earlier can be accessed through two accounts named IUSR_machinename and IWAM_machinename. Both the accounts are set up during IIS installation, and are automatically added to all the folders in every web site on the server. Anonymous access to a resource in IIS makes the task of identifying a user extremely difficult. But there is no need to authenticate a user in the case of IIS. When IIS receives a request for a web page or other resource that has permission for anonymous access, IIS treats the IUSR_machinename account as the user's account, to access the resources. If the resource requested by the user is an ASP page that uses a COM or COM+ component, that component is executed using the IWAM_machinename account. In ASP.NET, when impersonation is turned off, the resources can be accessed using a "local system process" account. When impersonation is turned on, ASP.NET executes every resource using the account of a specified user who is authenticated when the user makes the request. If you specify the IUSR_machinename account to be used as the user account, then ASP.NET will behave like previous versions of ASP, in providing access to the resources. In ASP.NET, you first need to check whether the application is configured to use impersonation. In the case of IIS, the IIS impersonates users with its own IUSR account. In the case of ASP.NET, impersonation is used to decide whether the user's request should be executed using the account of the requested user, or that of a local system-process account that ASP.NET uses for anonymous requests. The concept of impersonation is complex to some extent due to the fact that ASP.NET uses the dynamic compilation features of the .NET Framework. The IUSR account has only limited permissions on the local machine, and so is not suitable without some reconfiguration. This account is also used by IIS to access resources like HTML pages, documents, and zip files that are not executed as part of the .NET Framework. If impersonation is enabled in an ASP.NET application then: If anonymous access is enabled in IIS, the request is made using the IUSR_machinename account. If anonymous access is disabled in IIS, the request is made using the account of the authenticated user. In either case, permissions for the account are checked in the Windows Access Control List (ACL) for the resource(s) that a user requests, and a resource is only available if the account they are running under is valid for that resource. If impersonation is disabled in an ASP.NET application then: If anonymous access is enabled in IIS, the request is made using the system-level process account. If anonymous access is disabled in IIS, the request is made using the account of the

authenticated user. In either case, permissions for the account are checked in the Windows ACL for the resource(s) that a user requests, and a resource is only available if the account they are running under is valid for that resource.

http://www.4guysfromrolla.com/articles/031204-1.aspx

An Overview of Authentication and Authorization Options in ASP.NET


By Nandini Venugopalan
Security 101: Authentication and Authorization
Authentication and Authorization are two interrelated security concepts. In short, authentication is a process of identifying a user, while authorization is the process of determining if an authenticated user has access to the resource(s) they requested. Typically, authentication is achieved by the user sharing credentials that somehow verify the user's identity.

- continued -

Whenever a user logs on to an application, the user is first authenticated and then authorized. With ASP.NET Web applications, the users requesting a page are, by default, anonymous. There are different techniques available for determining the identity of an anonymous user, which we'll examine in this article. Realize, however, that, by default, Web applications allow for anonymous access.

This article provides a high-level overview of the authentication and authorization models available in an ASP.NET Web application.

Understanding how ASP.NET and IIS Handle Authentication and Authorization


Both IIS - Microsoft's Web server software - and ASP.NET provide means for authentication and authorization. It is important to understand that ASP.NET is not a stand-alone product - rather, it is utilized from IIS. When a request comes in for an ASP.NET Web page, the request is sent to the Web server software (IIS), which performs authentication and authorization. Depending on the settings in IIS and the user accessing the site, these checks might pass or they might not. If the user is not authenticated, or does not have access, they're request will be stopped and an appropriate message will be returned. If, however, the request passes IIS's authentication and authorization, the request will be handed off to the ASP.NET engine, which can impose its own authentication and authorization schemes.

The following shows the sequence of authentication and authorization actions performed by IIS and ASP.NET on an incoming request.

1. 2. 3. 4.

The incoming request is first checked by IIS. If the IP address from where the request is sought is not allowed access to the domain, IIS denies the request. IIS allows anonymous access by default and hence requests are automatically authenticated. However, this can be overridden for each application within IIS. Next in the sequence IIS performs this authentication, if it has been configured to do so. The authenticated user request is passed to ASP.NET. ASP.NET checks whether Impersonation is enabled or not. By default impersonation is not enabled in ASP .NET. Generally, some applications require impersonation for ASP compatibility and Windows server authentication. (By default, the ASP.NET engine operates under the

ASPNET user account. Impersonation is a means by which you can have the ASP.NET engine operates under the authenticated user's o o
If impersonation is enabled, ASP.NET executes with the identity of the entity on behalf of which it is performing executing the task. If impersonation is not enabled, the application runs with the privileges of the

user account. For more information refer to INFO: Implementing Impersonation in an ASP.NET Application.)

ASPNET user account.

5.

Finally, the identity that has been authenticated and checked for in the previous steps is used to request resources from the OS. ASP.NET uses two forms of authorization:

o o

FileAuthorization - relies on NTFS file permissions for granting access. UrlAuthorization - in the the

Web.config file you can specify the authorization rules for various directories or files using <authorization> element.

6.

If access is granted (successful authorization), ASP .NET returns the user's request through IIS.

The above sequence of steps is pictorially depicted in the diagram below:

Authentication Providers
ASP.NET provides three ways to authenticate a user:

Windows authentication, Forms authentication, and Passport authentication

It is the job of the authentication provider to verify the credentials of the user and decide whether a particular request should be considered authenticated or not. The authentication scheme an ASP.NET Web application uses can be configured in its refer to ASP.NET Authentication.

Web.config file. For more information

Windows Authentication Provider


The Windows authentication provider is the default provider for ASP .NET. It authenticates users based on the users' Windows accounts. Windows authentication in ASP.NET actually relies on IIS to do the authentication. IIS can be configured so that only users on a Windows domain can log in. If a user attempts to access a page and is not authenticated, they'll be shown a dialog box asking them to enter their username and password. This information is then passed to the Web server and checked against the list of users in the domain. If the user has supplied valid credentials, access is granted. The identity of the user is then passed to the ASP.NET engine. More information about the Windows authentication provider can be found here.

There are four different kinds of Windows authentication options available that can be configured in IIS:

Anonymous Authentication: IIS doesn't perform any authentication check. IIS allows any user to access the ASP .NET application. Basic Authentication: For this kind of authentication, a Windows user name and password have to be provided to connect. However, this information is sent over the network in plain text and hence this is an insecure kind of authentication. Basic Authentication is the only mode of authentication older, non-Internet Explorer browsers support. Digest Authentication: It is same as Basic Authentication but for the fact that the password is hashed before it is sent across the network. However, to be using Digest Authentication, we must use IE 5.0 or above. Integrated Windows Authentication: In this kind of authentication technique, passwords are not sent across the network. The application here uses either the kerberos or challenge/response protocols to authenticate users. Kerberos, a network authentication protocol, is designed to provide strong authentication for client-server applications. It provides the tools of authentication and strong cryptography over the network to help to secure information in systems across entire enterprise.

For more information on these four different types of IIS authentication consult IIS Authentication Methods Available for Windows 2000

Passport Authentication Provider


Passport authentication is a centralized authentication service. This uses Microsoft's Passport Service to authenticate the users of an application. If the authentication mode of the application is configured as Passport and if the users have signed up with Microsoft's Passport Service, then the authentication formalities are pushed over to Passport servers.

Passport uses an encrypted cookie mechanism to identify and indicate authenticated users. If the users have already been signed into passport when they visit the application page, ASP.NET will consider them as authenticated. Otherwise, the users will be redirected to Passport servers to login. Upon successful login, the user is redirected back to the ASP.NET Web page that they initially tried to access. If you use Hotmail you already have a Passport account and are familiar with the sign-in process from an end-user's perspective.

Forms Authentication Provider


The forms authentication provider uses custom HTML forms to collect authentication information. As an ASP.NET developer using forms authentication, you must write your own logic/code to check the user's supplied credentials against a database or some other data store. When a user is successfully identified via forms authentication, the user's credentials are stored in a cookie for use during the session. For more information on implementing forms authentication be sure to read Using Forms Authentication in ASP.NETand Getting Started With Forms Authentication. The method of authentication to use is specified in the Web application's

Web.config file:

<!-- For Windows Authentication... --> <authentication mode="windows"> <!-- For Passport Authentication... --> <authentication mode="passport"> <!-- For Forms Authentication... --> <authentication mode="forms">

ASP .NET also supports custom authentication providers. Setting the authentication

mode for the application to "none" and then writing our own

code to perform authentication can achieve this. For example, we might install an ISAPI filter in IIS that compares incoming requests' IP address with a list of source IP addresses and considers the request to be authenticated only if the IP address is found in the source list. In this example, we can set the authentication mode to

"none" in Web.config file. This will prevent any of the default authentication providers from being triggered.

Configuring Authorization
There are two forms of authorization available in ASP.NET:

FileAuthorization - relies on NTFS file permissions for granting access. UrlAuthorization - in the the

Web.config file you can specify the authorization rules for various directories or files using <authorization> element.

FileAuthorization works by checking the access rights of the user account that the ASP.NET engine is operating under against the NTFS file permissions. That is, if a user is requesting the file the ASP.NET engine is operating under has read permissions to that file. Recall that by default the ASP.NET engine operates under the account; however, this can be changed through impersonation.

C:\Inetpub\wwwroot\SomeFile.aspx, a check is made to ensure that the user account ASPNET user

Impersonation is a technique that allows the ASP.NET process to act as the authenticated user, or as an arbitrary specified user. ASP.NET impersonation is controlled by entries in the applications

Web.config file. By default impersonation is not enabled.

By default ASP .NET runs as an unprivileged account the

ASPNET. You can, however, configure the account that ASP.NET uses by changing userName attribute of the processModel section in the machine.config file. That is, you could modify this setting so that

the ASP.NET engine always operated under, say, the Administrator account (NOT A GOOD IDEA!!!!, but it can be done).

Using impersonation, the ASP.NET engine will operate under the identity IIS passes to it. If anonymous access is allowed in IIS, ASP.NET will run under the

IUSR_ComputerName account that IIS uses. If anonymous access is not allowed, ASP.NET will take on the identity of the authenticated Web.config file for impersonation, refer to ASP.NET Impersonation.

user. Impersonation can also be configured so that a single, static user account is used for all requests. For more information on using impersonation, including how to configure the

For information on UrlAuthorization, consult ASP.NET Authorization.

Happy Programming! By Nandini Venugopalan

http://msdn.microsoft.com/en-us/library/wce3kxhd(vs.71).aspx

ASP.NET Authorization
.NET Framework 1.1 Other Versions

The purpose of authorization is to determine whether an identity should be granted the requested type of access to a given resource. There are two fundamental ways to authorize access to a given resource:

File authorization File authorization is performed by the FileAuthorizationModule, and is active when you use Windows authentication. It does an access control list (ACL) check of the .aspx or .asmx handler file to determine if a user should have access. Applications can further use impersonation to get resource checks on resources that they are accessing. For more information about impersonation, see ASP.NET Impersonation.

URL authorization URL authorization is performed by the URLAuthorizationModule, which maps users and roles to pieces of the URL namespace. This module implements both positive and negative authorization assertions. That is, the module can be used to selectively allow or deny access to arbitrary parts of the URL namespace for certain sets, users, or roles.

The URLAuthorizationModule is available for use at any time. You only need to place a list of users and/or roles in the <allow> or <deny> elements of the <authorization>section of a configuration file.

To establish the conditions for access to a particular directory, you must place a configuration file that contains an <authorization> section in that directory. The conditions set for that directory also apply to its subdirectories, unless configuration files in a subdirectory override them. The general syntax for this section is as follows.

<[element] [users] [roles] [verbs]/>


An element is required. Either the users or the roles attribute must be included. Both can be included, but both are not required. The verbs attribute is optional. The permissible elements are <allow> and <deny>, which grant and revoke access, respectively. Each element supports three attributes, which are defined in the following table.

Attribute
roles

Description
Identifies a targeted role for this element. The associated IPrincipal object for the request determines the role membership. You can attach arbitraryIPrincipal objects to the context for a given request and they can determine role membership in whatever way you like. For example, the defaultWindowsPrincipal class uses Microsoft Windows NT groups to determine role membership. Identifies the targeted identities for this element. Defines the HTTP verbs to which the action applies, such as GET, HEAD, and POST.

users verbs

Anonymous users are also denied. The following example grants access to Kim and members of the Admins role, while denying it to John and all anonymous users:

<authorization> <allow users="Kim"/> <allow roles="Admins"/> <deny users="John"/> <deny users="?"/> </authorization>
Both users and roles can refer to multiple entities by using a comma-separated list, as shown in the following example.

<allow users="John, Kim, contoso\Jane"/>


Notice that the domain account (contoso\Jane) must include both the domain and user name combination. In addition to identity names, there are two special identities, as shown in the following table.

Identity
* ?

Description
Refers to all identities Refers to the anonymous identity

To allow John and deny everyone else, one might construct the following configuration section.

<authorization>

<allow users="John"/> <deny users="*"/> </authorization>


The following example lets everyone do a GET, but only Kim can use POST.

<authorization> <allow verb="GET" users="*"/> <allow verb="POST" users="Kim"/> <deny verb="POST" users="*"/> </authorization>
Rules are applied using the following heuristics:

Rules contained in configuration files at lower directory levels take precedence over rules at higher directory levels. The system determines which rule takes precedence by constructing a merged list of all rules for a URL, with the most recent (nearest in the hierarchy) rules at the head of the list. Given a set of merged rules for a URL, the system starts at the head of the list and checks rules until the first match is found. Note that the default configuration for ASP.NET contains an <allow users="*"> element, which authorizes all users. If no rules match, the request is allowed unless otherwise denied. If a match is found and the match is a <deny> element, it returns the 401 status code. Applications or sites can easily configure a <deny users="*"> element at the top level of their site or application to prevent this behavior. If an <allow> matches, the module does nothing and lets the request be processed further.

There is also a <location> tag that you can use to specify a particular file or directory to which settings wrapped by that tag (between <location> and </location> tags) should apply.

http://msdn.microsoft.com/en-us/library/xh507fc5(vs.71).aspx

ASP.NET Impersonation
.NET Framework 1.1 Other Versions

When using impersonation, ASP.NET applications can optionally execute with the identity of the client on whose behalf they are operating. The usual reason for doing this is to avoid dealing with authentication and authorization issues in the ASP.NET application code. Instead, you rely on Microsoft Internet Information Services (IIS) to authenticate the user and either pass an authenticated token to the ASP.NET application or, if unable to authenticate the user, pass an unauthenticated token. In either case, the ASP.NET application impersonates whichever token is received if impersonation is enabled. The ASP.NET application, now impersonating the client, then relies on the settings in the NTFS directories and files to allow it to gain access, or not. Be sure to format the server file space as NTFS, so that access permissions can be set. Impersonation is disabled by default. For ASP compatibility, the user must explicitly enable impersonation. If impersonation is enabled for a given application, ASP.NET always impersonates the access token that IIS provides to ISAPI extensions. That token can be either an authenticated user token, or the token for the anonymous user (such as IUSR_MACHINENAME). The impersonation occurs regardless of the type of authentication being used in the application. Only application code is impersonated; compilation and configuration are read as the process token. The result of the compilation is put in the "Temporary ASP.NET files" directory. The account that is being impersonated needs to have read/write access to this directory. If an application is on a universal naming convention (UNC) share, ASP.NET will always impersonate the token provided to IIS to access that share unless a configured account is used. If an explicit configured account is provided, ASP.NET will use that account in preference to the IIS UNC token. Applications that do want per-request impersonation can simply be configured to impersonate the user making the request. Impersonation is disabled at the computer level by default and, unless overridden, all the application domains inherit this setting. You can enable impersonation by putting a configuration file in the application root directory. For more information about the ASP.NET configuration system, see ASP.NET Configuration.

As is the case with other configuration directives, this directive applies hierarchically. It is respected by nested applications in the hierarchy, unless explicitly overridden. The default value for this setting is as follows.

<impersonation enable="false"/>
A minimal configuration file to enable impersonation for an application might look similar to the following example.

<!-- Web.config file. --> <identity impersonate="true"/>


There is also name support for running an application as a configurable identity. For example:

<identity impersonate="true" userName="contoso\Jane" password="pass"/>


This enables the entire application to run as contoso\Jane, regardless of the identity of the request, as long as the password is correct. This type of impersonation can be delegated to another computer. You can programmatically read the identity of the impersonated user, as shown in the following example. VB

Dim username As String = System.Security.Principal.WindowsIdentity.GetCurrent().Name [C#] String username = System.Security.Principal.WindowsIdentity.GetCurrent().Name;


In the preceding example, userName and password are stored in clear text in the configuration file. Although IIS will not transmit .config files in response to a user agent request, configuration files can be read by other means, for instance by an authenticated user with proper credentials on the domain that contains the server. To help increase security, the identity section supports storage of encrypted userName and password attributes in the registry as shown in the following example.

userName="registry:HKLM\Software\AspNetIdentity,Name" password="registry:HKLM\Software\AspNetIdentity,Password"
The portion of the string after the keyword registry and before the comma indicates the name of the registry key that ASP.NET opens. The portion after the comma contains a single string value name from which ASP.NET will read the credentials. The comma is required, and the credentials must be stored in the HKLM hive. If the configuration format is incorrect, ASP.NET will not launch the worker process and the current account creation failure code path will be followed. The credentials must be in REG_BINARY format, containing the output of a call to the Windows API function CryptProtectData. You can create the encrypted credentials and store them in the registry with the ASP.NET Set Registry console application(Aspnet_setreg.exe), which uses CryptProtectData to accomplish the encryption. To download Aspnet_setreg.exe, along with the Visual C++ source code and documentation, visit the Web site www.asp.net and search for "aspnet_setreg". You should configure access to the key storing the encrypted credentials so that access is provided only to Administrators and SYSTEM. Because the key will be read by the ASP.NET process running as SYSTEM, you should set the following permissions: Administrators:F SYSTEM:F CREATOR OWNER:F ProcessAccount:R This provides two lines of defense to protect the data:

The ACL permissions require the identity accessing the data to be an Administrator. An attacker must run code on the server (CryptUnprotectData) to recover the credentials for the account.