I work for a php user authorization class and now I’m confused about sessions and cookies. I learned that wordpress doesn’t use sessions and I asked some php programmers if cookies are enough for security. Most of them said that: you have to use sessions for security, cookies can be modified.
However I use hash_hmac (md5) function with user’s ip address, password and cookie expiration date and noone can decode my encripted cookies code. Now I think cookies can be as safe as sessions.
Now I’m wondering that whether using cookies is faster than sessions, or not. I did a few tests and found that using cookies was faster than using sessions.
However, still I want to learn why wordpress doesn’t use sessions for authification process. Maybe I miss something, because many of my coder friends prefer both of them for authorization process. Would anyone let me know about this problem? Thanks.
I use hash_hmac (md5) function with user’s ip address, password and cookie expiration date and noone can decode my encripted cookies code
Are you simply signing the cookie data with an HMAC? It sounds like it. All an HMAC does is prove that a message has not been tampered with. Further, the IP address restriction is going to severely irritate users behind certain proxy servers.
Because the HMAC is just a signature, the cookie data can still be read and is entirely unencrypted, unless you have done so separately. If you have placed any data in that cookie that would permit a third party monitoring the connection access to the site as your user (such as, say, a simple un-salted hash of the user's password), then the HMAC is utterly useless.
If you want to put confidential information in a cookie, you should be using real encryption here, not just signing the data. (Read: Do both.)
If you are unable to perform actual encryption of the data, and the data is so risky that it has to be protected from prying eyes, then you shouldn't be sending it in a cookie. Or your entire site should be served over SSL. Or both.
But let's get to the meat of the issue:
If you're trying to simply identify if the current user is logged in, then sessions are a fantastic choice. It's hard to make them not work.
If you're trying to make a user login persist longer than the length of a session, then cookies are pretty much the most effective tool. However, you don't need to (read: should not) store any interesting information in the cookie. You can simply store a hash of some random data and identify it in the database as belonging to the specified user. Here is where your browser/IP restrictions can come into play. When the user isn't currently logged in, then check the cookie. If it's still valid, set their session data and regenerate the cookie with a new hash, invalidating the old one.
Be sure to set it up so the same user can be logged in to different machines without logging the others out. That's annoying as hell.
As for why Wordpress allegedly eschews sessions... well, Wordpress isn't the paragon of good design, and has made some huge compromises in the name of working pretty much anywhere. Shared hosting is hell.
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 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)
I've made a website which has registration/login. I can see the PHPSESSID cookie in Chrome's Developer Tools, so I'm wondering how can I use this session id value to hijack into the account I'm logged, from let's say a different browser, for simplicity's sake?
Should a secure website be able to determine that this session is being hijacked and prevent it?
Also, how come other big sites that use PHP (e.g. Facebook) do not have PHPSESSID cookies? Do they give it a different name for obscurity, or do they just use a different mechanism altogether?
Lots of good questions, and good on you for asking them.
First.. a session is just a cookie. A 'session' is not something that's part of the HTTP stack. PHP just happens to provide some conveniences that make it easy to work with cookies, thus introducing sessions. PHP chooses PHPSESSID as a default name for the cookie, but you can choose any you want.. even in PHP you can change the session_name.
Everything an attacker has to do is grab that session cookie you're looking at, and use it in its own browser. The attacker can do this with automated scripts or for instance using firebug, you can just change the current cookie values.
So yes, if I have your id.. I can steal your session if you didn't do anything to prevent it.
However.. the hardest part for an attacker is to obtain the cookie in the first place. The attacker can't really do this, unless:
They have access to your computer
They somehow are able to snoop in on your network traffic.
The first part is hard to solve.. there are some tricks you can do to identify the computer that started the session (check if the user agent changed, check if the ip address changed), but non are waterproof or not so great solutions.
You can fix the second by ensuring that all your traffic is encrypted using HTTPS. There are very little reasons to not use HTTPS. If you have a 'logged in' area on your site, do use SSL!!
I hope this kind of answers your question.. A few other pointers I thought of right now:
Whenever a user logs in, give them a new session id
Whenever a user logs out, also give them a new session id!
Make sure that under no circumstances the browser can determine the value of the session cookie. If you don't recognize the cookie, regenerate a new one!
If you're on the same IP and using the same browser, all you have to do is duplicating the session ID (and maybe other cookie values: not really sure if browser specific things like its agent string is tracked/compared; this is implementation dependant).
In general, there are different ways to track users (in the end it's just user tracking). For example, you could use a cookie or some hidden value inside the web page. You could as well use a value in HTTP GET requests, a Flash cookie or some other method of authentication (or a combination of these).
In case of Facebook they use several cookie values, so I'd just assume they use one of these values (e.g. 'xs').
Overall, there's no real 100% secure way to do it (e.g. due to man-in-the-middle attacks), but overall, I'd do the following:
Upon logging in, store the user's IP address, his browser agent string and a unique token (edit due to comment above: you could as well skip he IP address; making the whole thing a bit less secure).
Client side store the user's unique id (e.g. user id) and that token (in a cookie or GET value).
As long as the data stored in first step matches, it's the same user. To log out, simply delete the token from the database.
Oh, and just to mention it: All these things aren't PHP specific. They can be done with any server side language (Perl, PHP, Ruby, C#, ...) or server in general.
Someone sniffs the session ID cookie and sets it for a subsequent request. If that's the only thing authenticated a user, they're logged in.
Most sites will use authentication based on cookies in some form. There are several ways to make this more secure such as storing info about the user's browser when they log in (e.g. user agent, IP address). If someone else naively tries to copy the cookie, it won't work. (Of course, there are ways around this too.) You'll also see session cookies being regenerated periodically to make sure they aren't valid for a particularly long time.
Check out Firesheep for a Firefox extension that performs session hijacking. I'm not suggesting you use it, but you may find the discussion on that page interesting.
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.