Skip to main content

Securing the integrity and authenticity of links

Posted by elevy on May 13, 2008 at 12:40 PM PDT

It has been a while since my last posting. As you can imagine, I have been really busy. Last week I was presenting at the JavaOne, and it was amazing. Thank you all for all the positive feedback on my session. I will most likely writing something about the demos I showed, and may be I will post them here with Java WebStart. That will have to wait for now...

Now back to the blog that I have been thinking to write:

Form hidden fields, query string arguments, and cookie values are frequently used as parameters to keep session state on the client of web based application. In this blog, I explore an option for securing those values. The key to this approach is that even if the developer is unaware of the problem, they are safe, thanks to the underlining framework.

The problem is that it is extremely easy for an attacker to change the values of any of these parameters. Making the Web Application vulnerable if the developers are not careful.

My first recommendation to address this problem is to avoid using those parameters in the first place. If that is not possible, then strong validation is necessary.

However, there are some cases where that validation is not easy to do. How do you achieve security?

In this blog, I am going to describe a solution for the parameters in the query string. It would be trivial to extrapolate it and apply it to the other cases.

The idea is to use a keyed-Hash Message Authentication Code (HMAC).

HMAC is just a hash value combined with a private key. In this case we are going to use it as a checksum.

The idea is to get the URL with the parameters, pass it through the HMAC algorithm, and append this "checksum" to the query string.

In this way when we receive a URL we can calculate the checksum again. If it matches, we know that the URL was generated from our application. If it doesn't, ALARM! someone modified the query string.

A problem that we would still have, is that if someone was to be able to get to the computer of an authorized user, after looking at the browse history, the attacker can replicate the requests, and potentially violate the system security.

A way to stop that from happening would be to include a timeout as part of the query string, and then obtain the HMAC. The validation phase would include validating that the timeout has not expired.

There is no constraint that does not have side effects. In this case, a bookmark would only be good for the lifetime of the session (until the timeout of the query string is good). I personally don't think of this as a problem, on the contrary I see this as a benefit. The links that we would protect using this technique, are the type of links we would not want the user to bookmark in the first place.

Now that we have gone through the theory, let's see some code of what would it take to implement something like this. In this case, I will extend the struts framework. Obviously, the same idea can be applied to almost any other framework as well.

The first step will be to identify which Actions are going to have this security. For that we can extend the Action Mapping class to include a requireHMAC parameter:

public class SecureActionMapping extends RequestActionMapping {

   protected boolean requiresHMAC;

   public boolean getRequiresHMAC() {
      return requiresHMAC;

   public void setRequiresHMAC(boolean requiresHMAC) {
      this.requiresHMAC = requiresHMAC;


Then in the struts-config.xml file we need to configure struts to use this as the ActionMapping class:

<action-mappings type="org.zilonis.hmaclinks.SecureActionMapping">
     .... all the action mappings
   <action path="/editUser" type="EditUserAction">
      <set-property property="requiresHMAC" value="true"/>

In the Struts html tag library we have the custom tag html:link. To generate the links all we need to do is extend it to include the HMAC and the timeout as part of the link.

To generate the HMAC:

   private final static JTIME="&time=";
   private final static HMAC="&jval=";
   public static String appendHMACSecurity(String url) {
      url+= JTIME + System.currentTimeMillis();
      url+= HMAC + HMACGenerator.genHMac(url);
      return url;

   public class HMACGenerator {
      private final static SecretKey key = genKey();
      public static String getMac(String url) {        
         Mac mac = Mac.getInstance(key.getAlgorithm());
         byte utf8[] = url.getBytes("UTF8");
         byte digest[] = mac.doFinal(utf8);
         String result = URLEncoder.encode(new Base64Encoder.encode(digest));
      private final static SecretKey genKey() {        
         KeyGenerator keyGen = KeyGenerator.getInstance("HmacMD5");
         return keyGen.generateKey();

I have omited purposely Exception handling for readability.

An interesting trick here is that I am generating the key in a static final field. That means that the first time the application gets started, the private key is going to be generated. In this way, there is no need to have any key management procedures with the operations team. If you were on a situation that your application does not get restarted in a long time (more than 15 days) you might want to considering putting some code there to generate a new key every now and then...

To verify the HMAC we just need to extend the FrontProcessor servlet to check if the action requires an HMAC. Then a similar piece of code to generate the HMAC and compare it with the one we are receiving. Notice that we are not decrypting the HMAC. The HMAC never gets decrypted. All we do is generate again our "checksum" and verify that it is the same we are receiving.

Finally we just need to check the timeout.

This technique might be overkill for some environments. But there are some situations where other options are not really feasible. This is easy enough to turn on/off on any use case you application might have.

Related Topics >>


Hi Elie, Jusr read ur presentation on 'Extending Swing: Creating Your Own Components' , Do u plan on showing some demo or releasing the code ..since that would make ur presented techniques ,in your slides ,much more clear. Regards, Pavan