Team LiB
Previous Section Next Section

Security

Security issues can take a whole book in their own right. Here we will try to cover some of the main issues you need to be aware of when you design an enterprise application. The following is based on the security guidelines from Microsoft, and the complete guidelines can be found at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/THCMCh04.asp.

Security issues can be divided into three different areas. The first is securing the network. The second involves securing the hosts for your application. The last block deals with securing the application itself. The measures you take to secure your information can also be divided into four categories:

The first category is the critical information you try to secure.

The second category is the physical protection you implement. To strengthen any security weaknesses you might have missed in your system, you should always start with your hardware. Reduce the number of open ports in the firewall and verify that the firewall is correctly configured.

The third category is the operating system. After you have made it more difficult to sneak into the system by "hardening" the physical environment, you will make it even harder for an intruder to invade your system if you clean up the operating system on your servers. The first step is to reduce the number of administration accounts on the Web server and the application server. Do not allow anonymous access to the Web server

The fourth category involves information access. Before you give someone access to data, you need to be sure that person is authenticated, authorized, and audited. A simple and effective way to prevent unauthorized persons from accessing the system via a computer that has been left wide open is to verify that all clients in the system actually have screen savers that automatically lock the client computers when they have not been used for a while.

A Web-based application has many different points where attacks may occur. The browser needs to authenticate users. When the browser has authenticated a user, the communication between the browser and the server needs to be secured. You need to be able to protect the communication and its data from being altered, and the communication itself from being hijacked or used in a replay attack.

When information has passed the first firewall and entered the Web server (see Figure 5-23), you need to be able to secure the configuration so no unauthenticated person on the server will be able to see important configuration strings. You also need to take care of exceptions and interpolate error messages before you send them back to the user, mainly for helping the user, but also to hide stack traces and other important information a hacker can use to get information about your system.

Click To expand
Figure 5-23: The different security issues that need to be handled

Authentication

Authentication is the process of determining caller identity. When implementing authentication, you need to consider a few things:

The first is that you need to identify where you want to use authentication. In general, you need to perform authentication when a trust boundary is crossed— such boundaries usually consist of assemblies, processes, and machines.

When you have identified where you need authentication, you must validate who the caller is to be able to authenticate him or her. The normal way is that the user authenticates him- or herself by giving you a username and password. The validation is not a "one time thing"—you need to do it every time a user comes back and requests information from your application. This requires some form of authentication token.

The most common approach to authenticating users in a Web-based application is to use the form authentication support found in ASP.NET. There you ask the user to supply you with a username and password in an HTML form. To make this secure, you cannot use the standard HTTP protocol, since it is wide open for anyone who knows how to monitor network packages. The solution here is to secure the communication by using HTTPS and SSL.

Another threat to the credentials for users is the storage of their information in your server. You need to ensure that no one can read usernames and passwords in plain text on your server. Therefore, you encrypt and hash your user credentials in the database to prevent Dirty Harry, who is serving out his last day at your company, from dumping the user table to a file and taking it with him.

Okay, now you are using SSL to secure the communication channel from the Web form into your server. You have also encrypted the user credentials in your database—but how are the credentials verified against the input from the user? If you only intend to verify that the user knows the password value, you do not need to store the actual password in your database. Instead you can calculate a hash value in the database and recalculate the hash using the supplied information from the user during the logon process.

The user has been authenticated and seems to know the right password, but how do you authenticate the user next time he or she requests some information from your enterprise application? You do not want to bring up the login page every time a user tries to add a new line to the current time report, right? Normally you give the user some kind of authentication ticket—for example, an authentication cookie. This cookie is sent to the user via some kind of transport protocol. If you are using HTTP, this makes your system wide open for a hacker to retrieve information from, or "tap," the cookie, and use it for his or her own purposes.

To make it more difficult for anyone to tap your enterprise application for important data, you try to "harden" the security on the Web server and the application server as mentioned previously.

The first step is to log any login failure that occurs in your enterprise application. When the user has entered the wrong password x times, you disable the user account automatically to prevent any further attacks and inform the administrator. (It might be a valid, possibly disoriented, user who has entered the wrong password three times, in which case he or she just needs to call the administrator to unlock the account.)

The operating system will take care of this disabling automatically for you if you are using Windows authentication, such as NTLM or the Kerberos Protocol. In the example application in Chapter 9 where we use form authentication, we handle these policies in the application.

Note 

