Jump to content

Session Security


timothyarden

Recommended Posts

Is it safe to use a session to validate whether or not a user is an administrator or not? (https is being used if it makes any difference)
For example:

 

$Administrator = // Get true / false from mysql database ;
$_SESSION[ 'Administrator' ] = $Administrator;
 
// And later use this to validate access to sensitive parts of a web application
CheckAdmin( $_SESSION[ 'Administrator' ] );

Is this practice safe because the session is stored on the server and the client only has an identifier with which the server recognises that the session belongs to that client. If not could you explain why and how I could achieve what I am trying to do / fix any vulnerabilities that using a session to validate administrator access would have.

 

Thanks in advance!

Link to comment
Share on other sites

Hi,

 

it's true that users cannot edit the session data, but storing the user role in the session is still a very bad idea, because it leads to redundant data. You now have two places where you store the information: the database and the session. If they fall out of sync, you have a problem. For example, a user who is no longer supposed to be an admin may still have a session with the admin status set to true. Or the other way round: You've just granted a user admin access, but they still run around as normal users until they log out.

 

How did you even get to this idea? Is this some kind of micro-optimization thing? Simply grab the data from the database.

Link to comment
Share on other sites

I disagree. The whole point of session data is to store data that you will use repetitively throughout the user's session. If you need to know whether the user is an admin when loading many or all pages, then storing that information in the session is perfectly acceptable.

 

However, Jacques1 does bring up a valid point about the fact that session values do persist for the entire session (obviously). So, if a user is logged in as an admin and you change their status to not be an admin, then that user will still be considered to be an admin until their session terminates. But, that is a business decision. That would likely be a very rare occurrence. Is the need to immediately remove the admin access important enough to incur the overhead of doing an additional DB request on each page load? If it s a very security critical site I would say yes. Otherwise, I'd say no.

 

Also, there are other workarounds you could use. For example, you might rely upon the session value for most pages. But, there may be critically sensitive pages that you would want to always check the DB. This is no different than how most sites save your login status. I can browse most sites after I login and it is using a session status as I go from page to page. However, if I go to a page to modify my account information, I may be asked to again provide my credentials as an additional check.

Edited by Psycho
Link to comment
Share on other sites

Thankyou for your responses Jacques, Psycho and David

For the purposes of this project there will be very little, if any changes to administrators once the application is launched. Once a user is admin, there should be no need to change admin status as these people are all part of an organisation and we can trust each other. But I had planned to set whether the user was an admin in the session and validate this from the database each pageload.

 

it's true that users cannot edit the session data

So does this mean that sessions are 100% secure and can only be viewed and edited by the server scripts (unless the script displays them in some form)?

Also does the above depend at all as to whether you have a secure connection with ssl?



And thanks for that David, I'm leaning towards 15 minutes lockout.

Link to comment
Share on other sites

Also how do sessions use cookies and aren't they vulnerable through this?

 

I'm not sure if i'm allowed to post a link to the devshed forums, but here's a pretty authorative post on the subject from Jacques. This should give you a "crash course" look at the subject of sessions in php:

 

http://forums.devshed.com/php-faqs-stickies-167/php-sessions-secure-953373.html

Edited by r3wt
Link to comment
Share on other sites

But I had planned to set whether the user was an admin in the session and validate this from the database each pageload.

 

What? Why would you do that? That's a waste. If you already pulled that info from the DB and saved it in the session, then pulling it again on each page load is not necessary.

 

 

So does this mean that sessions are 100% secure and can only be viewed and edited by the server scripts (unless the script displays them in some form)?

Also does the above depend at all as to whether you have a secure connection with ssl?

 

Nothing is 100% secure, but for all intents and purposes session data can only be accessed on the server. An SSL connection is used to encrypt data between the client and the server. Since the session data is never passed between the client and the server SSL has no impact on this.

 

 

Also how do sessions use cookies and aren't they vulnerable through this?

The only thing stored in the session cookie is the session ID which is the unique identifier for the user's session. When the user accesses a page, the server uses that cookie to associate them with the appropriate session data. But, the data exists only on the server.

Link to comment
Share on other sites

Thankyou for the posts r3wt and Psycho

r3wt: Could you please expand on why you said: "don't rely on the session for authentication"? Is it for the same reason as further above where Jacques said if the data is updated it will not updated for that individual user until they log out?

Psycho:
Point 1 - Okay I won't check the database on each pageload - only for sensitive pages like mentioned earlier.
Point 2 - Thankyou for explaining why ssl doesn't matter for sessions. If it isn't 100% secure is there any way I can increase it's security / any guidelines I need to follow?
Point 3 - Could a hacker potentially copy a persons cookie and use it themselves - having the server see the cookies identifier and then grant access to the session data which is stored and modified on the server?

Thanks for everyones help so far!


EDIT:
This is already in my code and executed on every page load

