Tools for making your web application more secure.

The Open Web App Security Project (OWASP) is an excellent guide for increasing the security of your web application, and is highly recommended.

An important point to understand is the separation of validation into two distinct parts - hard validation, and soft validation - see {@link hirondelle.web4j.security.ApplicationFirewall} for more information.

### Recommendations and Reminders

#### SafeText

Free-form user input should always be modeled as {@link hirondelle.web4j.security.SafeText}, not `String`. This provides protection against XSS (Cross Site Scripting) attacks, without forcing you to continually escape special characters in JSPs.

#### POST versus GET

Forms should always specify the correct `method` attribute. The general rule is that any action that has a side effect (database edits, logging off) should be a `POST`, while an action without any side-effect (list or search operations, reports) should be a `GET`.

#### Content-Type

Always specify the `content-type`. This can be done in template JSPs, to reduce the repetition of identical markup. Example using a directive to specify an HTTP header :

    <%@ page contentType="text/html" %>

Such directives must appear at the start of the page.

The `jsp-property-group` setting in `web.xml` can specify an `include-prelude` JSP, which will be automatically included at the start of your JSPs.

#### Filter

The {@link hirondelle.web4j.security.CsrfFilter} should be configured, to protect against CSRF attacks.

This filter requires configuration for `FormSourceIdRead` and `FormSourceIdWrite`. These items reference `SqlId`s. As usual, these `SqlId`s need to be declared in one of your application's classes, and also appear in an `.sql` file. (This ensures the usual matching of `.sql` file content to `SqlId`s will not fail. See hirondelle.web4j.database for more information.)

#### ApplicationFirewall

The {@link hirondelle.web4j.security.ApplicationFirewallImpl} provided by the framework is an excellent default for the {@link hirondelle.web4j.security.ApplicationFirewall} interface. It performs sanity checks on every request, to make sure they aren't hacks. You can subclass that implementation in order to add further checks, if desired. (Replacing the implementation entirely is possible, but is usually an extensive task, and should likely be attempted only if you are experienced.)

#### SpamDetector

Implementations for the {@link hirondelle.web4j.security.SpamDetector} interface can vary widely. The {@link hirondelle.web4j.security.SpamDetectorImpl} is a simple default, but you will occasionally need to replace it with something more appropriate> This will usually be easy to implement.

### Cross Site Scripting (XSS) Attacks

The {@link hirondelle.web4j.security.SafeText} class is provided as the main defense against XSS attacks. The {@link hirondelle.web4j.security.SafeText#toString()} method performs proper escaping for HTML, and {@link hirondelle.web4j.security.SafeText#getXmlSafe()} performs proper escaping for XML documents. For the most common case of presenting data in a web page, a `SafeText` object will be rendered safely by default. It is highly recommended that all free-form text input by the user be represented in a Model Object using `SafeText` instead of `String`.

Using `SafeText` will greatly increase your safety when using JSTL. The JSTL is a bit defective when it comes to protecting you from XSS attacks:

- the `<c:out>` tag escapes characters by default, but it only escapes for XML, and not for HTML. That is, it escapes only for 5 of the 12 characters recommended by the OWASP. The same is true for JSTL's `fn:escapeXml()` function.
- JSTL's Expression Language is nice and concise, but it doesn't escape any characters at all. It is dangerously open to XSS attacks, since the application programmer always needs to remember to manually escape special characters.

When JSTL is used with a `SafeText` object, however, these problems do not occur, since by default `SafeText.toString()` will do the correct escaping for you in the background.

### Cross Site Request Forgery (CSRF) Attacks

The central idea of protecting against CSRF attacks is that a server should be able to answer the question "Did this POSTed form really come from me?", and not from some unknown third party. The {@link hirondelle.web4j.security.CsrfFilter} is provided as a defense against CSRF attacks.

To use it, you must have the `CsrfFilter` configured as a Servlet Filter in `web.xml`. As part of that configuration, you must provide two `SqlId`'s, to tell the Filter what SQL statements to use to read and write 'form-source ids', the tokens used to identify forms generated by your web app.

Although it is not really necessary for those simply wanting to use `CsrfFilter`, the following is a description of its implementation.

#### Form-Source Ids

When a user logs in, {@link hirondelle.web4j.security.CsrfFilter} will create a 'form-source id', and store it in the user's session under the key `'web4j_key_for_form_source_id'`. This form-source id is constant for each session, and is hard to guess. The `CsrfFilter` will automatically modify all of your forms having `method='POST'` to include a hidden request parameter of the same name (`web4j_key_for_form_source_id`), whose value is simply the value created upon login.

#### Verifying Form-Source Ids

The default {@link hirondelle.web4j.security.ApplicationFirewallImpl} will verify that each POSTed form includes a parameter named `web4j_key_for_form_source_id`, and that its value matches either the current value stored in the user's session, or the form-source id used in the immediately preceding session for the same user.

The form-source id used in the previous session is needed to ensure smooth behavior upon re-login. Here is the use case in more detail :

- the user logs in
- the user navigates to a form (containing a hidden form-source id param)
- the session expires
- the user posts the form, without knowing the session has expired

When the form is POSTed, the user will of course need to log in a second time. After successful authentication, the action will continue in the usual way. In this case, however, note that there is a new session. Thus, the old form-source id attached to the first session is POSTed, not the current one. What is to be done? Well, if this use case is to be handled gracefully, then the 'old' form-source id must be remembered (in the database) and treated as second valid value. Then, a POSTed form will succeed only if its `web4j_key_for_form_source_id` has either the current form-source id value, or the 'old' form-source id value of the immediately preceding session.

This is the reason for the two `SqlId` configuration settings for the `CsrfFilter`: they tell the Filter how to read and write the form-source id for a given user. This allows the Filter to remember the previous form-source id value for each user.

When a user logs out, or when a session is about to expire, `CsrfFilter` will extract the user's form-source id from the session, and store it in the database for possible future use.

#### Sessions With No Login

There are some common forms for which no valid login is possible :

- creating an account
- recovering a lost password

In this case, a session is used, but without the usual corresponding login. Since the usual login mechanism does not apply, the Action itself must ensure that a session exists, and that a CSRF token is created. This is done simply by calling {@link hirondelle.web4j.action.ActionImpl#createSessionAndCsrfToken()} (typically in the Action's constructor).

There is one difference when a session does not include a user login: when a session expires, there's no way to recover using a 'previous' token from a previous session. Again, this is because the session is not attached to a specific user.