I'm designing a web based php reporting system. It involves multiple pages that insert and update to a mysql server. Basically, I want someone to be able to log on, start a report, then go through a fairly long reporting process step by step. Before they were simply filling out excel spreadsheets. I've basically set up a $_SESSION[$var] = (the auto increment ID) of the score table.
$returnQuery = "Select AssessmentID FROM opsassessment.assessmentscores WHERE Date = '$Date' AND InspectorID = '$inspectorResult2[0]'
AND PlantAssistID = '$assistResult2[0]' AND Plant = '$plantResult2[0]'";
$return = mysql_query ($returnQuery);
$return2 = mysql_fetch_row($return);
$_SESSION["return2"] = $return2[0];
echo "The ID for this session is: " . $_SESSION["return2"];
I then assign the session variable to a variable within each page. Then use that variable to update the assessmentscores table with data from several checkboxes. I have two questions about this:
Is there a "better" way of doing this? vague I know. While the system does work I have a suspiscion that there is an easier or more traditional way of doing it.
How much of a security risk am I running my using session?
Note: this is a closed off network so no one outside the company should be able to acccess the webpages unless the network is already hacked. Also, I've implemented SQL injection prevention such as stripping HTML and special characters.
Any comments and/or feedback would be appreciated.
The session data is as secure as your server is. None of the data stored IN the session is every physically transmitted to the user, unless you chose to do so.
The only session-related data that every is (or SHOULD be) transmitted to the user is the ID of the session.
However, storing the ID number in the session can be problematic. Consider the case where a user starts two reports at roughly the same time. Whichever report is started last will overwrite the ID number of the first report, and now all operations in both windows affect report #2.
Sessions were meant to do EXACTLY what you are doing.
And they are safer then the other options, because their storage is server-side (opposed to cookie storage), so the only way someone can access the sessions is if they have access to the webserver's session directory, and if that happens you have bigger problems to worry about.
It is possible to steal a session, but the attacker would need the user's session cookie.
But keep doing like you are doing, store the row's primary ID to prevent extra queries, it is the way it should be done (I would use the $_SESSION variable directly, instead of copying it to another var)
More on session security on SO:
PHP Session Security
Security of $_SESSION array
Related
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.
Another, maybe dummie, question. I'm making a website and now I've dilemma between $_SESSION and requesting user data directly from the table itself. So, my two ideas right now:
Retrieve needed values from mySQL and then set them to $_SESSION array. So, when I need something I can just call $_SESSION["username"]. It has some disadvantages also. For example, if admin changes some user data, ie username(that is a lame example, but still).
Retrieve value straight from SQL. In this case I can call some function what calls a SQL query and gives me result.
So, question is, which method is better to use or there are any alternatives you can suggest.
Thanks.
For frequently-used data but relatively unchanging data, such as names ("Hello, $firstname, welcome back") that would be used on every page request, you probably should cache them in the session. The slight additional parsing/loading overhead will be far less than having to yank that data out of the DB each time.
For relatively critical data, e.g. 'account is disabled', you may want to hit the database each time. However, this would depend on your security needs. If it's ok for a banned user to be able to wander around your system for a short period after their account is disabled, you can implement a time-out counter in the session, e.g. after every 50 hits, you refresh the data in the session regardless.
do not hold username in SESSION, instead hold user id, and don't let the admin to change the user id. once an account created, it's user id shouldn't be modified. and for each page load check stuff from DB.
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.
I'm currently building a web application that uses a combination of OpenID and uname/pw authentication to authenticate users. Users are supplied a PHP session when they login successfully, and some information about their account (email address, usergroup, blah blah) is written to that session.
However, there may be a need for me or someone else as an administrator to update a users details (or to ban them immediately if they're very naughty). I'm hesitant to use a killsession tag like this (pseudocode):
session_start();
mysql_start(connection_stuff);
if (mysql_query("SELECT FROM users WHERE uid = '$_SESSION['uid']' AND KillSession = true")) { Kill session, force reauthentication };
However, doing it like this has two flaws:
We have to query the database every time someone loads a page to see if something changed
We gotta log the user out which just annoys him (or reload all of his session variables, which doesn't seem efficient)
Is there some way I can modify a user's session while they're still in it without having to resort to forcing them to login again? Some people seem to suggest in this stackoverflow thread using session_id to change to the user and then fiddle with their variables, but that seems like a shoehorn way of doing it. Thanks in advance!
I think instead of storing that stuff along with the session, it should be kept (and cached) separately. That way you avoid data duplication and the issue you're running into right now.
If an admin needs to kill the session, just DELETE it from the table.
Even though you express concerns about having to query the database on every page load, my guess is that it most likely does not affect performance noticeably. If the website is database driven in the first place, them it's just a matter of a single more query. I'd actually say that moving the entire session handling to the database (store session variables in a table) can make your system better in terms on flexibility. It will be much easier to deploy your system on multiple servers and do proper load balancing if that is someting you think will become necessary at son point. That is how the bigger CMS systems handle their sessions. My advise is, in other words, to stick with the extra query and actually consider to move session state to the database.
I've got a php application and I'm saving the session variables for the user using $_SESSION itself. Is there any particular advantage of storing it in a database?
I'm looking for a reliable / well-researched article which talks more about this. I havent been able to locate anything yet.
The advantage you have of storing it in a database is that the data exists as long as you want it to exist.
Your browser will destroy the session according to how it is setup, which makes it a bit unreliable. I can't however find an article on this yet but this is what I use as a convention for a situation like this.
Any data that needs to be stored long term, like user details and activity I store in a database. Any data that is only relevant to the current workspace, like logging into a site and posting a few comments etc. can be stored in the session. For instance I store user authentication details in a session to constantly check whether the user is logged in or not and whether to redirect him/her to the correct page.
This works wonders when checking access rights throughout your application.
For me its much safer to store user details in a database because it cannot be publically accessed like the $_SESSION.
Please disagree with me if you want to though.
I would say storing in database is better.Because
When you are hosting your site with a shared host
PHP uses the same path for storing sessions for all the users,somewhere that is not in your folders.
You can track the users and their status easily.
For application that are running on multiple servers, you can store
all the session data in one database.
This article may help.
Well this is a question for the ages. Personally from what I have learned in my time. Unless your site starts booming on a massively large scale where you need to start using multiple servers for various aspects of the system such as load balancing where you have many mirror systems running. Or need to improve performance a little for an over populated system the benefits of using DB related sessions or File based sessions really isn't any different.. Grant it I could be wrong this is merely my own personal perception off my own experiences. Just like you Ive never really found any articles, posts, other that really put either to the test side by side hell I don't even think I have found anything that really puts either to the test stand alone for that matter. Personally I just go with what ever the need is (or desire of my client) usually I just stick to native sessions file based.
I hear they can be spoofed, but have seen no proof to that notion to date. So other than that potential I stick with file based. Unless I am using a system like code igniter then sessions seem to handle better DB driven with it rather than not.
At some point in time you're going to have to store something in a session. Whether it's all the session variables or just the ID of a row in a sessions table. That being the case it would be fairly easy to alter the ID stored in a badly encrypted session and hijack a different session.
Consider this:
Full Session Option. This has the User ID, Username and an encrypted and hashed password stored so that every time a page is called it verifies my login. To hijack someone else's session I'd have to know their User ID, Username and Password Hash and be able to overcome the sessions inherent encryption.
Session + DB Option. This just has a Session ID stored that references a row in a database. All I have to do to change the session I want is to break the encryption on the session and say add one to the Session ID. I'd then be authenticated as the user that logged in after me.
You could store login details in a session and then any none login related data in a session table if you have a lot of extra information but then again you might as well just remove the need for an extra table and extract the data from whatever relevant tables you need.
From my short experience, you should store in $_SESSION only data that you will NOT need to be refreshed in all sessions opened by a unique user in different devices.
(mobile/desktop/etc.)
In other words, data that you are sure will never change like a userID.
For example, I had stored the user profile picture path into
$_SESSION and it led to a strange User Experience. When changing the
profile picture in a desktop, it did not refresh the profile picture
for the user on his mobile. Other users saw the new picture though.
Indeed, the path was refreshed into the DB but not in the $_SESSION.
Login-out and Login-in would not change anything.
Remember that the default behavior is that $_SESSION passed with cookie will be different for each browser even if this is the same user logged in. You will have to do a session_destroy() to avoid being stuck with old data.
Very temporary data may be stored in $_SESSION as well I guess.
NB: the basic need of global session, out of these arguments, is to have variables available globally