Understanding Web Security

At the application level, Web security is first and foremost about securing pages so that they can鈥檛 be retrieved by unauthorized users鈥攆or example, preventing nonmanagers from viewing pages containing salary data and performance evaluations on the company intranet or preventing other people from viewing your My eBay pages. At a slightly deeper level, you might want to know who requested a page so that you can personalize it for that individual. Either form of protection requires two overt actions on the part of the application:

A Web server identifies callers using a mechanism known as authentication. Once a caller is identified, authorization determines which pages that caller is allowed to view. ASP.NET supports a variety of authentication and authorization models. Understanding the options that are available and how they interrelate is an important first step in designing a site that restricts access to some or all of its resources or that personalizes content for individual users.

Authentication

Authentication enables the recipient of a request to ascertain the caller鈥檚 identity. The caller might claim to be Bob, but you don鈥檛 know he鈥檚 Bob unless you authenticate him. ASP.NET supports three types of authentication:

When Windows authentication is selected, ASP.NET looks to IIS for help. IIS does the hard part by authenticating the caller. Then it makes the caller鈥檚 identity available to ASP.NET. Let鈥檚 say Windows authentication is enabled and Bob requests an ASPX file. IIS authenticates Bob and forwards the request to ASP.NET along with an access token identifying Bob. ASP.NET uses the token to make sure Bob has permission to retrieve the page he requested. ASP.NET also makes the token available to the application that handles the request so that at its discretion, the application can impersonate Bob鈥攖hat is, temporarily assume Bob鈥檚 identity鈥攖o prevent code executed within the request from accessing resources that Bob lacks permission to access.

For Web applications, Windows authentication is typically used in the following scenarios:

The overarching goal of Windows authentication is to map incoming requests to user accounts on your Web server (or in the Web server鈥檚 domain). In addition to preventing users who lack the proper login credentials from accessing parts of your site that require authenticated access, Windows authentication lets you use the operating system鈥檚 built-in security mechanisms to protect files and other resources from unauthorized access by authenticated users.

Passport authentication relies on Microsoft Passport to authenticate users. Passport is a Web service that serves as a front end to a massive database of user names and passwords maintained by Microsoft. Users who register with Passport can be authenticated anywhere on the Internet by applications that present login credentials to Passport. If Passport determines that the credentials are valid, it returns an authentication ticket that the application can encode in a cookie to prevent the user from having to log in time and time again. Further information about Passport can be found in the Passport SDK, which you can download for no charge from Microsoft鈥檚 Web site.

Forms authentication relies on login forms in Web pages to authenticate users. Figure 10-1 shows an example of forms authentication in action on eBay. You can surf most of eBay鈥檚 site without logging in, but to bid on an item or go to My eBay, you have to enter a user name and password to let eBay know who you are. Windows authentication isn鈥檛 very practical in this scenario because eBay doesn鈥檛 want to assign each of its millions of users a Windows account on its servers. Forms authentication fits the bill nicely because it doesn鈥檛 require users to have Windows accounts. It鈥檚 perfect for Internet sites designed to serve the general population but that have to know who a user is before allowing him or her access to certain pages. Forms authentication is as old as the Web, but ASP.NET makes it incredibly easy. You鈥檒l see what I mean later in this chapter.

Figure 10-1
eBay login form.

You tell ASP.NET what type of authentication, if any, to use through Web.config files. The following Web.config file enables forms authentication for the corresponding application:

<configuration>
聽聽<system.web>
聽聽聽聽<authentication聽mode="Forms" />
聽聽</system.web>
</configuration>

Other valid mode values include None, Windows, and Passport. The default, defined in Machine.config, is Windows. The authentication mode is an application-wide setting that can be set only in the application root and can鈥檛 be overridden in subordinate Web.config files. You can鈥檛 use Windows authentication in one part of an application and forms authentication in another.

Authorization

Authentication is an important element of Web security鈥攊ndeed, of network security in general鈥攂ecause it establishes trust. You can鈥檛 trust a user if you don鈥檛 know who he or she is.

Authorization is the other half of the security equation. Once you know who a user is, authorization determines what resources that person can access. On a company intranet, for example, you might want to prevent rank-and-file employees from accessing files and directories containing payroll data. That鈥檚 what authorization is for. ASP.NET supports two forms of authorization:

