You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.
Before diving into the details of various web vulnerabilities, it's important to understand what an attack vector is and how it is unknowingly exploited. In short, how are you, as a user, vulnerable. Even if you stay away from shady websites, it doesn't not necessarily mean you are protected. What makes an application vulnerable?
In order to recognize when your application is vulnerable, you have to learn to identify a technology attack vector. In this context, the term vector is borrowed from biology, where it is defined as
an organism that does not cause disease itself, but which transmits infection by conveying pathogens from one host to another. Thus, in web terms, we can define a technology attack vector as follows:
technology attack vector: A technology that does not attack a system itself, but which transmits an attack by conveying a request from one site to another.
The technology in this case is tremendously benign. It's nothing more than a request. But that request can be issued by sources such as an image tag, an iframe, or an XMLHttpRequest (XHR), which is where the abuse comes into play.
There are several terms for the nature of this attack (CSRF and session riding) and related vulnerabilities that facilitate the attack (XSS). The behavior of the attack is described as follows:
Commands are sent to the web application on behalf of the user when the user visits a specially crafted website or resource.
Let's consider the various roles the user can play in the attack.
The mislead user
We'll first look at the situation when the user makes a legitimate request, but would plead to being tricked. In this case, the user is presented with a link on a separate website or in an e-mail. That link contains URL parameters that will perform an action in the application so long as the user is logged in. If the application uses lazy authentication, the user may be directed to the login screen and the action performed immediately following successful authentication. The problem here is that the user is never presented with a screen in the application that states the intent of the action so the user is not able to make an informed decision. Although less convenient for the user, the application should require that the user visit a screen in the application before action is taken. A token can be incorporated into this form to validate that the user has, in fact, visited the form, a technique addressed in the countermeasures.
While you may assume it is the fault of the user for clicking on a link that performs an action, you have to realize that websites like tinyurl.com make it possible to create links that hide the real target and thus true intent. It's not always clear to the user why a link they clicked caused an action to be invoked in the application.
Links typically require clicking. But there are ways to force a browser to follow a URL without the user having to click on a link. There are a handful of HTML tags that can load an arbitrary URL. These tags include IMG, IFRAME and SCRIPT, to mention a few. If the user visits a site that uses one of these tags with a URL that points to a URL in another application that invokes an action, the user can effectively click on a link simply by visiting the site. In this case, the user really didn't do anything. But when the URL is requested, the session cookie is sent with the request and if the user is logged into the other application at the time, the request succeeds in performing the action.
Once again, this trap can be avoided by requiring that the user visit a form with a validating token in the application before any action is performed. The same recommendations regarding page actions apply here as well.
So far we have assumed that the user is innocent and is being mislead to make a request which the user did not intend to make. There is also the case that the user is not innocent and is manipulating the request to make the application do something out of bounds from what the developer intended it to allow. For instance, if there is a pagination control that offers page sizes of 5, 10, and 25, but does not enforce that one of those values is requested, the user could request 10,000 records, putting significant load on the application. In a similar way, the user could enter columns in the sort column that would reveal information that the application did not intend to transmit. So it's important not only for the application to filter out malicious characters (which should be obvious), but to validate that those values are within range.
Countermeasures to the web vulnerabilities cited in this document seek to answer two questions:
The second question is the easier one to answer. All input should be validated and cleaned. Don't just look for malicious characters that could alter the commands executed but also look for out-of-bounds values. Here, the framework should provide ways to define choice lists.
The first question is far more difficult since the browser acts as a proxy for the user and that proxy cannot always be trusted.
The most crude approach to validating the user's intent is to place a CAPTCHA on the page. The drawback of this solution is that it puts a burden on the user and can slow down the user's work. But the other major limitation is that it is not contextual. Thus, the pattern by which the CAPTCHA uses can be determined and defeated.
Support in Seam
Seam provides a basic, yet extensible CAPTCHA solution. Please see the CAPTCHA section of the Security chapter in the Seam Reference Documentation.
The best approach is to use a secure token in the form or link. The token is generated from the signature of the page, form, or specific action. It may also have a short timeout period set. When the request is submitted, the token in the request is validated against the saved token on the server and only if the two match is the action performed. This ensures that the user did witness the form prior to submitting it (assuming that the site does not suffer from a vulnerability that could automatically submit the form). The recommended approach for generating this token is as follows:
HMAC_sha1(Action_Name + Secret, SessionID)
Support in Seam
Seam provides the <s:token> JSF component tag that can ensure the validity of a form post.
The root of most CSRF vulnerabilities is that the session token is being transparently delivered along with the request as a cookie. The person crafting the URL does not need to know the value of the session id since it is conveniently sent by the browser when the request is made. A countermeasure is to avoid the use of a cookie for storing the session token. The downside of URL rewriting is that it makes it easier for the user to accidentally transport their session to another user by copying a link from the application into an e-mail. Thus, it's still necessary to use a secret cookie that can validate the origin of a session token.
Support in Seam
Most applications are going to prefer to use a cookie for tracking a user's session. Therefore, it's important for Seam to provide a mechanism for adding a secure token to forms to accommodate this preference in a secure manner.