How to resolve password hash complexity with HTTP basic auth? - security

Password hashes are stored as PBKDF2 with 512bits with 16384 rounds. This takes its time on my small server. Users are authorized with HTTP basic auth over SSL/TLS. With this setup every request requires to calculate the hash which puts a load on the server.
Current solution: After the first successful login I store a session cookie at client.
Pro: Minimal complexity that reduces time for hash calculation, still works for clients that do not store cookies
Cons: Clients that do not accepts cookies still create load.
Other ways to mitigate:
- Weaken password hash (doesn't feel right)
- Implement own/other authentication instead of basic auth (which one? adds complexity)
Priorities:
Security first, access to administration/monitoring is to be secured.
Then server load.
How to mitigate password hashing load? How to not sacrifice security? Is there an alternative to authentication without a secured channel (shared secret)?

Current solution: After the first successful login I store a session cookie at client.
This is the typical solution—either using actual stored sessions, or a signed user+timestamp token (HMAC being faster to verify than bcrypt).
It also solves the problem of HTTP Auth only being sent for pages under the same directory path as the first page that requested auth, and of the crazy browsers that don't re-send auth headers until prompted with 401 for every single request.
Cons: Clients that do not accepts cookies still create load.
Clients that don't accept cookies at all are relative rare and will break for almost all other sites that require a login, so for the common case you should generally be OK.
Implement own/other authentication instead of basic auth (which one? adds complexity)
If you are determined not to rely on cookies, the only other mechanisms I can think of with native browser support are Digest Auth (doesn't really solve the problem as it is still password-based) and HTTPS client certificates (may be an acceptable/convenient option depending on who your userbase are).

Related

ASP Classic user login system password security considerations?

All,
I'm currently designing a user account system in ASP classic...don't judge, it's what I'm comfortable with ;). I have several of the components built already, including the UI, database table, CRUD database ASP pages and a generic mailer. I'm curious as to some of the best practices for implementing secure login systems for ASP. Searching the web yields a ton of "simple ASP security" solutions, which I've used before, but this is my first time time building a robust and truly secure solution. The final implementation will be used for a job application system, so it definitely needs to be secure due to the content.
So far, I have:
Password recovery/reset goes only to the e-mail account on file
Hash stored passwords in the database
Do not set an expiration on session cookies so they are only stored in memory (read this somewhere today)
Get a certificate for the server and use https
A couple general questions that I have...
Submitting the password in a form passes it through the query string. Do I need to hash this somehow prior to submitting the form?
On a related note... If I am using https, since it is already secure, can I do the hash on the ASP page that handles the write to the database? I'm using AJAX to parse the query string from the sending form and pass it to the ASP page which connects to the database and does the CRUD operations.
Password recovery/reset goes only to the e-mail account on file
Make sure your send a reset link expires after a certain time or after it has been used whichever comes first
Hash stored passwords in the database
Use salts instead of plain hashes. Hashes of most common passwords are as simple to break as a google search.
Do not set an expiration on session cookies so they are only stored in
memory (read this somewhere today)
This will make sure that the cookies are wiped out when the user closes the browser. In addition to this, also consider a timeout on the session cookie on the server side which will timeout the user session after x minutes of inactivity.
Get a certificate for the server and use https
At the minimum, the login credentials absolutely need to be passed over SSL. It will also help to have the entire website on https instead of just the login page. SSL is no longer computationally expensive anymore. Having the entire site over SSL prevents any sslstrip attacks. Make sure your server doesn't support SSLv3 to prevent the recent poodle attack.
Submitting the password in a form passes it through the query string.
Do I need to hash this somehow prior to submitting the form?
Please don't pass credentials over querystring. Login form should always be POSTed. It'll get cached in server logs (and any proxy logs) if tacked to the URL as a querystring.
If you are posting the form over https (which you absolutely should), you do not need to hash before submitting the form. If you are not using https, there is no way to pass the credentials to server securely.
On a related note... If I am using https, since it is already secure,
can I do the hash on the ASP page that handles the write to the
database? I'm using AJAX to parse the query string from the sending
form and pass it to the ASP page which connects to the database and
does the CRUD operations.
Hashing should ALWAYS be done on the server side. If you hash the password on the client side and send it in plain text over http, a MITM might not be able to reverse the password from the hash, but he can always use the same hash to log on to the user's account. The hash essentially becomes the plain text password of the user in this case.
Always use HTTP POST with SSL for sure.
Protect your asp code against sql injections.
Storing a local cookie with an encrypted token to keep your users logged in after they close the session/browser - or use asp sessions for a single login that could expire in 20 minutes after last request or when closing the browser.
Protect your cookies for cookie/session hijacking. (http://en.wikipedia.org/wiki/Session_hijacking)
Also, you can use finger prints of your users by requesting/storing/validating the server variables like (a part of) the user agent.

Authentication system - is my one secure?

I want to authenticate my users based entirely on cookies and sql db.
What I do is:
1. Once they login, I generate a random string, create a hash from it, save it in the database along with the user id and his IP.
2. I send the hash to the user as cookie
3. Whenever he wants to access something, I verify if his cookie hash matches the one on the server and also if his IP matches. Of yes, he is valid or else, log him out.
4. (As pointed by Akhil) If he clears his browser cookies or anything does not match the information on the database, I clear all the rows with his username and log him out.
Note: I use a session cookie for storing the random hash, which again is generated using the timestamp, and as long as time doesn't repeat itself(I believe), its random in the corect way.
Is this fine? How can I make it better?
Once they login, I generate a random string
Make sure you use a cryptographically secure method to generate the random string. Do not use mt_rand use something such as openssl_random_pseudo_bytes.
create a hash from it,
Make sure to use a secure hashing algorithm (not MD5, and at least SHA-2).
save it in the database along with the user id and his IP.
One thing to bear in mind is that some internet connections share IP addresses or will sometimes change the client IP address (e.g. AOL or mobile).
I send the hash to the user as cookie 3. Whenever he wants to access something, I verify if his cookie hash matches the one on the server and also if his IP matches. Of yes, he is valid or else, log him out.
It sounds like a good way of doing it and there are no flaws in itself. I would implement a session timeout mechanism. For example, store the date last used in the DB for a sliding expiration and the query will only query records that have not expired. You could have a background process that runs to clear out old, expired records.
Also, use HTTPS and set the Secure and HttpOnly flags on the cookie. This will prevent them being leaked over HTTP, but I would not go as far as disabling HTTP on your system as there are workarounds for an attacker if it is anyway.
I would not be concerned with the cookie being stolen by another user on the same machine. If the cookie can be stolen in this way then the user's machine is probably compromised anyway and you cannot make your system protect data that is outside of your control. You could however renew the token (random string) on a periodic basis giving the user a rolling cookie. You would have to ensure only one user can be logged in at once under the same account though for this to be effective.
Your method only makes sure that the user possess the random string you generated and is using the same external IP address. There exists several way of abusing this system:
if your website doesn't enforce HTTPS then a user connecting using an unsecured public WiFi network could be at risk: if another user of the WiFi network is listening to all the packets being sent on the network, he could intercept your cookie and use it to access the website as your legitimate user. Your server would be unable to differentiate them because they'll both use the same IP address... (There is a Firefox extension available which enable anyone to intercept such login cookie easily: http://en.wikipedia.org/wiki/Firesheep)
This system is also more generally vulnerable to man in the middle attacks (without HTTPS)
If your cookie is stored on the user computer's hard drive it could be reused by another user.
So to answer your question, your system can be deemed as secured provided a few conditions:
you enforce the use of HTTPS on your website (unencrypted HTTP connections should be refused)
your random string is truly random (there exist right and wrong ways of generating random strings in PHP)
your cookie has a short expiry and preferably is set as a session cookie.
You should take a look at the following related question providing details about the proper way of doing what you want to do: How to secure an authentication cookie without SSL
One cannot say this is "bad". But in Web Development, and specifically in its security domain relativity talks. I recommend you to download a CodeIgniter (google it for more info) Session Class (standalone version) and use it. The basic idea is the same as yours, but it is properly more mature since it is developed in such a famous php framework. You can do your DB operations within that class too, since it allows session saving to DB.

Can I securely implement cookieless "keep me signed in" using localstorage in a mobile app?

I don't want users to have to enter their passwords each time, and I don't want to store the passwords locally. When the user first sends me their username and password, I'm planning to send back some hashed version of their password (hash of pasword+salt), which will be put into localstorage to be used to authorize subsequent calls to our web services.
I'm aware that if my localstorage is compromised (e.g. stolen phone), the thief will be able to steal the token and make web service calls as the user, but at least they won't have the user's password.
Are there other vulnerabilities that I'm overlooking? Is there a reason to put it in a cookie instead of localstorage?
There are a few things to consider. You should use SSL to protect against eavesdropping. Otherwise any peer (someone else at the same insecure WiFi spot as your user) may be able to record your hashed password and replay requests with it. Also, the strength of the hashing algorithm is important. With a known username and a weak password it may be possible to generate a table of potential hashes and test that against the known hash (if the attacker manages to compromise the hash).
Regarding the difference between this and cookies, it's pretty simple. Cookies are usually randomly generated by the Server and aren't derived from the password at all. Other than that, cookies are pretty much a shortcut to what you're talking about. Whether you save it in your own storage within your app or to the HTTP library's built-in cookie handler, doesn't really matter. As long as you make sure to use SSL to protect against the eavesdropping/replay attack you should be pretty safe.
Also, I would recommend that you use a server generated hash so that you take the user password out of the equation completely.

Is secure to store user data like logged status and id in cookies?

The question says pretty much everything. My point is, is the user able to change his cookie's values in order to appear "logged", when he's not really logged?
Cookies aren't secure. As others here have pointed out, you shouldn't trust any data received from the client, period. That said, cookies are often used to store Session IDs for logged in users, which is sort of what you're asking.
Signing your cookies will help you detect if they've been tampered with on the client. Basically, you create a HMAC of the keys/values and a secret key, known only to the server. On each request, you re-compute the MAC: if it matches the previous value, all is well; if not, you reject the request.
For more sensitive data, you can optionally encrypt the cookies. Most web frameworks will allow you transparently do these using some kind of "middleware" external to your application code, so the signing/validation and encryption/decryption happens for each request.
Also, you should know that simply securing your cookies doesn't guarantee, er...security :) You might still be vulnerable to Cross-site Request Forgeries.
For more information on cookies, check out this article.
So then if I change the user_id=1 do I become the administrator?
What if i type this into the address bar:
javascript:document.cookie=user_id=1&logged_in=true
In general it is a horrible idea to re-invent the wheal. Especially when it comes to security, a cookie should always be a very large random value. Whatever platform you are using should have a session handler already built for you.
Usually a server generated token is stored in a cookie. When the cookie expires the token is lost and the user needs to sign in again. You can't fake the token. It's not a boolean value stating whether the user is signed in or not.
Anything you get from the client (including cookies) is unsafe. The safe way is to set a cookie with a random hash, log the hash in the database together with an ID and a timestamp (and perhaps even IP) and then check the incoming cookies against the stored hashes. If you set the cookies to expire after some time, make sure you also reject them on the server if they arrive when they should not.

SSL session persistence and secure cookies

I currently have a roll-your-own application security service that runs in my enterprise and is - for the most part - meeting business needs.
The issue that I currently face is that the service has traditionally (naively) relied on the user's source IP remaining constant as a hedge against session hijacking - the web applications in the enterprise are not directly available to the public and it was in the past perfectly acceptable for me to require that a users' address remain constant throughout a given session.
Unfortunately this is no longer the case and I am therefore forced to switch to a solution that does not rely on the source IP. I would much prefer to implement a solution that actually accomplishes the original designer's intent (i.e. preventing session hijacking).
My research so far has turned up this, which essentially says "salt your authentication token hash with the SSL session key."
On the face of it, this seems like a perfect solution, however I am left with a nagging suspicion that real-world implementation of this scheme is impractical due to the possibility that the client and server can at any time - effectively arbitrarily - opt to re-negotiate the SSL session and therefore change the key.
this is the scenario I am envisioning:
SSL session established and key agreed upon.
Client authenticates to server at the application level (i.e. via username and password).
Server writes a secure cookie that includes SSL session key.
Something occurs that causes a session re-negotiation. For example, I think IE does this on a timer with or without a reason.
Client submits a request to the server containing the old session key (since there was no application level knowledge of the re-negotiation there was no opportunity for a new, updated hash to be written to the client).
Server rejects client's credential due to hash match failure, etc.
Is this a real issue or is this a misapprehension on my part due to a (to say the least) less-than-perfect understanding of how SSL works?
See all topics related to SSL persistence. This is a well-researched issue in the load-balancer world.
The short answer is: you cannot rely on the SSLID -- most browsers renegotiate, and you still have to use the source IP. If the IP address is likely to change mid-session then you can force a soft-reauthentication, or use the SSLID as a bridge between the two IP changes (and vice-versa, i.e. only assume hijacking if both IP address and SSLID change at the same time, as seen by the server.)
2014 UPDATE
Just force the use of https and make sure that that you are not vulnerable to session fixation or to CRIME. Do not bother to salt your auth token with any client-side information because if an attacker was able to obtain the token (provided that said token was not just trivial to guess) then whatever means were used to obtain it (e.g. cross-site scripting, or the full compromising of the client system) will also allow the attacker to easily obtain any client-side information that might have gone into the token (and replicate those on a secondary system if needed).
If the client is likely to be connecting from only a few systems, then you could generate an RSA keypair in the browser for possibly every new client system the client connects from (where the public part is submitted to your server and the private part remains in what is hopefully secure client storage) and redirect to a virtual host that uses two-way (peer/client certificate) verification in lieu of password-based authentication.
I am wondering why it would not be just enough to simply
require ssl in your transport
encode inputs (html/url/attribute) to prevent cross-site scripting
require only POSTs for all requests that change information and
prevent CSRF as best you can (depending on what your platform supports).
Set your cookies to HTTPOnly
Yes, but there are several things you can do about it. The easiest it to simply cache the session key(s) you use as salt (per user), and accept any of them. Even if the session is renegotiated you'll still have it in your cache. There are details--expiration policy, etc.--but nothing insurmountable unless you are running something that needs to be milspec hardened, in which case you shouldn't be doing it this way in the first place.
-- MarkusQ

Resources