Write-only form fields (was Re: Proposal for a credential management API.)
Forking this out into a separate thread, as I think it's a great idea, but tangential to the original proposal. :) TL;DR: I put together a strawman based on these suggestions which defines a 'writeonly' attribute on HTMLInputElement: http://projects.mikewest.org/credentialmanagement/writeonly/, WDYT? On Thu, Jul 31, 2014 at 6:37 PM, Brian Smith br...@briansmith.org wrote: And/or the password form could be annotated with an attribute that indicates for which domain an XHR should be allowed to submit the password to. And/or, you could have a submit-password CSP directive to indicate which domains passwords are allowed to be submitted to. We already have 'form-action', I think that serves the purpose suitably well: https://w3c.github.io/webappsec/specs/content-security-policy/#directive-form-action particular, if we are worried about XSS stealing passwords then we have to consider the possibility that XSS has inserted a form without any httponly attributes being used, right? Correct. I think we'd also want a new CSP directive which toggles write-only status for all password fields on a given page: how about http://projects.mikewest.org/credentialmanagement/writeonly/#credentials-directive ? I was thinking the placeholder would be a base64url-encoded cryptographically-random nonce of sufficient length, so that the browser can replace the placeholders within arbitrary HTTP requests, regardless of (most) use of JS to mangle forms before submitting them, and without worrying about replacing the wrong part. I agree, but I don't think we need to specify this normatively. User agents will know what they can easily replace and what they can't, if they choose to go down a nonce route. This would work with (C) too, would it not? It may be a good idea to add an attribute to XHR to trigger such replacement, so that the browser doesn't have to attempt substitution for every HTTP request. I think we'd be able to get away with relying on magical UA behavior: if the browser process hands a nonce to a renderer, it can set a flag, and then look at POSTs generated by the page. As soon as one POST contains the nonce, clear the flag. My suspicion is that most login pages don't do much POSTing, so the overhead would be trivial. I'd prefer that approach, because I don't think we want to expose the actual mechanics to the web. The website shouldn't need to care about whether or not the password it's received is the real password or not. Based on a quick read of Mike's proposal, this would require Mike's proposed API to change to pass around tokens that represent passwords, instead of the password values themselves. This would add complication, but it would be useful. This approach adds complication to the UA's implementation, but shouldn't add complexity to the site consuming the API. This would probably not interact well with use of the WebCrypto API to encrypt the contents of input fields (passwords, credit card numbers, etc.) before submission. I'm pretty happy to break that use case, given that the credential API I've proposed is locked to secure origins. There's no advantage to using WebCrypto to doubly encrypt the password in this context, and I don't think it's something we should encourage. Thanks! -- Mike West mk...@google.com Google+: https://mkw.st/+, Twitter: @mikewest, Cell: +49 162 10 255 91 Google Germany GmbH, Dienerstrasse 12, 80331 München, Germany Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg Geschäftsführer: Graham Law, Christine Elizabeth Flores (Sorry; I'm legally required to add this exciting detail to emails. Bleh.)
Re: Write-only form fields (was Re: Proposal for a credential management API.)
On Fri, Aug 1, 2014 at 5:37 AM, Mike West mk...@google.com wrote: On Thu, Jul 31, 2014 at 6:37 PM, Brian Smith br...@briansmith.org wrote: particular, if we are worried about XSS stealing passwords then we have to consider the possibility that XSS has inserted a form without any httponly attributes being used, right? Correct. I think we'd also want a new CSP directive which toggles write-only status for all password fields on a given page: how about http://projects.mikewest.org/credentialmanagement/writeonly/#credentials-directive? There is some tension here between making things password-specific and simple vs. making them general and harder to understand. Defining this as a mechanism to protect only passwords keeps it simple. But, it seems wrong to have a way to protect passwords but not credit card numbers and social security numbers and other very sensitive input fields that don't use input type=password. This would work with (C) too, would it not? It may be a good idea to add an attribute to XHR to trigger such replacement, so that the browser doesn't have to attempt substitution for every HTTP request. I think we'd be able to get away with relying on magical UA behavior: if the browser process hands a nonce to a renderer, it can set a flag, and then look at POSTs generated by the page. As soon as one POST contains the nonce, clear the flag. My suspicion is that most login pages don't do much POSTing, so the overhead would be trivial. I am not sure that looking only at POSTs is sufficient. Also, some websites put login forms on every page (whether they should or not). But, I agree that it would be better to avoid the need for the attribute if we can. I'd prefer that approach, because I don't think we want to expose the actual mechanics to the web. The website shouldn't need to care about whether or not the password it's received is the real password or not. I suspect some websites will want to disable some aspects of their form validation code if they are dealing with placeholders instead of the real values, especially if the mechanism is extended to things such as social security numbers and credit card numbers. Based on a quick read of Mike's proposal, this would require Mike's proposed API to change to pass around tokens that represent passwords, instead of the password values themselves. This would add complication, but it would be useful. This approach adds complication to the UA's implementation, but shouldn't add complexity to the site consuming the API. This would probably not interact well with use of the WebCrypto API to encrypt the contents of input fields (passwords, credit card numbers, etc.) before submission. I'm pretty happy to break that use case, given that the credential API I've proposed is locked to secure origins. There's no advantage to using WebCrypto to doubly encrypt the password in this context, and I don't think it's something we should encourage. I think it is fine to say that this would be mutually-exclusive with WebCrypto-based approaches to encrypting passwords in the short term. However, I think it is too early in the history of WebCrypto to say that there's advantage to encrypting passwords (or other sensitive information like credit card numbers) in a way that protects them from the from the web server. I think it is likely that some way of composing WebCrypto and this mechanism will be necessary, eventually. Cheers, Brian
Re: Write-only form fields (was Re: Proposal for a credential management API.)
On Fri, Aug 1, 2014 at 3:31 PM, Brian Smith br...@briansmith.org wrote: There is some tension here between making things password-specific and simple vs. making them general and harder to understand. Defining this as a mechanism to protect only passwords keeps it simple. But, it seems wrong to have a way to protect passwords but not credit card numbers and social security numbers and other very sensitive input fields that don't use input type=password. I hadn't considered autofilled credit cards; that's a reasonable use case. We could address credit cards by turning the CSP directive into a list of autocomplete attribute values: `form-readonly cc-number cc-csc ... current-password new-password`. That seems like it would address the credential use case, while leaving flexibility for future field types that developers might care about giving extra protection. That said, it gets quite verbose. If we go this route, perhaps we could come up with a chunk of those types we'd expect developers to want to protect, and give them a special keyword expression: `form-readonly 'the-usual-stuff'`. I am not sure that looking only at POSTs is sufficient. I don't think we should encourage GET-based submission of valuable information. websites put login forms on every page (whether they should or not). If we filled a form on every page, but the user never logged in, there would indeed be a (marginal?) performance impact if we had to examine every POST a website made. That feels like an edgy enough case that we don't have to worry too much about it, but I don't have any numbers to back that up. But, I agree that it would be better to avoid the need for the attribute if we can. The less work we make the website do to get some security benefit, the better. I suspect some websites will want to disable some aspects of their form validation code if they are dealing with placeholders instead of the real values, especially if the mechanism is extended to things such as social security numbers and credit card numbers. If the field is write-only, they won't be able to do client-side validation. That's a necessary consequence of keeping the password out of the renderer, and out of reach of JavaScript. I agree that this is more problematic for SSN or CC fields than for passwords, but I don't see an alternative that would keep the renderer in the dark about the actual value. If they use the credential management API to get credentials, they'll only be getting credentials the user saved. Presumably the user wouldn't save credentials that weren't valid for the site. I'm pretty happy to break that use case, given that the credential API I've proposed is locked to secure origins. There's no advantage to using WebCrypto to doubly encrypt the password in this context, and I don't think it's something we should encourage. I think it is fine to say that this would be mutually-exclusive with WebCrypto-based approaches to encrypting passwords in the short term. However, I think it is too early in the history of WebCrypto to say that there's advantage to encrypting passwords (or other sensitive information like credit card numbers) in a way that protects them from the from the web server. I think it is likely that some way of composing WebCrypto and this mechanism will be necessary, eventually. I'm curious about the use cases for protecting the password from the webserver. I've had some conversations with Sigbjørn Vik about returning hashed passwords rather than real passwords, which might be going along the lines you're thinking. That is, the site would provide hash function and a server nonce when requesting credentials, and the UA would return a client nonce and a LocalCredential whose password value was `hash(password + server nonce + client nonce)`. I think that's worth exploring, but it's tough to do well without requiring the site to hold passwords in plaintext. Is that the kind of use case you're considering? -- Mike West mk...@google.com Google+: https://mkw.st/+, Twitter: @mikewest, Cell: +49 162 10 255 91 Google Germany GmbH, Dienerstrasse 12, 80331 München, Germany Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg Geschäftsführer: Graham Law, Christine Elizabeth Flores (Sorry; I'm legally required to add this exciting detail to emails. Bleh.)
Re: Write-only form fields (was Re: Proposal for a credential management API.)
Your proposal decouples spec from implementation more than the placeholder approach does, which is good. I think the CSP directive is unnecessary and makes things more fragile. The 'protect this credential from XSS' attribute should be a property of a stored credential, not a web site. If the site has the correct CSP headers on 99% of its website, but then for some reason doesn't have them on one page, that page is a potential vector to expose the credential. I think making input fields write-only is more powerful than we strictly need. When a user is manually entering a password, it's okay for the page to be able to read the value they are typing in. If the page has been modified by an attacker at this point, it's too late. What we want is a mechanism to specify 'once this value is stored in a password manager*, protect it from future JS on this page.' That's why I feel like it's relevant to define credential management APIs for the web. *or credit card autofiller. The write-only spec fully breaks XHR form submission (style C in my earlier mail). As Brian pointed out, the placeholder approach can be made to work with XHR if you're willing to do a little extra inspection of arbitrary XHRs. Also, as you pointed out, write-only breaks client-side validation. Client-side validation is very broadly used for password strength meters during signup and change password. I think interfering with strength meters would make it a lot harder for implementers to adopt the spec. I'm curious about the use cases for protecting the password from the webserver. One common use case for client-side crypto is removing systems from scope in PCI (payment card industry) compliance. There's a set of standards related to the handling of credit/debit cards that involve auditing all systems that have card data. There are third-party services that offer compliance by having you encrypt card data in JS and pass it, encrypted, through all your non-compliant systems and into their secure vault where it is decrypted.
Re: Write-only form fields (was Re: Proposal for a credential management API.)
Thanks Jacob! On Fri, Aug 1, 2014 at 6:48 PM, Jacob S Hoffman-Andrews j...@eff.org wrote: I think the CSP directive is unnecessary and makes things more fragile. The 'protect this credential from XSS' attribute should be a property of a stored credential, not a web site. If the site has the correct CSP headers on 99% of its website, but then for some reason doesn't have them on one page, that page is a potential vector to expose the credential. 1. Nothing in the 'writeonly' document prevents UAs from using some sort of heuristic to determine when to fill forms. We already look at things like the form action, there's no reason we couldn't also look at the page-level policy, or field-level attributes. Tagging the credential as 'writeonly' is certainly compatible with this approach. 2. We need CSP anyway in order to specify where forms may permissibly be submitted. Using it as a mechanism for setting a writeonly policy seems like a reasonable extension. I think making input fields write-only is more powerful than we strictly need. When a user is manually entering a password, it's okay for the page to be able to read the value they are typing in. If the page has been modified by an attacker at this point, it's too late. It seems like we could prevent this attack if we stop firing events on 'writeonly' fields. At best, that would prevent reading the value. At worst, that would make the attacker's job harder (she'd have to layer an invisible field over the password field and do magic to get the value out of the one and into the other). What we want is a mechanism to specify 'once this value is stored in a password manager*, protect it from future JS on this page.' That's why I feel like it's relevant to define credential management APIs for the web. *or credit card autofiller. 1. How do we retroactively apply this policy to users' existing credentials? 'writeonly' is a nice, drop-in solution that works for existing credentials as well as new credentials. 2. I'd prefer not to rely on multiple subsystems' understanding of the protect from JS concept. In Chrome, at least, credit cards and passwords are in separate databases, and filled via different code paths. I suspect that doing the work once at the DOM-level would be less error-prone. The write-only spec fully breaks XHR form submission (style C in my earlier mail). As Brian pointed out, the placeholder approach can be made to work with XHR if you're willing to do a little extra inspection of arbitrary XHRs. This approach breaks XHR-based systems which read the data directly from the form field. It doesn't necessarily break an API-driven mechanism. Also, as you pointed out, write-only breaks client-side validation. Client-side validation is very broadly used for password strength meters during signup and change password. I think interfering with strength meters would make it a lot harder for implementers to adopt the spec. Would we need strength meters for sign-in forms? We'd really only need those for sign-up forms when users are creating an account, right? If we can find a reasonable way of distinguishing the two, we can address this use case. For example, if we set a CSP which includes `autocomplete=current-password`, but excludes `autocomplete=new-password` (and we assert that browsers are updated to exclude 'new-password' from autofill), we'd get the advantages of a blanket page-level policy, while allowing developers to help users create strong passwords. I'm curious about the use cases for protecting the password from the webserver. One common use case for client-side crypto is removing systems from scope in PCI (payment card industry) compliance. There's a set of standards related to the handling of credit/debit cards that involve auditing all systems that have card data. There are third-party services that offer compliance by having you encrypt card data in JS and pass it, encrypted, through all your non-compliant systems and into their secure vault where it is decrypted. Interesting. The proposal I've made doesn't support this use case. How common do you believe it is? If we need to support it, then blocking JS-level access to the form data will be difficult. -mike