Safe authentication in codeigniter - php

I'm trying to roll my own authentication system in codeigniter, and have stumbled onto a couple of roadblocks.
If I have the sessions set to use a database, is userdata stored in the database alone or in the cookie as well? I'd like to store the hashed password in it to verify each page load that a user is actually logged in with the correct pass, and I do not want the hash to be accessible clientside at all.
How can I prevent sessions from being stolen? I've enabled IP and hostname verification, is that stuff automatic or do I have to perform the checks myself? Will that be enough to stop people from stealing session data?

Userdata can be stored in the Session. If you have sessions setup to use a database, the only cookie will be a ci_session cookie or whatever you specify, and the cookie + ip/hostname will be matched to the database sessions table.
Storing the hashed password in-session will be completely safe, its in your own database. No problems.
Preventing sessions to be stolen should use a ip or hostname match (either every page load or a little less often, some people have dynamic IPs), not sure about automatic verification, but it's always nice if you check by yourself.
Preventing session data stealing is pretty much like that. Unless someone intercepts your cookie, and magically reports a false IP (or, well, shares an IP/hostname with the target), it's enough. You could also do another check, match the user_agent. That you'll have to do manually.
That's pretty much everything.

Related

Logging in via sessions - what is the proper way?

I just built a simple login system that uses sessions. When the script verifies that the username and password are both correct, it sets $_SESSION[username] and $_SESSION[role], and then on every page of the site it just checks whether these 2 session variables are set.
Considering that the server handles the sessions, this should be a secure solution, right? Or should I set $_SESSION[md5(password)] as well when logging in, and then check on each page of the site whether all session variables match the user data in the database?
Storing the password in your session is a bad idea, it also doesn't add any security to your website, since sessions are managed by the server.
You are however still vulnerable for session hijacking. Take a look at this question to learn more about how to prevent it.
Don't store passwords outside your database. Don't even return passwords from your database. All you should need to get for session storage is the userID. store that in the session and use it to lookup role level and name data when required. If you are concerned about someone hacking the session data and changing the userID number then you can store a hash of the userID number in the session aswell (I recommend using something a bit more secure than a simple md5 though, there are plenty of rainbow tables around for that nowadays) and compare the hash in the session to the hash of the userID at lookup and verify nothing untoward has been happening.

Is using cookies instead of a session for storing username and password wrong?

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.

best way to secure sessions (consulting)

Ok, yes, I've read the other Qs regarding this topic, but I have several questions more and some Qs were several years old.
Anyways, I'm building an admin cp for an insurance company that contains sensitive client info. Such as passwords, social security numbers, and drivers #.
First Q:
What's more secure, php sessions or cookies? From my understanding of cookies, you can strict them to http only and SSL. Don't know if you can do the same with php sessions. Seems also that php sessions are just quick cookies. Cookies seem more flexible and just as reliable. FYI, I'm using Cookies with http and SSL only. Is there a good reason to use php sessions in MY case?
Second Q:
My sessions/login work like this:
* Passwords are salted and hashed
* Sessions are 32 random chars long
* Sessions are validated when user enters correct pw and are tied to the user's IP
* When a user logs in, the session id and user's password are stored in 2 separate cookies
If the sessions are validated via user pw and tied to the user's IP, can I just have the session Cookie and remove the pw cookie? since I think it's kinda redundant since you can only get a session id if you enter the correct PW. I rather have the session id expose in a cookie than the pw (though it's still salted and hashed).
Appreciate it if my two Qs can be answered. Additional security advice is welcomed :D
Note: Sessions are tied to IP because it increases security greatly. I rather have my users a bit inconvenienced in having to enter their pw when their IP changes when we have SSNs and Driver License #s in our db. Only 3-5 users will have access to the system too.
Do not ever store the user's password in a cookie, in no form of representation.
Regenerate the session ID often
Use strong hashes (no MD5) like SHA512 (consider also stretching the hash)
Sensitive data should be on the server-sided session store:
Cookies are sent along every request to the cookies domain, hence increasing the chances of being intercepted greatly. Server sided session data is only outputted when needed.
Pass along a session-tied identifier to each sensitive request as an auth token to avoid CSRF
Do not directly bind the session to an IP. Two people using the same AP or private ISP have the same IP and sessions could be mixed up.
SSL is not magical. Don't relay on it too much.
Sessions are stored on server, cookies are stored on the client (browser). Session data that belongs to a user is identified by a cookie (Session ID).
I'd say Sessions are safer (you can also apply some encryption for better security).
Don't store the users password in a cookie. Not a good practice even if it's hashed.
You can store an encrypted serialized array containing necessary info to authenticate the user : ip, user agent, username, user id, but not the password.
You can also make the site (admin CP) work on SSL only. That way data is not visible in plain text on network.
Is the password in cookie salted and hashed? Beware - there is no good answer to this question!
Tying sessions to IPs really doesn't help much - IPs are cheap, easily spoofed etc. I'd go with SSL, cookies/sessions, perhaps even one-time-cookies, consumed and reset on each pageview.
Sessions are stored on a server, either in a database, filesystem, memcache, etc. User is tied to the session by session id, which is stored at client either in a cookie or in a URL. Neither is "very very" secure, since session hijacking is possible by stealing session id. But since you've tied session id to an IP, you've done quite enough.
Now to password stored in a cookie. Do not do this. Never. Even though they're hashes&salted, it's still better that attackers do not see them. You've got another level of security if they're only stored in a database, since in that case, attacker also has to break into db.
It helps if you're regenerating session id using session_regenerate_id() before doing any important action that could compromise the system. Also, take a look at XSS and CSRF attacks and mechanisms to prevent them, like form tokens.

Best practices to store login Information

How do you guys store login information?
Probably, store logged status at session. And username at cookies. But what are the safest practices to protect such crucial information, from falling into wrong hands.
Do not store the username in a cookie if you use it for identification. Because cookies are a client side storage and can be manipulated. Store it in the session instead that is a server side storage.
Normally, when authentication was successful, you store the user identification information in the session and only pass the session ID to the client. With that the user information stays protected on the server side.
Store the username as well in a session variable. Sessions are stored on the server, with only an identification number in a cookie.
If you need to protect the session number as well, encrypt the HTTP connection using HTTPS/SSL. This will however require you to buy a SSL certificate from an approved issuer.
If you're storing login information you need to take steps to avoid session hijacking. Store the session id in your database along with things like the users IP and browser useragent string and check that things match each time.
If you're storing passwords too then look at hashing them first - usually with some basic obfuscation like salting them first to avoid rainbow table attacks.
Store the user ID in a session variable; if you need to cache stuff like permission level, store that there too. Store the session ID in a cookie; use HttpOnly. If security/privacy is very important, use SSL for everything (and use an SSL-only cookie; also, have a look at the Strict-Transport-Security header, soon to be usable in Firefox). Otherwise, it is preferable to send at least the login through SSL. (Unfortunately, SSL requires a certificate from a provider trusted by mainstream browsers, which might be expensive to obtain.) Make sure a new session is started at login to prevent session fixation.
Use a salted hash to store passwords; preferably something slow like Blowfish, or SHA-256 repeated a few thousand times. (If you need your code to be extremely portable or run on old versions of PHP, MD5/SHA1 is fine too, but it will make ignorant people complain that you are using a hash that has been "broken".)

Php sessions secure log in

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.

Categories