function __construct( $SessionName = "developmentwebsite", $Secure = SECURE, $HTTPOnly = TRUE ){   // sec_session_start()
            if( ( ini_set( 'session.cookie_secure', 1 ) === FALSE ) || ( ini_set( 'session.cookie_httponly', 1 ) === FALSE ) || ( ini_set( 'session.use_only_cookies', 1 ) === FALSE ) ){   // Forces sessions to only use cookies.
                header( "Location: ../Error.php?error=Could not initiate a safe session (ini_set)" );
                exit();
            }
            
            $CookieParams = session_get_cookie_params();            
            session_set_cookie_params( $CookieParams[ "lifetime" ], $CookieParams[ "path" ], $CookieParams[ "domain" ], $Secure, $HTTPOnly );
                        
            if( !isset( $_SESSION ) ){
                session_name( $SessionName );
                session_start();            
            }
            
            session_regenerate_id();

            $_SESSION[ 'Expiration' ] = NULL; // This will be 15 minutes later and have validation in another part of the script
}
Edited by timothyarden
Link to comment
Share on other sites

Another question:

In my logout script I am doing this: unset($_SESSION)
 

But in the PHP manual it says
"Caution: Do NOT unset the whole $_SESSION with unset($_SESSION) as this will disable the registering of session variables through the $_SESSION superglobal."

It is currently having no problems and no errors so I don't understand what it means - could someone explain please? Thankyou
Link to comment
Share on other sites

I agree with Jacques. get the info from the db, don't rely on the session for authentication.

Whether you determine the status of the user from the db or not, you're going to use sessions to authenticate the user. The only other choices are to set a cookie on your own (and reinventing the wheel is error prone) or reauthenticating on every page. Assuming a hacker can take over a session that stores an admin's ID he'll be in as an admin whether you get admin status from the DB or from the $_SESSION array.

Link to comment
Share on other sites

Re: your points 2 and 3: The known issues with hijacking a session are discussed here. Unless you have a very sensitive app (financial transactions), I think the known issues can be pretty safely ignored.

 

In addition to unset you should technically kill the session cookie. An example is provided on the session_destroy manual page. I often don't bother in low security applications.

Link to comment
Share on other sites

Whether you determine the status of the user from the db or not, you're going to use sessions to authenticate the user. The only other choices are to set a cookie on your own (and reinventing the wheel is error prone) or reauthenticating on every page. Assuming a hacker can take over a session that stores an admin's ID he'll be in as an admin whether you get admin status from the DB or from the $_SESSION array.

the point was there is no reason to set an extra session for an admin, let alone rely on this for authentication.

Link to comment
Share on other sites

Okay thanks for explaining that (and the link) David, it helps a lot
I am already using session_destory() (I probably should have mentioned that sorry) I just dont understand why on php.net they say not to unset() the $_SESSION variable?

Thanks for that r3wt, I won't use a second session for admin's :)

Link to comment
Share on other sites

What the manual is saying is that you're not supposed to erase the $_SESSION variable itself, because PHP needs this for the session mechanism to work.

 

But you can and should overwrite the variable with an empty array during logout:

$_SESSION = array();

Otherwise, $_SESSION will still hold the old data while the script runs. This may confuse later parts of the code and make it assume the terminated session is still valid.

 

So logging out a user really consists of three different steps:

  • session_destroy() deletes the session file on the server
  • $_SESSION = array() clears all session data in the running script
  • asking the client to delete the session cookie

If you forget the latter, the client will keep sending you the old ID, and PHP will reuse that ID for the next session. This isn't necessarily a problem as long as you properly renegerate the ID in the login procedure. But it's still somewhat unclean.

 

I strongly disagree with the statement that you can ignore session security, and I find it sad that people still believe TLS/SSL is only for banks. How many more hacks do we need until everybody realizes that they, too, are affected by threats?

 

Without TLS, you have absolutely no way to tell who got your data, what server you're talking to and whether the page you received is authentic. Anybody who happens to be between you and the server may read, intercept or manipulate the communication. Do you really wanna use your admin account in this environment?

 

Yes, you may simply hope that everybody arounds you plays nice. But I don't think this is the right attutide for running a website.

 

The same is true for session security: If you don't take care of security, then attackers will exploit that as soon as they find it worthwhile. It's not always about big money. It could simply be a script kiddie trying to impress some friends. Or maybe somebody is angry at you.

 

Security is crucial, no matter if you're running a bank or a small homepage. Both are at risk.

 

And, really, there's simply no excuse for not securing your site. Getting a free TLS certificate from StartSSL, including it in Apache and updating the php.ini  is a matter of minutes and doesn't require any money or special knowledge.

Edited by Jacques1
Link to comment
Share on other sites

I strongly disagree with the statement that you can ignore session security, and I find it sad that people still believe TLS/SSL is only for banks. How many more hacks do we need until everybody realizes that they, too, are affected by threats?

 

