My question is about creating a secure log in routine. After comparing the user name and password to the stored values I set a session variable called logged to true. Then as the user surfs around the web page I just check the logged variable for true or false to determine if the user should have access.
This is my first time creating something like this. Is this secure? I feel like there is something else that I should be doing to make sure that users are valid.
Anyone that gets your session cookie, is able to login as you. If you bind a session to an ip address, it's a lot harder. But this can give you problems with people that have changing ip addresses. It's up to you to decide if that's worth the trouble.
If you're not handling any kind of sensitive information and just trying to provide a personal user experience, what you're doing is fine. However, if you're truly concerned about security, there are several other approaches you can take. The first is to create a database table called "user_tokens" or something similar. When a user signs in, create a random key and store their ip address in the table associated with the key. Also, store that key in a cookie on the clients' machine. Anytime they try to do something sensitive, you can compare their ip address and key of the cookie to that of the database.
Research a little bit into Cross-Site-Scripting (XSS) and session hijacking. The method I've outlined above will really cut down on this.
Sure, it's secure but there are precautions you should take to prevent insecure circumstances/attacks.
There is nothing wrong with the mechanism you've described, at all. But the implementation is incomplete/unspecific. You have to consider password storage, and the procedures you'll use for login.
In response to a complaint, here's some issues OWASP brings up about authentication/sessions.
1. Are credentials always protected when stored using hashing or encryption?.
Yes, store your users passwords as salted hashes.
2. Can credentials be guessed or overwritten through weak account management functions (e.g., account creation, change password, recover password, weak session IDs)?
No, those functions should be protected by a security question/email link.
3. Are session IDs exposed in the URL (e.g., URL rewriting)?
Nope, they shouldn't be.
4. Are session IDs vulnerable to session fixation attacks?
Nope, don't allow users to set their session id through any means besides login.
5. Do session IDs timeout and can users log out?
In cases where the user hasn't otherwise specified "to stay logged in for two weeks", sessions should expire soonish.
6. Are session IDs rotated after successful login?
Yes, using session_destroy() and session_start() will accomplish this.
7. Are passwords, session IDs, and other credentials sent only over TLS connections?
Sure.
Ultimately, you have to consider the kind of data you'll be handling. Never allow someone to gain access to a user's password, since it could compromise their data elsewhere. But, if you're running colorakitten.com, don't loose sleep over the possibility of hijacked sessions: "Oh no, someone hacked my account and discolored my kittens."
Read: PHP Session Security
You are probably going to want to store the username in session as well in order to properly customize any pages for the user. What you described is "secure" but the security of your application is hard to assess without knowing what else you are doing.
Related
Summarizing question
What arguments are there for or against saving password hashes in the session?
Idea
Store the password hash (as it is in the DB) in the session upon login and validate it against the DB hash on each access in order automatically invalidate all sessions on password change.
My thoughts
These are my thoughts so far on the subject.
Pro
Assuming two people legitimately share an account it would (mostly) prevent a sort of racecondition of both changing the password while the other is logged in. Confusion would only occur once and not twice.
Assuming a malicious attack the legitimate user could kick out the attacker if detected early enough.
Con
Possible dataloss if person A submits a form right after person B changed the password.
Assuming a malicious attack the attacker can kick out the legitimate user.
Neutral
No real performance impact. (Edit: Because I load the userinformation on each pageload anyway for other reasons.)
Security issues are almost non existant. If someone has access to the server the effort of accessing the database which has all the hashes is comparable to the effort of accessing the session store, which has the hashes of the loggedin users.
Answers and Comments please
I don't want to start a subjective discussion here. I would like to collect (as objective as possible) pros and cons on that subject. What have I not considered yet?
Edit:
Clarification: The idea of invalidating all sessions (except the session used for changing the password) came from the thought of "If one person changes the password without telling certain other people there is a reason for that, thus they should immediately loose access.", assuming there are no malicious users (what a wonderfull world that would be...).
The scenario about simultaneously changing the password sounds extremely rare and not a core premise to build a session architecture around. The scenario can also be better prevented with optimistic locking and other concurrency solutions.
You can invalidate sessions when a password is changed explicitly, you don't need to store the password in the session for that. This is trivial if you use a database to store sessions (preferably an in-memory database like Redis or memcached), but it's not impossible using standard PHP file-based sessions either. Just proactively nuke all active sessions by the given user when the password is changed, done.
The password is a secret and should stay out of circulation as much as possible. The hash is just a shadow of that secret, but even it you should keep secret. Storing it in the session is one step closer to accidentally leaking it than it would be when keeping it purely in the database.
There is a performance impact of doing a database lookup on every single page load.
Suggestion:
Instead of storing your password hash at session, you can generate a "token", here you can generate a random sequence of characters and numbers, and store it at the session and give it a expiration time.
Let's suppose you and I share an account with password cow123. When I get logged in, i will receive token $124abc and you a token %xyz222, both tokens are related to password cow123.
Now you changed the password cow123 to cat321.
Nothing will happen to me because my token is still valid (You can create a table to persist valid tokens with expiration date column)
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.
I would like some clarification on what are some best practices for secure web login and, further, persistent login for a PHP application that is authenticating against Active Directory.
At login, does it make sense to implement a Post-Redirect-Get model? Storing the password in $_SESSION probably isn't a good idea.
After authentication, is checking if a specific $_SESSION field is set a valid and secure way to check if a user is logged in?
It is NOT a good idea to store the password in plain text at any point in time.
1) I do not recommend the PRG model for a login page. The worst thing that could happen is that the person is logged in twice. That's not so bad.
Data stored in $_SESSION can typically not be read by the client. They ARE stored on the server where a malicious employee or hacker might get access to them.
2) After authentication it is ok to check the session to see if someone is logged in. Someone may spoof someone else's session id but the chance of that is minimal as long as you are running SSL. I recommend storing the IP, user agent, and other information you can get easily in the $_SERVER variable and comparing it either on occasion or every time. To reduce the chance that someone has hacked the other person's session id.
Regenerating a session id on login doesn't make a lot of sense to me, although I don't know your particular scenario. My suggestion is to simply regenerate it on log out. Also, you can add a time out feature to the session if you like.
You should only store something to differentiate anonymous users and logged in users, like a is_valid keyword in the session.
This mean that anybody catching the session id (which is a cookie value sent in clear at each request) would get the session. This is called session hijacking and is now the only thing you should fear.
The way to protect you against this is to handle all connected-users pages in HTTPS while they're logged in... or to prey that noeone will make an XSS attack or will hack your user wifi hotspot to get the session id.
Well, in fact they're several other ways like storing some sort of signature of the client browser (user-agent, maybe the IP-can be problematic with moving proxies, list of intalled plugins, etc), and make a nice hash of that. Store it in the cookie and check it sometimes. Edit: you can check my answer to this question as well on some ways to track & identify one user browser, can be used to ensure the session is still used by the same user.
Never store the password in the session file, never store the password nowhere.
I'm very much stuck with the reasonable secure approach to implement 'Remember me' feature in a login system. Here's my approach so far, Please advice me if it makes sense and is reasonably secure:
Logging:
User provides email and password to login (both are valid).. Get the user_id from DB Table Users by comparing provided email
Generate 2 random numbers hashed strings: key1, key2 and store in cookies. In DB Table COOKIES, store key1, key2 along with user_id.
To Check login:
If key1 and key2 both cookies exist, validate both keys in DB Table COOKIES (if a row with key1, and key2 exists, user is logged).
if cookie is valid, regenrate key2 and update it in cookie and also database.
Why re-genrating key:
Because if someone steals cookie and login with that cookie, it will be working only until the real user login. When the real user will login, the stolen cookie will become invalid. Right?
Why do I need 2 keys:
Because if i store user_id and single key in cookie and database, and the user want to remember the password on another browser, or computer, then the new key will be updated in database, so the user's cookie in earlier browser/PC will become invalid. User wont be able to remember password on more than one place.
Thanks for your opinions.
Consider this: How does adding a second cookie make it any more difficult for someone who can steal arbitrary cookies to log in as that user?
It doesn't. You have to tie it to something that the user can provide, but it can't be the same thing. If you can tie it to IP address, great. If not, consider hashing the user agent + user id using that first key as an HMAC or something. I'm still in the process of trying to design a secure login system myself, so I can tell you what definitely doesn't work--and this is one of those things.
Your scheme is based around cookie theft paranoia. There are really only three ways to steal cookies:
Man-in-the-middle attacks.
Cross-site Scripting or similar vulnerabilities that let arbitrary code run in the security context of your site.
Physical access to the machine with the browser.
We'll also classify malware as physical for our purposes.
Let's not worry about physical security. If a user loses control of his machine, he's going to have plenty more problems than worrying about your website!
Let's also not worry about XSS, blindly assuming that you're already doing all you can to prevent it.
That leaves MITM attacks.
One of the best (read: only) protections you can get against MITM attacks is SSL. If you are truly worried about MITM, you should be serving your entire site over SSL.
You don't need two of your own cookies. You just need the session cookie and a Remember Me cookie, which, by the way, you can simply store in a many-to-one table. This prevents the forced one-to-one relationship between users and Remember Mes.
Jay - this is the same thread as yesterday:
PHP login security
The answer is still the same, which is to say that SSL is the only way to ensure people can't sniff your plain text cookies. If you make a judgement call that you are willing to accept the risk that cookies might be intercepted, then your approach is fine (but more complex than necessary).
Assuming you've already concluded SSL isn't the approach you are going to work with, I'm not sure what benefit you think having two separate cookies provides over just a single cookie.
Don't tie to IP Address. This will render your website useless to any group of people sitting behind a NAT (or in a lot of cases aol).
Multiple cookies are only really helpful when one cookie is a prerequisite to receive the other.
In the case that the website requires a login, a secured session cookie can be generated and assigned and is then regenerated on subsequent page loads (it's impossible to perform session fixation against a site that doesn't keep the same session state identifier through the session).
In the case the website now prompts a user through some sort of checkout process, maybe you want to implement the second cookie as a secure token that is somehow linked to the first cookie. Both cookies become a prerequisite to transact through the site making it difficult to fixate.
Lastly, you'll probably want to do this linking in the $_SESSION super global. Doing this in the database can become quite costly if your website does any reasonable amount of traffic. That means each time a users session needs to be manipulated or started or stopped it requires a database connection and any number of queries/deletes/inserts/updates. This is not scalable.
I am working on an ajax application just wondering how much reliable sessions are in terms of security.
Can I rely on session as User Identification and let them change they are password without asking for current password?
Just dont save sensitive data in sessions. They are also not very reliable in terms of "existence" ;)
Dont let anybody change a password without providing the current one. Imagine you just leave your computer and somebody change the password "for you".
I am not sure what you mean by how much reliable sessions are in term of security.
But, regarding your other question, I would never allow a user to change his/her password without providing current one. The reason is simple: if I sit down on a computer with an authenticated session, I will be able to change password without actually owning that account.
Sessions are stored server-side, so they are as secure as possible. That said, there is still the chance that someone will steal the unique session key for your site which then would give them full access to the user's account, but that is just the issue with storing stuff client-side.
You could do the second thing, but you could always do that even without a session ... so I'm not sure where you are going with that. Putting in the current password is just for additional security measures / verification.
Session uses a cookie. That cookie is vulnerable to all cookie-based attacks. Including firesheep style attacks.
You can change how PHP does cookies to only send them over SSL (Https). That helps, but doesn't prevent an attack that has access to that same machine from gaining access.
It is always a good idea to re-authenticate on password replacement. Just like you should never show a user their whole credit-card number, or SSN.
Passwords shoud be always encoded so I not see why you have to store it in session password is reqired only one time when you logging to the page and then save some info in session saying user is signed maybe userid..