PHP Session Validation - Best Practices - php

I have a database in which I store session ID's once they have been validated to a user.
From a security standpoint, should I be checking the session ID against the session ID stored in the database for every protected page being accessed?
If I do not do this, wouldn't it be possible for someone to hijack the validated session ID, and do a post with the necessary variables to access restricted pages?
From a performance standpoint - if I should be checking the session ID against the database for every request, would it be significantly more efficient to store validated session ID's in their own text files instead of making so many database queries?
Thanks in advance.

Yes, you should check the session ID on every request. It's still possible for session hijacking to occur, although a rolling session ID would help mitigate this (i.e. change the session ID on each request).
It would not be more efficient to validate session IDs in a text file versus a database if your RDBMS supports results caching (MySQL calls this query caching).
If your query just verifies the existence of a session id like SELECT COUNT(session_id) FROM sessions WHERE session_id = ? (you are using parametrised queries to prevent SQL injection, right?) then this may be cached (although MySQL may not do so in versions earlier than 5.1.17).
If/when there is no cache, the lookup should not cause any issues. Switching to an in-memory table at that point may be a good idea.

About security:
You describe the hijack risk yourself quite well. More important is the question of how likely this would happen and how sensitive your site / data is.
Now if someone takes over the pc of a registered user who didn't destroy the session (log off), how would you determine this? And why / how should the session ID change and still be valid?
It would probably be better to check the identity of the caller by accessing a cookie, checking the ip (on ip change re-logon), ...
About performance:
In general a text file query should take much longer than a database query, since the text file is almost always a file system / storage query, while the database query will often be in memory (cached).
Think of your database as another software program running in the background - it's basically instantly accessible if it runs on the same server.
-> Correct me if I'm wrong...

From a security standpoint, should I
be checking the session ID against the
session ID stored in the database for
every protected page being accessed?
If I do not do this, wouldn't it be
possible for someone to hijack the
validated session ID, and do a post
with the necessary variables to access
restricted pages?
Yes, and you'll probably want to include some additional information in your database - e.g. last time accessed, ip address.

Generaly speaking checking and regenerating ID session occurs when you change status of user.
IE : user X get the admin access : You must check is session id before grant access and you regenerate a new id after the operation.

Related

Is restoring a session with cookies the right way?

