I am trying to understand security when it comes to session cookies in php. I've been reading a lot about it, but I still lack the specifics. I need the basics, someone to show examples.
For example: Do I place session_regenerate_id() before every session cookie? What more shall I think about. I am asking about specifics in code - examples if possible.
Thank you very much.
I am using 4 session cookies after logging in.
SESSION "site_logged_in" = true
SESSION "site_user_nr" = the number of the user to access user_table_nr
SESSION "site_user_id" = the user's id to use when changing data in tables
SESSION "site_user_name" = the name of the user to display on page
When I check if the user has access, I check if all 4 cookies are set, and if site_logged_in is set to true.
Are there better ways? Do I have the completely wrong idea about this? Can users easily be hacked?
In fact you need to have only one session in your website. When you call session_start() session is being created on server and user automatically gets session cookie. Think like session is a some sort of container that placed on the server, you can put whatever you want in that container. However session cookie is just a key to access that container on the server.
It means that you can safely put some data in the $_SESSION and only the user that have cookie with matching session id can read it.
About users being hacked. Yes they can be hacked as long as you don't use HTTPS connection, because cookies and all other data is being transferred in clear text, so if someone intercept users cookie he can access the data stored in the session.
Always use a security token for logging users. This security token could be generated by using crypt(). After logging users in, change the security token periodically until they log out. Also keep the server backup of all the session variables including the security token (in a database). This would also help you to track user login history.
One more personal suggestion: Never use any data from the database as session variables without encrypting it with any of the hashing functions or functions like crypt().
The session information is stored server-side. What you should check is that they're logged in, and that they exists/can log in (in case of deletions/bans).
As you're checking they exist/can log in, you can pull the other information from the database such as name, nr and so on. All you really need is a key called 'logged_in_user' or something that stores the ID of the logged in user. As Alex Amiryan said, the cookie can be copied, so you might also want to store the IP address of the last accessing view in the session, so you can try to ensure security.
Related
I am using PHP and Codeigniter to do this. Currently I am just saving a cookie to the user with their username and a $logged_in variable set to true. Then when they try to access a page, I check for the status of their $logged_in, and if they are, they're free to access.
It occurs to me that this may not be the safest way to go about this. Is there a better tactic I should be using?
It's not safe at all. Cookie is considered user input and it can't be trusted in any case.
Use sessions instead.
Also you could use some sort of custom login encrypted code (I'd personally suggest SHA1) that is matched against the login code in the database and is refreshed every, let's say, 5 minutes.
CodeIgniter offers a nice solution to this problem - You can use Database Sessions.
With Database Sessions, all the data you put in a session is stored within your SQL database. The user gets a cookie with a unique session ID that changes on a regular basis. The session ID along with IP and User Agent is used to match up the user with their session data, thus making it impossible for users to tamper with their own session data, and very hard for them to hijack someone else's session.
You can read more about CodeIgniter Database Sessions in the CodeIgniter User Guide.
Sorry for the newbie question! I'm making a small website that allows users to create their own accounts. It's not a banking system, and it's unlikely that someone would want to hack it. That said, I am trying to make it reasonably secure, as there are plenty of bored script kiddies out there.
Could someone describe a basic workflow for a user logging in and having a cookie set that will keep them logged in for 30 days?
At the moment I have the following:
Validate and sanitize inputted data.
Check supplied credentials against bcrypt hashed password in DB.
If correct then call "Login" function.
Login function:
a. Delete any session data from DB with userID (table with two columns: SessionString and UserID).
b. Add new session data to DB (newy random generated string and UserID).
c. Write random generated string and UserID to cookie.
d. Set $_SESSION("UserID") with $userID.
But although the two cookies are being created and written to, the $_SESSION("UserID") remains blank... I'm guessing because I can't write to $_SESSION any time I like?
And even once that's fixed, how do I use the data stored in the cookie to log a user in? I'm guessing I don't want to go to the DB on every page load. And it will still require me to create a database object to see if the credentials in the cookie are ok. Is this the right way to this?
Once again, apologies for the newbie question!
UPDATE:
Yes, I do understand the difference between $_SESSION variables and a cookies. I also have session_start() at the top of every page (right after <php with no blank lines). $_SESSION("UserID") just remains blank.
Here's the code from the top of the page:
<?php
session_start();
if(!isset($_SESSION['initiated'])) {
session_regenerate_id();
$_SESSION['initiated'] = true;
}
Thanks for the help.
First off, there is an important difference between a session and a cookie. When you use the $_SESSION[".."] you are creating a session (which lives on the server, compared to a cookie which lives on the client), even though the browser uses a cookie to keep track of the session id. To create a cookie you would use the setcookie() method.
That said, I would recommend you to read through this article which is a step-by-step guide on how to create a secure login script, with persistence using a cookie for a "Remember me"-feature. Describe how to do it in detail would be to extensive for an SO answer im afraid.
Side note:
To be able to write to the session, you might have to call session_start(); prior to getting or setting a session variable using $_SESSION[".."].
Did you write a custom session handler that has your session-files stored in the db? I guess you don't.
If you want to use $_SESSION you have to also do session_start(). When using PHP sessions the cookie to identify the user will be set for you. You will also get session files created in your /tmp directory. That's the location your variables and anything you assign to $_SESSION will be stored.
Unless you define a custom session handler, that will manage the location of the session files, you won't need to query your database. Just save the users credentials in $_SESSION.
See this Tutorial on how to use PHP sessions.
PS: You access arrays like this: $_SESSION["UserID"], not with ().
you might want want to look at this article in which i have already discussed about various types of session hijacking and how you could avoid it.
session security in php
I'm using the following code for my user login. Everything works fine but im just wondering the security of using this. I'm using the userid as the sessionid when a user logs in.
What are my security issues with using this?
Can the user change the sessionid to a different number and then be logged in as a different user? (how do i stop this?)
if (!empty($row['member_id']))
{
$_SESSION['id'] = $row['member_id'];
header ("Location: team.php");
exit();
I'm not a security expert by any means.
There was an uproar back in, I want to say, 2010 about session theft. So much so that a group put out a tool called Firesheep that would let you quickly steal other sessions in an open wifi situation. The solution is to protect the entire logged in session with SSL or not be on an open network. Back when SSL was first being used, it proved too slow to be used as a session long security measure, but now computing is fast enough.
TLDR: If you don't SSL, someone can steal your session. Facebook and Google both had the same problem.
For clarification, they can't "steal" sessions so much as they can find out the SESSIONID being passed around in the POST request in order to keep you logged in and then modify their cookies to send that around as you instead. The Firesheep tool could snag Facebook logins in seconds. By modifying the cookie with someone else's SESSIONID, the tool was able to pretend to be the original user, allowing full access to the areas of the account that were unlocked upon login. See also: this.
Another good solution to help things is to reprompt the user during any account sensitive activity regardless of their session. For instance, if they try to change their password or change other account info, make sure to ask for their current password again.
The contents of the $_SESSION server-side are only safe as long as there is no way to submit user data in any way that would eventually end up in the session variable. If someone stole a SESSIONID and then entered data on some form (or if you blindly use the name of the form element as the index into the $_SESSION array) they could get stuff in there. The key is to never ever ever ever ever ever ever ever...EVER....trust what the client side has sent as valid or trustworthy. Paranoia is your friend.
I think you are mixing up the Session ID (SID) with your own login id, you save in $_SESSION['id'].
Your code is fine. Session data is saved on the server and cannot be manipulated by the client directly. So he cannot change the value of $_SESSION['id'] (btw: I suggest to use a more unique key name like 'login_id').
Talking about the real Session ID (SID). The SID is a random string generated by PHP automatically and saved as a cookie on the client’s machine. The client can actually manipulate his SID and so potentially takeover a different session. This is called Session Hijacking and it’s a general problem of using sessions, no special problem of your code. Have a look here for further information: PHP Session Fixation / Hijacking
I have created a registration/login system for my members area. Once the user has logged in I want to store a session variable that I can use to retrieve data associated to the user from the database.
Should I in encrypt the variable in any way? The data I want as a variable will either be the username or the id, which is best?
Should session ids be regenerated in anyway and when??
Data storage in session is considered to be "safe", so you dont need encrypt-decrypt it.
You should regenerate your session id after a successful login/logout. For security reasons, I would reccomend to ask the user for his password if he want's to perform a critical action (changing important data, deleting account or submit an order for example).
As AurimasL stated, you don't have to worry about session data on the server side. I reccomend this reading, if you are on a shared host, because then there are some security aspects: http://phpsec.org/projects/guide/5.html
Session IDs are stored like a cookie on the client's machine, and are passed back to the server for every single request. This is how PHP determines what information to load into a session once it receives the request.
Since sessions live on the server and not on the client, you only need to worry about session hijacking in regards to whether the information stored in them is secure or not. The answer to your question is no, I would not try to encrypt the information that is stored in session.
Just an add in the comments bellow,
Keep in mind that creating a sessions are expensive for your server app. Sometimes is a good idea stores the id in the session and other informations in cookies (informations that dont need security as the username).
Hey guys, I was scanning my site for security and I noticed that it was possible for non users to send requests and post information, so I decided to put login checks on all information posts. I was wondering if it was a good way to keep a session id that is created by md5(uniqid()); in a session variable $_SESSION['id']=md5(uniqid()); for each user and then store that in a database under active users for that user. Then when a user tries to insert information, verify that their $_SESSION['id'] variable is equal to the one in the database where the username equals their $_SESSION['username']. What are your ideas on this guys? Thanks in advance!
One solution would be to set a session variable called "loggedin" or something when the user logs in, and make sure that variable is set when you do the database updating (call session_start() before doing the SQL calls, and check the variable in $_SESSION before you send the queries). That way, non-logged in users can't update the database, unless they steal a session from a user already logged in. From what I understand of the problem, this sounds like the simplest solution.
It sounds to me like the solution you came up with is already built into PHP sessions with SESSIONID. A new session in PHP automatically generates a random string identifying your session from the sessions of others. I could be misunderstanding, though.
Why not to just check if $_SESSION['username'] is set?
I've done this before on sites, but it's less of a security measure than it is a feature to allow users to have multiple concurrent sessions. The real key is to check for a valid login token whenever you're performing an operation that requires authorization, and to run your site over HTTPS so that the session cookie can't be hijacked.