ACL authorization is based on file system permissions. Most Web servers that run IIS and ASP.NET use the NTFS file system. NTFS uses ACLs to protect file system resources鈥攖hat is, files and directories. It鈥檚 trivial, for example, to tag a file with an ACL that permits only system administrators to read it. You simply pop up the file鈥檚 property sheet, go to the Security page, remove the security principals (users and groups) that are currently listed, and add administrators. If you don鈥檛 want Bob to view a particular ASPX file, you can deny Bob read access to the file in an ACL and Bob will be greeted with an access denied error when he tries to view the page. Because ACL checks are performed against access tokens representing Windows security principals, ACL authorization is typically used in scenarios in which Windows authentication is used too.

URL authorization works differently. Rather than rely on NTFS permissions to protect resources, it relies on configuration directives in Web.config files. URL authorization is wholly a function of ASP.NET and does not require the complicity of IIS. It鈥檚 most often used with forms authentication, but it can be used with other authentication types as well.

IIS Security

IIS is a Web server. Its primary job is to accept connections from remote clients and respond to HTTP requests arriving through those connections. Most of the requests are HTTP GET and POST commands requesting HTML files, JPEG files, ASPX files, and other file system resources. Obviously, you don鈥檛 want someone who connects to your Web server to be able to retrieve just any file that resides there. IIS protects a server鈥檚 content in four ways:

All of these protection mechanisms are important to ASP.NET programmers, but item number 2 merits special consideration because ACL checks are entirely dependent upon the identity assigned to a request, and when Windows authentication is the chosen form of authentication, ASP.NET works closely with IIS to resolve issues involving identity.

IIS runs in a process named Inetinfo.exe. Inetinfo.exe typically runs using the identity of the built-in SYSTEM account, which is highly privileged on the host machine. Requests forwarded to ASP.NET by IIS don鈥檛 run as SYSTEM, however. They鈥檙e assigned the identity of a specific user. Which user depends on the configuration of the requested resource.

Through the IIS configuration manager found under Administrative Tools, IIS permits authentication control to be applied to individual files and directories. A given file or directory can be configured to allow anonymous access (access by unauthenticated users), authenticated access, or both. Let鈥檚 say a request comes in for a file that allows anonymous access. By default, the request executes as IUSR_machinename, where machinename is the Web server鈥檚 machine name. IUSR_machinename is a special account that鈥檚 created when IIS is installed. You can use the IIS configuration manager to map anonymous requests to other accounts, but assuming you don鈥檛 change the defaults, requests from anonymous users are tagged with IUSR_machinename鈥檚 access token. It follows that Web pages intended for anonymous users should not be tagged with ACLs that deny access to IUSR_machinename.

If, on the other hand, the requested file requires authenticated access, IIS assigns the request the identity of the account whose credentials the requestor supplies. If the user is Bob and can prove as much to IIS, then the request is tagged with Bob鈥檚 access token.

How does IIS ascertain a requestor鈥檚 identity for authenticated accesses? How, for example, does it know that Bob is Bob? It depends on the type of authentication used. IIS supports four different forms of authentication. As far as ASP.NET is concerned, all four fall under the category of Windows authentication:

Basic and digest authentication rely on user names and passwords to authenticate users. When the client is a browser, the browser prompts the user for a user name and password and transmits them to the Web server. Basic and digest authentication work well over the Internet because they piggyback on HTTP. Integrated Windows authentication uses Windows login credentials to authenticate users. It鈥檚 ill-suited to general Internet use, in part because both client and server must support Windows security protocols, and also because the client must validate against a domain controller that it can鈥檛 get to through a firewall. SSL client certificates are also limited primarily to intranet use because they require clients to be outfitted with digital certificates.

ASP.NET Security

Figure 10-2 diagrams the relationship between IIS and ASP.NET. When IIS receives a request for a file registered to ASP.NET (for example, an ASPX file), it hands off the request to an ISAPI DLL named Aspnet_isapi.dll. Aspnet_isapi.dll runs in the same process as IIS鈥攖hat is, inside Inetinfo.exe. ASP.NET applications run in a separate process named Aspnet_wp.exe. Aspnet_isapi.dll forwards requests to Aspnet_wp.exe using a named pipe. When the request reaches the worker process, it is assigned to a specific application executing in a specific application domain. Once inside an application domain, the request travels through ASP.NET鈥檚 HTTP pipeline, where it is examined by various HTTP modules and ultimately processed by the HTTP handler that corresponds to the resource type requested. Machine.config contains the master list that maps file types to HTTP handlers.

