Covering J2EE Security and WebLogic Topics

Encrypting Only the Login Page

I occasionally hear people say that they don’t want to use SSL for anything other than the login page for fear of the performance hit that SSL adds. Most recently, I came upon this post which claims to show how to implement such functionality in a J2EE web application.

While the above post seems to have some technical inaccuracies, I’m not writing to criticize it. Rather, I think it’s interesting to consider the ramifications of only encrypting the login page. The issues fall into three categories:

  • Performance
  • Maintainability
  • Security Impacts

Let’s have a look at each category in turn.

Performance

Performance is the crux of the reason to only encrypt the username and password. Developers hear that SSL adds a 30% overhead to response times, freak out, and then don’t want to use SSL or to only use it sparingly as this use case indicates. But really, the biggest hit of SSL is the initial setup of the socket. Once that is done, a big chunk of the SSL performance burden is gone. Since the socket is usually maintained until a timeout happens, multiple requests can leverage that same one-time setup cost.

Another thing to realize about SSL performance is that you don’t pay the overhead for your total response time. For example, assume that you have a dynamic page that takes 1 second to complete. Let’s further assume that 25% of that time is socket-level and 75% is making the database call and rendering the page. Clearly, I’m just fudging these numbers but you’re not going to see a 30% increase in the 650ms database access time, for example. By the same token, the more data you present (including images!) the more encryption has to be done which will take time.

Finally, a hardware SSL accelerator will go a long way toward reducing the SSL overhead. I don’t have any numbers for this but encryption in hardware will beat encryption in software any day.

Maintainability

While it doesn’t seem like this should be the case, encrypting only the login page introduces a software maintainability issue. Specifying that the login page should have a transport-guarantee of CONFIDENTIAL in web.xml will do the trick of ensuring that SSL is used for the login. No custom coding is required.

However, once the browser has switched to the SSL port, how do you declaratively tell it to go back to the clear (non-SSL) port after login? The answer is you can’t. Even though other resources defined in web.xml may not have the CONFIDENTIAL guarantee, the server will not automatically switch back to the clear port.

I can only think of two ways to switch back to the clear port — a servlet filter or links.

By using a servlet filter you could examine the request and then redirect to the clear port for anything other than the login page if the request was made over SSL. Do-able but not pretty.

The other way is to have all of your links specifically refer to the clear port with something like http://whatever/somepage.jsp. Clicking such a link will cause the request to be serviced without SSL but now you have hard-coded links all over the place. You could also build your link dynamically but then you’d have that code to maintain.

So far, we’ve talked about performance and maintainability. Now it’s time to consider the security aspects…

Security

In this section you’ll see what that 30% SSL premium buys you.

It makes sense that you’d want to protect the user’s password and perhaps even the username itself. You wouldn’t want anyone sniffing the wire and finding those goodies. But by not encrypting the link post-login, all data sent or received from that user can be sniffed. You require authorization for the user to see the data but allow anyone with a packet sniffer to see social security numbers, medical conditions, or whatever sensitive data your application handles. Shouldn’t that be kept safe, too?

Perhaps you think you’re safe because you’re not going out over the internet. That is a good thing, of course, but the majority (80% is what sticks in my head) of attacks are from insiders. Kinda risky.

You’ve now seen that sensitive data can be sniffed from the link. Here’s where it gets really interesting…

You’ve encrypted the username and password during login so that no bad guys can login as that user in the future. But since subsequent traffic is unencrypted you’ve just given away the keys to the kingdom. How’s that? Session hijacking.

Now that traffic is unencrypted, someone sniffing the network can see session IDs either as a request parameter or in a cookie. Given this information and an active session on the server, the malicious use can become the previously authenticated user and access the application as if he were the legitimate user. Scary stuff…

Summary

I think you can tell by now what side of the fence I fall on. I think the security issues alone call for SSL during and after login. That 30% premium allows me to sleep at night.

Did I forget or overemphasize anything? Please post your thoughts below.

Fallback Authentication in WebLogic 9.2

Ah, nothing like blogging near a crackling fire. Sort of sounds like a line from a Christmas song, doesn’t it?

Speaking of hot topics, I recently noticed that BEA added the concept of container-managed fallback authentication to WebLogic 9.2. What’s fallback authentication? Here’s an example of a use case that I’ve heard more than once:

Imagine your application uses client certificates to authenticate users. Unfortunately, sometimes reality is less than tidy and you find that some users don’t have certificates nor are they able to get them for some reason. You’d like to be able to use form-based authentication if the user doesn’t present a valid certificate. In other words, if client certificate authentication fails, you want to have a fallback method for authentication.

You can do this today with any servlet engine but you’ll have to handle security on your own. Container-managed security is out because the servlet specification does not consider fallback authentication. After all, you can only supply one auth-method in web.xml. (For the literary buffs among you, the previous line is a foreshadowing detail.)

So now back to WebLogic’s support for fallback authentication. The documentation for it is here. Essentially, you have two choices for enabling fallback authentication:

  1. Supply a comma-separated list of auth-methods in web.xml
  2. Specify the REALM auth-method in web.xml which ultimately grabs the comma-separated list from the security realm

I tried the first approach first. Just kinda made sense. Here’s the snippet from my web.xml:

<login-config>
  <auth-method>CLIENT-CERT,FORM</auth-method>
  <realm-name>ArbitraryName</realm-name>
  <form-login-config>
    <form-login-page>/login.jsp</form-login-page>
    <form-error-page>/login.jsp</form-error-page>
  </form-login-config>
</login-config>

This login-config element should allow me to implement the use case given above. However, upon deployment, WebLogic complained with the following message:

Invalid auth-method list – CLIENT-CERT,FORM as the auth-method in web.xml, which is not valid. Valid values are BASIC (default), FORM and CLIENT-CERT.

Well, I could have told it that. Wasn’t WebLogic going to do some proprietary magic to get past the deployment descriptor compliance check? Apparently not, and I don’t know of any way to turn it off. I even removed the web-app DTD DOCTYPE entry in web.xml to no avail.

I’m just tenacious (stupid?) enough to try the other approach where you specify REALM as the auth-method in web.xml. Not surprisingly, it also failed compliance checking. What is surprising is that it didn’t fail because the auth-method was the non-standard "REALM" but because it was null. Now, I knew I hadn’t set the auth-methods attribute on the RealmMBean as described in the doc, but I was doing test-driven configuration so I had to see it fail first. 😉

I suspected that WebLogic was correctly substituting the auth-methods value in the RealmMBean when it encountered the REALM auth-method in web.xml. The value just happened to be null. So, I fired up WLST, set authMethods to "CLIENT-CERT,FORM", and saved the change. After restarting WebLogic, the exact same error occurred as with the plain web.xml method. The comma-separated list was not valid. However, WebLogic did correctly substitute the value from the realm when it saw the REALM auth-method in web.xml.

Sorry to say, but there’s no happy ending here. I can only surmise that BEA’s implementation was half-baked and wasn’t supposed to make it into the docs. Perhaps the next release of WebLogic will have a working implementation. In the meantime, we’re stuck with rolling our own fallback authentication scheme. It’s also very possible that I missed a step somewhere. Please let me know if I did.

Well, the fire’s not really dying, but here I am goodbye-ing… 😉

 

Bookmark this page on del.icio.us