Correct me if I'm wrong please:
Sessions will last a finite amount of time (refreshed from the server every 15 or so minutes until the browser is closed) - more secure/short term
Cookies on the other hand can last until the browser closes or to some specific time in the future - least secure/long term
Given this, how do allow a user to close his/her computer, come back a few days later and open a site and still be logged in using cookies and still somehow being secure?
How does someone like, amazon for instance do this?
EDIT:
To be more clear, here is an example:
if (!isset($_SESSION['id']))
{
$_SESSION['id'] = $_COOKIE['id'];
$_SESSION['email'] = $_COOKIE['email'];
}
this is obviously bad, what is a better way?
First of all, "session" is more of a concept rather than a concrete implementation.
For PHP I believe the default way that session data is stored on the file system and it is associated with a session id that is usually stored in a cookie (although it can also be sent via query string parameter:http://stackoverflow.com/a/455099/23822).
It's also possible to store session in a database. Doing so allows you full control over how session data is stored and when it expires so you can have sessions that last as long as you want them to. You just need to make sure the session cookie also shares the same expiration time as the data in the database.
As to your question of in a comment about "What's stopping someone from grabbing the cookie data and falsifying a login using the token?" Theoretically that can happen, but the session ID stored in the cookie should be random so it would be highly unlikely that it would be guessed (an attacker would have a much easier time guessing the user's password). In fact the same thing is already possible with any kind of session.
Sessions expire mostly because keeping them open on the server is inefficient. You need a cookie (or some other mechanism, but cookies are usual) to associate them with a browser anyway.
Amazon handles security by having three levels of "being logged in".
Level 1: Basic functionality just works.
Level 2: You must reenter your password to access some things (e.g. order history)
Level 3: You must reenter payment information to access some things (e.g. adding a new delivery address)
For the cookies I use the method described here:
http://fishbowl.pastiche.org/2004/01/19/persistent_login_cookie_best_practice/
and here: http://jaspan.com/improved_persistent_login_cookie_best_practice
You store a session-based security token inside the user's cookie data, and store that same token in the user's db table. At session creation, you check if this username/token pair can login to your website according to the previously stored data, and then invalidate the token.

User login security. Session vs Mysql active users table

I'm thinking about security problems, made some questions, read some articles..... it's too difficult to get all information from all those articles with very different methods and put them in 1 place to have normal user login and user check system.
Today I've read about haveing mysql table with active users list instead of storing sessions.
As I understand sessions are too difficult to secure, and on the other hand mysql table I think is very easy to make.
For example, users loggs in. Instead of making some 'user' session, I can simply insert new data into active_users_table and add user ip there.
And on all pages I can ask client for ip, then go to mysql table check if such ip-user is logged in, if yes check what rights does the user have and give him corresponding access.
Question 1. Isn't it simple ? easier to make then securing sessions?
Question 2. If this system is good enough so I could stop my research and construct site using this method question is how can I understand if the user is still active ? If he will press 'log out' button ok , I will log out him and delete his record from the table. But if he restarts his PC or something? how can I understand when the record will be available for destruction ?
Question 3. one guy told me to use mysqli instead of mysql commands when I'm working with database. Are they the same so I just have to add "i" to all my commands and it's ok, or mysqli is a bit different and needs some study ? and also why is it better ? WHy I cannot use normal mysql commands to which I got used to?
NO, it's not that simple. (if it was that simple, we would do it like that : )
You need something that uniquely identifies the user. IP won't do. Also, it needs to be non-predicatble, hard to hijack, not show up in server logs, etc, etc, etc.
The current accepted standard is: use a long, high entropy random token and store it in a cookie.
For PHP, use PHP's build in session functions.
Security is a very delicate area of expertise, the best advice is: do not invent your own security scheme.
You can store the session data in a database instead of in a file, no problem. It might even add to the overall security. But then again, it might just ass well not do anything at all. (it depends on may factors)
Session CAN BE and often IS stored in the database. So there is no session vs database. Session is a way to persist information between HTTP requests, as HTTP is stateless protocol.
The difference between session and your approach is that session relies on cookie, and you are relying on IP. But there can be multiple users with the same IP. So your approach is not secure, session is more secure.
The database is offered instead of the default file-saving mechanism from a security point of view, because in a shared environment other user can read the session files. Also, session in a database can scale easier, if you have a lot of active users.
You should care about session hijacking and session fixation attacks. None of these is related to how you are storing the session data.
Question 3 have nothing to do with the session and deserves own question. But mysqli is just the newer extension, and supports more functions. In most cases it's used exactly the same as the mysql functions.

Is it safe to store a value in a session variable and make queries on the value?

I have a site, where the username is stored in a session variable when they are logged in, I am wondering is it safe to make queries off of the value stored in this session variable?
yes, session are stored on server side.
instead of saving user name, you can save user id (int), so that it takes less space on
server. Remember that you should handle CSRF, and Session hijacking
Yes it is save. However, always escape any input that goes into a query (the best way is a bound parameter). Never trust any variable explicitly, especially if you can't see directly where it comes from (meaning unless you can scroll up and see $foo = 'bar';). So the better method is to just not trust everything, and you'll be safer in the end...
Sessions work by storing a session ID in a cookie sent to the user machine and storing all actual variables on the server. As such, your main worry is that the user will be able to find out the session ID of another user and pretend to be them; i.e., session hijacking.
Given that, you aren't really worried about SQL injections here as much, so you should be OK so far as making queries off the variables stored in the session. However, you should be worried that data can be viewed by someone other than the intended recipient. If you take precautions against hijacking, then you should be OK.
It depends.
If the pages in your site that are using the session are protected by encryption (HTTPS), then that mitigates the risk of session hijacking due to sniffing network traffic (the cookie containing the session id is protected.)
However, if you're on a shared host, the session file is typically stored in a central location and trusting unencrypted session data does entail some risk.
You could encrypt the session data, or you could develop a custom session storage as outlined in the link below:
Trick-Out Your Session Handler
But, no matter what you do or how much you trust your session data, you should use prepared statements or stored procedures to protect the integrity of your SQL statements, preventing SQL injection.
in fact, it's safe to use ANY variable in the SQL query, As long as you're following syntax and safety rules.
And data source has nothing to do here. No matter if it's session or a file, or an RPC request or POST data. All data is equal for the query and should be processed always the same way.
I know it's hard to understand but it's very important too, so, at least try it.

What to store in a session?

I know about all the issues with session fixation and hijacking. My question is really basic: I want to create an authentication system with PHP. For that, after the login, I would just store the user id in the session.
But: I've seen some people do weird things like generating a GUID for each user and session and storing that instead of just the user id in the session. Why?
The content of a session cannot be obtained by a client - or can it?
You're correct. The client just sees a randomly generated session id token. There are ways this token can be misused (hijacked, etc.), but having a GUID on top adds nothing. In contrast, options like session.cookie_httponly (JavaScript can't see session cookie) session.cookie_secure (Cookie can only be transmitted over HTTPS) protect against certain attack scenarios.
The short answer is that $_SESSION is safe and you do not need to worry about its contents being leaked to a user or attacker.
The content of the session is not normally be accessible to the user. You should be able to store the user's primary key and you'll be fine. There are cases where the session can be leaked, on a normal linux system the session folder is in /tmp, however this could be changed in your php.ini to the web root (/var/www/tmp) and then could be accessible. The only other way is if the user is able to get access to the $_SESSION super global by hijacking a call to eval() or by the variable being printed normally.
If you are running on a shared host and using an old version of PHP and/or your server is misconfigured it might be possible for another user on this system to read or even modify a session file stored in /tmp/. I don't know of a single application that takes this attack into consideration. If this is a problem you can store the information in a session table in the database.
Sometimes, for added security, developers may assign a long string to the user's session in order to make hijacking even more difficult. By setting a cookie with this new string at the time of session creation, the app can check for the correct string on subsequent requests to better ensure it is the person who actually logged in.
It's just adding one more thing a wannabe hijacker would have to guess. However, it can be a false sense of security as it does little to protect the session if sniffing is involved because the new cookie is sent right along with the php session cookie. Also, session id's are very hard to guess as it is (as I'm sure you know, just don't place it in the url but, rather, in the cookie).
Session info is stored on the harddrive so it's not obtainable by clients without application intervention.
I've never seen GUIDs being used for sessions, but there are a couple of additional methods I have seen that do add a little more security.
Storing the user's IP - if you need to force a session change based on locations (sometimes geoIP stuff will do this)
Storing the user's HTTP_USER_AGENT header string. Can provide a bit of security against hijacking if the hijacker happens to be using a different browser.
There's a great article on session hijacking countermeasures on Wikipedia, actually.
That being said, I would imagine that anyone storing a GUID as part of a session to use in session security might be failing to see a better solution (such as session regeneration). I can see other uses for a GUID to be stored (maybe it's part of a random generator for a game), but not for use with session security.

a few questions regarding php sessions

ive heard a few timse that sessions need to be cleaned with mysql_real_escape_string or htmlspecial chars because they can be modified. what im wondering is how are they modified because when i look at a websites session named PHPSESSID the value it contains is always encrypted.
first of all what encryption method is it using and how is it modified. the reason i want to know this is to better understand how to secure myself based on what methods people are using out there to high-jack sessions
thanks.
They cannot be modified, they're stored on the server. The PHPSESSID is just an identifier, it's not encrypted but randomly generated (so it's unique to each user). People hijack sessions by stealing the PHPSESSID cookie, usually through a cross site scripting attack. Read the answer to this for a nice summary of sessions in php - What do i need to store in the php session when user logged in
Sessions are stored on the server. That means all data is stored in temporary files and are deleted after an x amount of time. The browser does not store session data. It stores an ID of the session, which the server uses to get the right temporary file.
So the user never actually has access to variables stored in a session. But has a reference to their session. It is possible to get someone else's session ID. This way you can pretend to be another user. If sessions are used for validation.
Read up on session hijacking here.
The thing that can get modified is the session id send to you by the client. So, as with all user supplied data, this needs to be 'cleaned' before you use it anywhere, like for example with mysql_real_escape_string before inserting it into a MySQL database.

Categories