As Web services increase in complexity and connectivity, security is growing as a major concern. Many security breaches have been the result of poorly tested software that allows unexpected inputs to pass and weaken security measures. Such inputs can create conditions in which intruders can obtain access to parts of the system that would otherwise be secure. One effective way for development teams to prevent unexpected inputs is to perform thorough white-box testing at the unit level. Unlike specification testing (which tests that code behaves as it was intended), white-box testing checks for the conditions and inputs that are not expected, thereby enabling developers to more thoroughly test for what they cannot foresee. By performing such testing at the unit level, developers can quickly and easily identify and correct any weaknesses before security breaches have the opportunity to occur.
Web service security is much more critical and complicated than most people in the industry seem to realize. Most of the current security discussions address identity authentication and message exchange privacy. These are undoubtedly critical security issues, but solving these problems will not guarantee security. In fact, I expect lack of security to remain a huge menace even after these authentication and privacy issues are solved. Why? Because Web services' fundamental architecture opens the door for serious security breaches. Anyone who passes a Web service's first layer of defense can reach the parts of your application you made available, but also might be able to access and manipulate parts that you thought were private. Fortunately, practices such as unit testing can help you create a multilayer defense which prevents authorized visitors from performing unauthorized actions.
Establishing the First Layer of Defense
Most current discussions of Web service security focus on the mechanics of the following fundamental security issues:
- Privacy: For many services, it is important that messages are not visible to anyone except the two parties involved. This means traffic will need to be encrypted so that machines in the middle cannot read the messages.
- Message Integrity: This provides assurance that the message received has not been tampered with during transit.
- Authentication: This provides assurance that the message actually originated at the source from which it claims to have originated. You might need to not only authenticate a message, but also prove the message origin to others.
- Authorization: Clients should only be allowed to access services they are authorized to access. Authorization requires authentication because without authentication, hostile parties can masquerade as users with the desired access.
For a detailed discussion of these issues, see the article I wrote with Jim Clune, "Security Issues with SOAP," Crosstalk, July 2002.
By dealing with these four fundamental security issues in whatever manner makes most sense for your Web service, you will establish a critical first line of defense against security breaches. If you don't have at least this layer of defense, your Web service (and all of the data that passes through it) will be wide open to anyone who wants to access and manipulate it.
Understanding the Potential for Danger
The very nature of Web services provides clients who pass the first layer of defense with unprecedented access to the system's inner parts. While other types of applications have executables that act as a skin that covers and protects the application's inner functionality, Web services peel back this skin and actually expose the system's inner functionality to outside Web service clients. This is done by providing a public interface through which clients can invoke the service's methods. However, through this interface, clients can access and manipulate not only the exposed methods, but also any part of the application that can be accessed from the exposed methods.
If it's possible to wreak havoc on your system by executing methods anywhere within your Web service, you'd better be 100 percent certain that clients cannot reach these methods through the designated service entry points. Often, unexpected paths through an application provide clients access to areas that you thought were private. If the service is implemented in C or C++, these unexpected paths can stem from obvious sources such as buffer overrides or general data corruption. However, even "safer" languages such as Java can be tricked into providing unexpected access to supposedly private methods.