GlassFish 3.1 SecureJDBCRealm - Detecting failed logins.

Markus Eisele
5
Playing around with security in GlassFish is a lot of fun. If you have a project and some kind of security organization in place and you have to implement stuff, that fulfills requirements regarding high or higher protection needs, you most often are alone with that. This is a short howto about what I did to extend the existing JDBCRealm a bit to keep track of failed logins and deactivate users after they reached their configured limit.

What's there and what did I do?
You probably know the GlassFish JDBC Realm already. It's a quite comfortable way to use a database as a user back-end for your container security. If you configure your web application appropriate your can ensure, that only valid users hit your protected resources. The only thing you have to do is to configure your JDBCRealm and off you go. If you are not familiar with the topic so far, I suggest, you dig into the Java EE 6 tutorial a bit to get a basic understanding.
So far so good. But what happens in an environment where you have to take care of additional protection needs? Some typical ones? Encrypted passwords in your database. You could achieve this with setting a digest-algorithm (MessageDigest: e.g. MD5) and off you go. What about tracking failed logins? Here we go. That's most obviously nothing the standard JDBCRealm does. So, I was trying to build a more SecureJDBCRealm and add this feature.

Starting point
If I already have an example, I am going to add my stuff there. So I started over looking at the code already there. The com.sun.enterprise.security.auth.realm.JDBCRealm is an excellent place to look at.
So I basically copied it (with remaining copyright-headers of course ;)) and added my own features. Beside the fact, that you need at last two more properties for your realm, you need some additional prepared statements to execute in order to be able to keep track of the tries a user did. And you also do need your own SecureJDBCLoginModule to call your realm.
The steps I took in a very high-level view:
0) Add two more params to the realm (user-tries-column and user-tries-max)
1) change the passwordQuery to include the new "sanity-check" for userTriesColumn + " <=" + userTriesMax
2) Add three new prepared statements triesReadQuery, triesUpdateQuery, triesResetQuery
3) Change the isUserValid() method to include the test if more tries are available for a given username and add some logic for handline the tries colum (increment and reset)
4) I added a new public property to the realm to be able to getTriesLeft() for a given user.
5) implement the SecureJDBCLoginModule

Great. That basically was it. Now you have a new column mapping in your login module to track the not successful login attempts a user does. To be honest, this is not high performance in general. And using the programmatic request.login() with it's simple ServletException that is thrown is not very convenient. So even if you use this login module, you still have to find a way to tell the user about it's left tries and what he possibly did wrong.

Try it out - and give feedback!
If you are willing to try it out: Here you are. I made the complete maven based project (GF 3.1) available for you on github. Use it as it is. Without any warranty. And don't blame me, if something goes wrong. If you have ideas or better approaches: let me know! Happy to discuss this a bit!

Post a Comment

5Comments

  1. I noticed recently that both this Glassfish and the WebLogic JDBC Realms do not implement password "salting". Which makes the hash values that they rely on very weak and vulnerable to "rainbow" table attacks. See the following links;

    http://en.wikipedia.org/wiki/Password_salt
    https://www.owasp.org/index.php/Hashing_Java

    Using the code attached to this article would expose your application to this security weakness.

    I need to solve this problem myself and still want to use JDBC rather than LDAP, so I'm going to have a go at fixing these classes.

    ReplyDelete
  2. Hi rperfect,

    that's sad and true. There are so many things, the standard login modules doesn't do.
    On the other hand: There is infrastructure for that, that plug in very decently. And it's more easy to separate problem domains with them.
    So, you have to get your hands on many many small problems if you are going to secure a standalone GF instance according to state of the art OWASP criterias ...
    But if you hand it over to Enterprise Access Management Systems (EAM) you are fine.

    Thanks,
    M

    ReplyDelete
  3. A bit later on yesterday I ran across the following library which also implements a JDBC Realm for Glassfish and supports password salting.

    http://flexiblejdbcrealm.wamblee.org/site/

    Unfortunately it doesn't support the failed login and lockout functionality.

    ReplyDelete
  4. This comment has been removed by a blog administrator.

    ReplyDelete
Post a Comment