Derek Williams

Menu

Friday Fixes

It’s Friday, and time again for some Friday Fixes: selected problems I encountered during the week and their solutions.

This week’s challenges ran the gamut, but there’s probably not much broad interest in consolidated posting for store-level no advice chargebacks, image format and compression conversion, SQLs with decode(), 798 NACHA addenda, or many of the other crazy things that came up. So I’ll stick to the web security vein with a CSRF detector I built.

Sea Surf

If other protections (like XSS) are in place, meaningful Cross-Site Request Forgery (CSRF) attacks are hard to pull off. But that usually doesn’t stop the black hats from trying, or the white hats from insisting you specifically address it.

The basic approach to preventing CSRF (“sea surf”) is to insert a synchronizer token on generated pages and compare it to a session-stored value on subsequent incoming requests. There are some pre-packaged CSRF protectors available, but many are incomplete while others are bloated or fragile. I wanted CSRF detection that was:

I also wanted to include double submit protection, without having to add another filter (certainly no PRG filters – POSTs must be POSTs). Here below is the gist of it.

First, we need to insert a token. I could leverage the fact that nearly all of our JSPs already included a common JSPF file, so I just added to that. The @include wasn’t always inside a form so I added the hidden input field via JavaScript (setToken). I used a bean to keep the JSPF as slim as possible.

I didn’t want to modify all those $.ajax calls to pass the token, so the ajaxSend handler does that. The token arrives from AJAX calls in the request header, and from form submits as a request value (from the hidden input field); that gives the benefit of being able to distinquish them. You could use a separate token for each if you’d like.

The TokenUtil bean is simple, just providing the link to the CSRFDetector.

A servlet filter (doFilter) calls CSRFDetector to validate incoming requests and return a simple error string if invalid. You can limit this to only validating POSTs with parameters, or extend it to other requests as needed. The validation goes like this: