PHP session id in cookie and storage - php

I've read multiple comments about encrypting PHP session data, in case it is stored in a temp directory that is available on multiple accounts on a shared server. However, even if the data is encrypted, session_start() still generates filenames containing the session_id. For example,
sess_uivrkk2c5ksnv2hnt5rc8tvgi5
, where uivrkk2c5ksnv2hnt5rc8tvgi5 is the same session id I found in the cookie my browser received.
How is this problem typically addressed / could someone point me to an example? All of the simple examples I've found only address encrypting the data, not changing the filename.
Just to see what would happen, I made a SessionHandler wrapper that would do an MD5 hash on the $session_id variable before passing it on to its parent function, but that did not work. Instead, I ended up with two files: a blank one (with session_id as a part of its name) and a full one (with an MD5'ed session_id). Also, there was the problem of close() not accepting session_id as a parameter, so I couldn't pass it on to its parent.
EDIT: I 'm learning about php sessions, this isn't for a live commercial site, etc.

Yes, in some scenarios (i.e. a very incompetently configured server - although these do unfortunately exist) on a shared server your session data may be readable by other people. Trying to hide the session files by changing their names serves no useful purpose - this is described as "Security through Obscurity". Go and Google the phrase - it is usually described as an oxymoron.
If your question is how do you prevent other customers accessing your session data on a badly configured server then the sensible choices (in order of priority) are:
switch service provider
use a custom session handler to store the data somewhere secure (e.g. database) There are lots of examples on the web - quality varies
use a custom session handler to encrypt the data and use file storage. Again you don't need to write the code yourself - just scrutinize any candidates
If you want to find out if your provider might be a culprit - just have a look at the value of FILE. Does it look as if you have access to the root filesystem? Write a script which tries to read from outside your home directory. If you can't then the provider may have set an open_basedir restriction (it is possible to get around this - again Google will tell you how).

Related

Is it bad to get all of the variables from your database and store them as session variables?

Using the jQuery load function, i made it to where only the body of the website loads/changes. My header stays the same.
Rather than accessing your database, say, 50 times and requesting the same information on different pages, could I just risk a longer original loading time and include a php file that has everything i need stored in session variables for a user's account?
Are there any big security concerns for this or just any reason I am not seeing why this would be a bad idea?
I am finding myself accessing the same variables over and over again (like a unique id) on various php pages.
Sounds ok to me.
Consider if you need to synchronize and update the domain model (user account data) during access and want to resynch it to your client (view). What you describe however is common session behavior.
It sounds like you are doing it very low level, so you can go for this, without using a repository layer or dao or alike. Just read the date you need, be aware of concurrent access and ok.
For read only it is perfectly fine way of caching it.
It is a good idea imho. What else would you do besides a session, preferably via https.
Consider the security guidelines made here:
PHP Session Security
Yes, it is a bad idea:
Can a user alter the value of $_SESSION in PHP?
http://c2.com/cgi/wiki?GlobalVariablesAreBad

PHP sessions: isolate subdirectory login system

I have a php based software that use a login system with php sessions. I need to replicate this php software in a subdirectory of the same domain in this way:
/root/phpsoftware1
/root/phpsoftware1/phpsoftware2
The problem is that if I login in the php software 1 and then try to access the php software 2 the system recognize a valid session when htere is not.
Is it possible to isolate the two directory so that sessions valid for software 1 are not valid for software 2 and vice versa?
Set two different session names with session_name($somename). This needs to be called before session_start() or session_register() in both places and will set the name of the session used in client cookies (the default is PHPSESSID otherwise).
You can't set two different sessions for the same client, on one server. PHP Sessions are stored on the server per client (Browser or whichever application is making a request) (See: where does session save?) .
To achieve what you requested, you could either take Hanky 웃 Panky's approach (Mentioned in the comments of your question), or once the entry point for /root/phpsoftware/phpsoftware2 has been reached, unset() your session key, so a new one can be created (Note that this will also kill the session for /root/phpsoftware1, so I would rather take Hanky 웃 Panky's approach)
Hope it helped a bit. Lemme know if you need more elaboration.

Storing data into session and storing to database upon "major" action

