Summarizing a discussion from here – things to watch out for when using sessions for your sites login system;
1. Shared web servers – anyone else on the server can read your session files (typically in the /tmp directory) if PHP is running as an Apache module (so the session files belong to the web user) and possibly when PHP is used as a CGI (depending on how sessions are implemented).
Someone browsing the session files (probably) won’t know the site the server the sessions apply to (so may not be able to use a username / password combination they found) but you may still be putting sensitive info (like credit card details) somewhere for all to see. Plus they’ve got a list of valid session IDs…
If you’re just storing passwords in the session, you can get away with this by using md5() (preferably twice) to one-way encypt the password. This doesn’t help though if you need to recover the value of a session variable.
Using a custom session handler to store the sessions in a database is probably the best solution. You might consider MySQL HEAP tables if performance is an issue (assuming MySQL running on same machine as Apache). If it gets to very high traffic, it’s time to think about getting your own server…
2. XSS exploits (and session hijacking) – using JavaScript users can be fooled into giving away their active session_id.
All someone needs to “hijack” a session is the unique session id. It’s like the key to a railway station locker. The locker doesn’t check you’re the valid owner of the key, before allowing you to open it so anyone with the key can get in.
Research XSS and how to prevent it.
Accept that session hijacking cannot be entirely prevented (checks on IP address, for example, is foiled by AOL, who assign a new client IP on more or less every page request) so double check “critical actions” a user can perform when logged in e.g. when changing password – require the old password, which the session hijacker will (hopefully) not know. Displaying credit card infomation – do like Amazon and only display the last four digits. Basically limit the damage someone can do if they hijack a session.
3. Session IDs in URL (and hijacking) – if you’re using session IDs in the URL (as opposed to a session cookie), make sure offsite links do not contain the session ID (or the remote site will be able to hijack) – PHP should take care of this. Also your visitors may give away the session ID in the referrer field – ideally pass off site links through a redirect page, to elimate the referrer (although, unfortunately, some browsers keep the last 3 pages viewed I believe – unsure of facts).
Ideally, don’t pass session ids in the URL – require users to accept a cookie if they need to “log in”.
4. Session Fixation (pre-hijacking) (see http://www.acros.si/papers/session_fixation.pdf).
If you assign a session to a visitor to your site, before they are logged in (for example for clickpath analysis), make sure that you assign them a new session id when they do login, so that if someone pre-generated the initial session id for them, they won’t get the new ID.
For PHP 4.2.0+, see session_regenerate_id() (in particular the user submitted comments). For PHP < 4.2.0, you'll have to destroy the session and re-create it when the user logs in, carrying any stored data between the two. The session_id() function may also be useful (haven’t explored it in this context myself).
5. Sniffing Packets (use SSL [HTTPS]) – a session ID can be “sniffed” between the client and your server. If it’s a site where money is changing hands or other sensitive personal information is involved, SSL is a requirement.
Otherwise, without SSL, you have to live with the risk (just like you do every time you use that FTP client…).
6. Cookies are not for session data – on a related note, don’t use cookies for store sensitive information.
Cookie data, unlike sessions, gets stored on the client site. Apart from the “sniffing risk”, a large majority of Windows users have little idea of security and may be “owned by haxor”.
Otherwise, cookies (aside from session cookie PHP creates for you) are generally meant for long term (i.e. between visits) data persistance (e.g. “Remember Me”) rather than “active session” persistance.
There’s probably more things to watch out for (or facts to correct) – suggestions appreciated.







Hi Harry. That’s pretty informative for a blog entry. :-)
I have some resources that might help elaborate on some of these things.
Session Hijacking:
http://shiflett.org/articles/the-truth-about-sessions
Session Fixation:
Security Corner in the current issue of php|architect. Unforunately, this is not yet available for free.
XSS:
http://www.phparch.com/issuedata/articles/article_66.pdf
Shared Hosts:
I’m finishing up an article about this (and safe_mode) for the next Security Corner, and here is a script that developers can use to better illustrate how open a shared server is (when safe_mode is disabled, which is common):
http://shiflett.org/code/browse.phps
March 3rd, 2004 at 10:32 am
Hi Chris. Thanks for some those very informative links. And thanks for all the hard work you’re doing on phpcommunity.org.
Perhaps one phpcommunity “deliverable” might be to compile the various documents on PHP Security out there and submit it to http://www.owasp.org – I notice thier Guidelines document has a blank PHP section and, in general, is almost entirely focused on J2EE and .NET.
March 3rd, 2004 at 3:55 pm
Hi Harry,
Thanks for bringing this up again. Security seems to be highly overlooked among the average PHP programmer.
I’m writing an article on using mcrypt to encrypt and decrypt data in a variety of formats, including cookie data, and explaining a bit about how this can add security to sessions as well. Using true and tested cryptographic techniques is about as “good as it gets” dealing with passing data to and from an untrusted client. The article is forthcoming from International PHP Magazine, however I also posted a basic tutorial on installing mcrypt for those interested.
Cheers,
Robert
March 3rd, 2004 at 9:13 pm
Let’s try that again. The article is coming out in International PHP Magazine:
http://www.php-mag.net/
But for now you can learn how to install and test mcrypt at:
http://dotgeek.org/tutorial.php?action=view&id=140
March 3rd, 2004 at 9:19 pm
Hi Harry,
the furthcoming OWASP Version 2.0 will have a section about PHP,
http://cvs.sourceforge.net/viewcvs.py/owasp/guide/php.xml?rev=1.2&view=markup
BTW, there is another article (in german) about this topic and can be read on
http://phpmag.de/itr/online_artikel/psecom,id,396,nodeid,62.html
March 4th, 2004 at 8:13 am
Hi,
Can I translate your text in french for my website http://www.phpsecure.info ?
I wait your reply,
frog-m@n
leseulfrog@hotmail.com
March 4th, 2004 at 12:48 pm
Thanks for the info. I’ve been looking at sessions, cookies, and security in the past couple of days, so this blog is right on time for me.
It would be nice if an article on SSL could be written or some information on where to learn more about implementing it. I’ve been looking for a while and can’t find anything that makes much sense.
March 5th, 2004 at 8:47 am
Just thought I’d mention that while some time ago AOL might well have performed the IP jiggery-pokery that you mention above, AFAIK in v6 and above this certainly does not happen. A related issue (the inverse, really) is multiple machines hiding behind a single IP, as with a corporate internet gateways.
June 28th, 2004 at 6:12 am
Armor2net Personal Firewall software provides a complete spectrum of Internet security and Internet privacy for computers. The program protects the computer from hackers, data thieves, and other Internet-based dangers.
For more information, please visit: http://www.armor2net.com
August 5th, 2004 at 5:51 am
The last post is very ridiculous. I hope no one will go try that weak, and seriously not working well, firewall. There is NO way to prevent a hacker to crash your computer, software, connection or whatever would make your day more bad. Don’t be fooled, Even windows XP native firewall is better than this one.
And since it a unknow firewall, and probably not professional, we can’t even know it is not a virus or a trojan itself so it is not reporting as is.
Thanks for your patience and NOT TRYING armor2net…
August 25th, 2005 at 8:36 pm
kujikuk
March 11th, 2007 at 9:08 pm
uuuuuuu
March 11th, 2007 at 9:28 pm
lol at “encrypting” with md5, preferably twice. This gave you away.. you don’t know what you’re talking about.
May 21st, 2008 at 9:35 am
I am shocked that you have stated that “if your only storing passwords in the session”. Why on earth would you be storing passwords in the session anyway! You store them in the database (file, mysql, xml etc) and compare them with form values and set a flag in the session as $session->Autheticated = true;
There is absolutely no need to carry around a password in a session.
July 29th, 2008 at 12:30 am
asasasasasSeptember 18th, 2008 at 3:29 pm
hello.
php’s built-in session_x() functions work well enough, but there are cases where you will want to roll your own. the first to come to mind is that you’ll run into trouble when implementing a single site (domain) across multiple machines (httpd processes) as in a web server farm.
fortunately, php’s header() or setcookie() functions make this an easy task.
i have monkeyed up a function called session_begin() which takes two optional arguments: session_id, and session_key.
session_id is, of course, a string which identifies a given unique session; session_key is a string which is intended to help ensure that the provided session is indeed unique. consider the following.
http client one comes along and acquires a legitimate session, abc123. along with generating this session, the server records something unique about http client one, or about the communication itself, such as http client one’s remote ip address (not a good idea, keep reading). this can be anything at all, not necessarily limited to an http context, and this is stored as session_key. all subsequent requests from http client one will contain the session abc123. the idea is that session_key should be something determined by the server, on the server-side, not provided by the client (i.e., javascript or hidden form-field or whathaveyou), as this is trivial for an attacker to spoof.
now, sitting across the coffee shop, http client two has been watching http client one’s tcp packets and knows exactly what that session_id is. therefore, http client two does not need to poke around for usernames or passwords. no need for a phishing site. no trojan horse, spyware, keystroke logger, fraudulent phone calls, or anything else. http client two needs only to make a request to the same domain with the same session_id, while http client one is logged in. http client two now has immediate access to anything and everything available to http client one, and nobody even knows about it. that’s right, a simple, untraceable attack. this works, by my testing, with yahoo! mail, gmail, hotmail, and probably about every web site i could try it on, though ssl makes things more cumbersome – i should say, not very much more cumbersome, if the attacker can see the underlying tcp.
…however, since the server is also using session_key to store and retrieve it’s sessions, http client two must appear to the server as identical to http client one. for example, say the server stores http_client_id (”mozilla” or “ie” or whathaveyou) in the session_key. now, http client two must make it’s request to the server not only with the same session as http client one, but also with the same browsing software. or, say, session_key is remote_addr: now http client two must also spoof his victim’s ip.
the obvious argument to this is that, in our scenario, http client two sees the whole http request made by his victim. therefore, it is entirely probable that he will spoof his request to match his victims to the greatest extent possible, in trying to make his hijack. therefore, the server would see the same http_client_id (or accept_charset or whatever else you could think of). and using the client-provided ip address or any function of the underlying ip connection as a session_key would be stupid on the server’s part since the server may not know about http tunnels, proxy servers, ip-masquerading firewalls, or anything else which could (and inevitably would) obfuscate the reliability of such a method.
so, here is my post in a nutshell: what would serve as a good spoof-proof session_key? that is, what can a web server (or the system running a web server) see about a web client that is not likely (even better, not possible) to be reproduced in an attacker’s hijack request? answer that, and you’ll have a secure, unbreakable session management implementation. you will no longer need ssl, even when dealing out credit card numbers and social security numbers and the like.
it’s not a rhetorical question. i don’t expect anybody to be able to answer, or else yahoo! and hotmail, gmail at least, would not be quite so easy to break into. if you can answer, though, you would be well-advised to seek a patent.
October 31st, 2008 at 12:03 pm
very nice post dogglebones
November 25th, 2008 at 7:16 am