Tuesday, June 24, 2008

Red Listing

At work we found that hackers were trying to brute force our login page. In other words, they were trying every combination of username/password that they could find to gain access to the site. You will often see lists of u&p's on random forums and they were using these lists to hit our login page many times a second. This creates an unnecessary load on the servers which can impact performance for our paying customers. Not a good position to be in.

There is several ways to defend against this attack and the most common one is to display a kaptcha for each login or registration. Sadly, this is a real pain for members because they have to try to type out the kaptcha and often end up failing. Why should paying customers suffer because of a few hackers? In the end, this causes more support requests or people just give up and go away. A far better solution is one that I just implemented that I'm proud of (so I'll talk about it here. heh). I'm sure I'm not not the first person to do this, but the implementation seems pretty rare because I haven't seen many websites doing it this way.

The solution involved creating a simple @Session bean to store state in memory on each of the servers in the cluster. I could use the clustered cache, but so far I haven't seen a need for the overhead of doing that. Using a ConcurrentHashMap, I store the zone the IP address was seen in (optional), IP address, first access time, last access time and a counter. Then, I apply some fairly simple logic to the stored information:
  • if someone fails more than 3 times, they are shown the kaptcha.
  • if someone fails for more than 1 minute, they are shown the kaptcha.
  • if someone fails because they aren't doing things correctly, they are shown the kaptcha.
The first two options have the benefit of allowing people to screw up a couple times before they are required to pay the kaptcha tax. The third option is more like an immediate red listing. I use that when someone tries to send clearly invalid data to our servers.

Right now, I'm watching the logs and things are pretty promising. I'm a bit surprised at how many IP addresses are being red listed, but I think it will decrease with time as the 'hackers' realize that their tricks won't work with us.


jergendutch said...

If your website requires JavaScript you could use something similar to WordPress HashCash:

Jon Scott Stevens said...

a) we don't require javascript for login (or our sites). that might have an impact on sales.
b) all spammers need to do is use Rhino (or another javascript engine) to get past that check.

jergendutch said...

a) Wow.
b) Yet the attack would be made more expensive for them.

Jon Scott Stevens said...

a) why wow? it makes sense to me to not want to impact sales. =) we require cookies to be enabled though. i wish we didn't, but in order to implement our cross domain single signon system (SSO), we had to do it. we display a nice "we require cookies page" similar to the one that gmail displays.

b) I'll make another posting at a later date about how I already tried making it more expensive for them and they (within a day) worked around it. Sure, it wasn't as expensive as firing up rhino, but it required parsing the html. Executing the javascript in rhino is just the next step for them. Not a big deal if you are a hacker and know what you are doing.