blog.smart-java.nl
Ordina J-Technologies – Java Blog

Archief voor September, 2009




Websphere classloading issues

Door: Sander Abbink, 18 September 2009

Most of us who deploy on Websphere have at some point encountered classloading issues. Websphere provides a lot of libraries which are loaded by default (parent first) before the libraries supplied by the application. IBM explains the classloading order on this site:
http://www.ibm.com/developerworks/websphere/library/techarticles/0112_deboer/deboer.html

At my current position some Websphere installations have installed feature packs while others have not. You can view which feature packs are installed by running:
versionInfo.bat/sh from the Profile directory (e.g.: /opt/IBM/WebSphere/AppServer/profiles/AppSrv01/bin).
This can also cause version mismatches.

The following examples are from Websphere 6.1

Viewing classloader order:
You can view the order in which the libraries are loaded by following these links in the admin console:
Enterprise Applications > [ear module] > Manage Modules > [ war module] -> view module classloader.

You can expand the tree or export the contents of the Classloader viewer to a XML-file. Here you can easily tell if a library is provided by Websphere or your application.

Changing classloader order:
To change the classloading order follow the following link:
Enterprise Applications > [ear module] > Class loader

You can set the value of Class loader order to parent-last or application-first (depends on Websphere version) to make sure the jar-files of your application are loaded first. If the jar-files are also present in WEB-INF/lib you can alter the setting in:
Enterprise Applications >[ear module] > Manage Modules > [war module] (again parent-last or application-first)

If you cannot change these settings and you are deploying through WTP then you must change the file: application.xml.  You can enter these settings at the deployment tab (maybe only in RAD?)

Creating your own classloader
Another way of preventing Websphere to load its own libraries first is to use a shared library.Jar-files in the shared-library are automatically placed on the classpath. You can create a special classloader to make sure certain libraries are loaded before anything else:

Application servers > server1 > Class loader

Select ‘new classloader’ and choose ‘Classes loaded with application class loader first’. After you have created this classloader you can attach your shared library to this loader.  After this you can restart your application server for these changes to take effect. For me this is the cleanest solution but remember this affects all applications deployed on the server. The benefit is that you can change the classloading order on a per-library basis i.s.o. changing the order for all the libraries in the application.




Cross Site Request Forgery: Implementation patterns

Door: Jan-Kees van Andel, 7 September 2009

In the previous blog, I’ve shown you a tip of the CSRF iceberg and a simple prevention mechanism. In this blog, I’ll elaborate a bit more on the implementation of a successful CSRF prevention mechanism.

Ad-hoc token per form implementation

As stated, the solution is simple, just include a hidden field in every form, store the same value in the session and compare the two when the form is submitted.

Although working, this fix has some disadvantages.

  1. First, security is not turned-on by default. Every developer needs to be aware of the concept of CSRF and may not forget it when adding new forms. This also applies to developers that have to maintain the website in the future. They may not even know CSRF in the first place and just remove ‘that silly token’ from the form.
  2. Second, it’s probably not the most elegant solution from a Separation of Concerns perspective. Now, every form needs to be aware of security and you need to perform a check in your side controller logic.

So let’s elaborate on some more mature solutions.

What are the variables?

Like always in computer science, there is no single, one-size-fits-all, perfect solution. It always depends on the context. Well, let’s give it a bit of context!

  • Token freshness
    How often is a new token generated? In other words, what’s the time-to-live of a token?
  • Token quality
    How random should the token be? What algorithm should you use?
  • Token storage
    You’ll need to store the token in two places to compare them. First, the HTML where your forms and links reside. And somewhere else…
  • Back buttons and bookmarking
    How to deal with users pressing the back button and seeing a cached web page which they submit? How to deal with bookmarks? Also, you can have Single Sign On, paving the way for deep linking into your system without re-authentication.
  • Ajax
    When using Ajax, many server side requests may occur before a full page refresh happens (if any). What to do with token management?
  • Punishment
    What to do with hack attempts? Do you log an error and short-circuit the server side processing? Or do you log the user off?
  • Logging
    How do you log the event? What kind of information do you include in the logging?

As you can see, there are many variables and all of them may impact your implementation. Most of them even influences each other. In the next section, I’ll discuss all of them in isolation.

Token freshness

This is a major one. A choice needs to be made here. Do you generate one token when the user logs in or do you re-generate a new token each time an action is made?

