Best Practices for Secure Web Development
Surprise, surprise. Until the past year or so, security and business did not often come together in the same paragraph.
Well, it shouldn't be a surprise because ultimately, security is not about technology but about managing risk. Security is present in Internet projects precisely because it's needed to mitigate some risks. Any business has some assets to protect, and in the Internet world, it's the information assets we are concerned with. Examples of assets are: integrity of the site content, site availability, data privacy, trust. As you can see, not all assets are physical.
Once the assets are identified, the next step is to identify the risks. If we look at the example above, we can quickly derive some risks associated with the enumerated assets: site defacement (the integrity is lost), sites brought down (remember the DDoS attacks?), customer data published on the Web (credit card info is a typical example), or transactions made with the wrong party.
Now, with the risks clearly spelled out, thinking of what security measures must be used becomes an easier task, which brings us to the next step:
Security as Part of Requirements Gathering
This stage is not specific to security, but a normal step in building any project. The security would come into place for the following topics:
Identifying the assets.
Use cases. How the application will be used is essential for understanding the security implications.
Identifying the users, their roles and rights. Again, this goes straight to designing the authentication and authorization schemes.
Legal and business issues: Support for nonrepudiation? An audit trail? Digital signatures? (If so, what is their legal status in the countries/states/provinces where the customers are?) Strong encryption? (Fortunately, the last months have seen a relaxation of export regulations, but it's still worth checking.)
Security as Part of the Architecture
As with any other item in the requirements list, the first place to address them is at the architectural level. Most of the professionals who have been in the software industry for a couple of years have seen what happened with projects with poor or missing architecture: scrambling teams trying to patch the system so it provides the desired functionality or performance; unscalable applications; lost money and time.
In a parallel with the items under the requirements section, the security architecture will focus on:
Protective measures around the assets: permissions, logins, encryption, etc.
Possibilities to abuse the use cases (this includes thinking of malicious use cases).
Selecting the platform and technologies that support the users, roles and access rights. This includes choosing an operating system, the Web server, an application server if applicable, the directory service when a large number of users is concerned, a user authentication mechanism (anonymous, cookie, basic, challenge response, digest, certificate-based), the authentication mechanism between the different application tiers, and so on. Certainly, the decisions are not made solely from the security standpoint, but this is the role of the architect: To take in all the application requirements and find the best possible solution within the constraints.
Watch What You Use
The security of the entire application is dependent on all constituent parts. It is not enough for only the OS and the Web server to be secure; all exposed services must be so. What this boils down to is that if you integrate another product into the Web application - such as streaming media or a chat server or any piece someone could connect to, directly or indirectly - you need to understand the risks the new piece adds.
We mentioned the streaming or chat servers because they are becoming more common these days. If these servers can be compromised (e.g., via a classic buffer overflow attack), then the entire application will be as well. Now, hosting a streaming server on the same machine as the main Web server is not a good idea when you take performance into account, but even if the machines are different but located on the same network segment, a sniffer installed on the compromised server can gather data from the other, non-compromised machines.
The same principle applies for the main server as well. I prefer to use a server that had security problems in the past which have been fixed (naturally) than to use an unknown product that has no reported vulnerabilities. No news doesn't necessarily mean good news - it can simply indicate that no one bothered to really test the server, or if someone did, it hasn't been made public.
If time is on your side, you can try to evaluate the product's resilience to malicious attacks by using tools (commercial or crafted by yourself) or by reviewing the code (for open source software).
Never Trust Incoming Data. Never.
You've got to be paranoid if you want to build the application securely. One strategy is to only rely on what you control, and even then, doubt yourself. We cannot control what comes from the client's browser (even if we think it comes "back"). Therefore, we must validate everything. Now, in the real world, this level of distrust has various degrees. For instance, it will probably be higher for an Internet site compared to an intranet. Or it will be higher when the stakes are higher, such as with ecommerce sites.
When Possible, Help the User
The strength of a chain is as good as its weakest link, and in practice, the human user is often the weakest. We cannot completely fix this with code, but we can help the user make better decisions. Perhaps the most typical example is when the user is asked to choose a password. Don't put meaningless limits on them (such as a small length), and consider using password strength validators.
This isn't the only possible application of this recommendation. Help users understand the various settings or decisions they are prompted for which have security implications. A message such as "Do you want to allow this ActiveX object to run?" would not tell much to someone having no idea what ActiveX could be. By providing an explanation about the risks ("selecting yes may allow malicious actions to take place") and by preselecting safe (not necessarily convenient!) default values, we can go a long way in preventing problems.
Code Reviews Are Your Friends
There is no better tool in your arsenal in your search for security holes than a code and architecture review done by trained eyes (the more the better). For serious applications, you should have code reviews anyway; so here is a great opportunity to add the security review in. This isn't the place to discuss how reviews should be done, though, so we'll leave this item this short.
Privacy & Law
Depending on where in the world you live, the Internet may not be near as unregulated as it was some years ago - or, if not the Internet itself, the actions you can use it for, no matter what side of the server you are on.
This section cannot possibly cover the entire span of computer and Internet law. We will focus on what would matter from an application development standpoint, and not on monitoring, protecting from and reacting to intrusions.
Perhaps the most important issue that comes up is the collection and handling of private data. The advent of stricter privacy laws makes it an early requirement to identify how customer data will be stored and used on the application side.
For sites having European customers, make sure you check the Data Protection Act.
If you plan to use encryption, Bert-Jaap Koops' Crypto Law Survey may prove helpful. http://cwis.kub.nl/~frw/people/koops/lawsurvy.htm
Stay Up to Date!
Security is a changing world, and keeping abreast of the developments is a must. Granted, not all vulnerabilities are within the scope of this document (application security), but new ways to exploit a Web application are found often enough that subscribing to the vendor's bulletins and to the relevant mailing lists becomes a necessity.
Document, Document, Document!
The most wonderful security solution is of little value if everything is in its designer's mind. As Bruce Schneier likes to say, "Security is a process, not a product." A process includes the ability of being repeatable, and how to ensure correct repeatability unless the steps are documented.
What to include in the documentation? Perhaps the best answer would be anything that you need in order to maintain the same level of security if the system is changed (updated, rebuilt, etc.). For an Internet-based application, this means documenting the server and application settings, resource permissions, what the sensitive resources are, and, quite important, how to do things the appropriate way. Imagine that for some reason some operations are performed by someone less familiar with the application (say, during vacation time). It's likely that that person will not have time to read and understand all processes to follow. Help your teammates.
Note: This is the first in a two-part series. Check back Friday for an in-depth, technical look at all the fundamentals described here.
The author would like to thank the following people: Jesús López de Aguileta, Vittal Aithal, Toby Barrick, Gunther Birzniek, Matt Curtin, Dig Dug, Tiago Pascoal, Dimitrios, Petropoulos, Steve Posick, Dave Rogers, Kurt Seifried, David Spinks, David A. Wheeler, David Woods and Greg A. Woods.
The reader is encouraged to consult two excellent documents:
David A. Wheeler's Secure Programming for Linux and Unix HOWTO
Lincoln D. Stein's The World Wide Web Security FAQ
SecurityPortal is the world's foremost on-line resource and services provider for companies and individuals concerned about protecting their information systems and networks.
Th e Focal Point for Security on the Net (tm)