I've been interested in how sessions work internally, but I have little knowledge of C (and am unsure where to look in the PHP source for this).
This is what I understand of sessions at the moment:
When you start a session the user gets assigned a session id which is stored in a cookie.
When session data is saved (via $_SESSION) it is stored on the filesystem, with the relevant session id and an expiry time.
Is this correct? Also what is the method in which session id are created? I assume it's based on time but what if two users send a request at the same time? What methods are in place internally to prevent them getting the same id?
Thanks,
My understanding is of the internal session handling process is the following:
When session_start is called, PHP is looking for a parameter from the client that was sent via POST, GET, or in a cookie (depending on the configuration; see session.use_cookies, session.use_only_cookies, and session.use_trans_sid) with the name of the value of session.name to use the session ID of an already started session.
If it finds a valid session ID, it tries to retrieve the session data from the storage (see session.save_handler) to load the data into $_SESSION. If it can’t find an ID or its usage is forbidden, PHP generates a new ID using a hash function (see session.hash_function) on data of a source that generates random data (see session.entropy_file).
At the end of the runtime or when session_write_close is called, the session data in $_SESSION is stored away into the designated storage.
Look at php_session_create_id in ext/session/session.c in the php source
It goes like this:
get time of day
get remote ip address
build a string with the seconds and microseconds from the current time, along with the IP address
feed that into configured session hash function (either MD5 or SHA1)
if configured, feed some additional randomness from an entropy file
generate final hash value
So getting a duplicate is pretty difficult. However, you should familiarise yourself with the concept of session fixation, which allows an attacker to potentially choose the session_id their target will adopt - see Sessions and Cookies for a good primer.
The session ID is probably just a random string of letters and numbers. Also it would be strange if PHP didn't check to see that it is unique and therefore cannot be the same for two users. As for (1) and (2), I'd say you're correct, but I haven't worked with PHP recently, so feel free not to believe me.
Related
So I recently made the decision to use Session ID's for authentication on my website instead of JWT's, so I'm still trying to play catch up a little bit here.
I guess my concern is pretty simple. If I'm going to have my database handle my sessions that are currently active for the users that are logged in (probably through a table that has a column with the UserID and the SessionID) how can I use PHP to generate a completely random Session ID? I will then pass that Session ID into a httpOnly cookie.
I assume this will work with my Angular front-end as I can use the withCredentials boolean option on every http request since I won't have direct access to the Session ID cookie.
So when a user wants to access a restricted area, their http request will contain the Session ID cookie and my PHP will determine what their User ID is by doing a lookup on the CurrentSession table. This will then allow PHP to determine the user's access level.
All this will be done over a HTTPS connection but I think I will still have to worry about CSRF attacks so I will probably use the Double Submit Cookie method as Angular already provides support for it.
So I guess my main question is, would simply finding out a way to generate a unique Session ID with PHP work for securing my app? Or would somehow encrypting the Session ID so only my PHP can decrypt it be a good idea, so in case somehow an attacker got access to the Session ID from the cookie, it would solely be an encrypted version of it, so it would be useless.
I would suggest using PHP's session_start() which will handle the session in its entirety including any cookies that need to be written to maintain the session depending on your particular connection at the time.
All you need to do is put this at the very top of your PHP scripts:
<?php
session_start();
A PHP constant "SID" should be available to get your session id which you could store in MySQL for other purposes if you wanted to - but it may not be necessary. You can also use session_id() as well.
I am a little confused on storing sessions with regards to having multiple users logged in at the same time...Does the session key have to be unique or just the value? Like is this ok, if all the $userIds are unique?
//if the user logs in:
$_SESSION['loggedIn'] = $userId;
In testing this it seems like if you have two logged in with separate $userIds at the same time and are trying to enter data to a db, it causes errors. Should the key be a random #? Not worried about security at this point.
The $_SESSION vector is part of the [Session management] of PHP:
Session support in PHP consists of a way to preserve certain data across subsequent accesses
It basically let's you store information in a per session fashion, and retrieve that same information in a subsequent call from the same session.
Each session have it's own data set.
PHP uses a cookie or a POST/GET parameter to identify each session and thus determine if the current call is part of a existing session and provide you with the data you stored there in previous calls.
session_start() creates a session or resumes the current one based on a session identifier passed via a GET or POST request, or passed via a cookie.
For more info, take a look at this topics in the manual:
session_start()
session_name()
session runtime configuration
$_SESSION is stored on the server side and is not a good way to track a user as a session can be terminated after a short period of inactivity. You'd be better off using cookies, if possible.
But to address your specific question, your code should work as the session will almost always be unique.
I am just starting to learn to program in PHP and have ran into a slightly confusing area, Sessions and Cookies.
I understand the server-side and client-side storage differences but i cant see how they differentiate and in what circumstances would each be appropriate for?
Also, i have seen people say that the cookie could be used to store a session id, How would this be done and why would this be advantageous?
Thanks for any feedback.
First of all, let's bust the longstanding myth (or at least I think it's an existing myth) that a session cookie is something different than a regular cookie. It is not. A session cookie is just a regular cookie. Only the properties of the session cookie that are set (or rather not set) are typically different. But the mechanism is exactly the same.
A cookie is set by sending a http response header to the browser:
Set-Cookie: name=value[; possible expiration-date][; other possible properties]
What typically distinguishes a session-cookie from a regular cookie is that no expiration date is set (or the expiration date is set to a date in the past). Which means the browser will dispose the cookie after closing the browser. But a 'regular' cookie can do this just as well. Thus thereby making it a 'session cookie' so to speak.
Now that we have that out of the way; the mechanism by which cookies are typically utilized by applications to make them act as even more of a session cookie, besides above mentioned properties, is that the value of the cookie only holds a uniquely identifiable value of some sort. Perhaps an md5 of maybe a sha1 hash.
Each time the browser requests a resource on the server it sends along this cookie (unless it has expired) with a http request header like this:
Cookie: name=value
The session mechanisms in the backend (being PHP in your case) linked the unique id of the cookie with data that has been stored in a file in the servers filesystem, or perhaps in a database. This way, each time the cookie is received it is able to retrieve this data and link it to the request.
The advantage of this, is that sensitive information 1) can be hidden from not having to travel over the net, and 2) doesn't end up in the users browser cookie cache, by keeping it at the server.
So, basically you want to send non-sensitive, and non-application-vital information in a regular cookie (think of: layout preferences, a non-persistant playlist such as on YouTube perhaps, etc.), and use a session to store sensitive information.
edit:
Sorry, ignore the "or the expiration date is set to a date in the past", as it was false. This will cause the cookie to immediately be invalidated by the browser, and thus not be sent along with requests anymore.
The advantage of using cookies over sessions is that cookies are persistent.
In other words, when the user visits your site weeks later, their session has more than likely expired. However, if they have a cookie that can uniquely identify them to your script, then you can automatically log them in and reestablish the session.
...what circumstances would each be appropriate for?
The answer looks something like this:
Session data should contain information that does not need to be persistent or is only needed for a short period of time. For example, if you are presenting a multiple-page form to the user, it makes sense to take advantage of sessions.
Cookies should be used to store an ID or hash that uniquely identifies not only the user, but also the browser / device they are logged in with. Keep in mind that cookie data is out of your control and can only be manipulated / removed by HTTP requests made by the user (or under certain circumstances, by a script on a page).
Also, i have seen people say that the cookie could be used to store a session id...
I'm assuming what was meant by that is storing a unique value in a cookie that identifies the user / browser / device that they are using. Implementing something like this would look like:
Let the user log in as they would normally.
Generate a unique hash (SHA-1 is your best bet) and store that in a cookie. You also store the hash in a database linked to that user.
...
The user returns after their session has expired and visits a page.
Your script sees the cookie and looks up the user that the hash belongs to.
The user is logged in.
Both cookies and sessions are used to keep user-specific information in order to track a user. A lot of times you can use either one, but they have some differences.
A cookie is a text file kept on the user's machine. Every time the users visits your site he hands over the cookie letting you know who he is. The advantage of this is that the information is kept on somebody else's machine so you don't have to worry about it. As such you can leave it there until the cows come home. When/if the user comes back he'll bring the information with him. The downside is that the information is out of your control because the user can easily edit the cookie you gave him. This makes any information in a cookie untrustworthy and has to be checked every time the user gives it to you.
A session is like a cookie except you keep the information on your server. The advantage is that you can trust a session to keep data exactly like it was when you put it in. The downside is that you have to store that information which means that eventually you'll need to discard it lest your webserver fills up with information that will never be used.
Now this is where it gets a bit tricky. You see while the mechanism of a session is as I described above, the actual implementation can vary depending on PHP's settings. The session data can be kept in individual text files or in a database on your server. Also you need some way of recognizing which session corresponds to which user. The usual (but not only) way to do this is with cookies. What happens is that the actual data stays on your server and is linked to a unique session id. That session id number is put on a cookie and given to the user so you can later look up his data when he comes back.
The above process is performed automatically by PHP when you use the session functions; you do not need to implement it by hand. If for whatever reason you need to change how sessions are implemented you can do so by changing the session parameters in php.ini.
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.
ive heard a few timse that sessions need to be cleaned with mysql_real_escape_string or htmlspecial chars because they can be modified. what im wondering is how are they modified because when i look at a websites session named PHPSESSID the value it contains is always encrypted.
first of all what encryption method is it using and how is it modified. the reason i want to know this is to better understand how to secure myself based on what methods people are using out there to high-jack sessions
thanks.
They cannot be modified, they're stored on the server. The PHPSESSID is just an identifier, it's not encrypted but randomly generated (so it's unique to each user). People hijack sessions by stealing the PHPSESSID cookie, usually through a cross site scripting attack. Read the answer to this for a nice summary of sessions in php - What do i need to store in the php session when user logged in
Sessions are stored on the server. That means all data is stored in temporary files and are deleted after an x amount of time. The browser does not store session data. It stores an ID of the session, which the server uses to get the right temporary file.
So the user never actually has access to variables stored in a session. But has a reference to their session. It is possible to get someone else's session ID. This way you can pretend to be another user. If sessions are used for validation.
Read up on session hijacking here.
The thing that can get modified is the session id send to you by the client. So, as with all user supplied data, this needs to be 'cleaned' before you use it anywhere, like for example with mysql_real_escape_string before inserting it into a MySQL database.