I know there are hundreds of these questions but what I am asking however is slightly different.
When the user logs in I would like to get all their data from each table in a database and store it in a session variable (obviously not sensative data such as encrypted password/salts etc basically data that would be useless or have no value to a hacker!!), and whilst the user uses the website the relevant data stored in the session will be used as opposed to accessing the database everytime. Moreover when the data is changed or added this will be written or added to the session file, and upon a major action such as "saving" or "loggin out" the new/changed data will be written to the database.
The reason I wish to do this is simply for efficieny, I want my application to not only be fast but less resource consuming. I am no expert on either which may explain why my idea makes no differnece or is more resource intensive.
If there is an alternative to my solution please let me know or if there is something to improve on my solution I will be glad to hear it.
Thank you.
My application is using PHP and mysql.
If any of these don't apply to your app, then please ignore. In general, I'm against using sessions as caches (especially if anything in the session is going to be written back to the DB). Here's why.
Editing the session requires a request from the user. Editing a php session outside of the request-response cycle is very difficult. So if a user Alice makes a change which affects Bob, you have no way to dirty Bob's cache
You can't assume users will log out. They may just leave so you have to deal with saving info if the session times out. Again, this is difficult outside of the request-response cycle and you can't exactly leave session files lying around forever until the user comes back (php will gc them by default)
If the user requires authentication, you're storing private information in the session. Some users may not be happy about that. More importantly, a hacker could imploy that private information to conduct a social engineering attack against the end-user.
Mallory (a hacker) might not be able to use the information you put in the session, but she can poison it (ie. cache poisoning), thereby causing all sorts of problems when you write your cache to your permanent storage. Sessions are easier to poison then something like redis or memcache.
TL;DR Lots of considerations when using a session cache. My recommendation is redis/memcache.
You can also go for local-storage in HTML5, check The Guide and THE PAST, PRESENT & FUTURE OF LOCAL STORAGE FOR WEB APPLICATIONS
Local Storage in HTML5 actually uses your browsers sqlite database that works as cookies but it stores data permanently to your browser
unless someone by force remove the data from the browser finding the data files
Or if someone remove/uninstall browser completely,
or if someone uses the application in private/incognito mode of the browser,
What you need to do
Copy the schema for required tables and for required columns and update data at a regular interval
you dont have to worry about user's state, you only have to update the complete data from the localStorage to mysql Server (and from the mysql server to localStorage if required) every time user backs to your application and keep updating the data at regular interval
Now this is turning out to be more of localStorage but I think this is one of the best solution available for me.
redis is a good solution if it is available for you (sometimes developers can't install external modules for some reason) what I would do is either go with your Session approach but with encoded/encrypted and serialized data. Or, which I really prefer is to use HTML5 data properties such as:
<someElement id="someId" data-x="HiX" data-y="Hi-Y" />
which BTW works fine with all browsers even with IE6 but with some tweaks, specially if your application uses jquery and ajax. this would really be handful.
You need to use Memcache for this kind of work. To solve the problem of keeping the updated data everywhere you can create functions for fetching the data, for example when the user logs in you, authenticate the user and after that insert all the user data into the memcache with unique keys like :-
USER_ID_USERNAME for user's username
USER_ID_NAME for user's name
etc...
Now create some more functions to fetch all this data whenever you need it. For ex
function getName($user_id){
if(Memcache::get($user_id."_name"){
return Memcache::get($user_id."_name");
} else {
//Call another function which will fetch the data from the DB and store it in the cache
}
}
You will need to create functions to fetch every kind of data related to the user. And as you said you want to update this data on some major event. You can try updating the data using CRON or something like that, because as tazer84 mentioned users may never log out.
I also use what the OP described to avoid calls to db. For example, when a user logs-in, i have a "welcome-tip" on their control panel like
Welcome, <USERS NAME HERE>
If i stored only his user_id on $_SESSION then in every pageview i would have to retrieve his information from the database just to have his name available, like SELECT user_name FROM users WHERE user_id = $_SESSION['user']['user_id'] So to avoid this, i store some of his information in $_SESSION.
Be careful! When there is a change on data, you must modify the data in db and if successfull also modify the $_SESSION.
In my example, when a user edits his name (which i also store in $_SESSION so i can use it to welcome-tip), i do something like:
If (UpdateCurrentUserData($new_data)) // this is the function that modifies the db
{
$_SESSION['user']['user_name']=$new_data['user_name']; // update session also!
}
Attention to:
session.gc_maxlifetime in your php.ini
This value says how much time the $_SESSION is protected from being erased by the garbage collector (the file that exists on your disk in which the $_SESSION data are stored)
If you set this very low, users may start getting logged-out unexpectedly if they are idle more than this amount of time because garbage collector will delete their session file too quickly
if you set this very high, you may end up with lots of unused $_SESSION files of users that have left your website a long time ago.
also i must add that gc_maxlifetime works together with session.gc_probability where in general you need lower probability for high-traffic websites and bigger probability for lower traffic since for each pageview there is a session.gc_probability that garbage collector will be activated.
A nice more detailed explanation here http://www.appnovation.com/blog/session-garbage-collection-php
I know this sounds stupid but ....
If ur data is not sensitive the best way to make it accessible faster is to store it in hidden variables inside the forms itself. You can save comma separated or values in an array.

Is it bad to store $_session variables for every user?

Question basically says it all. I get a lot of traffic, about 200k hits a day. I want to store the original referrer (where they came from) in a session variable for various purposes. Is this a good idea or should I stick in a database instead?
You can do both at once :). PHP allows you define the storage logic of your sessions in scripts. This way it is possible to store sessions in a database as well. Check the manual of set_session_save_handler()
Using a database would have its advantages if you use load balancing (or plan to do it once). This way all web servers could read the session data from the same database (or cluster) and the load balancer would not have to worry about which request should be forwarded to which web server. If session data is stored in files, which is the default mechanism, then a load balancer has to forwared each request of a session to the same physical web server, which is much more complex, as the load balancer has to work on HTTP level.
You could just store the information in a cookie if you only need it for the user's current session. Then you don't need to store it at all on your end.
There are a few down sides as well:
They may have cookies disabled, so you may not be able to save it.
If you need the information next time you may not be able to get it, as it could have been deleted.
Not super secure so don't save passwords, bank info, etc.
So if needing this information is required no matter what, maybe its not the way to go. If the information is optional, then this will work.
The default PHP session handler is the file handler. So, the pertinent questions are:
Are you using more than 1 webserver without sticky sessions (load balancing)?
Are you running out of disk space?
Do you ever intend to do those?
If yes (to any), then store it in a database. Or, even better, calculate the stuff on every request (or cache it somewhere like Memcached). You could also store the stuff in a signed cookie (to prevent tampering).

using mysql to track sessions instead of trusting the server?

Some context...skip to the bottom for question if you are impatient...
I am trying to limit access to four pages on my (future) website to users with a valid username and password pair. To this end, I have a simple PHP/HTML form...in my PHP/HTML form the client types in a username and password, hits 'submit'...the data goes to POST and another PHP script validates the user/passwd pair by using a SELECT in my mySQL database...
userpassword table:
uid (PRIMARY KEY,INT), username (varchar 32), password (char 128)
If the match works then it looks up the access table to see what page that particular username has access to (1 for access, 0 for no access):
useraccess table:
uid (PRIMARY KEY,INT), securename0(TINYINT), securepage1(TINYINT)...
The PHP script then prints out links to the secure pages they have access to. If I understand them correctly, the articles and books I have read state that you normally store a cookie on the client side with a session ID that points to a session file on server that stores the username/password pair and whatever other session variables until it either times out or the user logs out.
I don't want to spend the money for a dedicated server. So all that PHP session info is saved all lumped together on the server, along with the other half dozen websites from other customers running on it. This strikes me as horribly insecure...
The question is...would it be any more secure to circumvent all that and store/track the per-user session information in my own mySQL table? ie. something like this:
session table:
sessionkey (PRIMARYKEY, CHAR(128)), uid(INT), expiretimedate(DATETIME), accesstosecurepage0 (TINYINT), accesstosecurepage1(TINYINT)...
So when a user hits any "secure" page it would check their session id cookie (if present) and then do a SELECT on the session table to see if that particular "sessionkey" is present, then give them access depending on what accesstosecurepage0,1,2,etc. are set to.
Would this work better than the alternative or am I wasting my time?
This question is about as old as sessions themselves, although possibly for slightly different reasons than yours. Security is not the issue, as session hijacking occurs when someone gets hold of a user's session ID and sends that to the server. Therefore, using a database to store session data is as insecure as using a file on the machine - it essentially amounts to the same thing.
Database sessions tend to be used when multiple servers are required to host one site, or sessions need to be stored across different but related domains. However, it is considerably more work to set this up from scratch, if not using a pre-built framework.
If you don't need this functionality then using the standard session should be adequate.
I don't see this making your application any more secure. Session hijacking occurs when someone retrieves another user's session ID and pretends to be them. Your session table would not prevent this from happening. (I skipped to the bottom btw, hope I didn't miss any important details:)
It might even make it less secure since you are now giving hijackers two ways to steal session data: One through the file system and one through the DB. As to which one is more secure over the other, I'm not too sure, but I would think it depends on well you secure either one yourself.
Potentially more secure, yes -- after all, shared hosting is an infamous target for exactly the kind of security breaches you fear but, once again, the MySQL server is shared and accessible by other users just like all other resources so, worst case scenario, the damage is exactly the same.
The efficiency hit, however, would probably be unbearable and would almost certainly mitigate the extra peace of mind. To avoid the use of sessions or similar mechanisms completely, you wouldn't even have an easy way to cache the db results and a query per page load, per person - an unnecessary query - may well prove unacceptable.
Not to mention, you're replacing one class of vulnerability with a whole new one in the form of SQL injection.

Categories