While re-generating a new token with every request may be very secure, it’s not the most practical solution in reality. In practice, it doesn’t even add that much security, because the Same Origin Policy takes care of the integrity of the token. I also wouldn’t worry about brute force attacks for the token, since the user will probably be logged off long before the attacker guesses right. But when we throw back buttons, Ajax, double-clicking users, etc. into the mix, changing the token during a session has serious disadvantages.

So, unless you have really really really weak token (which will never happen unless you pick an integer between 0 and 1), I would generate the token once (@login) and reuse that value.

Token quality

First of all, we’re not talking about high end encryption stuff here. The only use of the token is turning the URL into a “random” URL. So simple tokens will do.

Important to note is that the attacker will probably never see any token, unless he logs into the system (the token is only used for secure pages). So we need something between an incremental counter and some heavy duty 1024 bit encryption.

I would say, keep it simple. Just use a Random generator or a simple AES key, if it makes your security department happy. When using something like AES, remember to encode it using Base64. It only needs to be one way encryption, since you can compare the encrypted values.

This is a simple AES token generator which also encodes the token using Base64 so it can be used in the HTML.

import java.util.Random;
 
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
 
import org.apache.commons.codec.binary.Base64;
 
public class IntegrityTokenGenerator {
 
    public static void main(String[] args) {
        IntegrityTokenGenerator integrityTokenGenerator = new IntegrityTokenGenerator();
        System.out.println(integrityTokenGenerator.generateToken());
        System.out.println(integrityTokenGenerator.generateToken());
        System.out.println(integrityTokenGenerator.generateToken());
    }
 
    private static final String ENC_TYPE = "AES";
 
    private final SecretKey key;
    private final Cipher cipher;
    private final Random random;
 
    public IntegrityTokenGenerator() {
        try {
            KeyGenerator keyGen = KeyGenerator.getInstance(ENC_TYPE);
            key = keyGen.generateKey();
 
            cipher = Cipher.getInstance(ENC_TYPE);
            cipher.init(Cipher.ENCRYPT_MODE, key);
 
            random = new Random();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("Error generating integrity token");
        }
    }
 
    public String generateToken() {
        try {
            String tokenString = "" + System.nanoTime() + "" + random.nextInt();
            byte[] tokenBytes = tokenString.getBytes("UTF-8");
            byte[] encoded = cipher.doFinal(tokenBytes);
            return new String(Base64.encodeBase64(encoded));
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("Error generating integrity token");
        }
    }
}

I used AES in this example, but you can use anything, like Blowfish. Performance is not an issue, because of the small token length. I’m talking about less than milliseconds. Also, encryption strength is not very important, because you only need a simple token. Remember to base64 encode binary tokens into plain text.

Also be sure to use a random value each time when you generate a token. This way, the token sequence becomes less predictable. To make it a bit more secure, include some personal data in the token, like a customer ID. The combination of data make the key even less likely to guess. Don’t put any confidential data in the token. It doesn’t add any security and only increases the risk of information leakage.

And make sure not to throw too specific exceptions. Just log them and throw a general exception. Details may never end up in the wrong hands!

One more note about the snippet. A big advantage of this approach is that you don’t have any key management. Keys may leak and key management puts another burden on the system administrators. This implementation generates a key once (when the class is instantiated) and reuses it. Java takes care of the details.

Token storage

There are many ways to keep track of the current token for the currently logged in user, but the HttpSession and Cookies are the most common. Cookies decrease the amount of state your server must manage, but for some reason, developers think cookies are unsafe.

When used for storing CSRF prevention tokens, cookies can be safe. Why? Because an attacker cannot see the contents of the cookies. It’s the browser that appends the cookies to an HTTP request, but the attacker cannot see them. A mechanism like HttpOnly makes cookies more secure, because it prevents scripts to access them. But storing security tokens on the client is inherently unsafe and is probably the prime reason not to use cookies to store the tokens. You CAN do it, but you must be very careful AND rely on the browser to do the right thing. For example, Firefox ignores HttpOnly, causing cookies to be quite unsafe.

But why not store the token in an HttpSession attribute? Generate it once, put it in the session and then compare this token with the submitted token. It has a little bit of overhead, but that will probably be nothing compared with the rest of the session data.

I prefer the HttpSession over cookies by a mile length. With session attributes, I don’t have to think about token confidentiality and with cookies I do. Easy choice.

Back buttons and bookmarking

