I've built a class that provides some basic "can I do this?" authorization functions for my site, stuff like "can this user view this resource?" or "can this user add an image?"
So the class object is instantiated in quite a few pages (potentially, every page that has a user interaction) using $authorize = new myAuthorizationClass();
The myAuthorizationClass class then looks up the user's ID and check their access level.
I can then say something like
if ($authorize->canAddImage()){
// do image add stuff
}
Is it possible, secure and "best practice" to store this $authorize object into the session? Is there another way to avoid the overhead of building this auth object on every page, and doing the DB interactions etc?
I don't think it can be as simple as just saying "set the user's auth level to A, B, or C, and set that in their session!" since their access to a particular resource depends on who owns the resource, what role the user has in the site, etc. and we have to check a few different things depending on what type of resource is being accessed.
Thanks
Storing user data within a session (not cookie) is acceptable, as this data is stored on the server side and randomly generated for every user, and as long as your session handling storage is protected, will not be accessible to other users.
If you want to reduce database load by not having to look up the users role/access for every page request, you may want to consider pulling the information upon successful login then storing the (in serialized format) into a session variable. Then, for protected resources, you can unserialize the data stored within the variable, do your check, and proceed accordingly.
I believe it is considered bad practice to store authorization data within sessions.
The reason is quite simple, while the data itself is stored on the server side, where it's safe, the weaker link is actually still (like always) on the client.
The server must identify the client who owns the data somehow, that is usually done in a form of a session_id cookie sent to the user. That cookie will be sent to the server in each request, and the server will be able to figure out who you are by the (very random) ID.
However, over an unsecured WiFi (or a computer), that cookie can be rather easily stolen by an attacker, which will cause the server to identify him as you.
There is no simple way around this, other then SSL and user education. If your site requires very high security (such as money transactions or critical database operations), inform the users about it and advise them to confirm their local security measures.
Also, if your site deals with critical database operations, don't allow anything critical (deletion, table drops etc) done from the web application. Only via the root user.
Related
I've been reading up on (mysql) triggers the last few days... specifically what I'm trying to do is figure out a good methodology for updating a user's information.
The case use for this is related to a user management system:
Take for instance a admin user updating a regular user to a manager, this user type change would then enable|disable software features on the interface.
Problem:
You won't know about this user type change unless you query the database and reset say for example the $_SESSION['user']['type'] variable, and or the user logs-in|out of the system.
Question: Is there any good methodologies to solve this headache?
I don't think mysql triggers would be ideal for this. Why? Because you will most probably end up with part of logic in php and part in mysql. It's a good thing to stay with one technology because it will be easier to maintain/debug code for you and your colleagues later.
So in your case, if you want the change of user role would take immediate action, you would have to either load user role on each script run or log out user using some flag in database that would signal that his session is not valid anymore (or you could implement your own session_set_save_handler that would save session somewhere in file where you could delete it to log out user).
It depends on your needs which solution would better fits your case.
If your roles logic is complicated and it consists of multiple roles assigned to one user as well as extra permissions assignments/excludes per user it may be better to do this check once on user log in and then just remember the result using session.
If checking for permissions on each script run isn't an issue, you can do it. But be aware, for security reasons, it may be a good practice to force user to log in again.
If the user log out could cause lose of work, you should let user log out itself and apply new permissions after next log in (you can show user a message that new permissions are awaiting log in to take effect).
So it really depends on your needs to choose if it's better to log out user, give him new permissions right away or wait until next log in.
Question: Is there any good methodologies to solve this headache?
Find good reasons not to do it!
While this might sound like a joke, i am completely serious. You have to consider:
What is the value of that feature?
Is it worth the headache cost?
What are the risks of that feature (incomplete work / system consistency)?
Do you have to change the system core?
Would you have to revalidate the system?
Are there other really great features (system improvements) waiting to be implemented?
Someone who doesn't feel comfortable answering these questions doesn't really need that feature.
Find simple alternatives:
Call the user and ask to log out.
Notify the user per email.
Provide a button for email notification.
Send email notification automatically after changing permissions.
This is no laziness. Just focus on real value.
One alternative would be to do ajax requests, with some time interval, that will update your user $_SESSION.
If you have any changes in your 'type', you can do whatever you want, like force user do re-login your application, or do nothing but update $_SESSION information.
Of course, you need to know if you really need to get this information before user logout and login next time, with updated profile.
I think storing your session into caching mechanism like Redis would give you added advantage. It is light weighted than storing session data in database. You can create clusters very easily. Click here to see sample implementation.
So once a user "type" changes, you can load the redis data cache and update it as per your wish.
I think the safest way to do this, and the one that I would choose is the "headache" way.
'regular' user A logs in and opens session A1.
'admin' user upgrades A to a 'manager'.
For now, session A1 is a valid session, but it will not grant the user 'manager' privileges.
When user A logs out and logs back into session A2, this session will now grant the user all the privileges of a 'manager, having looked up the current 'type' from the database.
Alternative that may be slightly expensive depending on your application:
Every time a user presents a session token, use the database to check against the validity of the session. If that session has invalid info (ie. the 'type' no longer matches) then force the user to log back in again.
Adding another alternative:
Don't use a MYSQL trigger, when the application caller (the admin) updates User A's 'type', it also makes a call to wherever you're caching the sessions and either (a) updates the session (inadvisable*) or (b) renders the session invalid and forces the user to log in again.
*Note that all of these solutions require the user to re-enter their credentials after they have new-found 'manager' power before they have access to the 'manager stuff'. I think this is a safer practice than updating the session without any authentication.
My recommended methodology would be to store the type of each user in the database. The problems that would arise if you decided to store the type as a session variable would be (among others):
Once the session expires, this information would be lost. Usually sessions last 30 minutes, though you could modify this to be as long as you want. However if you create a session that lasts 1 month, then anyone who has access to that users computer would be logged into the users account without needing to use any password.
You would be unable to use powerful and advances queries offered by databases (like MySQL for instance which uses SQL). If you store your information in sessions, sure you can find a way to look up each users information 1 by 1, but why reinvent the wheel? It is not easy developing a database structure from scratch, so I wouldn't recommend doing it.
Regarding your concerns on accessing a database once the information has been updated, I wouldn't say this information is as concerning as you might believe it to be. Lets imagine the following examples:
1)
If a user for instance is a manager currently and loads a website where he can do powerful actions, and right afterwards he is demoted to being a normal user, then having this information in the database would work perfectly. If the user tries to use his powers (that are no longer his), he would click a button that would send an a request to the database to confirm his type. Database queries are very fast, so speed is not an issue. I would be more concerned of the speed it takes for you to obtain information from a session variable than from the database.
2)
If the user was on a page while he was a normal user, and while on the page he became a manager, then he would be able to exercise his powers after refreshing the page. I mean if you used sessions and you wanted to have the page obtain the information automatically with something like AJAX and then update his options on the page, that would consume much more server power than a simple refresh.
To give a simple SELECT * FROM myTable WHERE id = 4 can take as little as 1 millisecond to be executed on a database. Databases have been especially designed for their speed which is why they are prefered
HOWEVER, maybe you don't have access to a database and that is why you are searching for an alternative? Well you are in luck! MySQLi is a database which only uses a file to store the information. It was especially designed for users that don't have much resources, and has many of the capabilities as MySQL would have.
Since every user has a role or type it means that the ability of viewing or editing content in your application is solidly connected to this factor. This means that the 2 basic things that your session variables should have are userID and userType which you should also store in your database
These pieces of information can be passed to $_SESSION['user'] for example as a small array where your array key can be the userID and the userType the value.
$_SESSION['user']=array($userID => $userType);
Once a user login your initial values are stored to session. In order for your application to know what userA can view or edit in your application, you basically run a comparison in your script against the userType that userA has. But to achieve what you want you basically need to re-fetch the piece of information in the beginning of every VIEW/PAGE of your application. If new userType has been assigned to userA simply show a message that he/she will log out automatically in 15 seconds (give time to read the message itself) in order for the changes to take effect. While your user sees this message you take the current session data he/she may have and save it in database, since some session variables might be (or not) available in a upgrade or downgrade of userType. By placing the comparison of the userType in the beginning of each VIEW/PAGE of your application you save yourself of the headache that a user can loose data.
If your scripts use $_SESSION['user']['type'] to know about the user's privileges, I would just change its value.
Or perhaps I didn't understand the issue ?
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.
My question is if a user comes along and uses an Object Oriented PHP application, how are those objects tied to the user and what happens to them once the user leaves?
I understand how OO
PHP is a shared-nothing architecture, which means that for every HTTP request the browser makes, the application starts with an empty sheet (so far as PHP internals such as variables and loaded classes are concerned). Every PHP object disappears at the end of the request. Permanent data needs to be stored elsewhere (typically a database plus possibly a key-value based cache such as memcached). How user-related data is handled in those outside storages depends entirely on the application.
Objects are not really ever tied to a user... It sounds like you are talking about sessions variables. You can store some information for an individual user by adding it to the php $_SESSION variable like this for example: $_SESSION['user_id'] = 5. Once the user leaves, that information will still be accessible until it expires (You can set the expiration date, or typically it will expire when the user closes their browser). For most web applications dealing with users, the user will be asked to log in and when they do, information about that user gets stored in the session. This allows a user to stay signed in across multiple pages of the pages application. Then if the user decides to log out, this is when you unset or destroy that session data.
When an HTTP request is received, PHP is fired up, sets up the runtime environment for your code and runs it. Afterwards all of this is torn down, to be re-created from scratch on the next request.
So unless you take explicit steps to persist your objects (or any other type of variable, really) to e.g. disk and then read them back on a subsequent request, there will be no trace of objects created in the past at all.
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
This question may expose my ignorance as a web developer, but that wouldn't exactly be a bad thing for me now would it?
I have the need to store user-state information. Examples of information that I need to store per user. (define user: unauthenticated visitor)
User arrived to the site from google/bing/yahoo
User utilized the search feature (true/false)
List of previous visited product pages on current visit
It is my understanding that I could store this in the view state, but that causes a problem with page load from the end-users' perspective because a significant amount of non-viewable information is being transferred to and from the end-users even though the server is the only side that needs the info.
On a similar note, it is my understanding that the session state can be used to store such information, but does not this also result in the same information being transferred to the user and stored in their cookie? (Not quite as bad as viewstate, but it does not feel ideal).
This leaves me with either a server-only-session storage system or a mem-caching solution.
Is memcached the only good option here?
Items 1 and 2 seem to be logging information - i.e. there's no obvious requirement to refer back them, unless you want to keep their search terms. So just write it to a log somewhere and forget about it?
I could store this in the view state
I'm guessing that's a asp.net thing - certainly it doesn't mean anything to me, so I can't comment.
it is my understanding that the session state can be used to store such information
Yes - it would be my repository of choice for item 3.
does not this also result in the same information being transferred to the user and stored in their cookie?
No - a session cookie is just a handle to data stored server-side in PHP (and every other HTTP sesion imlpementation I've come across).
This leaves me with either a server-only-session storage system or a mem-caching solution
memcache is only really any use as a session storage substrate.
Whether you should use memcache as your session storage substrate....on a single server, there's not a lot of advantage here - although NT (IIRC) uses fixed size caches/buffers (whereas Posix/Unix/Linux will use all available memory) I'd still expect most the session I/O to be to memory rather than disk unless your site is overloaded. The real advantage is if you're running a cluster (but in that scenario you might want to consider something like Cassandra).
IME, sessions are not that great of an overhead, however if you want to keep an indefinite history of the activity in a session, then you should overflow the data (or keep it seperate from) the session to prevent it getting too large.
C.
Memcached is good for read often/write rarely key/value data, it is a cache as the name implies. e.g. if you are serving up product info that changes infrequently you store it in memcached so you are not querying the database repeatedly for semi static data. You should use session state to store your info, the only thing that will be passed to and fro is the session identifier, not the actual data, that stays on the server.