I am programming a PHP site that allows users to register, and both registered and unregistered users can enter their respective usernames and passwords (for example smith8h4ft - j9hsbnuio) for school site.
Then, my PHP script sends some $_POST variables, downloads and parses the marks page, making an array called:
marksDB = Array("subject" => Array("A", "B", "A", "C"), ...), and writes it reformatted.
My question is:
How should I keep the username and passwords safe?
For unregistered users, I currently forget username and password and put the marksDB into $_SESSION. When user is inactive for e.g. 30 minutes, marksDB is deleted. How safe are these data in $_SESSION ? And how about users that log in, view page once, and never view it again, so the script doesn't delete the marksDB from session? Is the session deleted automatically (gc.maxlifetime)?
And what about registered users? I want to have everything safe, but I don't want to annoy user with password prompts every 30 minutes of inactivity. Is it safe to encrypt credentials like described here, but without the third user-set password? Or have I to ask the user for his password every time?
EDIT:
Thanks for quick replies,
#Justin ᚅᚔᚈᚄᚒᚔ : I doubt they have some API, but I can ask them, just for case
#Abid Hussain: Thanks for very useful links. (Thanks both for answers too).
I will throw users' credentials away and have only parsed markDB, which I will probably throw away too (after logout or inactivity) - it is cheap to retrieve marks again when needed.
If the school site doesn't expose an API for this (for example, using OAuth like the StackExchange sites do), then your options are limited.
Generally speaking, it is never a good idea to keep a user's plaintext credentials for longer than is absolutely necessary. There are security implications for any possible way you can imagine to try to do it (session hijacking, stolen keys, decryption, etc).
A better approach might be to make the marks download process strictly user-initiated. Give them a button that says "retrieve my marks", and go through the authentication process there, download the marks, and throw away their credentials. Each time they "sync", they should have to authenticate. Unless the marks change on a frequent periodic basis, there should be no reason you can't download all the information you need at once and then cache it securely on the server for later usage.
session files will be deleted by the garbage collector after a certain time, but a good rule of thumb for storing in _SESSION is only store data that you would output on the screen, i.e. the password is probably not something you want to store in the session. Session files can be read from the server and it's possible for some nefarious user to hijack the session and see things they are not supposed to see or even somehow see a var_dump($_SESSION).
If you want to allow registered users longer sessions you can have periodic page refreshes with JS (not necessarily refreshing the page .. just an asynchronous request will do) or perhaps even increase the session time with ini_set if allowed. It's not necessarily safer to ask for passwords repeatedly .. it depends on how vulnerable the password is when you are asking.
Another solution is to have the infamous "Remember Me" cookie keep the users logged in.
Passwords are not for decrypting. Encrypt for secrecy. Hash for authentication.
Everything in the session is server side, so it's not accessible by others. However, sessions can be 'hijacked' as explained here.
You could increase the length of the session in your PHP.ini or use periodic AJAX calls on the background to keep the session alive. The sessions are deleted when they are expired by the server.
Encrypting a password so it can be decrypted is usually frowned upon unless there is no alternative. With encrypting, not only you, but also everyone else with access to your database and/or source code can retrieve the passwords.
See URL
http://phpsec.org/projects/guide/4.html
http://www.sitepoint.com/blogs/2004/03/03/notes-on-php-session-security/
http://talks.php.net/show/phpworks2004-php-session-security
http://segfaultlabs.com/files/pdf/php-session-security.pdf
safest way to create sessions in php
Also Read it
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.
The session file is server side so it should be invisible to clients. But they still can trick your program into using another session if they know the session ID.
For the registered users you can store the password in a DB or a file after you have encrypted it with a key that only you know (maybe a new one generated randomly and stored for each user)
Related
So I have my database with the standard usernames and hashed passwords (password_hash).
There's a login form on my site, where users type their details and a session gets created based on that.
<?php
session_start();
//if the username and password is valid
if(validLogin){
$_SESSION['account'] = $username;
}
//$_SESSION['account'] is used from now on for backend user activities
?>
If the credentials are correct, an account session variable is created pointing to the username.
I have increased Session lengths to 1 month (as users complained they kept getting logged out before)
What can I do to increase security here?
If I go into Dev Tools, there is only a single cookie called PHPSESSID, which holds a 26 character value.
However, anyone can just copy and paste that value into their own browser and hijack someone's account - if they had the value.
I am not sure what to do and quite lost.
How can I improve the security here? Besides logging out users every 24 minutes
Firstly, The concept of a session (originally) implied:
The session begins when you open an application, continuous as long as
you work on it, and ends when you close the app.
Since the nature of apps changed and for convenience reasons, this basic pattern has been extended, and sessions kept alive much longer, even if the user is not actively working on it. However, if security is your main focus use a more strict approach, i.e. shorter expiration time and forced logouts.
Secondly, PHP sessions have been invented to solve many of the problems that plague regular browser cookies (stored on the client as text, limited to 4KB, rather accessible, sent along with every request, hence bloating the HTTP request). A PHP session only sends a hashed ID to the browser, and stores all data on the server. If an attacker owns the client security is indeed compromised. But this may be out of your hands if you cannot control the client device security. Security is a multi-layered concept that implies varying degrees of trust..
This answer gives more context on PHP session security and has some useful security recommendations. However, I have one additional recommendation: If you do not need to work with the PHP session id in your client code (i.e. JavaScript) disable session.cookie-httponly in your php.ini (or alike).
If this all is not 'good enough' you will need to implement a more secure protocol, use multi-factor-authentication, or alike. In general, session ids are probably your least concern; having a properly configured web server and following best practices is more important.
I've started learning PHP by myself, and in the beginning, I would often choose the simplest way to do a task instead of the best way. Now that I'm developing important websites that need to be 100% secure, I hit this dillema,
I'm using cookies on my main page, to store the login session. Basically, the username and the hashed password is stored in a cookie and is loaded and checked against the database any time the user visits a mustbeloggedin page. For my main page, I'm using md5. Not because I want to, but because I have to. I know that poses a great security risk for the user because a keylog attack can basically freely take his password.
On this new website, I'm gonna use sha256, so that shouldn't be an issue.
Here's my question: what other security issues does storing this kind of data in a cookie and not in a session pose?
Here's mine:
Anyone with physical access to the computer can get the user's hash and store it for later use, by manually setting his cookie.
Any infected computer does the same as the above
Data is loaded, parsed, checked every load (not a security issue but still optimization-wise, it's not very good, but I don't mind that)
Anything else?
Does the domain variable inside the cookie make it secure enough not to be read by any other site?
Edit:: I'm also reading about someone intercepting the data being sent from a client to the server. How are sessions different than this? If I store a session , can't the identifier cookie still be hijacked and used by someone else? Would also adding an ip address to the cookie, then when validating the cookie, also check the IP address and if it's different then print the login form again help?
It seems you are trying to make some improvements, but not enough really.
There should never be a need to store passwords in a cookie, session, array, or anything else.
The password should be in the database and not be taken out to chance further access to it, or manipulation of the data holder in some way.
Otherwise, your highly secured database with hashes and salts on passwords, is only as secure as the framework/scripts and variable or cookie you store the password in (which is less secure than the aforementioned DB setup)!
From your comment:
Your question and statement makes no sense, you're describing a login
page and I'm describing about how the website knows you're logged in.
The cookie has the username and the hashed password, not plain text
password
So you store Bob's password in a cookie, with hash etc.
I steal Bob's password cookie. It's hashed, so safe right?
Ok, so I (James) use it on your site. How does you site know I am James, not Bob? It cannot.
It checks the cookie I stole, and password hash/salt/whatever you do match in your checks (otherwise it wouldn't for Bob either so would be useless).
It thinks I am Bob.
So now you start to check other things, if I have another cookie, perhaps username.
I have already stolen that.
So now your site looks at my cookies, sees a username and password, checks them, and says "welcome Bob, here's your personal/sensitive details, do as you wish...".
Passwords stay in the database!
You could try checking user agent, IP, and a load of other arguably less than useful/sometimes useful things etc, but these are things you can do "as well" as password+has+salt, and at the same time not store passwords in cookies or Sessions.
If your only methods to stop a hacker from using that stolen golden password cookie (hashed or not) is to check user agent, IP, and something else that can easily be faked, then your site is not secure.
Also, anytime the user needs to do something like change their password or email address, or check their whatever sensitive data on your site, you ask them to re-type their password.
Possibly resetting their cookies/hash/hash+salt stored in the DB, but depends on scenario really.
EDIT {
Use a cookie to store the Session reference, and any sensitive data in the Session.
Again, what you should store in the session depends on what data it is, if you run your own server, or shared, etc. Shared hosting can have bad config, opening up other security issues, even extending Session security issues.
(Info is in the links below - as said in comments, reading is your friend ATM - and then some evaluating and considerations of your specific needs)
}
Here is some serious reading for you:
First, your MD5 and even SHA256 are not secure:
http://php.net/manual/en/faq.passwords.php#faq.passwords.fasthash
Hashing algorithms such as MD5, SHA1 and SHA256 are designed to be
very fast and efficient. With modern techniques and computer
equipment, it has become trivial to "brute force" the output of these
algorithms, in order to determine the original input.
Because of how quickly a modern computer can "reverse" these hashing
algorithms, many security professionals strongly suggest against their
use for password hashing.
Also read the link for that quote - the bit about how you should hash, and the bit about salts.
Also, importantly, read about how to correctly store salts and hashes. There is a LOT of BAD advice out there which is misleading to the point you end up with barely any more security than if you just used MD5.
Storing the salt in the DB with the hashed password is fine, just also use unique salts etc (it's all there in the link, about mcrypt/blowfish etc)
A must read, even if you only take bits from it (and even if you ignore the rest of my answer):
The definitive guide to form-based website authentication
Faking Session/Cookies?
More reading:
What is the best way to prevent session hijacking?
Also read about:
Session fixation; Session sidejacking; Cross-site scripting;
And again, given you stated this:
Now that I'm developing important websites that need to be 100% secure
You should really spend a lot of time reading about all these things.
Cookie/session hijacking is real, and generally simple (script kiddie stuff).
If you want to produce secure websites and applications, you really need to learn about quite a few attack methods, preventions, etc.
Best way is read the links I've given, then any "branches" which stem from that read about them too.
Eventually you'll have a larger picture of the vast range of security concerns and resolves to them.
Some takeaways for cookies.
You want to limit any sensitive information saved within as it is not secure.
Cookies are perfect for session ids which you can then use to query your database and check if it is expired, matches an ip, matches user-agent and any other security/validation checks you want to do before you route to relogin or resume session.
http://php.net/manual/en/features.cookies.php
You mentioned user authentication. Most encryption protocols can be broken by using and md5 is considered 'broken' at this point due to completeness of lookup tables with all the hashes and the slight variations between hashes.
How can I make MD5 more secure? Or is it really necessary?
Salting your hash is crucial which adds another layer of security as is additional cdn/server restrictions to block/restrict brute force attacks:
https://crackstation.net/hashing-security.htm
http://www.cs.virginia.edu/~csadmin/gen_support/brute_force.php
If one is overly paranoid you can implement two factor authentication ( expensive? ):
https://isc.sans.edu/forums/diary/Implementing+two+Factor+Authentication+on+the+Cheap/9580/
http://www.twilio.com/docs/howto/two-factor-authentication
Don't store any credentials in cookies. There is session cookie and that is enough. In your database you can create a table where you will store PHP session ID together with user id. It is enough to check user's login and password once, at the logging, to establish a session.
I was doing the same as you do: storing login, password and session id in cookies and had many problems - occasionally for unknown reasons the browser was not deleting one of those cookies, or I had problems with paths of those cookies. I had to develop very complicated methodology for assuring that those cookies are properly set and that all of them are present in a given moment - I tinkered with removing and adding those cookies manually in the browser and had to come up with new ways of preventing the problems arising from such activities, but I was always able to make up new way of breaking that down and had to come up with new mechanism for preventing that.
All of this mess stopped when I finally decided to leave only one cookie - session ID, which I authenticate before every session_start() call - you can check if such a session exists and even compare current browser footprint with previously saved one. It is then very simple to foresee bad scenarios - when somebody deletes this cookie, session is over, garbage collection will clean it up. If somebody changes it or adds fake one - you can compare it against your sessions table and not start a session. To have better control over the sessions, use session_set_save_handler functionality.
There is a lot wrong with your chosen implementation.
the username and the hashed password is stored in a cookie
Don't do that. You should consider the content of cookies insecure.
and is loaded and checked against the database any time the user visits a mustbeloggedin page
There is no need to do that at all, if you know the user is already logged in (session).
I'm using md5
Using md5 at all precludes any semblance of security.
On this new website, I'm gonna use sha256
That will make almost no difference if credentials are still stored in a cookie.
So what should you do?
When a user authenticates themselves store their user info in the session. Any time you need to check if the current visitor has already authenticated check the session data. The session's data is stored on the server - it is secure. There's no need to call the db to find out who the user is on each page load, if the user's data is stored in the session.
Do not use cookies to store user credentials, especially if you're storing the password hash as stored in the db.
Don't use md5 - and if you're "forced" to do so change it at the very first opportunity.
When a user logins I get him/her's ID and save it in a session var. What I wonder is, is this the way to go? Or should I use cookies? so it automatically login and so on.
session_start();
ifcorrectlogin {
$_SESSION['id'] = mysql_result($loginQuery, 0, 'user_id');
}
how do you authenticate your users?
//Newbie
Yes, this is the way to go. The session itself is already backed by a cookie to remove you any programming efforts around that. The session (actually, the cookie) will live as long as the user has the browser instance open or until the session times out at the server side because the user didn't visit the site for a certain time (usually around 30 minutes).
On login, just put the obtained User in the $_SESSION. On every request on the restricted pages you just check if the logged-in User is available in the $_SESSION and handle the request accordingly, i.e. continue with it or redirect to a login or error page. On logout, just remove the User from the $_SESSION.
If you want to add a Remember me on this computer option, then you'll need to add another cookie yourself which lives longer than the session. You only need to ensure that you generate a long, unique and hard-to-guess value for the cookie, otherwise it's too easy to hack. Look how PHP did it by checking the cookie with the name phpsessionid in your webbrowser.
Cookies can be manipulated very easily. Manage login/logout with Sessions. If you want, you can store the users emailaddress/username in a cookie, and fill the username box for them the next time they visit after the present session has expired.
I would try to find a session engine so you don't have to deal with the misc. security issues that bite you in the ass if you do the slightest thing wrong. I use django which has a session engine built in. I'm not aware of the other offerings in the field although I would assume most frameworks would have one.
The way they did it in django was by placing a cryptographic hash in the user's cookies that gets updated every page view and saving all other session information in a database on your server to prevent user tampering and security issues.
As BalusC mentions, the session_-functions in php are the way to go, your basic idea is sound. But there are still many different realisations, some of them have their pitfalls.
For example, as Jonathan Samson explains, using cookies can result in security holes.
My PHP is a bit rusty, but I remember that the session_-functions can also use session IDs that are encoded in URLs. (There was also an option to have this automatically added to all local links (as GET) and form targets (as POST). But that was not without risks, either.) One way to prevent session hijacking by copying the SID is to remember the IP address and compare it for any request that comes with a valid session ID to to IP that sent this request.
As you can see, the underlying method is only the start, there are many more things to consider. The recommendation by SapphireSun is therefore something to be considered: By using a well tested library, you can gain a good level of security, without using valuable development time for developing your own session system. I would recommend this approach for any system that you want to deploy in the real world.
OTOH, if you want to learn about PHP sessions and security issues, you should definitely do it yourself, if only to understand how not to do it ;-)
I am creating a login system for a web application using PHP. My question is, is it safe to only store the user login information in the current session? For example, if a user named John logs in successfully to my site, can I just store $_SESSION['Username'] = 'John' and $_SESSION['LoggedIn'] = 1 then check that $_SESSION['LoggedIn'] is equal to 1 on each page to verify the user is actually logged in? Or is there a better way to do this? I am not aware of any problems this may cause off the top of my head, but I wanted to make sure I wasn't leaving a big hole in my site that would cause problems down the road.
Also, I am storing an md5 hash of the user's password + salt in the database, not their actual string password so that is one less thing to worry about.
Let me know if you need any more information or if this is not clear. Thanks!
That's a perfectly reasonable approach. Your visitors will never be able to edit the session data on your server (unless the server itself is insecure, in which case anything's fair game), so a LoggedIn=1 value in the session is perfectly safe.
However, do keep in mind the risk that one visitor hijacks the session of another (by stealing the session key). One way to help protect against this is to also store the visitor's IP address (from $_SERVER['REMOTE_ADDR']) in the session and then in later requests confirm that it hasn't changed.
There are a number of risks to consider:
Session hijacking: this is where someone steals the user's cookie and pretends to be them. Some will suggest IP filtering to counter this but that can have awkward side effects. People use Websites from mobile devices or on laptops that are used at work, home and at wifi hotspots and there are other cases where IP addresses can change. So my advice is only do this for highly sensitive Websites (eg online banking);
Your Site is Compromised: in this case the user will have access to your database anyway so there is no extra risk with storing authentication information in the session. They can just as easily change who they are by issuing UPDATE statements to your database;
A Co-Hosted Site is Compromised: if you use shared hosting, a completely unrelated site could put you at risk (with or without this scheme) because a bunch of sites are all running on the same Apache instance and can thus access each other's files (although it can be hard to figure out what site they belong to). So if a site you've never heard of is hacked it can impact your site;
A Co-Hosted Site is Malicious: similar to (3) except the threat is internal but is otherwise similar.
So I'd say it's fine (subject to (2)) but just be aware of the risks. Follow, at a minimum, these best practices:
Never store unencrypted passwords;
Use a strong hashing algorithm (SHA1 preferred or MD5 at least);
Make sure authentication cookies expire at some point. How long depends on your site. It could be a week or two or an hour or two of inactivity or both.
Consider SHA1 or an even stronger hash instead of MD5. You're salting it, though, that's good.
Back to your question: yes, that's fine. However, implement measures to make sure sessions are not hijacked. Wikipedia actually has a fairly good article on it.
In most of the systems I've written, I've included logic to verify the remote IP hasn't changed. You can store that in the session, too, since the session vars don't get passed to the user (only the session ID). If you really want to get creative, you can add other checks -- user-agent, and what not.
You also have to account for session attacks. Check referrers. If you have a disastrous operation, let's call it a POST to DeleteMyAccount, I can write a form submission plus javascript to hit DeleteMyAccount in a forum post on an unrelated site, counting on that session to be present in the user's information.
Sounds OK; you may want to think about setting an expiry time (so if someone walks away and leaves the browser open they're not in too much danger).
On the whole, you are definitely on the right track. I would recommend you use IDs for your users in the session rather than the username as IDs are a better unique reference inside your code.
Also, md5 is not considered strong enough for password hashing anymore: it's is too fast to hash and you don't want that in a check that an attacker will need to run over and over again (whilst a real user only needs to do it once). I wish I could find the reference, but leading edge wisdom is to do lots of rounds of a leading edge hashing algorithm, like sha512.
You can use COOKIE instead of SESSION variable. you may set COOKIE by following
setcookie('ID', $variable, time()+8*60*60);
You have to be aware about SQL Injection. When you Insert or Update your database where user textbox relates please be aware about SQL Injection. Insert / Update your values by htmlentities() function.
It keeps running in my mind the last couple of days, but I read some articles about how to make your PHP sessions more secure. Almost all of these articles say that you need to save the useragent in the session WITH an additional salt. Something like this:
$fingerprint = md5('SECRET-SALT'.$_SERVER['HTTP_USER_AGENT']);
The salt would make it harder for an attacker to hijack or whatever the session. But WHY add a salt every time you would check it like this:
md5('SECRET-SALT'.$_SERVER['HTTP_USER_AGENT']) == $_SESSION [ 'fingerprint' ]
So WHY would a salt make it more secure, since the attacker still only needs the useragent (which is relativly a small set of different useragents) and the sessionid?
Probably something small I'm overlooking, but can't figure it out, drives me crazy haha
Thanks!
The reason that it's suggested to add a salt is simple. Generally, when you're creating this "fingerprint" - if you're using only one item of data, which has a limited dataset, then it makes it easier for an outside hacker to generate this, and hijack the session.
In your example above, yes, if the attacker has both the "fingerprint" and the User agent, then they will be able to hijack the session.
Adding a salt only makes it harder for an attacker to generate the fingerprint, it's a case of "if they have all but one piece of information, then the last piece of information is rendered useless)
I'd suggest that you add some more things in, for example, within vBulletin (a project I used to work on) the session ID hash (which is basically the same as the fingerprint) is generated with the following code.
define('SESSION_IDHASH', md5($_SERVER['HTTP_USER_AGENT'] . $this->fetch_substr_ip($registry->alt_ip))); // this should *never* change during a session
Also, a session hash is generated using
md5(uniqid(microtime(), true));
These are both checked when trying to identify the session
So, to hijack the session, the person would need to know the following
The time (exactly) on the server when the session was created
The users Browser agent string
The user's IP address
They would also have to spoof the IP address (or at least the first 2/3 octets) to be able to do this.
If they're actually at a point where they've managed to get the above information, then they're probably likely to be able to attack in other ways than just session hijacking.
vBulletin don't actually use a "salt" per se, but, in your above example, the salt is just adding a limited amount of entropy, it's always best to find as much entropy as possible.
For example, in something I'm currently writing in python, I generate a hash for usage with XSRF protection. The following is what I use.
self.key = sha1(
self.user.username +
self.user.password +
settings.SECRET_KEY +
strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())
).hexdigest()
Which takes the user's username and password, the current time, and a preset salt to generate this. This would be hard for an attacker to generate due to the salt, and the time (though, do note that this is only made secure by the fact that it changes once it's used, with time, it wouldn't take much for someone to crack this for a particular user if it wasnt changing)
If I understand correctly, you want to prevent session hijacking by a remote attacker that guesses session IDs?
If this is not the case, then you are seriously out of your depth - an attacker that can snoop the traffic can also mimic the user agent, and an attacker that gains access to your session storage has you by the balls anyway.
If you store the user agent string to "lock" the session to the current user agent, then there is really no point in hashing it - string comparison on the full user agent string is faster (then hashing and then comparing) and not significantly more expensive in terms of storage.
I don't believe storing the user agent is providing enough differentiation - something better would be to generate a larger ID (with more bits) at session start time (maybe sha1 the current time stamp + user name + user agent + something), then store that in a cookie as well as in the session and match it up on each additional request. This doesn't change the attack vector much (you still need to guess some number), but its easy to significantly increase the number of bits that must be guess for a successful attack there by massively increasing the difficulty of the attack.
Update:
Something that other answers have mentioned in passing but is important to point about salting hashes: salting your hashes only makes sense if you expect an attacker to gain access to your stored hashes but not to your code, and then somehow uses it to leverage an attack.
This makes sense to passwords that are stored for a long time, usually in a well known location, and used by code that is hard to locate.
This does not make sense for your use case because:
The information is only viable while a session in progress (before timing out) this is rarely more than a few hours, after which - even if they got the storage and decoded everything - the session cannot be hijacked because it is over.
Usually if the attacker has timely access to your session storage, they have access to your plain text PHP code and can see your salt.
Unless you store your sessions in a completely unreasonable place (such as an S3 bucket), a hash stealing attack is mind boggingly less likely than a lot of other attacks that will be a lot more useful.
In short: don't waste your time writing session verification code - PHP built-in session management is already secure enough.
If you are on your own server, encrypting session variables is pointless, because they don't get out of the server. See Linead answer to What do I need to store in the php session when user logged in? for more info. If you are in a shared server, you may need to encrypt every session variables, besides the session ID, because they are stored on temp files readable by the same web server all your neighbours are using.
Anyway, if you are really worried about security, you are better with your own (virtual or not) server, so danger will only come from outside your server.
Some examples of risk to your sessions:
Your server sends the session ID in the URL, and your user follows a link to badguys.com They will get in server variables the referer (complete URL, including your session ID), the browser and the IP address of your user. If you are not checking IPs, or your user uses an open proxy, they only have to install same browser version, paste the URL, and they're done.
User go to a public PC, logins, and leave without closing his session (hey, he's human after all). Next guy in the row opens the browser, check history and finds an open session. Yuck.
So, some measures you can take, by my usual preference:
Don't send the session ID in the URL; enable session.use_only_cookies in PHP. Cons: User needs to enable cookies.
On dangerous actions (change password, make an order...), ask user for password again. You can do it periodically too. Cons: Annoying.
Timeout sessions fast. Cons: In most sites, this will force users to login often, annoying them.
Use SSL (only way to avoid 'man in the middle' attacks). Cons: Slow. Stupid browser messages. Need SSL on server.
Check the IP. Cons: Inneffective for visitors using a public proxy. Annoying for dynamic IPs.
Check the User Agent (browser). Cons: pretty much useless, UA is easy to get and trivial to imitate.
(I take for granted you have yet PHP configured for maximum security).
Some more extreme measures:
Maintain a permanent connection between server and browser, e.g. using a Java applet. No connection, no session. Cons: User needs Java, ActiveX or whatever you use. Session closes with browser (this can be good). Doesn't work on very slow connections. Higher load on server. You need to open ports, have a special server for the applet.
The same, but using asynchronous requests (e.g. AJAX) to refresh very frequently the session, and a very short timeout. Or refreshing a hidden IFRAME. Cons: User needs JavaScript. Doesn't work on very slow connections. Higher load on server.
The same, but reloading the whole page. Cons: User needs JavaScript. An automatic reload while you are reading a page is very annoying.
In some corner cases, you can forget about sessions and use Apache authentication instead. Simplest solution, but a lot of limitations.
As the fingerprint is stored on the server side, you don’t need to use a salted hash. A “normal” hash is enough to reduce the data.
I see one purpose in salting your fingerprint. If a bad guy gets hold of your session-db (god knows why) but not of your code he couldnt "guess" your fingerprinting method by trying the common user-agents against it.
I do that as well to partially protect from session impersonation attacks. You need to include the IP address as well.
Keep in mind that when the client's browser auto updates the user agent changes and you'll think that his session has been hijacked ;)
Bear in mind that if you do that you're forcing people to login again if they upgrade their browser. This can be OK but just make sure it's your intent.
Using the user's remote address is not without problems either. Many people use the same computer from different locations. Mobile devices, laptops being used at home and work, laptops being used at Wifi hotspots and so on. IMHO it's a bad idea to use IP address in such a way that a new IP address requires a login unless you're dealing with highly sensitive information such as online banking. Is that the case?
What are you concerned about? External attack? Or in a shared host situation that someone can read your session information?
If it's the latter, the solution is simple: just don't store anything sensitive in the session. Anything sensitive should be stored in the database.
In terms of creating a secret salt, you need to use something that isn't guessable. I would go for something like a random string that's created when the user is created. If necessary recreate it each time the session is invalidated.
As for what it would make it more secure, you said it yourself: there are limited user agent strings (less than a hundred will probably cover 99.99% of users). A salt simply increases the number of possibilities. That being said, if you use the same salt for all sessions then it's only a matter of time before it's found with brute force.
Okay, for example I'm using the following fictional code:
<?php
// The sessionid cookie is now a certain hash
if ( array_key_exists ( $_COOKIE [ 'sessionid' ] ) )
{
// Get the session from database
$db_sessid = $pdo -> getStuff ( 'session_database', $_COOKIE [ 'sessionid' ] );
if ( $db_sessid !== null && $db_sessid [ 'fingerprint' ] == sha1 ( 'SOMESALT' . $_SERVER [ 'HTTP_USER_AGENT' ] ) )
{
set_cookie ( ... ); // New sessionid and write also to DB
// User is now logged in, execute some user stuff
}
else
{
// Session doesn't exist, or the fingerprint does not match
}
}
Now the attacker only still needs the sessionid, which is in the cookie (sent along HTTP headers) and the useragent. So what's still the point of the additional salt?
Checking for IP's is also in my opinion not such a good option, some providers or proxy's change them every single request.
Thanks so far (-:
you allow the cookie after all the safegard parameters are met to just set a cookie if parameter are not met the cokkie will never be set nice but if the cookie has a parameter vissible what happens then. as well if conditions are never met the session willneevr be met.is that what you realy want. remeber a check met conditions give session and seession data way through the cookie
remember the cokkie sits on the clients browzer
regards stelios