| CONTENTS | PREV | NEXT | INDEX | J2EE BluePrints |
In a distributed computing system, a significant amount of information is transmitted through networks in the form of messages. Message content is subject to three main types of attacks. Messages might be intercepted and modified for the purpose of changing the affects they have on their recipients. Messages might be captured and reused one or more times for the benefit of another party. Messages might be monitored by an eavesdropper in an effort to capture information that would not otherwise be available. Such attacks can be minimized by using integrity and confidentiality mechanisms.
Integrity mechanisms ensure that communication between entities is not being tampered with by another party, especially one that can intercept and modify their communications. Integrity mechanisms can also be used to ensure that messages can only be used once.
Message integrity is ensured by attaching a message signature to a message. The message signature is calculated by using a one-way hash algorithm to convert the message contents into a typically smaller, fixed length message digest that is then signed (that is, cryptographically enciphered, typically using a public key mechanism). A message signature ensures that modification of the message by anyone other than the caller will be detectable by the receiver. Although there are always things a sender can do (including publishing its private authentication keys), to compromise a receiver's ability to hold it accountable for a received message, both parties to the communication would be wise to select an integrity mechanism that appends a message confounder (typically a sequence number and a timestamp) to the message before the digest. The purpose of the confounder is to make the message authenticator useful only once. This prevents a malicious recipient from claiming that it received a message more times than it did or from reusing an intercepted message for its own purpose. In exchange for these receiver-side limitations, a measure of accountability is transferred to the sender.
In the J2EE architecture, a container serves as an authentication boundary between callers and the components it hosts. Information may flow in both directions on a call (that is, a call may have input, output, or input and output parameters). The Deployer is responsible for configuring containers to safeguard interactions between components. A Deployer must configure the containers involved in a call to implement integrity mechanisms either because the call will traverse open or unprotected networks, or because the call will be made between components that do not trust each other. The latter is necessary to ensure that messages can only be used once, and to reduce the plausibility of arguments made by either of the communicants that they did not send the messages claimed to have been received. When integrity mechanisms are configured by the Deployer, the calling container must compute and attach a message signature to the call request, and verify the correspondence between the call response and the message signature attached to the call response. The called container must verify the correspondence between the call request and the attached message signature, and compute and attach a message signature to the call response. If either of the verifications fails, the call should be abandoned, and the caller notified (for example, by exception) of the failure.
The performance cost associated with applying integrity protection to all message communication is as much a property of the operational environment as it is a consequence of the cost of the protection. One way to safeguard the integrity of application messages without unnecessarily limiting the space of operational environments, is to capture application-specific knowledge identifying which messages must be integrity protected. The place to capture this information is in the application's deployment descriptor.
Confidentiality mechanisms ensure that communication between entities is kept private. Privacy is achieved by encrypting the message contents. Because symmetric (that is, shared secret) encryption mechanisms are generally much less expensive (in terms of compute resources) than are asymmetric (that is, public key) mechanisms, it is quite common for an asymmetric mechanism to be used to secure the exchange of a symmetric encryption key, which is then used to encrypt the message contents.
The Deployer is responsible for configuring containers to apply confidentiality mechanisms to ensure that sensitive information is not disclosed to third parties. Despite the improved performance of the shared secret mechanisms, the costs of message encryption are significant, and should be expected to have an adverse effect on performance when confidentiality mechanisms are applied where they are not needed. The Application Assembler should supply the Deployer with information on which method calls of which components feature parameters or return values that should be protected for confidentiality. The Deployer then must configure the containers involved in a call to employ a confidentiality mechanism whenever one of the method calls identified by the Application Assembler will traverse open or unprotected networks. In addition to applying confidentiality mechanisms where appropriate, the Deployer should configure containers to reject call requests or responses with message content that should be protected but isn't protected. Message integrity is typically verified as a side effect of confidentiality.
We recommend that the Application Assembler identify the components whose method calls feature parameters or return values that should be protected for integrity and/or confidentiality. The deployment descriptor is used to convey this information. For enterprise beans, this would be done in a description subelement (most likely of a method-permission element). For servlets and JSP pages, this would be done in the transport-guarantee subelement of the user-data-constraint subelement of a security-constraint. In cases where a component's interactions with an external resource are known to carry sensitive information, these sensitivities should be described in the description subelement of the corresponding resource-ref.
In addition to understanding how to configure Web transport guarantees, it is important to understand the properties of HTTP methods, and the effects these properties have when a link is followed from one Web resource to another. When a resource contains links to other resources, the nature of the links determines how the protection context of the current resource affects the protection of requests made to the linked resources.
When a link is absolute (that is, the URL begins with https:// or http://), the HTTP client container will ignore the context of the current resource and access the linked resource based on the nature of the absolute URL. If the URL of the link begins with https://, a protected transport will be established with the server before the request is sent. If the URL of the link begins with http://, the request will be attempted over an insecure transport. When the link is relative, the HTTP client container will protect an access to a linked resource based on whether the resource in which the link occurs was protected.
The application developer should consider these link properties most carefully when a linked request must carry confidential data back to the server. There are a few choices available to ensure security in such cases. For example, an application developer might choose to use secure absolute links to ensure the transport protection of requests that carry confidential data. This would solve the security problem, at the expense of constraining the application to a very specific naming environment.
Another option, assuming that an application opts for portability and uses relative links, is for the Deployer to configure the application so that wherever there is a confidential interaction from one resource to another, both are deployed with a confidential transport guarantee. This approach will ensure that an HTTP client container will not send a request to a protected resource without protecting it.
As a related point, the POST method is favored over the GET method for delivering confidential request data, since data sent via GET appears in both client- and server-side logs.