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..
Related
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 was doing some research on StackOverflow on how to properly set sessions and prevent hijacking, etc. I found an answer that someone posted on one of the questions and he provided the following code:
For when a user logs in and the username and password match
$_SESSION['fingerprint'] = md5($_SERVER['HTTP_USER_AGENT'] .''. $_SERVER['REMOTE_ADDR']);
Checking if user is logged in, for protected pages:
if ($_SESSION['fingerprint'] != md5($_SERVER['HTTP_USER_AGENT'] .''. $_SERVER['REMOTE_ADDR'])) {
session_destroy();
header('Location: login.php');
exit();
}
It seems to work fine, but my questions are: how secure is this, is this a good method or should I try something else? The post had no upvotes or anything so not sure if it's good.
Also, not sure how to get information about a user with this session .. do I need to store anything in the database?
Thank you!
There are two major problems with this code.
1) IP addresses change for legitimate reasons. If the client is behind a load balancer, like at a corporate network, then he will be unable to use your web app.
2) Checking the user agent is a lot like having a get variable that says ?is_hacker=false. If the hacker has the session id, he has the user agent and its trivial to spoof.
Further more i have no idea why you would want to use md5 for this when doing a plain text comparison is actually more secure. Because the user agent is first an attacker could use the md5 prefixing attack to produce a collision and there for would bypass the REMOTE_ADDR check. (A useful md5 collision attack doesn't come up too often, but this one is fun!)
Even with this check in place CSRF and XSS can still be used to influence the session. XSS can be used to read a CSRF token and then use XHR to make any request the attacker desires. One could make the argument that this is trying to mitigate OWASP a9, but really you need to be using SSL to protect the session id.
This looks like a good method, however the fingerprint hash is generated by client data, which can be spoofed. A good method to use for the login form is to generate a random token that is stored in the session and passed through the form. Once the token is validated (or not) it should be unset for a one time use only.
The session should also store the user id once the user is logged in to retreive the user info stored in the databse.
I agree with Rook's comments, it's a pretty good analysis of your code.
There's lots to consider for securing PHP sessions but with an up to date version of PHP it's not difficult to achieve, some things to think about:
- Where the session files are stored on your server (mainly an issue if it's a shared server)
- Using a secure connection for all sensitive data and cookies going between the client & server
- Doing what you can to make the cookie session ID on the client secure
- Not storing any sensitive data in a session variable
As for storing things in a database it depends on your needs but I'd say you probably don't need it and storing data in the session variable is fine for security, just (as I've already stated) don't store anything sensitive there. Retrieve sensitive data from another location, most likely a database.
If you need to know more about PHP session security I've got a series of blog posts on the subject.
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 usually hang out in a community that uses a bulletin board software.
I was looking at what this software saves as cookie in my browser.
As you can see it saves 6 cookies. Amongst them, what I consider to be important for authentification are:
ngisessionhash: hash of the current session
ngipassword: hash (not the plain password probably) of the password
ngiuserid: user's id
Those are my assumptions of course. I don't know for sure if ngilastactivity and ngilastvisit are used for the same reason.
My question is: why use all these cookie for authentication? My guess would be that maybe generating a session hash would be to easy so using the hashedpassword and userid adds security but what about cookie spoofing? I'm basically leaving on the client all fundamental informations.
What do you think?
UPDATE #1
The contents of these cookies are what I think they contains. I'm not sure about it.
Of course if call a cookie ngivbpassword and contains an hash, my guess is hashedpassword. Probably it could be password+salt.
My main concern is about these solution giving to much information when under a cookie spoofing attack.
UPDATE #2
This question doesn't want to criticize the way these specific software works but, thorugh these answers I want just to learn more about securing software in a web environment.
This happens because session and login cookies may have different lifecycles.
Imagine website with millions of users every day. The website won't store your session for a year just to log you back the next time you get back.
They use login cookies for that.
These cookies are also called Remember-Me cookies.
Sessions are not persistent. Cookies are.
Update #1: I haven't worked with vBullettin but it looks like the classical "Remember me" feature.
Update #2:
Yeah, it's a remember me feature, I'm
asking why they're doing it in that
way
Alright... How do you implement a "Remember me" feature? You obviously need to use cookies, I assume that's clear. Now, what do you store?
The naivest way is to store user and password in clear text and perform regular authentication. It's among the most insecure mechanisms you can use yet some sites actually do it that way.
Second slightly less naive way is to store a hash of the user and password and perform a modified version of the regular authentication. Is not as bad as the previous method but it still suffers from some issues; for instance, there's no effective way to disable or expire a saved cookie from the server.
Third way is to keep a database table with "remembered" sessions, identify each one with a long unique string and store such string in the cookie. The string can be random or calculated but, of course, randomness has the advantage that the string cannot be guessed even if you know the algorithm.
Further security can be accomplishes by storing dates, IP addresses and other piece of data in the server.
As I said, I know nothing about vBulleting but it seems they're using method 2 or method 3.
Update #3:
The contents of these cookies are what
I think they contains. I'm not sure
about it. Of course if call a cookie
ngivbpassword and contains an hash, my
guess is hashedpassword. Probably it
could be password+salt.[...] My main
concern is about these solution giving
to much information when under a
cookie spoofing attack.
A successfully cookie spoofing allows you to fully impersonate the user so you can just enter the control panel and enjoy the free buffet, thus making the cookie content irrelevant.
Whether they store a salted password or it's just a name it's something I don't know.
Here is a question, what are your concerns? Are you building some kind of authentication system?
I also think that having the user id and password in cookies can be a security issue.
is user id encoded or an integer?
Cookies should be as-small-as-they-can peace of information about who you are on the server.
Sessionhash, session_id or sid is unique ID of you (your session on the server). The rest of cookies can be easily hidden on the server side.
Holding password hash in cookies is a security issue. You should avoid that.
Last 4 cookies comes from google ads.
PS. Most bulletin boards are not so great software anyway.
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.