Is there currently - or has there ever been - any serious or significant problem with PHP's built-in session handling?
I mean, it's always worked for me and my projects.
But I see some codebases and frameworks out there seem to use a custom handler. Is this reinventing the wheel? Or improving on some flaws? What flaws?
Pros and cons of PHP's built-in session handler
Pros:
Easy to use (just use session_start() and you're done)
Available OOTB.
Cons:
Uses only SESSID (or SID, SESSIONID, etc.) cookie to recognize user. That's not much, and this information can be easily stolen using XSS attacks or something like that.
In most cases you aren't able to do things like get total count of active sessions (often used in Who's online? features)
Pros and cons of your own session handler
Pros:
Works in the way you want it to work
Total control over how do you recognize users. You can use cookie, IP address, browser signature to make sure that stealing session is impossible (or at least it's much harder task).
You can chose the place where the session data is stored (database/filesystem)
You've got control over session mechanism as a whole
Cons:
You have to spend several minutes to create a such handler
Is there currently - or has there ever
been - any serious or significant
problem with PHP's built-in session
handling?
No problems with the built-in handlers. Access and deletion of old session files are implemented well.
Is this reinventing the wheel? Or
improving on some flaws? What flaws?
File based session handling works fine for single server websites. Problems may arise when applications need to be run on multiple servers (scaled out). A master database can be used to store and provide session information across multiple servers. This can make things easier when an application is scaled out. Custom session handlers can be used to interact with the database.
One of the major advantages of overriding the session behavior is being able to persist the session information into a database. When that is combined with user authentication it can become a powerful tool.
It really opens up a whole new set of possibilities:
Build session management tools for site administrators
Audit trail of a user's session data.
Ability to lock a users account and easily kill active sessions
etc.
A reason to roll your own session handlers would be implementing a single-sign-on system, or session sharing with other applications (= validation of sessions by a Java/CF/whatever application).
Sessions can only be up to a certain size no?
Related
A user logs in using default Laravel authentication, which puts an encrypted cookie in the browser, and saves the session in the database.
The user moves to a classic asp page, where I check the cookie value, get the hash, and call the laravel app back passing the session id hash.
Then I use that in laravel to see if there's an active session for that id, and if so I return true, so the user can be logged in, in classic asp.
On each page request in the classic app, I check the last_updated_time in the db and update it on each page. All logging in and out is done in laravel, and classic relies on the database to see if a session is active.
I would also call a public url to get sessions variables and add session variables using laravel, since it's all encrypted and using classic asp for this would be hard.
The only risk I see is session highjacking, but I don't think it's a higher risk than usual.
Is it important to lockdown the laravel URL I call to check if it's a valid session?
Am I missing a security hole here?
Is this method secure?
From what you've stated you probably haven't opened up any security holes. The session cookie is not itself encrypted on the users machine, but you are making sure it is encrypted between their machines and yours, as well as between each of your machines. You should make sure you've set the Secure Flag to help prevent the cookie being accidentally sent over traditional unencrypted transport (HTTP), but as stated, this doesn't effect storing the cookie itself.
That being said, you are essentially hijacking your own users sessions. While a hole might not be introduced now, you are potentially weakening the overall system, which could lead to hole in the future.
Is there a better way to do it?
This might well be a dumb question, but are you sure you need the session? If you're juggling credentials between servers, it sounds more like you want to use Access Tokens and scrap the session.
Using Access Tokens is similar to using sessions, but you need to make your services stateless. This means your no longer storing information about the logged in user any specific machine so you'll need to pull anything you need from the database every time they hit a server requiring that information.
This is a good thing in the long run as it's much easier to scale your services when you don't need to worry so much about where the session is and what's inside it.
OAuth 2.0 is widely used standard (Facebook, Twitter, Google), and was specifically designed to be easy to use. The RFC is complex, but there's a log of good guides out there don't worry.
The one slight down side (if you can call it that) to OAuth 2, is that it MUST happen over an encrypted connection. If your use case can not guarantee encryption over SSL or (preferably) TLS, then you should use OAuth 1.0 (WITH revision A) instead.
This is due to the fact that OAuth 2.0 exposes it's "secret" token in requests, where as OAuth 1.0 only ever uses it to provide a signature hash. If you take this route it's advisable to use someone else's library as the hash is very, specific.
Further Improvement
(Note: This section added after the answer was accepted)
One system I've been exploring recently is Json Web Tokens. These store information about the user to save each machine repeatedly looking it up in a database. Because the token is hashed with a secret, you can be sure that, so long as your secret isn't exposed, a valid token represents a successfully logged in user, without having to touch the database.
You should avoid putting anything too personal in the tokens if possible. If you must store private or secret information in the token, you can encrypt it, or you can use a reverse caching proxy to exchange the JWT for a traditional security token. This may initially seem to defeat the purpose, but it means some of your services may not need database access at all.
I'm no security expert but I don't see an issue with this. The packaged Laravel database session handler works the same way. The cookie contains a hash that references a record in the database. The session data is base64 encoded but that's neither here nor there. I think you could actually avoid rolling your own and just use Laravel's DatabaseSessionHandler.
Illuminate/Session/DatabaseSessionHandler
... I just read a little deeper into your question and noticed the part about the public URL to set and retrieve session data. I think this is a really bad idea. Mostly because it will provide an open door to the end user allowing them to read and write session data. This can only end badly.
Like I said above, the data is only base64 encoded so I believe you'll be able to parse, read and write that to your hearts content within asp.
Edit
Ok... I think this is the last edit. The data is php serialized and then base64 encoded. This question looks like it may help you to that end. If it doesn't and an API endpoint is the only way, find some way to block the end user from accessing it.
Aside from session-hijacking, no. This is the standard way applications interact on a internal basis. Of course there might be a better way to get at the data if you choose a different type of session store other than your database, Memcached for instance.
There are couple of things that can be done.
Make the channel HTTPS. It will make almost impossible to sniff on your transport layer.
Rather than making interactions with your cookie, you could use a JWT to get this task done. Which will help you to use the existing functionality in your system while connecting with ASP system as well. You can write a small REST web service which allows ASP to connect. You could use this lib. You can refer this article which will give you an idea how it should be done.
Please let me know if you need more information.
I always set several vars on $_SESSION array to control access on my sites, but I would like to know if this is a safe solution or there would be something better than:
($_SESSION['admin'] == 1) ? take_control_of_my_site : get_back;
Session data is maintained on the server side. You can rely on the data as long as
Your server is secure
You carefully validate any data that you place into the session.
Session is safe. Even the name of a session variable is safe and choosing another name will not increase security.
The problem in PHP is the session mechanism. It uses files by default which can slow down your site considerably and scales very poorly, and can potentially be insecure hence the suoshin php patch.
Using sessions from a database back end is much more secure, scales well, and keeps your session data safe (relies on database based security). If a hacker has your database, sessions are the least of your worries as they probably have all your password hashes as well.
Sessions are not inherently unsafe. There are risks, but they can be mitigated.
It is good to be aware of the risks, so that you can learn how to avoid them, but the one thing you shouldn't do is avoid using sessions altogether because of them. Sessions are a well-established tool, and used properly they are perfectly safe and secure.
In fact, it's pretty hard to write a useful web site that doesn't use some kind of session. If you don't use the built-in one, then you'll end up writing your own -- and in most cases, that really is a security risk. (I know of programmers who have become obsessed with the security risks of sessions, and ended up implementing far less secure solutions simply because they didn't want to use sessions).
It's worth pointing out that recent versions of PHP have made huge strides forward in terms of security. There were a number of features in old PHP versions that were genuinely bad for security; recent versions of PHP have made big efforts to deprecate and remove these bad features. You will note that sessions are not in that list. They haven't needed any significant security work. This should tell you all you need to know.
Sessions are stored by default on the server in plain text. This shouldn't be a problem, unless your server can be accessed by unwanted users. If this is the case, then your security is probably already shot, so it's not really an issue, but in the rare occasion that you might be worried about that, it is possible to get PHP to provide session encryption via the session_set_save_handler() function.
I'm not concerned with browser compatibility.
I want to know if I move my state from PHP Controlled ( Server-Side) sessions to the JavaScript Controlled ( Client - Side ) HTML 5 local storage will I gain or loose security.
I think that I would gain security because now instead of having the user identifier residing in a cookie, which is usually a file, or sql database that is easily accessible...it is not inside some sort of internal browser storage. + b.c. it is a newer technology I would hope that more security was designed into it.
Do I gain or loose security by moving from PHP Sessions to JavaScript Local Storage. ( This is for things like user id, page_id, etc, the current state that remains after a reload and longer if needed ).
I have a JavaScript solution I want to replace my PHP Sessions with. That is why I ask. I don't care about browser compatibility.
Here is an informative site on Local Storage. But Security was not mentioned.
Both types of local storage (localStorage and Cookies) use some sort of identifier which is obviously stored on the client.
Both use a hash mechanism to secure it from altering to another user.
Local Storage is more secure then cookies ( see here ).
And obviously you have to write the session protocols if you want to move your user identifier from cookies to localStorage.
Both can be stolen to fake being another user. Though less likely with localStorage.
And to make robust you need a fingerprinting technique that will help with above problem.
I have a JavaScript solution I want to replace my PHP Sessions with.
No. Do not do it. Sessions are stored in the server side. The cookie that is sent out to the browser is typically an identifier for that record. Session stores user-specific data. Almost anything stored on the client side can be easily modified by the user. So if the user modifies the session to point to another user, the security would no longer hold.
LocalStorage is NOT for storing sessions. Stick with PHP sessions, or any other session mechanism that is implemented on the server side.
Update
But the same security flaw is present...a user can login as one
person...fiddle with the session_id of the Session and become someone
else...fiddling with a session_id...equates to fiddling with who you
appear to be to the server ?...this would be the same as fiddling with
an encrypted user_id in local_storage.
No. Suppose I figure out the algorithm you are encrypting with. And I know of another user say UserB. I encrpyted his username using that algorithm. If I somehow overwrite my localStorage with that encrypted string, I am him now. That is not much possible practically. Think of it as there are 100 users and 128 byte-string is the identifier. Are you sure you would be able to fiddle with it and modify it into another record which exists in the table of sessions?
Local storage is best suited for data that you want to cache on the client in a (more permanent) way then with the regular browser cache. The only way it's "more secure" is if you want to allow the user to work with data that's never sent to the server.
If you're worried about session hijacking, the preferred solution would be to use https/ssl and encrypt all traffic between you and the client. There's a general overview of the problem and solutions on wikipedia (we'd need more information to give you anything much more specific than that, though).
You wouldn't gain or lose security as in most browsers all data set by sites are stored in the same folder
I know that codeigniter stores it's sessions as a cookie, which, from reading around I understand to be somewhat insecure. So... I am planning to enable database storage for sessions, which I believe:
a) Is safer?
b) Allows you to store more data than the 4kb limit offered by cookies?
However on the flipside I guess this will be slower for the system to retrieve, for example, in my application I regularly want to query the session data to determine if a user is logged in.
Is is a good idea to store sessions in the database, or will this slow down my app considerably?
Any other ideas or suggestions regarding sessions and cookies would be most appreciated.
Well, that is true and false. CodeIgniter can be configured to store its data on a DB, but it can encrypt the cookies before storing them on the client. It also MD5's the cookies contents to ensure data integrity (basically if the Cookie's MD5 doesn't match correctly, then it is rejected). So while by default it is possible to edit the cookies, it is more than annoying to do so.
Personally, I generally prefer to store session level data in the $_SESSION and have modified my session object to allow me to do that. I also make the PHPSESSID variable a good deal more complicated.
As to your question, "Is it a good idea to store sessions in the database", well, that depends on how fast your database is and what your memory requirements are. It could slow things down or it could, conceivably, speed things up based on configurations et al.
I have website w1 written in rails using auhtlogic for authentication and w2 in PHP(say), I want w2 to access session information stored by w2 and login user into w2 and also retrieve user_id from session.
By default, Rack (which Rails uses to manage its sessions) stores session information in cookies by marshalling the session hash (see here), which results in a string that is specific to Ruby. It would be extremely difficult to use PHP to deserialize this information.
If you're dead set on doing this, you're going to have to handle the session serialization yourself. I think a full solution is outside the scope of a single question on SO, but a few pointers:
It would be wise to store only a session id in the cookie, and then keep the actual session data in a database that would be accessible from both the PHP and Rails apps. If you really want to keep the session information in a cookie (or in another place like memcached, where you'd also have to serialize it), look into serialization strategies that work across languages, like MessagePack.
You'll want to do something to ensure that the cookie is not tampered with by the user. Rack uses HMAC, which is a good solution. I've never used PHP, but I'm sure they also have a library for it.
You probably already know this, but just in case: This is all assuming that your two apps are sharing the same domain name. If they're not, then your users' browsers won't share the cookie between the two apps, and there's not really anything you can do. For example, you could share sessions between railsapp.yourdomain.com and phpapp.yourdomain.com, but not railsapp.com and phpapp.com.
Good luck!
i tried a solution sometime ago that was more a hack, but for my propose it worked.
after login, i used to write the user's cookie in a file in a public directory and when this user tried to access the other server where he had to access too, my application on this second server, just had to "know how to access" the remote file stored in the first server and load this content as cookie. I did used CURL at that time.
Note that it introduce some security breaches, and probably your security will rely on "obscurity" - for example, the algorithm to mount the file name where the cookie is stored and how to access it and any external webserver configuration.. Said that, i think we could think as well use a shared memcached to store the cookies..
Have you considered using Open ID?