Re: Proposal for a credential management API.

On Thu, Jul 31, 2014 at 8:19 AM, Jacob S Hoffman-Andrews <jsha@eff.org> wrote:
> I'd say there are approximately three styles for login form submission:
>  A) No JS. A <form> with some <input type=text>'s that gets submitted when
> you click an <input type=submit>.
>  B) Some JS. A <form> that gets submitted by JS calling form.submit().
>  C) All JS. A set of <inputs> whose contents are extracted by JS and POST'ed
> via XHR to the server.
>
> Clearly we can't make C safe against XSS. But I think a lot of web sites
> currently use A or B, or would be willing to use them in exchange for better
> security.

I think we can make C work too.

> Here's a rough idea: Define a new attribute 'httponly' for input elements.

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. In
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?

> When a text input has httponly=true and the password manager saves the input
> value as a PendingCredential or a Credential, the password manager also
> stores an attribute httpOnly=true on the Credential. When the password
> manager autofills forms using a Credential with httpOnly=true, it should
> fill a placeholder value (possibly a numeric identifier for the Credential).

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.

> When a form is submitted, the password manager should intercept the HTTP
> request and replace the placeholder value with the contents of the
> Credential.

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.

Web browsers with sandboxed child processes have the networking logic
in the more-privileged parent process. The purpose of sandboxing is to
protect against exploits in the child process. It would be useful for
the process/privilege separation of sandboxing to be able to protect
the values of passwords--even if it can't always protect the *use* of
the passwords--even in the event of a compromised child process. The
placeholder technique described by Jacob would facilitate such
protection by giving the browser the ability to withhold passwords
from the child (renderer) processes.

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 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. However, it seems reasonable to think that we
could provide some way to integrate both things. One way would be to
define a new API for declarative crypto operations, that allow the
browser to do the substitution and then the crypto without the
application's JS logic ever seeing it. Another way would be to provide
a mechanism for isolating JS code from the DOM (possible reusing the
worker infrastructure) so that some small part of the page's JS code
can do the necessary transformations given the cleartext passwords,
without leaking them; this seems hard though.

Also note how this is pretty at odds with the idea (as I vaguely
understand it) that ServiceWorkers should be able to do anything that
the browser could do, unless the placeholder replacement was done for
outgoing requests made by ServiceWorkers too. But, I think the
protection of passwords and similar secrets is worthwhile enough to
make exceptions and/or do extra work to resolve this conflict.

BTW, Jacob's placeholder idea is similar to the ideas in:
https://bugzilla.mozilla.org/show_bug.cgi?id=653132 and
https://bugzilla.mozilla.org/show_bug.cgi?id=759860#c2

AFAICT, many "security" people at Mozilla thought it was a good idea,
but nobody has tried to implement it in Firefox yet. I also think it
is a good idea for some browser to try it out.

Cheers,
Brian

Received on Thursday, 31 July 2014 16:38:21 UTC