Attention developers: Your SESSIONIDs are showing
You don't know sidejack
Protecting passwords is important, but do you take the same care with your SESSIONIDs? You should.
Here's how they work: When you log into a web application, you exchange your credentials for a SESSIONID cookie. This cookie gets sent with every subsequent request from your browser until you log out or the session times out. During that window, if an attacker steals your SESSIONID, they have full access to your account.
So what do you need to do to protect your application's SESSIONIDs? Here are some tips.
Don't roll your own
First, you want to make sure your SESSIONIDs are not guessable. Just like a password, they should be long and random so that attackers can't use a brute force attack. Some web applications and web services still create their own SESSIONID token, and a few even use a sequential integer. You should stick to the standard SESSIONID provided by your container.
Believe in SSL
Some web applications use SSL for the username and password, but then fall back to a non-SSL connection after authentication. Unfortunately, this means that the SESSIONID is transmitted in the clear in every HTTP request, where it can be easily read by anyone with access to the network. This attack is called "sidejacking," and there are simple tools available to exploit this weakness.
Don't forget your AJAX requests, as they may also contain a SESSIONID. Gmail has this problem, as the application sometimes falls back to non-SSL for AJAX requests, exposing the user's Gmail SESSIONID on the wire. Google recently added a setting to "always use SSL" that you should enable right now. Despite performance issues, the only solution to protect your SESSIONIDs on the wire is to use SSL for every single page from your login form to your logout confirmation.
Fly the cookie flags
Even if your application always uses SSL, attackers may try to trick the browser into exposing the SESSIONID over a non-SSL connection by getting victims to view a page including the following type of tag:
When the browser sees this tag (even in the attacker's page), it will generate a non-SSL request and send it to www.example.com. The request will include the SESSIONID, and the attacker can sidejack the user's session. The solution is to use the "Secure" flag on your SESSIONID. This flag tells the browser to send the cookie only over an SSL connection.
Another way an attacker might steal the SESSIONID is to use a cross-site scripting (XSS) attack. The injected script simply accesses the cookie and sends it to the attacker. Another cookie flag called HttpOnly can protect against this attack, as it tells the browser not to allow scripts to access the SESSIONID. While most browsers respect the HttpOnly flag, many development environments do not yet make it easy to set. You may have to set your own cookie header something like this:
response.addHeader( "Set-Cookie", SESSIONID=" + session.getId() + "; Secure; HttpOnly" );
Avoid that URL re-write
Back in the early days of the web, the US Government (wrongly) concluded that cookies were evil and they banned them. Developers quickly came up with a workaround that involved including the SESSIONID directly in the URL. Unfortunately, URLs are frequently disclosed via bookmarks, referrers, web logs, cut-and-paste, and more. So the cure was much worse than the disease.
Given the small number of web users that do not allow session cookies and the high risk of SESSIONID exposure, this URL rewriting technique should not be used. Disabling this may not be trivial, as many frameworks fall back to this technique when cookies are not accepted. You can test your environment by disabling cookies and browsing your site.
Change SESSIONID on login and logout
One creative way for attackers to steal SESSIONIDs is to grab them before the user logs in. For example, imagine an evil coworker goes to your desk, browses to a sensitive internal application, and writes down your SESSIONID. Then when you come in to work and log in, the SESSIONID is now authenticated, and the attacker can use it to access the application as you.
The solution is to always change the SESSIONID whenever anyone logs in or logs out. This is simple to test for using the alert method described above. Many environments do not support changing SESSIONIDs, so you have to copy anything you need from the old session and put it in a brand new session.
Watch the skies
Even though these problems are easy to identify and relatively easy to fix, many web applications still have them. These issues seriously undermine your overall authentication scheme, preventing compliance with any application security standard, including the PCI. So protect your users and make sure your application doesn't make it easy for the bad guys to hijack their sessions. ®
Jeff Williams is the founder and CEO of Aspect Security and the volunteer chair of the Open Web Application Security Project. His latest project is the Enterprise Security API, a free and open set of foundational security building blocks for developers.