55

I have a login script that verifies a username/password against data in a 'user' table. Furthermore, I have a 'roles' table that specifies the access level of a given user. Assuming I am using safe login scripts, are there any security holes in simply performing an additional query, upon successful login, against the 'roles' table to discover the user's authorization level and storing this into a session variable? The idea would then be that on any page with mixed authority, I could simply query the session variable to discover the logged in user's authorization level.

Thanks.

oym
  • 6,983
  • 16
  • 62
  • 88

4 Answers4

78

Sessions are significantly safer than, say, cookies. But it is still possible to steal a session and thus the hacker will have total access to whatever is in that session. Some ways to avoid this are IP Checking (which works pretty well, but is very low fi and thus not reliable on its own), and using a nonce. Typically with a nonce, you have a per-page "token" so that each page checks that the last page's nonce matches what it has stored.

In either security check, there is a loss of usability. If you do IP checking and the user is behind a intranet firewall (or any other situation that causes this) which doesn't hold a steady IP for that user, they will have to re-authenticate every time they lose their IP. With a nonce, you get the always fun "Clicking back will cause this page to break" situation.

But with a cookie, a hacker can steal the session simply by using fairly simple XSS techniques. If you store the user's session ID as a cookie, they are vulnerable to this as well. So even though the session is only penetrable to someone who can do a server-level hack (which requires much more sophisticated methods and usually some amount of privilege, if your server is secure), you are still going to need some extra level of verification upon each script request. You should not use cookies and AJAX together, as this makes it a tad easier to totally go to town if that cookie is stolen, as your ajax requests may not get the security checks on each request. For example, if the page uses a nonce, but the page is never reloaded, the script may only be checking for that match. And if the cookie is holding the authentication method, I can now go to town doing my evilness using the stolen cookie and the AJAX hole.

Anthony
  • 36,459
  • 25
  • 97
  • 163
  • 29
    Should be noted that PHP stores the session ID as a cookie. – Michael Mior Jul 25 '09 at 04:07
  • 6
    The wiki article on nonce is pretty light, but has decent links: http://en.wikipedia.org/wiki/Cryptographic_nonce the basic idea, as I understand it, is like a token, but it can only be used once (number used once). Each page request checks the last nonce and creates a new one. So if I try a brute force attack on your password, I get one shot, as the nonce won't match on round 2. If I steal the session and the nonce of that page, I could keep making requests and renewing the nonce until you make a request that throws off the nonce match. Because it would see my request and my nonce, update... – Anthony Jul 25 '09 at 04:29
  • to the new one, and then your request (with your nonce that you got before that last request I made) would be out of date, thus causing the script to kill the session. – Anthony Jul 25 '09 at 04:29
  • @michaelmior : I was pretty sure that was the case, but recently was confused on the finer points. Or let me rephrase: I was afraid that was true, but was hoping it didn't HAVE to be true. – Anthony Jul 25 '09 at 04:31
  • 1
    @Anthony If you regenerate the session id for AJAX requests as well, the "hole" couldn't be exploited. – Pacerier Jun 26 '12 at 01:12
  • 2
    @Pacerier - 2 years later and both me and AJAX have come a long way. I now try to implement the same security techniques at every level possible, as you are suggesting. One feature I didn't know about back then was the ability to reset the session ID on every request. Not only does this reduce the risk of a stolen session ID cookie, it also is done per-request, so that ajax and standard requests get the same security benefits (and exploits, potentially). – Anthony Jun 26 '12 at 21:52
  • I would argue that if your AJAX is vulnerable in this way, you're not doing it correctly. I always build full security measures into the code that processes any AJAX request, as stringent a standard as any HTTPS request, and sometimes additional measures are necessary depending on what the script does. The syntax of AJAX requests is freely viewable in the source of any webpage that calls them, so the only rational assumption is that an attacker *will* try to exploit them. – cazort Nov 17 '21 at 17:51
  • *"steal a session and thus the hacker will have total access to whatever is in that session"* — This is not fully correct. Stealing the session cookie allows the attacker impersonation of the user, but it still doesn't give them any *direct* access to anything stored in `$_SESSION`. This is probably not very important, since impersonating the user is the much bigger problem, but values within `$_SESSION` are never directly accessible by anyone per se. – deceze Sep 14 '22 at 07:13
18

Only scripts executing on your server have access to the _SESSION array. If you define the scope of the session cookie, you can even restrict it to a specific directory. The only way someone besides you could get that session data is to inject some PHP code into one of your pages.

As for the system you're using, that is acceptable and is a good way to save database calls, but keep in mind that it will require the user to log out and log in again for any authorization changes to apply. So if you wanted to lock out an account and that user is already logged in, you can't.

Twipped
  • 1,149
  • 12
  • 24
14

It should be noted that in Apache the PHP $_SESSION superglobal is accessible across virtualhosts. Consider this scenario:

  • Your server hosts two domains, example.com and instance.org. PHP sessions are stored in cookies that are restricted to the domain.
  • A user logs in to example.com and receives a session ID. Example.com sets some session variables (which are stored on the server, not in the cookie).
  • A third party intercepts the cookie during transmission and passes it to instance.org. Instance.org now has access to the example.com session variables.

This is not such a big deal when you control all the virtualhosts on your server, but if you are on a shared machine, it's problematic.

Brendan Berg
  • 1,918
  • 2
  • 19
  • 22
  • 1
    do you know how to restrict one sperglobal per virtual host, if possible? – JRsz Nov 10 '15 at 09:59
  • @JRsz you can change the directory where sessions are stored in your php.ini ou through session_save_path() function (http://php.net/manual/en/function.session-save-path.php). – SandroMarques Jul 13 '17 at 18:30
3

If you rely on a value stored inside of a session variable to determine roles then you lose the ability to change the value in the DB and have it reflected against the user's current session. If you look at Zend Framework, there's a clear distinction between authentication and authorization, and strongly-worded warnings in the manual to only store the minimal amount of data in the session (ie "Yup, he's user #37 & he logged in").

As far as 'safety' goes - unless you're on shared host, there's nothing to worry about. On a properly configured shared host, they should be relatively secure, too.

Sean McSomething
  • 6,376
  • 2
  • 23
  • 28