If you are using this approach, you need to be sure that important accounts like IUSR_MACHINENAME are not locked out because of a denial-of-service attack. Try to use other accounts instead of the IUSR_MACHINENAME account.

The second step is to ensure that no password will last forever. Passwords should expire on a regular basis, and a dictionary of the last five passwords for a particular user should be created so none of the last five passwords can be used when it is time for the user to change his or her password. Unfortunately, people are lazy by nature, and we have seen many change their passwords by bumping up an appended numeral; for example, the password mysecretpassword1 is changed to mysecretpassword2, and so on—not so difficult to figure out. A good approach is to also enlighten users about security issues before an application is delivered to try to lift the security level a little bit. (How many of you have a screensaver that is password protected and is turned on after a couple of minutes of inactivity?)

Normally an enterprise application might have different areas with different levels of access. Some areas may be accessed anonymously, whereas other areas require authentication. It can be wise to portion the site into a public area and a restricted area to make it easier to maintain and to avoid the performance overhead with SSL for the restricted area. A good rule of thumb is to limit the use of SSL because it takes a lot out of your system's performance. For instance, do not run a whole retail application under SSL; let the anonymous users browse the products, but as soon as they would like to add stuff to the shopping chart, require authentication via a secure transport protocol.

Require Strong Passwords

We have already shown the "increment example" of old passwords by lazy people. Try to teach users to use strong passwords, which have a minimum of eight characters with at least one number in it. We recently ran a brute-force hack tool on one domain controller—it took about two hours to crack the administration password for the machine. Do not make it easy for attackers to crack passwords. Many guidelines are available on the Internet for creating strong passwords.

Do Not Send Passwords over the Wire in Plain Text

Even if you are using strong passwords, you need to secure the communication channel when you send passwords over the network to prevent hackers from tapping passwords out of a message. You can, for instance, use SSL to encrypt the communication, or for SOAP messages, the WSE toolkit.

Protect Authentication Cookies

Protect authentication tickets using encryption and secure the communication channels. Also limit the time interval in which the authentication ticket remains valid, to reduce the chances of a hacker decrypting the message and using the authentication cookie. Reducing the cookie timeout does not prevent replay attacks, but it does limit the amount of time the attacker has to access the site using the stolen cookie.

Input Validation

Input validation is of great importance to your enterprise application to prevent malicious data from entering the system. It is also one of your strongest defenses against application attacks. Proper input validation can easily prevent hackers from doing SQL injection, buffer overflows, and other input attacks. Input validation is challenging because it differs among applications and even within an application itself.

Do Not Trust Input Until Proven Safe

The best way to prevent your application from input hacking is to assume that all input is malicious until proven otherwise, and that the input needs to be verified not once but twice no matter where it comes from.

Centralize Your Validation

To make validation efficient and be able to change it easily and quickly when bugs and new requirements appear, centralize the validation code in the enterprise application. Put the validation code in shared assemblies to be able to reuse them from the whole application. This ensures that you are using the same validation rules everywhere, and no missed validation somewhere could possibly let malicious input in.

Do Not Rely Entirely on Client-Side Validation

You need to capture invalid data as soon as possible to avoid extra round-trips to the server and/or between the different processes on the server side. However, you cannot entirely rely on client-side validation—even if it is easy and quite fancy to use the validation controls in a Web application. The reason you cannot trust the validation on the client side is because the validation controls are using client scripts to do their validation in the browser. A hacker may turn off the support of client scripts, and thereby bypass your validation! In our example application later in this book, and in the proposed enterprise architecture, we include both client-side validation (to reduce the number of round-trips to the server) and server-side validation (to prevent the aforementioned types of attacks).

Constrain Input and Reject Data

The preferred approach to validating input is to constrain what you allow from the beginning. It is easier and safer to validate data from specific known valid types and ranges than to validate unspecified data. When you design your enterprise application, you normally know the range and the type of data that can be entered by the users. Everything that does not fit into your defined types, lengths, formats, and ranges is rejected as bad data. For instance, you should use stored procedures for fetching and sending data to the database instead of building the update or insert query based on the user's input.

Identification numbers, post office boxes, and zip codes are data that can easily be verified as correct or not. The length of string fields should also be checked, since there will normally be a maximum length for string fields that can be stored in the database. Rejecting "bad" data is in general less effective than checking for valid data. This is due to valid data seldom changing, whereas the "bad" data may change over time.


Team LiB
Previous Section Next Section