Yes, I will talk in this article about why it is not good to leave your session files in /tmp. But first, allow me to follow Jason's lead and talk about the session attacks he discussed in Part 2 of his ASP.NET article. I will keep it short
Session fixation isn't really that much of a problem as long as you stick with a few simple principles. Remember we called this blog "App Sec Streetfighter"? It's about simple and reproducible techniques that work while under attack. So lets keep it simple:
- Use only cookies to transport the session token. This considerably raises the bar on session fixation. The attacker now has to set a cookie which isn't easy at all.
- Change the session ID whenever the users state changes (logged in vs. logged out).
- Change the session ID every so often. (every X pageviews, every X minutes).
In order to change the session id, PHP offers a simple comand, session_regenerate_id, just add it to your header and you will get a new session ID on every page. If that works for you: great!. If it causes performance issues, then add some logic to limit the life time of sessions or add the session_regenerate_id whenever the user logs in and out.
One important caveat for session_regenerate_id: It uses one parameter. Set it to "true." The default is "false," which will leave the old session intact.
Now to the part everybody appears to be waiting for: Why not /tmp ?
/tmp is a convenient location for session data. Every Unix system I have seen has a /tmp directory that is globally readable and writable. But this is just the problem for session data. The file name itself gives away the session ID. A listing of all session files will give an attacker a list of all valid sessions. In most dedicated web server scenarios, the risk of leaking /tmp file names is low. But the defense is simple enough to "just do it" ™:
- Create a directory which will only hold session data (let's call it /tmp/phpsessions).
- This directory should NOT be owned by the apache user, but by root and the apache user's group.
- Set permissions to 770. Sadly, 760 is not possible. Theoretically, it should work. PHP (the web server) doesn't really need to be able to get a list of valid sessions. But sessions will fail if you set the permissions to 760.
I typically prefer to keep my sessions in a database, less for security reasons but more for scalability. Memcached sessions is an other great way to get sessions to scale.