Securing Your Web Applications


Whether you run your Web applications on your local computer or you run them on a hosting site, you need to run your ASP.NET Web applications securely. In this section, I ll discuss various security issues that pertain to ASP.NET applications specifically and recommend strategies that you should follow to help keep your application secure.

Understanding the ASPNET Account

To run your application, users request pages from the Web site where your ASP.NET pages are located. As you know, users don t need to log in or otherwise identify themselves to browse the pages on a site that is, visitors visit the site as anonymous users. (In a few moments, I ll talk about situations where you do want people to identify themselves, but by default, visitors are anonymous users.)

In Windows, all processes need to run in a specific user context, or to put it another way, Windows always needs to know which Windows user is requesting a resource a file, memory, or any other resource. Knowing who is requesting a resource helps Windows determine whether the requestor has permission to access the file, run the program, or perform other actions requested. For example, when you log in to Windows, any program you execute runs in the context of your user account.

However, as I just said, users access a Web server anonymously. If a user visits your site and wants to run a Web page, how does Windows know whether to allow that user to read the page from disk? The answer is that when ASP.NET Web pages run, they run in the context of a special user account named ASPNET. The ASPNET user account is created on a computer automatically as part of the Microsoft .NET Framework installation process. By default, the ASPNET user account has fairly limited privileges; the account does not have administrative privileges, for example. The limited privileges of the ASPNET account help protect the Web server computer by restricting what users can do while running your Web application. For example, the ASPNET user account doesn t have permissions to read or write files in the root (C:\) of the Web server computer or to its various Windows system folders, so even if a cracker managed to take control of the Web application, the cracker wouldn t be able to write malicious information in dangerous places.

The fact that your Web applications run in the context of the ASPNET user account has implications for how you configure your applications. For example, in Chapter 8, we created a page that reads and writes a text file. We can read and write this file only because the ASPNET user account has read-write privileges on folders under inetpub\wwwroot. (More precisely, the ASPNET user account belongs to a group that has those privileges.) You might remember that in Chapter 15, in order to configure the SMTP server, I had you go to a Windows system folder and grant the ASPNET account execution privileges on the cdosys.dll file. If you hadn t granted those privileges, when the Web page tried to send e- mail messages, Windows would have examined the permission of the ASPNET user account that was running the page, determined that the ASPNET user account didn t have permission to run that DLL file, and denied access to the DLL file. The upshot, as you can imagine, is that your application wouldn t be able to send e-mail messages.

As you develop Web applications, you might stumble across other situations in which the limited permissions of the ASPNET user account prevent your application from accomplishing some tasks. From the security point of view, these limitations are good you want your application to run with the least privilege permissions possible, so that the application can t be bent to perform malicious deeds. If you do find yourself granting permissions to the ASPNET user account so that your application can accomplish a needed task, follow the general security rule that you should try to constrain those privileges as tightly as you can and still get the job done. Above all, never be tempted to make the ASPNET user account a member of the Administrators group on the Web server computer. If you do, you re giving every user who accesses your application administrative privileges, and that s asking for a lot of trouble.

Note 

Microsoft Windows .NET Server 2003 introduces many new features to enhance security, including changes in how IIS 6.0 handles requests for ASP.NET Web pages. For starters, IIS is not installed by default and ASPX pages are disabled. For more information about changes in IIS 6.0, refer to the article What s Changed at http://%20msdn.microsoft.com/library/default.asp?url=/library/en-us/iisref60/ htm/gs_whatschanged.asp. For information on enabling ASPX pages, see the topic Enabling and Disabling Dynamic Content in IIS Help, available from the Internet Services Manager.

Protecting Against Malicious User Input

In Chapters 10 and onward, I urged you never to trust any information that comes from users, whether that information is in a text box on a page, in a cookie, or in a query string. As I explained in Chapter 10, malicious users can embed HTML codes or script into a string, and if you send the malevolent string to a browser as part of a page, the script can run on the browser and wreak havoc.

I ve advised you to filter any user input by calling the Server.HtmlEncode method, which converts HTML characters from an executable format into a display format for example, <b> becomes &lt;b&gt;. Filtering user input in this manner is a reasonably effective way to normalize HTML characters. The downside of filtering, however, is that it turns all HTML characters into display characters. Under some very limited, controlled circumstances, you might want to allow users to include some HTML when they enter information into a page. A good example is the guestbook. When visitors make comments in the guestbook, perhaps they would like to add some pizzazz to their entry with simple HTML formatting such as bold and italics.