For some reason, clients want us to build systems in web browsers that are not specifically designed for such a purpose. But it’s a fact of life, so we need to deal with it. Browsers have back/forward buttons, refresh buttons and bookmarks and allow users to navigate freely by using the address bar. If you want your users to be able to use these features, here are some notes.

Only check the CSRF prevention token on state changing actions. Users often don’t bookmark actions, but they bookmark pages. When you only check the CSRF token when the form is submitted, the user can use a bookmark to navigate to the form. The server then renders a token into the form. The user submits the form and it works. You just need to give the server a chance to render a form before the user triggers an action. Using post-redirect-get makes it even more robust, because it prevents users to bookmark the POST request.

Also, don’t re-generate tokens with each request. When you want to support back buttons, you’ll have to be aware of the possibility that the rendered page may be a cached (stale) page which contains an outdated token. So, use the same token for the duration of the session.

You might also want to consider storing the token per user in a persistent store, so that when the same user navigates to the site (after a time of inactivity, maybe days or weeks) he gets the same token, thus fixing possible bookmarking problems.

If you implement your own home brewn CSRF prevention mechanism you can redirect the user to a proper page when the integrity token is absent or invalid. This way, the user doesn’t see some strange error but a proper page instead.

Ajax

When securing your website, you also need to secure your Ajax actions. After all, an Ajax request is just the same (from the server perspective) as another request. So you need to include CSRF tokens in the Ajax requests as well.

Luckily, with most JavaScript libraries, this is easy, since they provide a generic abstraction for Ajax requests and often provide a way to append generic parameters to a request.

The implementation is really easy, just render the CSRF token to a script variable and append it to all requests, like shown below.

var globalIntegrityToken = '<%=(String)session.getAttribute("integrityToken")%>';

Yeah I know that scriptlets are ugly, but I don’t care in this example. You can use EL or whatever you like.

Appending the token to the URL is easy, for example using JQuery:

$.ajax({
  type: 'POST',
  url: '/changeEmail.do',
  data: {
    newEmail: $('emailaddress').val(),
    integrityToken: globalIntegrityToken
  }
});

Again, reusing the same token for a longer period of time makes your job a lot easier. Otherwise, if you re-generate the token per request, you need a way to update all tokens that exist in the DOM when the request is completed. This has performance impact on the client and makes the code a lot more complex. You’ll have to make sure you update all tokens, which include:

  • The global variable, which is easy to update in a generic way
  • All hidden fields that contain a token. If you can easily find the fields, this should also be easy
  • Any tokens in querystrings. This may be a bigger challenge and you may end up using regular expressions to parse and replace the querystrings

So, when you reuse the same token for the duration of the session (or longer) Ajax will probably not be difficult.

Punishment

What do you do when you see someone fiddling with the CSRF prevention token? First of all, don’t proceed with the action the user invokes. But do you log the user off?

If you can, I would suggest making a switch to turn the logoff mechanism on and off. Turning it off makes it easier to test, but you need to turn it on in production. If you’re afraid that you (or the sysadmin) forgets to turn the mechanism on, you can skip this switch.

Just be sure your prevention mechanism doesn’t give false positives, because users will be very annoyed if they are logged off often.

Logging the user off has some other benefit. If there is a hacker messing around with your website, users will get logged off very often and complaints will come in often at your help desk. This way, you have the opportunity to detect hackers. If you let the user proceed working without notification, you will never know that something happened. Unless your sysadmins proactively scan the log files, but unfortunately I don’t see sysadmins do these kind of things very often… :-(

Logging

How do you log the event? I would suggest creating a separate security log file so that sysadmins can react to hack attempts. It’s also useful as a proof in a lawsuit. I would log as much as possible. You can think about:

  • Date/time of course and also the timezone.
  • The entire HTTP request, with cookies, referrer, user agent, etc.
  • The source IP address. However it may be spoofed or a proxy, at least you can see that there is a difference with the “real” user’s IP.
  • The invoked action, along with it’s parameters.
  • Any server side state, specific to your system.

It might be a good idea to also log the first two items when the user authenticates so you can compare the two values.

To summarize

In most cases, you’ll want to use a static CSRF prevention token for the duration of the session. It makes Ajax implementations easier and gives browser features like back buttons and bookmarks a more natural behavior. When you do, implementing a working CSRF prevention mechanism may not be a big issue anymore.

The other variables don’t have this much impact, but be sure to pick a good combination, because some variable combinations may harm each other.