I know this has been asked billions of times, but I'm super paranoid/OCD about the security of my coding. I'm working on a little project. The session data will only contain:
user_id 1
user_name MyUsername
logged_in true
csrf_token 87cc51ee94178df79cccce2aebc45d53
Here's my code. Is it secure enough to use on a small CMS?
session_start();
ini_set('session.cookie_httponly', 'On');
ini_set('session.cookie_secure', 'On');
ini_set('session.use_cookies', 'On');
ini_set('session.use_only_cookies', 'On');
$rand = rand(1, 10);
if ($rand != 1 || $rand != 3 || $rand != 5)
session_regenerate_id();
$user_ip = md5($_SERVER['REMOTE_ADDR']);
$user_agent = md5($_SERVER['HTTP_USER_AGENT']);
if (isset($_SESSION['user_ip'], $_SESSION['user_agent'])) {
$session_user_ip = $_SESSION['user_ip'];
$session_user_agent = $_SESSION['user_agent'];
if ($session_user_ip != $user_ip || $session_user_agent != $user_agent) {
unset($_SESSION);
session_destroy();
die('Error');
}
} else {
$_SESSION['user_ip'] = $user_ip;
$_SESSION['user_agent'] = $user_agent;
}
Then to call the sessions:
$_SESSION['user_id'] = 1;
$_SESSION['user_name'] = 'MyUsername'; // etc.
Extra Info
I'll be using the session data to check if user has permissions to do something. Example: if ( user_has_perm( $_SESSION['user_id'] ) )
Thanks for your help in advance.
To be honest, I think you're being over-cautious, but not in a very useful way.
If you're really worried about session security, don't try to do it yourself. Use a PHP security patch like Suhosin. Let it do all the hard work for you. Suhosin is a well-established patch for PHP. It includes stuff that deals with all the ways a PHP session can be hacked. If you've got it installed, then you don't need to be doing anything extra to secure your session. If you don't have it installed, then you definitely can't claim to be super paranoid about security!
So in short, install Suhosin (if you haven't already), and forget about it.
But just for completeness, I'll make a few comments on at your actual code, just to point out a couple of things:
I'm not sure why you think MD5 hashing makes any difference. MD5 hashes can be cracked in seconds, so having them in any kind of security function is completely arbitrary. It may as well be plain text. That said, I don't really see the need for them to be anything other than plain text anyway -- if a hacker has managed to get hold of the session data to be able to read the IP address it contains, then you're already beyond worrying about whether they know the IP address or not.
They are just only two major session attacks
1.) Session fixation Attacks.
This can be prevented by using
session_regenerate_id()
2.) Session Hijacking:
This can be prevented via data encryption by using SSL Certificates. your site will now run on https and not http.
3.) If you are on a shared server where CloudFare or JailRoot is not implemented. You can show to store your sessions in a database as opposed to default file system storage.
With this three implementations, Let me see that hacker who claims to hack usesrs session...
$FirstName
$post_desc"; } $page.=" "; include('include/main_file.php'); ?>
I'm not a security expert. However, I humbly doubt that your security enforcements will bring substantial benefits.
If there's one who can steal the session ID of your users, for example by eavesdropping an unencrypted wireless network, I bet he can steal also the username and password your users send to your server when they authenticate. Once he has the access credentials, the attacker can login the day after, or a week after, and will have his "safe" - and 100% valid - session to play with.
I believe there is no session security without channel security. If you use SSL, you ensure that the session ID is sent only via cookies (you're already doing it) and your sessions expire soon, I believe you are reasonably safe, and safer than making these enforcement on an insecure channel.
Firstly, you have a mistake in the session regenerate code. The following if will always evaluate to true:
If
$rand
is not 1, it returns true. If$rand
is 1, then it's not three, and it returns true. You probably meant to use anand
here.Secondly, you don't need to MD5 the
user_ip
, or theuser_agent
strings. If someone can access the session data on your server directly, you're so deep in it that hashing that data won't save you.CLARIFICATION: As SDC and crush point out in the comments, MD5 is good for hashing passwords if you hash it with a salt. This means that your user's passwords are generally still secure, even if a SQL Injection attack succeeds and your database is exposed to the world. However, if your server is compromised, and the salt is compromised, then it becomes possible to generate a set of known hashes, and to attempt a reverse lookup of a specific password. Bottom line? Hash your user passwords, with a salt.
Thirdly, most security holes don't come from spoofing sessions. They come from poor input checking. A book like Essential PHP Security should be a good introduction to the kind of input checking you should do in a PHP project. Failing that, at least read the security section of the PHP Manual. Pay attention to the SQL Injection bit. It's cool!
Finally, I fully agree with the other poster that you should use SSL to secure communication to your website.