You can enable this kind of limited HTML formatting with a simple filter. The problem is that it s hard to create a filter that works well. Security experts strongly recommend that if you re going to create a filter, you create one that explicitly defines only the allowable characters. You should never write a filter that tries to identify bad input and then allows everything else through, because it s virtually impossible to anticipate every way in which malicious users can try to sneak code past the filter.

To allow some simple HTML formatting, first run the user input through the Server.HtmlEncode method, as usual. Then use the String object s Replace method (which you used in Chapter 7) to convert selected strings back into HTML. The following example shows you how to use this technique to allow bold tags (<b>, <B>) in user input. The code reads user input from a text box, converts it, and then displays it in a label.

Sub buttonFilter_Click(sender As Object, e As  EventArgs     Dim userInput As String = textUserInput.Te x     userInput = Server.HtmlEncode(userInput       Accepts <b> and </b>, case-insensitiv     userInput = userInput.Replace("&lt;b&gt;", "<b>"     userInput = userInput.Replace("&lt;/ b&gt;", "</b>"     userInput = userInput.Replace("&lt;B&gt;", "<B>"     userInput = userInput.Replace("&lt;/ B&gt;", "</B>"     labelDisplay.Text = userInpu End Sub

This filter is simple, but deliberately so. Trying to write a more complex filter that allows HTML such as anchors (<a> tags) is hard, because you need to account for the attributes for those tags. For the time being, I advise you to stick with this simplistic kind of filtering.

Note 

Version 1.1 of the .NET Framework introduces a change in how HTML filtering works. By default, the page itself checks for HTML during postback, and if the page finds any HTML in any user input, it raises an error. The change was made so as not to put the burden onto the page developer of filtering HTML out of user input. Because of this change, however, a custom filter of the type I just illustrated won t work by default; the page raises an error before your code converts the HTML. If you want to accept some HTML in user input, you can turn off page-level checking for HTML by adding the attribute ValidateRequest="False" to the @Page directive in All view. However, you should never set the ValidateRequest attribute to false unless you include your own checks for HMTL in user input.

Guarding Secrets

If your application handles user names and passwords, you probably want to hide that information from users. Sensitive information of this type is referred to generically as secrets in the security world. An entire science cryptography is devoted to the interesting problems of hiding secrets. I would love to show you an easy way to encrypt information such as passwords, but unfortunately, ASP.NET doesn t currently offer any encryption facilities accessible to people without some grounding in cryptographic procedures. However, I can offer you some general advice on guarding secrets:

  • Never keep secrets in any location that a user can easily get to. For example, never store a password in a cookie or transmit the password in a query string.

  • Avoid storing secrets in a Web page. For example, if your application requires a password, don t hard-code the password into a page so that you can compare a user s input against the password. If a cracker can get hold of the page, the secret is compromised.

  • Don t write your own encryption process. One of the reasons that secure encryption is hard is that most encryption algorithms are crackable.

User names and passwords aside, your application probably works with sensitive information more than you think. Many functions in your application routinely involve information that crackers could exploit if they knew the information. For example, your application knows the server name of the SQL Server or MSDE instance it uses and the name of a database. Server names are gold to crackers. Unfortunately, the data- access tools in Web Matrix have a bad habit of embedding information such as connection strings in your Web pages. If you re running your applications on your own site, I urge you to consider revising your data- access pages by moving connection strings outside the page. I show you one way to keep connection strings outside the page later in the appendix, in the section Accessing Databases Securely. Better yet would be to encrypt the secrets, but as I said, encrypting information in ASP.NET is not an easy task.

One way that your application might inadvertently spill some secrets is via error messages. In Chapter 13, I showed you a technique for creating a custom error message when you detected a duplicate record in a data table. An insecure way to alert the user to this problem would have been to simply display on the page whatever error information the database returned. If you pass through error information from another process, you never know what information the error might contain; it might contain information valuable to a cracker, such as the name of the table in which the error occurred. My advice on preventing errors is therefore threefold: first, anticipate problems in your application and prevent them. For example, use validator controls to avoid data that s too long or of the wrong type build your applications with the assumption that users will enter the wrong information. Second, use Try-Catch blocks liberally to maintain control over error conditions; don t let ASP.NET display an error for you. Finally, when you detect an error condition in a Catch block, filter the error information carefully and don t simply dump onto the page whatever error information happens to be handy.

Authenticating Users

By default, users visit your site anonymously, and the Web pages you ve created for this book are accessible to any user who knows the URL of the page. That s fine for most pages for example, the guestbook page from Chapter 10 is probably most useful if anyone who visits your site can make comments. However, you might create pages that you don t want just anyone to use. Among the pages you created, the pages for updating master-details tables (Chapter 13) and the calendar pages (Chapter 14) perform functions that you might want to limit to known users.

The process of identifying users is known as authentication. When you log in to your computer, for example, Windows authenticates you by checking your user name and password (that is, your credentials). In your Web applications, you might occasionally want to authenticate users as well. IIS and ASP.NET both offer various facilities for authenticating users. One authentication strategy is to use your Windows credentials; in fact, that s what Web Matrix does when you connect to MSDE to create data access in your Web pages. However, it s impractical to use Windows credentials in a public Web site, because even if visitors to your site are using Windows which they don t have to be using their browser doesn t send the users credentials to your site.

If you want to authenticate users, therefore, you need to prompt users for their credentials. If your application requires authentication, you typically keep a database table with user names and passwords. For example, you might maintain a database table named Users that has two columns a Username column that acts as the primary key and stores the user s unique name or ID, and a Password column to store the user s password. You can then create a login form as an ASP.NET Web page with text boxes for the user name and password. (You can create a Windows-style password text box by using a TextBox control and setting its TextMode property to Password.) When the user attempts to log in, you can use the user name and password to search the database table; if you get no return values from the search, the user credentials are invalid. If the user logs in successfully, you can store the user s name in a Session object so that you can check the name in other pages. The following snippet from a login page shows a simple way to check user credentials::

Sub buttonLogin_Click(sender As Object, e As E ventArgs     Dim userName = Server.HtmlEncode(textUsern ame.Text     Dim password = Server.HtmlEncode(textPassw ord.Text     Dim userDataset As System.Data.Datase     userDataset = GetUser(userName, password     If userDataset.Tables(0).Rows.Count =            Found record in database table that  matches credentials         Session("username") = userNam         labelStatus.Text = "Login successful.     Els         Session("username") = "         labelStatus.Text = "Invalid login name or password.     End I End Sub

The page contains two text boxes (textUsername and textPassword). The GetUser method is similar to the GetSlides function we created in Chapter 12. This method returns a dataset after searching a database table.

Note 

Text entered into an ASP.NET Web page, including passwords, is posted from the browser to the Web server as clear text. If the post is intercepted, the information can easily be read. If you re concerned about using clear text to send credentials, you should investigate using the Secure Sockets Layer (SSL), which allows you to use encrypted HTML protocol (https://) to exchange information between the browser and the server. Setting up SSL requires some knowledge of digital certificates and of how to configure IIS. You can find more information about setting up SSL in the Microsoft Knowledge Base article Q307267, HOW TO: Secure XML Web Services with Secure Socket Layer in Windows 2000. KnowledgeBase articles are posted on the Microsoft support Web site at http://support.microsoft.com/.

Once you have a login page, you can add a Page_Load handler to any page you want to protect from unauthenticated users. In the handler, check for a user name in the Session object. If the Session object doesn t contain a user name, you can redirect the user to the login page. Use code such as the following:

Sub Page_Loa     If Session("username") Is Nothing or Sessi on ("username") = "" The         Response.Redirect("Login.aspx"     End I End Sub

The type of authentication I ve just showed you is suitable for simple Web sites with just a few pages to protect. If you have a larger Web site with many pages to protect, you can use an ASP.NET feature named Forms authentication. Forms authentication works much like the example I just showed you, but ASP.NET manages much of the process for you. For example, you don t need to add code to each page to protect the page; ASP.NET automatically checks for credentials in every page in your application. For more information about ASP.NET Forms authentication, see the ASP.NET Quickstarts tutorial at http://samples.gotdotnet.com/quickstart/aspplus/doc/formsauth.aspx.

ASP.NET supports many more security features as well. For example, you can assign roles such as manager and guest to users of your application and allow or deny permission to users based on their roles. I don t have the room in this book to document all the security features available in ASP.NET, in IIS, and in the .NET Framework. Once again, let me recommend that if you want to learn more about security in your Web applications, you should investigate additional resources, perhaps starting with the ASP.NET site (http://www.asp.net/).

Accessing Databases Securely

Many of your applications will involve database access. You can help keep your data secure in two ways: by preventing users from executing malicious SQL statements and by guarding access to your database. Let me talk quickly about malicious SQL statements and then I ll tackle the more long-winded issue of login permissions.

An indirect way that a cracker might try to get to your site is by performing a variant of a script exploit. However, instead of entering executable HTML into a text box in a Web page, the cracker enters a malicious SQL statement, such as one that will delete all the data in a table. The idea is that your application will blindly take the cracker s input, put it into a SQL statement, and then execute the statement. (The exploit is a little more subtle than I m presenting it here, but that s the outline.) The defense against this exploit is never to create SQL statements by concatenating user input into a string that you then execute as a statement. Instead, you create parameterized SQL statements such as SELECT * FROM [Slides] WHERE slideshowname=@slideshowname and use the Parameters collection to pass values to the statement at run time. We ve followed this practice throughout the book.

A more complicated security issue is guarding access to the database. As you know, when you work with MSDE or SQL Server, you need to log in to the database server before you re allowed to work with data your login information is part of the connection string. As with Windows and your Web site, you need to guard your database so that malicious users can t steal or damage your data. The Microsoft SQL Server team recommends that if possible, you connect to MSDE or SQL Server using Windows-integrated security. That s what you do when you work in Web Matrix; you re using your Windows credentials to access the database. When your ASP.NET Web pages are running, however, they don t have your Windows credentials. Instead, as I explained earlier in the section Understanding the ASPNET Account, your pages run in the context of the ASPNET user account. If you re hosting a Web site on your computer and if MSDE or SQL Server is on the same computer as IIS, you can use Windows-integrated security and set MSDE or SQL Server permissions to allow the ASPNET user to log in to the database. I discuss how to set these permissions in Appendix B.

If your pages are running on a hosting site or if your SQL Server is on a different computer than IIS, you can t use Windows integrated security. Without Windows integrated security, you have to include explicit credentials in the connection string by setting its uid attribute to a user name and its pwd attribute to a password. (If you re copying files to a hosting site where you have access to a SQL Server, the hosting site administrator has probably sent you the connection string with the credentials you need to use.) You can probably see why including a user name and password in a connection string is not secure effectively, you re storing a secret (the user name and password) in the page, a practice I advised against earlier in the section Guarding Secrets.

Ideally, you would remove connection strings from your pages and store them in a safer location. (In your applications, you re likely to use the same connecti file is an XML file that stores various settings used by your application, such as authentication and debugging information. The file contains a section where you can keep any application-specific information that you want to be able to read at run time such as a connection string.

Caution 

Don t store any secrets in a plain TXT file. IIS and ASP.NET will render the contents of a TXT file to the browser if a user requests the file with a URL such as http://www.contoso.com/myapplication/text.txt.

To use the  Web.config file to store a connection string, in Web Matrix create a file and select  Web.Config as the type of file to create. (The file must be named  Web.config, not case sensitive.) The file opens in the code editor and consists primarily of comments. Look for the section named <appSettings> and uncomment the section by moving the end comment marker (-->) from below the <appSettings> section to above the <appSettings> section. You can see that the <appSettings> element already contains an <add> element whose key attribute value is connectionstring. Like cookies and the Session object, the <appSettings> element can contain multiple values under different names. Change the connection string in the value attribute to the connection string you use. Save the  Web.config file.

In your Web pages, read the connection string from the  Web.config file using code like this:

Dim connectionString As Strin connectionString =      ConfigurationSettings.AppSettings("connect ionString" sqlDataSourceControl1.ConnectionString = conne ctionString 

In other words, call the AppSettings method of the ConfigurationSettings object to read the connection string and then assign the connection string to the connection object in code. The practice of moving connection strings out of pages and storing them elsewhere offers a small measure of protection, but only some. The connection string is still stored as an unencrypted string, but at least ASP.NET protects the  Web.config file somewhat by refusing to send it to a browser if a cracker requests the file in a URL.




Microsoft ASP. NET Web Matrix Starter Kit
Microsoft ASP.NET Web Matrix Starter Kit (Bpg-Other)
ISBN: 0735618569
EAN: 2147483647
Year: 2003
Pages: 169
Authors: Mike Pope
BUY ON AMAZON

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net