Figure 10-2
The relationship between IIS and ASP.NET.

The architecture shown in Figure 10-2 changes somewhat when ASP.NET is paired with IIS 6.0. Slated for release in 2002, IIS 6.0 features a more robust security model that gives IIS administrators the ability to segregate applications into surrogate processes that are very much like Aspnet_wp.exe. In IIS 6.0, there is no Aspnet_wp.exe; instead, IIS provides the worker process. At the time of this writing, Microsoft planned to connect Inetinfo.exe to worker processes using local procedures calls (LPCs) rather than named pipes.

What does all this have to do with security? When Aspnet_isapi.dll forwards an HTTP request to Aspnet_wp.exe, it also forwards the access token that it obtained from IIS. That access token is typically one of the following:

Before processing the request by sending it through the targeted application鈥檚 HTTP pipeline, Aspnet_wp.exe does the following:

The importance of these actions cannot be overstated. The ACL check that ASP.NET performs before processing the request means that you can deny Bob access to an ASPX file simply by tagging that file with an ACL that denies Bob read access. The fact that ASP.NET makes the caller鈥檚 access token available for impersonation purposes means you, the developer, have some latitude in deciding which identity to use when processing the request. The right choice depends on what the application is designed to do and how it鈥檚 designed to do it. Here鈥檚 some background to enrich your understanding.

By default, Aspnet_wp.exe runs as ASPNET, a special account that鈥檚 set up when ASP.NET is installed. ASPNET is a member of the Users group, so it鈥檚 privileged enough to perform most of the actions a legitimate application might want to perform, but it is restricted enough to prevent certain kinds of attacks. Unless you specify otherwise, requests executed by ASP.NET use Aspnet_wp.exe鈥檚 identity. Therefore, by default, requests run as ASPNET. Among other things, this means that, barring configuration changes, an ASP.NET application can鈥檛 perform certain actions, such as modifying entries in the HKEY_LOCAL_MACHINE section of the registry.

The other option is to execute the request using the access token provided by IIS, a technique known as impersonation. Impersonation is enabled by including the following statement in the system.web section of a top-level Web.config file or modifying the identity element already present in Machine.config:

<identity聽impersonate="true" />

If IIS assigns a request the identity IUSR_machinename, impersonation won鈥檛 buy you much because IUSR_machinename is a weak account that enjoys few privileges on the host machine. But if Windows authentication is enabled and IIS presents ASP.NET with a token representing the actual requestor, impersonation ensures that the application can鈥檛 do anything on the Web server that the requestor isn鈥檛 allowed to do.

To further complicate matters, Aspnet_wp.exe can be configured to run as a principal other than ASPNET. Suppose you write an ASP.NET application that must have wider-ranging permissions than those afforded ASPNET鈥攆or example, the freedom to write to any part of the registry. You can configure Aspnet_wp.exe to run as SYSTEM by changing the statement

<processModel聽userName="machine" ...聽/>

in Machine.config to read

<processModel聽userName="SYSTEM" ...聽/>

This change enables your application to do almost anything it wants on the host machine, but it also makes ASP.NET less resistant to attacks. SYSTEM was the default when ASP.NET was in beta, but that was changed shortly before the product shipped.

Another possible complication arises from the fact that in IIS 6.0, ASP.NET requests will default to Network Service rather than ASPNET. If you use ACLs to allow access to the ASPNET account while denying access to other security principals and find that requests mysteriously fail with access denied errors after you install IIS 6.0, modify your ACLs to allow access to Network Service rather than ASPNET.

Clearly, the identities assigned to the ASP.NET worker process and to the requests that it executes play crucial roles in determining how successful an application is in carrying out its appointed mission. If your head is spinning right now trying to make sense of it all, don鈥檛 fret; ASP.NET security will be far easier to grasp once you鈥檝e experienced it first-hand. In the meantime, here are some guidelines to help you sort through the options and figure out which of them really matter for a given deployment scenario:

A final thought to keep in mind is that if you use ACLs to limit access to directories in an ASP.NET application, always grant the ASPNET account鈥攐r whatever account Aspnet_wp.exe runs as鈥攔ead access to them. Otherwise, ASP.NET itself will be unable to retrieve files from the directories and you鈥檒l experience all kinds of access denied errors that you probably didn鈥檛 expect.