I'm working on a website and want to create user login and session. What is the safest way to check if session exists or not (like cookie or session variable check), or any better idea then using sessions in php?
session_id() returns the session id for the current session or the empty string ("") if there is no current session (no current session id exists).
http://de.php.net/manual/en/function.session-id.php
but that just tells you if a session is active or not.
most of the time, i just call session_start(); at the beginning of every script (even if the user's not logged in). on login, i set $_SESSION['user'] with the userid or an user object. on logout, i just unset($_SESSION['user']);. by checking empty($_SESSION['user']) i can check if someone's still logged in or not. don't do this if you're storing user-dependant information elsewhere in your session, otherwise the next guy logging in may get info he's not supposed to see (in this case use session_destroy();).
but safety? just deactivate session-id propagation by GET/POST url rewrites (cookies only), so they don't end up in URLs that can be cached or distributed to others (in this case, session hijacking would be possible). you can do that by setting session.use_only_cookies in the php.ini.
there may be additional safety issues if you're hosting on an untrusted and/or misconfigured shared server - it could lead to other people on the same machine reading your session data. in this case you could store your session data in a database by rewriting your session handler. just search for session handler mysql on the intertubes, i'm sure there are enough ready-to-go solutions. and don't store sensitive information like passwords in the session, better do a query everytime you need to compare it.
other than that ... use ssl/https for login and user management, so no plaintext passwords are transfered. store only pw-hashes with salt in the database. don't let anybody see the passwords (meaning: never print them to html or emails). don't use auto_increment values for ids the user can see (and therefore, guess). ok, that's already out of the questions scope.
Here's some tutorials on Session Safety
PHP Security Guide: Sessions
Notes on PHP Session Security
PHP Session Security - php|works 2004 (old but still interesting)
PHP Session Security (PDF)
Related
I have two possibly elementary questions about php SESSIONs and cookies
1) How does the server know when a session terminates? Or when to get rid of the session_id and info etc. (that is, if session_destroy isn't called)
2) Being that on the client side a cookie is stored containing a unique session id that the server uses to identify the individual, if someone were to gain access to that session id they could access all of the same information right? Is there an extra level of security necessary then to identify a user other than simply checking the session information?
How does the server know when a session terminates?
Session is basically a bunch of data, stored on the server. The client is recognized and matched to a specific session by the session ID, stored in the session and on the client side in a cookie with the default name of PHPSESSID. (You can find its value in your browser or using session_id() function in PHP.) If the browser deletes this cookie, the session ID is lost on the client side, and there is no way the client can get back other data stored in the session on the server. This data is eventually deleted by the garbage collector.
The garbage collector is called with some probability each time when session_start() is called. The probability equals to gc_probability/gc_divisor. Garbage collector deletes the session data if the session was around for more than gc_maxlifetime seconds. You can check all these values in phpinfo() output or using e.g. ini_get('session.gc_maxlifetime'). That's about the session data on the server. Now about the client.
Session configuration contains a value session.cookie_lifetime. Quoting PHP manual:
session.cookie_lifetime specifies the lifetime of the cookie in seconds which is sent to the browser. The value 0 means "until the browser is closed." Defaults to 0.
From PHP Sessions and security:
0 have special meaning. It tells browsers not to store cookie to permanent storage. Therefore, when browser is terminated, session ID cookie is deleted immediately. If developer set other than 0, it may allow other users to use the session ID. Most applications should use "0" for this. If auto login feature is required, implement your own secure auto login feature. Do not use session ID for it.
You can check the setting using any of the following:
phpinfo(), look for session.cookie_lifetime in the session section.
session_get_cookie_params()['lifetime']
ini_get('session.cookie_lifetime')
So basically, if the session cookie lifetime is 0, the browser deletes it when it is closed and the client loses access to the session data.
If someone were to gain access to that session ID, they could access all of the same information?
Yes. As long as the ID is known to (any) client and the session data is not deleted on the server, the client can access it.
Is there an extra level of security necessary then to identify a user other than simply checking the session information?
It depends on your application. Getting the session ID is not trivial, one needs either to intercept the communication or have direct access to the client data. Interception can be prevented using TLS-based encrypted connection. Getting the client data requires some malicious software.
This article describes a safer cookie implementation for user authentication. In short, while it still doesn't prevent cookie hijacking, it gives you a way to detect it, notify the user and prevent the stolen cookie from being re-used.
Another article lists gives a more complete overview of good practices for user authentication. As usual, security requires that the whole project is implemented in a secure way, not just one, seemingly critical part of it. But if my suggest, don't overdo it. The effort should be reasonable for the particular requirements of each project.
This question already has answers here:
Creating a secure login using sessions and cookies in PHP
(5 answers)
Closed 9 years ago.
I would like to know what would be a proper way to create a login procedure.
Up to this point I thought it would be a good way to create a $_SESSION['login'] and even a $_COOKIE['login'] that both have the same content which is a kind of a timestamp plus an encrypted form of the password.
The logic behind that idea is to check if both exist and to compare their contents. If both exist and is the content equal you get access to the protected pages.
I do know that a Cookie is a kind of a Session. A Cookie will be stored on the users client site and the a Session as well but will last only as long as the browser will be open. I thought it would be possible to extend the lifetime of a Session even when the browser will be closed and the Session destroyed.
This should ensure that the SESSION could not be hacked and the COOKIE be stolen what makes it impossible for a hacker to get access to a profile of an User.
Am I right with that thoughts or how do you people did it?
Thanks alot.
First off you need to understand the difference between sessions and cookies.
Sessions and cookies are both key=>value stores. But where they're stored has great impact on their security properties.
Cookies are stored on the client machine. They are unsafe. A user can modify the value of a cookie, forget a cookie, send more cookies etc. Cookies can be stored for a very long period of time (months, years). Since the client stores the cookie you don't need to worry too much about space constraints. Just keep in mind that all the cookies are sent with every request.
Things you store in cookies are typically fairly inconsequential things like some preference settings or "I've already seen your popup asking me about questionnaire".
Session data is stored on the server, only the server can read from it and write to it. The user never sees what is in the session. Session data typically expires quickly, let's say anywhere between 30 minutes and 24 hours.
But how do you know which session belongs to which visitor? Well, you use a session identifier cookie. This is the only cookie you need for authentication. In PHP this cookie is PHPSESSID and it's created and used automatically when you call session_start();. The session cookie is a cookie with a random value that is hard to 'guess', which makes it secure.
The user will keep the session cookie. You can find the associated session data (automatically using $_SESSION). In the session data you can store whether the user is logged in, if so as which user, you can even store the rights a user has (like a mini-cache). You can treat this as an untamperable key=>value store, just make sure not to store too much in there (the limits depend on the storage mechanism).
Sessions are stored in a specific place; where depends on your webserver and OS. In PHP you can specify your own session storage handler by calling session_set_save_handler. This allows you to, for instance, keep your session data in a database.
If the value of the session identifier cookie is somehow exposed an attacker can hijack the session. It can be exposed by using an unsecured connection on a wifi access point (like in a bar). To counter this use HTTPS; cookies sent over HTTPS are encrypted and safe from this kind of man-in-the-middle attack. This is what the Firesheep plugin did (in 2010)
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.
IN PHP:
Is there a way for the user to fake a session variable?
Is it secure to trust in the value of a session variable for a login system?
The session data is stored on the server. Only the session id is transferred forth and back between the client and the server. Unless a server-side script messes up (or there is a bug) the client cannot change the session data directly. But you have to ensure that only the "correct" client knows the session id, as it ties this particular client to a particular session. E.g. (since you mentioned a login) use session_regenerate_id() whenever a login (attempt) is performed to prevent session fixation
Sessions are stored on your server, either in a file or in memory. The user only holds a cookie that defines the path (usually a hash of some form) to the session data on your server. Theoretically you could change the cookie to someone else's hash, but that is very, very improbable, unless you store them as files and don't delete them after they expire, in which case the probability of someone exploiting an old session would increase.
Yes.. It's called session forge/hijack.
You change the value of the session cookie until you get another user session.
To avoid storing session data in the server, you can sign the content you want to protect from change, before storing it on session, and then validate just after retrieval from session. In PHP this process is reasonable simple and eliminates server storage issues.
Notice that this does not protect session data from being visualized. If you need this protection, you can still avoid server storage by using safe encryption. Just beware that virtually every encryption scheme based on key size can be broken on near future. So if you need to protect your session data for say, 5 years, the secure choice of key and algorithm might create performance issues.
I'm looking for tips and ideas on how to best incorporate authentication with PHP using Cookies.
Should each php script check for the cookie value to determine if the user is still logged in? Should there be one script that does this check and Include that script from each of the other scripts? Can the cookie value be seen by php from different depths of the filesystem?
Like: blahblahblah.com/ and blahblahblah.com/login/
Can they both read the cookie?
Lots of questions on one post, but thanks!
nothing is safe on the client side.
You change the login flag on Cookies easily on any browser. Thus it is more recommended to be saving login-related data on php's $_SESSION
If you wish to extend the session, simply look at session_set_cookie_params().
By default, the same session will be used for the current domain and all the paths on that domain. Thus it is readable for both blahblahblah.com/ and blahblahblah.com/login/
When the user logs in, save the username and the hash of the password in the Session.
At the start of each script, verify the Session's username and password with the one in database. If is correct, then set a flag (e.g. $userLoggedIn = true) to indicate on server-side that the user is logged in. else false.
Some thoughts, in no particular order:
Separate out the various layers: persistent storage vs authentication.
PHP sessions are quite robust and are the recommended way to maintain persistent storage.
You can have a valid session, but not a valid login.
Avoid multiple cookies. One is enough. PHP sessions work with one cookie.
You can set sub-domains and paths on cookies, but there's really little point unless you set lots, which is not recommended (see above).
Put everything you think you might want in a cookie in the session instead.
You should have some common code that all your pages include. That is where you initialize your session. Then everything will Just Work. It can also verify the login is valid, too.
Have one place that does the login authentication and everything associated with that.
Don't forget a logout screen!
Its a good idea to have one script do the session/login check and include it in the secure pages. AS for the depth , you can define that in the setcookie() if the directory parameter is set to "/" then its accessible all across.
Generally its a good idea to use sessions instead of cookies , as thats more secure , but you can decide to build your own session system based on encrypted data in the cookie and that can work too , but again sessions, which store data on the server side are recommended.
The cookie is per domain, so no matter how deep you are in your directory structure, the cookie will be read OK (as long as your domain stays the same - NB this means that www.example.com and example.com can be different cookies).
I'd suggest having an authentication check that compares the session ID in the cookie with eg a database table listing logged in users and their session ID - this check can be in its own method/include file that is include()'d on each page. That way the check will be performed on every page load. NB this is basic and there are much more secure methods - some of which have been mentioned in other comments here.
As Mauris said though, nothing is safe on the client side - don't use a cookie to store a "logged_in" value which you check for true/false!