By Robert L. Bogue
Cookies offer an excellent way to keep small bits of information about the user readily available so that they don't have to be looked up again. They can allow you to keep users' numeric IDs handy instead of their logon names, which makes getting back to their security and authorization easier and quicker. However, cookies represent a dangerous risk: Users may choose to tamper with the information and see what havoc it might cause.
Cookies and persistence
A cookie is a small amount of data that defines state information for the user that the Web browser can return upon request to help the Web server know more about the user. This can greatly improve performance for many transactions. Since the user can provide the necessary keys to information stored in the site's data repositories (such as SQL server databases), lookups for menus, navigation, etc., are much quicker and require less system resources. Ultimately this helps to improve a site's speed.
There are two basic types of cookies: persistent and nonpersistent. Persistent cookies are available across sessions in the browser. They're stored as text files on the client computer after the user exits a site and closes the browser. Nonpersistent cookies are the same small bits of data, but they are never stored to the user's hard drive—at least not in most browser implementations.
There's no guarantee that every browser will keep nonpersistent cookies in memory. It's just that most browsers choose not to write nonpersistent cookies to disk.
Risks of cookie tampering
To understand how using cookies can create huge security risks, consider a site that stores the user's ID in a database in a cookie. The cookie is persistent, and the site never validates the information in the cookie. It's assumed to be correct. The user goes to the site and logs in. He or she looks at the cookie file and determines that only an ID is being stored in it. The user resets the number in the file to 1 and logs back into the site.
For most sites, the super user is the first ID inserted into the database, and it's usually never disabled. If the site doesn't validate the value from the cookie, the user has become a complete administrator with a trivial amount of text editing. Any unchecked information placed in a cookie can represent a potential security problem.
The key to using cookies safely is to know when you need to verify the information in them. You might not always need to verify the user's information. For instance, you could use the information in a cookie to display navigation information. However, you shouldn't blindly use information from a cookie to allow users access to a page.
One way to make it more difficult for someone to hack into a cookie is to encourage browsers not to write them to disk by setting them not to persist. But this doesn't make them completely hacker-proof—it just makes the task more difficult for the hacker. There is another challenge with setting cookies not to persist in ASP.NET: The technology provides no direct way of controlling whether a cookie will be persisted. By default, cookies added to the Response.Cookies collection will be persisted to disk.
The best way to guarantee that a cookie is not tampered with is to encrypt it. By encrypting the data in a cookie, you simultaneously make it unintelligible to the user and build in a way to detect tampering. A cookie that has been tampered with will not decrypt, so you can be assured that the cookie data is valid.
To encrypt a cookie, you must first decide upon an algorithm and a key. Because the Web application both creates and consumes the cookies, the traditional problem of using symmetric encryption—having to share the key securely—is not necessary. Because of the additional overhead and size of an asymmetric encryption, a symmetric encryption method is a good choice for encrypting cookies. It's fast and lightweight and can be executed quickly.
Listing A shows a process for adding an encrypted cookie. This listing uses the Triple DES algorithm for encryption because of its general widespread acceptance. But because generating sound keys is difficult, this routine takes a string of arbitrary length and converts it into a hash. The hash is used as the key to the encryption. In a production application you would convert this hash one time. Decrypting the key is similar to encrypting the key, as shown in Listing B.
Changing the cookie key
The preceding approach works great if you select and keep one cookie key forever. If your users tamper with the cookie, you'll get an error thrown and you'll know about the tampering right away. However, it does limit you to the one key.
An alternative strategy is to write two cookies. The first is an identifier indicating which cookie key is being used, and the second is the actual encrypted value. On the decryption side, the cookie key identifier retrieves the cookie key from a database so that it can decrypt the value. This allows for different secret keys to be used in the creation of cookies. By storing an identifier with the cookie key in the database, you can invalidate any cookie that uses a key that may have been compromised without accidentally tripping logic designed to capture those who tamper with cookies.