I'm not saying that you should ignore session security if the result of the blown security is possible fraud or compromise of your website, but sessions can be used for all sorts of low security purposes. I think that I stated that ignoring the threat of a hijacked session was true only if you are coding a low security application. Perhaps I was unclear. As an example, one site that I am working on now is a teach yourself Japanese site. It keeps track of which questions a user has answered on a quiz in a session variable. Nobody will ever care enough to hack the sessions and if they do, the repercussion is a missed question or incorrect score on a quiz that the user is taking. For that kind of application I can't see why I would need to worry.

Link to comment
Share on other sites

Since the OP explicitly asked about admin sessions, I think we all agree that this does not fall into the category of low-security applications. If he had asked about a different situation, then, yes, this would be a different discussion.

 

My point is simply that things like using HTTPS and hardening the PHP sessions are relevant for everybody and should be the default until there are good reasons against them (like in your case). Personally, I don't like terms like “highly sensitive data” or “high-security website”, because it makes people think that their own data and their own website aren't important enough to be protected. But we actually need much better security on average websites.

Link to comment
Share on other sites

I think this thread has come off the rails a bit. Let me clarify a few things.

 

Determining if a user is an 'admin' or not and storing that information in the session is perfectly acceptable. The whole point of session data is to store information that you will use throughout the session. The only potential problem with this is if you will need to immediately know if their admin status has changed during the session. That is a business decision. If the answer is absolutely yes, then you would have to do an admin check on each login. If the answer is 'sometimes' based on what the user is doing, thenyou could add a DB check for the specific functions where you need to reverify their admin status. Otherwise, you can use the data in the session to check their admin status.

 

The discussion about using SSL is irrelevant to the discussion about using session data or not. If you are not using SSL, then ALL traffic between the client and host is in clear text - this includes the user's credentials when logging in. If the communication between the client and server is compromised, it wouldn't matter if you store the admin status in the session or not. Yes, a malicious user could potentially capture the session ID and then hijack the session. But, they could just as easily get the login credentials which is much more significant.

 

So, I still stand by my earlier statements that determining if the user is an "admin" at login and then storing a value in the session to reference makes the most sense (assuming you don't have a business need pursuant to the requirements noted above). For the vast majority of general purpose sites, this is acceptable.

 

As an additional comment to using SSL, my opinion is that if you are not storing sensitive information or are not a high-visibility site, it is probably not necessary. There will always be people at both extremes and I would typically err on the side of security. But, the reality is that it is not a significant of a problem (at present). Plus, if your site warrants SSL, then there are a whole lot of other things you need to be doing to secure your site other than SSL. Most website attacks are not done through the data transport. Also, SSL doesn't come without a cost both financially and with performance.

 

So, as to using SSL, think about what would happen if your site was compromised. I.e. all the data exposed to a malicious user. Is there any confidential/financial data that would be obtained? If yes, use SSL, it probably isn't necessary. You should, of course, have regular backups in case you need to restore your site from any loss of data - whether it is malicious or not (e.g. failed hard drive). The chances of someone trying to use an unencrypted transmission (i.e. HTTP vs. HTTPS) to try and gain access as an admin is extremely unlikely. There are many much easier methods (e.g. social engineering) to gain such access.

Link to comment
Share on other sites

I understand what you're saying, I just don't agree with it.

 

To me, caching the status in the session in order to save one trivial query per request (maybe not even that, because the script may already have a query on the users table) is a classical premature optimization. I have absolutely no reason to believe that this has any relevant performance benefit whatsoever. If Timothy provides us with a concrete profile or benchmark which indicates the opposite, I'm happy to change my mind. Until then, this is pure speculation, especially since none of us has any information about the website. Is this a private homepage with 10 users per day running on a cheap shared host? A commercial site with thousands of requests per second? 

 

Yes, you can do this. It's acceptable. But when I implement something, it should be more than just acceptable. So what are the benefits?

  • It may theoretically save us a fraction of a millisecond under certain circumstances. Frankly, I don't care.
  • Checking the status is slightly easier, because you can just get it from the session. But you might as well wrap the database stuff in a function or method.

Compared to the downsides (duplicate data, risk of running into weird situations), I don't find this very convincing.

 

Again: Both is valid. This is not some life-altering decision. But when I have to choose between clarity and some speculative micro-optimization, I always go with clarity.

 

 

 

The arguments against TLS are rather weird in my opinion. When you're dealing with the passwords and e-mail addresses of other people, then this is sensitive data. It's not always about money.

 

How do you come to the conclusion that attacks against plaintext traffic are “extremely unlikely”? This certainly depends on how exactly each user accesses the Internet. If you have TLS enabled, you let them make that decision instead of forcing HTTP on everybody.

 

Worrying about the performance or possible costs is, again, speculative. If we're talking about a big site, then, yes, you'll have to take this into account. But who said anything about a big site? As far as I'm aware, Timothy might as well run some small personal website, in which case there would be zero costs and zero performance issues.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.