38

I'm primarily a C++ programmer, but I'm trying to pick up some PHP.

Apparently the way to implement web user sessions is to store the user's login ID in a cookie using the $_SESSION variable.

Is it not possible for someone to just modify their cookie, to give them different privileges or log in as a different user?

It seems like this authentication mechanism is just having the user store their ID in a file - and then just trusting them not to change it.

Is there something that prevents this?

Thanks!

James
  • 1,430
  • 4
  • 20
  • 27
  • 4
    there are whole books on this topic. –  Apr 15 '12 at 19:48
  • 2
    http://phpsec.org/projects/guide/4.html, http://stackoverflow.com/questions/3641958/secure-sessions-cookies-in-php, http://stackoverflow.com/questions/5608764/purpose-of-php-sessions-and-cookies-and-their-differences, http://stackoverflow.com/questions/4110986/new-to-php-logins-and-sessions-is-this-safe-enough, http://stackoverflow.com/questions/1181105/how-safe-are-php-session-variables – Taz Apr 15 '12 at 20:02
  • 2
    Possible duplicate of [How safe are PHP session variables?](http://stackoverflow.com/questions/1181105/how-safe-are-php-session-variables) – Alexander O'Mara Apr 15 '17 at 06:38

6 Answers6

71

PHP sessions are only secure as your application makes them. PHP sessions will give the user a pseudorandom string ("session ID") for them to identify themselves with, but if that string is intercepted by an attacker, the attacker can pretend to be that user.

What to do

This information is taken from "Session Management Basics" in the PHP manual, but simplified a bit. Some things may have been missed. Be sure to read through that as well.

  1. Always use HTTPS

    • Prevents attackers from reading the session ID cookie
  2. Enable session.use_strict_mode:

  3. Enable session.use_only_cookies and disable session.use_trans_sid

    • Avoids user sharing session ID accidentally by sharing a URL with the session ID in it
    • Prevents the session ID from appearing in a Referer header
  4. Periodically regenerate the session ID and invalidate old session IDs shortly after regenerating

    • If an attacker uses another user's session ID, regenerating will invalidate either the user's or attacker's session, depending on which makes the request that regenerates the ID. You can then track when someone tries to use a session that has been regenerated already, and invalidate the regenerated session at that point. The user will be able to log in, but the attacker (hopefully) won't be able to.
  5. Optionally keep track of additional information in $_SESSION that relates to the request (IP address, user agent string, etc)

    • If an attacker somehow gains access to a session ID, this can possibly detect the intrusion before the attacker can access any data. However, keep in mind that this may worsen the user experience. For example, the IP address may change when the user switches from a mobile network to Wi-Fi, and the user agent string may change when their browser automatically updates. Adjust the data checked according to the tradeoffs your site is willing to deal with.
Sina M
  • 84
  • 11
0b10011
  • 18,397
  • 4
  • 65
  • 86
  • 1
    Great answer, but as said on [another question](https://stackoverflow.com/questions/1181105/how-safe-are-php-session-variables) *(accepted answer, 3rd paragraph)*, there can be a usability issue with *IP tracking* method, right ? – AymDev Sep 27 '17 at 13:45
  • 4
    @AymDev Unfortunately, yes. IP could change due to switching from LTE to WiFi. Browser version could change with an automatic update. I've updated the answer with a note about that and added some additional (and better) recommendations for securing PHP sessions. – 0b10011 Oct 05 '17 at 18:11
  • The security benefit gained by including IP info with the session is worth the potential usability issues in my opinion. All users receive increased security and only a small percentage have issues. On our system, those that do have issues and report it to us, understand the security benefits. – John.M Nov 11 '19 at 23:02
  • 1
    This should be the accepted answer because it deals with the fact that the session id is stored on the user's side, not the server. – dmuensterer Oct 04 '20 at 15:49
  • 1
    Great answer, but just some additional stuff: 1) [Set short session lifetimes](https://www.php.net/manual/de/session.configuration.php#ini.session.cookie-lifetime), 2) [Set path where your session cookie should be available](https://www.php.net/manual/de/session.configuration.php#ini.session.cookie-path), 3) [Set domain availability](https://www.php.net/manual/de/session.configuration.php#ini.session.cookie-domain), 4) [Make the session cookie only available across secured HTTP connections](https://www.php.net/manual/de/session.configuration.php#ini.session.cookie-secure) – DevelJoe Jan 01 '22 at 12:45
  • 1
    And 5) [Disable that session cookie is sent in cross-site requests, if not needed](https://www.php.net/manual/de/session.configuration.php#ini.session.cookie-samesite). 4) and 5) will contribute to a better protection from the stealth of the session ID via XSS and/or CSRF, which to me appears to be one of the main dangers. Still, even if all of this done, if a user leaves the machine unattended while in a session, someone could still easily steal it. In the end, the human factor is still decisive :D And yeah, ideally 4) consists in both setting the secure and the httponly flags. – DevelJoe Jan 01 '22 at 12:49
  • @DevelJoe comments are critical for enhanced security, it would be great if the original answer was updated. – 8ctopus Sep 01 '23 at 06:30
25

No, a session is stored on the server and cannot be accessed by the user. It is used to store information across the site such as login sessions.

Here is an example of the usage:

<?php
session_start();
if (password_verify($_POST['password'], $hash)) {
    $_SESSION['auth'] = true;
}
?>

The session can then be accessed across the site to check to see if the user has been authenticated.

<?php
session_start();
if ($_SESSION['auth']) {
    echo "You are logged in!";
}
?>

The user cannot edit these values however the session's ID is stored on a computer through a cookie as a long random string. If an unauthorized user gains access to these strings it is possible for them to access the site.

Community
  • 1
  • 1
Cameron
  • 1,011
  • 1
  • 10
  • 20
  • 1
    So session data is stored on the server. That's where I was going wrong.. Thanks – James Apr 15 '12 at 20:03
  • 9
    @James, the *session information* isn't stored publicly, but the *session ID* **is**. There is additional precautions that should be taken to prevent this from happening. See my answer. – 0b10011 Apr 15 '12 at 20:06
  • You both may now understand it better because its 2016 Oct, and the question was asked and active almost 4 years ago from now. What I mean is this answer is apart wrong from the security aspect. – MNR Oct 28 '16 at 05:08
7

If do this:

$_SESSION['user'] = $username;

Then $username will not be directly stored in a cookie. Instead a unique session id will be generated and stored inside a cookie.

The info that you store in $_SESSION is only stored server side and never sent to the client. On subsequent request by the client, the server will load the session data by the id stored in the cookie when you do session_start().

It relatively secure. The only thing that can happen is that somebody could intercept the session id and thus steal the real users session. HTTPS can prevent that from happening though.

d_inevitable
  • 4,381
  • 2
  • 29
  • 48
  • 1
    Actually, HTTPS only makes it impossible to read the Cookie as it's sent to the user. However, if the attacker somehow comes up with the session value, then they gain access. – 0b10011 Apr 15 '12 at 19:57
6

Answering this question needs 2 approaches:

  1. PHP session IDs are hard enough to guess for most use cases. Not much harder or less hard than other widely used systems.

  2. Trusting only a session cookie (and only the existance of a session cookie) seems not to go very far security-wise to me, no matter where this session cookie comes from - PHP or elsewhere.

So, in short: PHP sessions are as secure, as your use of them makes them be. This is true for any session-cookie-based system I know of.

Eugen Rieck
  • 64,175
  • 10
  • 70
  • 92
1

Whatever answer you get on this topic you are most likely not going to be satisfied because there are so many different opinions on the topic. There are even entire books written about sessions and PHP security in general.

The best answer you can hope to get here is probably "sessions are as safe as you want them to be". More work and a larger number of precautions will obviously make them safer to use but the implementation itself will consume more time. As with everything you are the one to measure how much safe is safe enough for your needs.

1

Since you are a C++ programmer, you only need to know that the session visible to the client side is just a pointer on a different address space (the server) and, therefore, the session cannot be accessed from the client mode.

Michael Chourdakis
  • 10,345
  • 3
  • 42
  • 78