Currently I autheticatic user sessions by matching a key in the session to the same key in a MySQl database. I regenerate the session with a random number that is MD5 protected on every page load. I am aware that sessions are not inherently secure and I'm looking for further security options that can be attached to this method in a speedy manner.
Any Ideas?
Since the session data is stored on the server side and the session ID is used to associate a client’s request with a certain session, it’s the session ID that needs to be protected. And the only viable measure to protect that session ID is to encrypt the connection between the client and server using TLS/SSL.
So you can use sessions as long as the data transfer between client and use is secured. Additionally, you can fix the PHP session to the TLS/SSL session so that the PHP session is only usable within that specific TLS/SSL session.
You're already jumping through hoops which do nothing to enhance the security, and potentially compromise the functionality of your site.
I autheticatic [sic] user sessions by matching a key in the session to the same key in a MySQl database
Even leaving aside the spelling mistakes, this is nonsense. Do you mean you authenticate requests by this method? If so, it's still not helping your security. You've already authenticated the request by de-referencing the session. Whether the request is authorized is completely different - if you need to authenticate the user then you should flag this in the session data.
It sounds like you're trying to prevent a CSRF, but getting this all mixed up with whether you're authenticating a user, a session or a request.
I regenerate the session...on every page load
Again, this is semantic nonsense. You can't "regenerate the session". Do you mean you create a new sessionId? If so then all you are achieving is creating errors when users try to open a second window or use the back button. It provides very little CSRF protection.
is MD5 protected
Just using random cryptographic functions doesn't make your application secure. It doesn't matter what the mapping between the real data and a surrogate identifier is, on its own it provides no protection against MITM.
Either you've done a very bad job describing your current security measures, or you've written lots of code which serves no useful purpose.
Go and read a lot of Stefan Esser's and/or Chriss Schiflet's stuff.
Related
Lately I have stumbled upon some articles that suggest using a cookie to store session data.
I liked the idea and extended my session storage by adding a CookieStorage class which works fine (note that per user I use a unique hash key for sigining and encrypting data)
However, there are a lot of other articles that suggest against storing sensitive data in a cookie, even though you encrypt and sign the value.
Personally, I find no reason why not do it especially when encrypting and signing the value with a different key for each user. The risk of the data being compromised is the same as with normal sessions, no? Not to mention that if you use SSL then the risk for hijacking is eleiminated.
What I see as a benefit with such an approach, if the session data are not large, is fewer IO operations on the server for opening/reading/writing session data, whether the storage is file, db, memory based
I would appreciate your feedback on the matter
Thanks
If you're using pure cookie storage with no server-side component at all, then the user is in control of the data. The only thing keeping him from it is your encryption/signing method; but that can be attacked. If you're not using encryption/signing keys specific to the user's session (i.e. you're not using a server-side session), then you're pretty much limited to a static secret. Someone could attack that offline, trying to brute force it. Once they did, they could spoof their entire session.
If you are using more secure one-time random secrets stored in a server-side session... you're already storing data in a server-side session! Why not keep it simple and store everything there? It would also reduce the bandwidth needs required to transfer all the cookies back and forth with every single request.
If you're doing this mainly to save I/O operations on the server: use a more efficient session store like a memcache based store.
Although nowadays session id transferred only via cookies, initially there was other ways, which are still supported and can be used.
Sometimes server needs to know or alter the session info.
That point from #CBroe on the cookie size.
I read on how to protect a session in php, there are a few, but they are not so effective like adding to a session the useragent,ip and port and encrypting them both.
What is a good way to prevent session hijacking?
I thought to take the following steps:
Change the PHPSESSID key altogether to something generic like id
Generate token per page and put it on the page and then validate it as well as teh session. That would reduce my reliance on session alone for validation.
I would add a short session expiration.
Add more variables to the session id and encrypt it, so it would be longer and harder to crack. Perhaps I would use RSA encryption.
Put a logout button, so that the user will be able to terminate his session.
Use javascript to count the time, over 5 mins will alert the user to continue his session.
Save session in cookies only.
The difficulties that I heard are: When you use token per page, you need to disable the back button? why is that?
A few other things are also unclear? Is saving session in the database more secure? why?
How more secure is to use SSL? How about regenerating session id very quickly, would it help?
What system would prevent brute-forcing the encryption key (would identifying the ip of the user who tries to flood the server with massive attempts to guess the session id would help?)?
How does session regeneration works, is the old session key destroyed automatically, what if the hacker obtains an old session key would it still work? Please, it is important for me to understand session security, because I am learning how to be a penetration tester?
UPDATE
I thought to do this:
Symmetric encryption on the session id with key A
Symmetric encryption on a randomly generated token that will be in the post field with key
The randomly generated token will be appended to the session id too and then encrypted.
On Request, I should get those variables:
$_SESSION['PHPSESSID'] (has the randomly generated token encrypted in it)
$_POST['RandomlyGeneratedToken']
Decrypt session id with key A and decrypt randomly token with key B.
Do 2 checks:
-Check the token if it is the same as the token on the first request sent.
-Check if the token exists in the sessionid.
Possibility for the hacker:
-Bruteforce the session id.
My session id is long enough it would take him time. I could employ a system that detects massive flow of requests from the same ip with different session id and slow him down with the sleep function.
-Eavesdrop the traffic and get the session id from the user and also the token and try to submit those.
hmm... I will have to regenerate the session id with every request and expire the session quickly on certain pages..may be 1 minute..
But how fast can he eavesdrop?
"Change the PHPSESSID key altogether to something generic like id"
This is security through obfuscation and a weak on at that. The user only needs to view their cookies and put together which is being used for the session id to bypass this
"Generate token per page and put it on the page and then validate it as well as teh session."
this is an interesting idea. but what if the user has multiple pages open? can you support multiple tokens? when do the tokens expire?
"I would add a short session expiration."
Good idea but this might effect users who stay on a page for a long time and then hit refresh only to find that they are logged out too soon
"Add more variables to the session id and encrypt it, so it would be longer and harder to crack. Perhaps I would use RSA encryption."
why use RSA encryption? why not hash it with something one-way like SHA? don't forget to add salts or intialization vectors
"Put a logout button, so that the user will be able to terminate his session."
who ever hits the logout button? ;-)
"Use javascript to count the time, over 5 mins will alert the user to continue his session."
YES
"Save session in cookies only."
dont do this, save the data server side always. cookies can be manipulated as they are stored client side
as for your other comments: you can store your session variables in a database and this allows you to check for other things like ip address and the like (though you can check ip etc with custom session handling functions: http://php.net/manual/en/session.customhandler.php). However, if you use a database and you regenerate your session ID too frequently (e.g. with every page load) you'll find that if your user hits the refresh button rapidly the id will regenerate more quickly than your server can update it in the database and the session will be lost.
"How does session regeneration works, is the old session key destroyed automatically"
yes unless you write custom code then it depends on your custom code
I hope my answers were somewhat useful, but i recommend following the guidelines for OWASP for session management so that you follow best practices:
https://www.owasp.org/index.php/Session_Management_Cheat_Sheet
EDIT
im not sure what do you mean by token? do you mean token as in session id? What value would that provide?
Is your token a session variable? that doesn't make sense as it's value is stored server side the key to which is the phpsessid whose abuse you are trying to prevent.
Also- never count on a hacker's ability not to understand your logic. If they want to understand it they will.
lastly, why do you need so much security? there is such a thing as good-enough security (if you follow certain standards). you likely don't need to protect against foreign government hackers else you'd probably outsource this project. follow best practices outlined in easily googled tutorials or guidelines such as the OWASP one i provided above. It'll be sufficient :-)
edit
"Also, you say the optimal storage is database? what about the last method that I described against brute forcing"
database session storage isn't necessarily optimal. you use it when you need to such as when you load balance multiple web servers that need to share session data.
two ways to hinder brute force attacks are to 1) have a really long session id, and 2) regenerate it frequently
I'm bit confused. I've been building my sites with my own session system, but i'm not sure how secure the php's own session system is. My session system usually just has user id and quite harsh hash, which does not include user name or password for generation. I save the hash in the user database and as a cookie to confirm the user session on every page load. So my question is can i trust php sessions or keep using my own?
PHP saves a unique session id in a cookie, and all values related to the session in it's own text file on the server. You have to get the session id to steal the session, which means you have to steal the session cookie from the victim's computer. PHP's own system is at least as safe as your homebuilt system
The difference may be how hard it is to find an active session by brute force. That is entirely up to the hashing algorithm and the random number generator.
You can configure PHP to use different hashing algorithms or you could even use your own algorithm to create the session ids for PHP's session system if you don't trust PHP to do it properly.
Storing data in cookies versus using PHP's sessions is very different. Cookies store data on the client-side; sessions store data server-side, which has a number of benefits:
The user can't see it
The user can't modify it
The browser doesn't need to send the data to the server with every request
Normally PHP sessions do store the session key as a cookie (although they don't have to), but none of the data you actually care about is ever sent to the user, it's stored on the server and looked up using the session key
i'm not sure how secure the php's own session system is
And the rest of the world is not sure how secure your's is. A lot of people have looked at the session handler in PHP and not found any flaws in implementation. Its also well characterizied and integrated but supports the notion of user defined handlers.
I'd recommend using the standard session code - but you might want to write your own handler functions.
C.
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.
What's the best and most secure way to go when writing an authentication library in a model-view-controller way?
The things that give me a hard time are keeping track of the users activity and remembering users via a cookie or storing sessions in the database?
Thanks in advance :).
If you want to use sessions, you have secure them against attacks like session fixation and session hijacking.
To prevent both you have to ensure that only authenticated requests are allowed to use the session. This is commonly done by chaining as many specific (possibly unique) informations about the client as possible with the session. But as some informations may change on every request (like the IP address), it can be difficult to find good one.
This is why it is useful to use the method denoted as Trending.
Another good protection measure is to swap the session ID periodically. Thus the period for an attack on a valid session ID is smaller.
The simplest way to implement it is with PHP SESSIONS.
just session_start (); near the beginning of your script and you have access to the $_SESSION global array for holding your authentication data.
Depending on the configuration of your server all the data stored in $_SESSION will only be available on the server from which it is hosted (with few exceptions). You can configure it to be saved in a temporary directory, in memcached, or even a database.
The only thing that is transmitted between the client and your server is a "session key". The key can be passed by cookie or URL-rewrites (which are transparently handled by the start_session output buffer).