Re: [Acme] On multiple CAs and contact-based recovery

Ron <ron@debian.org> Fri, 25 March 2016 02:59 UTC

Return-Path: <ron@debian.org>
X-Original-To: acme@ietfa.amsl.com
Delivered-To: acme@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id CD5AF12D169 for <acme@ietfa.amsl.com>; Thu, 24 Mar 2016 19:59:24 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -1.61
X-Spam-Level:
X-Spam-Status: No, score=-1.61 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, FORM_FRAUD=1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, T_FILL_THIS_FORM_SHORT=0.01] autolearn=no autolearn_force=no
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id QDxo1yjbYhBJ for <acme@ietfa.amsl.com>; Thu, 24 Mar 2016 19:59:22 -0700 (PDT)
Received: from ipmail06.adl6.internode.on.net (ipmail06.adl6.internode.on.net [150.101.137.145]) by ietfa.amsl.com (Postfix) with ESMTP id 11E4012D17A for <acme@ietf.org>; Thu, 24 Mar 2016 19:59:20 -0700 (PDT)
Received: from ppp14-2-14-167.lns21.adl2.internode.on.net (HELO mailservice.shelbyville.oz) ([14.2.14.167]) by ipmail06.adl6.internode.on.net with ESMTP; 25 Mar 2016 13:29:19 +1030
Received: from localhost (localhost [127.0.0.1]) by mailservice.shelbyville.oz (Postfix) with ESMTP id 175FFFFD86; Fri, 25 Mar 2016 13:29:19 +1030 (ACDT)
X-Virus-Scanned: Debian amavisd-new at mailservice.shelbyville.oz
Received: from mailservice.shelbyville.oz ([127.0.0.1]) by localhost (mailservice.shelbyville.oz [127.0.0.1]) (amavisd-new, port 10024) with LMTP id SNcFYPPmN97H; Fri, 25 Mar 2016 13:29:16 +1030 (ACDT)
Received: from hex.shelbyville.oz (hex.shelbyville.oz [192.168.1.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mailservice.shelbyville.oz (Postfix) with ESMTPS id 3EAF8FF81E; Fri, 25 Mar 2016 13:29:16 +1030 (ACDT)
Received: by hex.shelbyville.oz (Postfix, from userid 1000) id 2D71E80470; Fri, 25 Mar 2016 13:29:16 +1030 (ACDT)
Date: Fri, 25 Mar 2016 13:29:16 +1030
From: Ron <ron@debian.org>
To: Richard Barnes <rlb@ipv.sx>
Message-ID: <20160325025916.GK15641@hex.shelbyville.oz>
References: <B594A7FA-1F8B-489C-8A7D-328BCD60C79A@inria.fr> <CAL02cgQPDogLc=JAjC8BD6tQkWDU4XNCmofm1H6BaCAJ3j9n-A@mail.gmail.com>
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Disposition: inline
Content-Transfer-Encoding: 8bit
In-Reply-To: <CAL02cgQPDogLc=JAjC8BD6tQkWDU4XNCmofm1H6BaCAJ3j9n-A@mail.gmail.com>
User-Agent: Mutt/1.5.23 (2014-03-12)
Archived-At: <http://mailarchive.ietf.org/arch/msg/acme/33pQ2dCyqAGhqt2ceXjnPzbH2NM>
Cc: Karthik Bhargavan <karthikeyan.bhargavan@inria.fr>, "acme@ietf.org" <acme@ietf.org>
Subject: Re: [Acme] On multiple CAs and contact-based recovery
X-BeenThere: acme@ietf.org
X-Mailman-Version: 2.1.17
Precedence: list
List-Id: Automated Certificate Management Environment <acme.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/acme>, <mailto:acme-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/acme/>
List-Post: <mailto:acme@ietf.org>
List-Help: <mailto:acme-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/acme>, <mailto:acme-request@ietf.org?subject=subscribe>
X-List-Received-Date: Fri, 25 Mar 2016 02:59:25 -0000


Keeping this whole message intact for now, feel free to trim it if we
split this into threads on the individual parts.


On Thu, Mar 24, 2016 at 11:33:18AM -0400, Richard Barnes wrote:
> On Wed, Mar 23, 2016 at 6:33 PM, Karthik Bhargavan <
> karthikeyan.bhargavan@inria.fr> wrote:
> 
> > Dear All,
> >
> > Recently, after being asked by Josh Aas, I wrote a formal model of the
> > ACME protocol
> > in ProVerif and analyzed it for various properties. I am still in the
> > process of cleaning
> > up the model and writing up a proper report, but with the next IETF being
> > so close,
> > here’re some early comments that may be useful for the group to discuss.
> > These notes are inspired by my model of the -01 draft and some of it may
> > be out of date.
> >
> > Summary:
> > -------------
> >
> > Against a classic symbolic protocol adversary, ACME achieves most of its
> > security goals.
> > Notably, it prevents many more attacks than traditional CAs through its
> > use of client signatures,
> > and specifically through the strong binding between the client’s account
> > key and the validated domain.
> >
> > However, there are two scenarios of concern that should be studied more
> > carefully:
> > (1) if an ACME client supports multiple CAs or ACME servers and one of
> > them may be malicious or compromised;
> > (2) if the contact channel is used for account recovery or, in the future,
> > if an email channel is used for domain validation.
> >
> > In both these cases, the protocol as it is currently specified (in -01) is
> > not strong enough to provide the desired guarantees,
> > but the good news is that it can be easily strengthened to prevent abuse.
> >
> > We describe 3 issues, in increasing order of seriousness. The first two
> > are closely related and may have been discussed
> > in the list before. Issue 3 seems to be new and should probably be
> > considered an attack on the stated goals of the ACME -01 spec.
> >
> > Model:
> > ---------
> >
> > Our model consists of four kinds of principals:
> > - Domain Owners (who can answer domain validation challenges)
> > - ACME clients (who own account keys)
> > - ACME servers (who own HTTPS certificates acceptable to ACME clients)
> > - CAs (who own CA signing certificates)
> >
> > An ACME client can talk to any number of ACME servers over three kinds of
> > channels:
> >
> > - HTTPS channels, which are treated as server-authenticated
> > request-response channels
> >   That is: anybody can send a request but only the server can read it,
> >      only the server can send a response,
> > and furthermore only the client who sent the request can read the response.
> 
> You might want to consider one additional nuance here.  The threat model
> we're considering includes the ability for the CA to use a CDN that
> terminates TLS.  So this particular entity is able to forge responses from
> the server and block messages to the server.  (And of course, it can act as
> a client if it wants to.)  That is the reason, for example, that the
> keyAuthorization includes the account key being authorized, so that the
> intermediary can't swap tokens to cause a domain holder to authorize its
> own key pair.  I have pretty good confidence that we're OK in this model,
> but the attacks can be subtle, so some modeling would be really helpful.
> 
> 
> > - DNS/HTTPS/SNI validation channels, which are treated as
> > sender-authenticated asynchronous channels
> >   That is:  only the domain owner(s) can write on the channel, but
> > anybody can read it
> >
> > - Contact/Email channels, which are treated as receiver-authenticated
> > asynchronous channels
> >   That is: anybody can write messages on the channel, but only the domain
> > owner(s) can read it.
> >
> > In our model, we can experiment with the compromise of various
> > combinations of principals.
> > When a principal is compromised, all the channels they control become
> > available to the adversary.
> > For example, if an ACME HTTPS server is malicious or compromised, then its
> >  HTTPS certificate
> > signing key is known to the adversary, and consequently the ACME channel
> > is compromised.
> >
> > The ACME spec informally assumes that at most one channel is compromised.
> > In the rest of this email, we primarily consider compromise of the HTTPS
> > channel
> > between ACME clients and servers. We assume that the CA signing key and the
> > honest client’s account key remains secure.
> >
> >
> > Issue 1: No Mutual Authentication
> > ---------------------------------------------
> >
> > The first issue already appears when we model the ACME HTTPS channel.
> > We would have expected to model this as a mutually-authenticated channel
> > since the client always signs its messages with the account key.
> > However, although the client’s signature is tunnelled inside HTTPS, the
> > signature itself is not “bound” to the HTTPS channel.
> >
> > This means that a message from an ACME client C to a server S
> > can be forwarded by S to a different ACME server S’ (as long as S’ is also
> > willing
> > to accept C’s account key). This is a classic “credential forwarding”
> > attack
> > that is typically mitigated by channel binding.
> 
> I think we had considered this in some pre-WG analyses of ACME.  At that
> point, it seemed that these risks were not so severe, since the attacker
> cannot cause the CA to assert a name/key binding that the domain owner
> didn't intent; he can only cause that binding to be asserted by a CA other
> than the one that the client expects.
> 
> However, if there's an easy way to to fix this, is seems worth nailing down.

It possibly could be used to trick an inattentive client to propagate
assertions that S’ is authorised to issue certificates for the owner.

Which might not pose a viable attack on ACME itself, but could be a
lever for one against the owner in some other corner.


> > For example, ACME could rely on the Token Binding specifications
> > to securely bind the client signature to the underlying channel:
> > https://datatracker.ietf.org/wg/tokbind/documents/
> >
> > Alternatively, all ACME messages could include the identity of the ACME
> > server
> > (this could, for example, be the SNI or server domain name that the ACME
> > client
> >  checks in the certificate when it connects to the server.)
> >
> > Either of these choices would make the HTTPS channel truly
> > mutually-authenticated,
> > simplifying a lot of the subsequent analysis.
> >
> 
> Between these two options, I would be more attracted to the latter.  It's
> always been a bit of a sore point that the request URI was not covered by
> the client's signature, but to avoid the complexity of URL comparison, we
> did the "resource" thing instead.  But maybe it makes sense to include the
> whole URL after all.
> 
> OLD: { "resource": "new-reg", ... }
> NEW: { "url": "https://example.com/acme/new-reg", ... }
> 
> Now that I look at that, there's one more additional property, in addition
> to mitigating issues (1) and (2) here.  In cases where the server might
> have multiple ACME services running (e.g., for different CAs), it prevents
> a TLS MitM like a CDN from switching requests between them.

I think, all else being equal, I prefer the latter for its simplicity too.

How about: { "resource": "https://example.com/acme/new-reg", ... }

The distinction being, we don't assert it is a URL, and it should not be
compared using the rules for URI equivalence.  It's still just a simple
string that must compare exactly to be accepted.

It just now specifies exactly _which_ resource is requested, rather than
_what_ resource is requested.

For clients that shouldn't be a major change, they already need to do
the mapping "new-reg" <-> directory resource URI anyway, and boulder
can allow a grace period where either is accepted while the existing
client software is being updated and deployed.

I like the idea of using that field to contain a more specific request,
including information which we already know but would otherwise discard
in the JWS.

This seems worth doing to me.


> > Issue 2: Certificate Request not bound to CA
> > ------------------------------------------------------------
> >
> > Suppose an ACME client C connects to an ACME server S,
> > and suppose that S’s HTTPS private key is compromised (or that S is
> > malicious,
> > or a man-in-the-middle has compromised the ACME channel or that the
> > attacker has obtained a mis-issued certificate for S, or that the attacker
> > has fooled the client into accepting its certificate).
> >
> > Now, the attacker can intercept authorization and certificate requests
> > from C to S,
> > and instead forward them to another ACME server S’. If S’ requests domain
> > validation with a token T, the attacker forwards the token to the client,
> > who
> > will dutifully place its account key K and token T on its validation
> > channel.
> > S’ will check this token and accept the authorization and issue a
> > certificate
> > that the attacker can forward to C.
> >
> > This means that C asked for a certificate from S, but instead received a
> > certificate from S’.
> > Moreover, it may have paid S for the service, but S’ might have done it
> > for free.
> > This request forwarding “attack” can be prevented if C checks the
> > certificate
> > it gets to make sure it was issued by the expected CA. It can also be
> > prevented
> > by channel binding.
> >
> > An alternative mitigation would be for ACME to extend the Key
> > Authorization string to include the CA’s identifier. E.g.:
> >
> > key-authz = token || '.' || base64url(JWK_Thumbprint(accountKey)) || ‘.’
> > || base64url(server_id)
> 
> I think channel binding, in the form discussed above, is a more elegant
> solution to this.  IIUC, with channel binding, the token would implicitly
> tie in the server's identity, since it was issued in response to a request
> for that server.
> 
> 
> > Where server_id could be the ACME server’s SNI or certificate-hash.
> > In other words, the domain validation challenge currently includes the
> > client’s identity and the server’s challenge,
> > but it does not include the server’s identity, allowing the challenge
> > response to be used with multiple servers.
> > This may well be a privacy feature (?) but if not then adding further
> > context to the challenge response will add protection
> > in the multiple CA use case
> >
> >
> > Issue 3: Contact-based Recovery can be Hijacked
> > -------------------------------------------------------------------
> >
> > The use of sender-authenticated channels in ACME (HTTPS/SNI/DNS) seems
> > to  be relatively secure.
> > However, more attention needs to be paid to the receiver-authenticated
> > channels like email, because they are
> > easy to get wrong. For example, if the ACME server (in some future draft)
> > uses the website administrator’s email
> > address to send the domain validation token, a naive implementation of
> > this kind of challenge would be vulnerable to attack.
> >
> > In the -01 specification, the contact channel (typically email) is used
> > for account recovery
> > when the ACME client has forgotten its account key. We show how the
> > careless
> > use of this channel can be vulnerable to attack, and propose a
> > countermeasure.
> >
> > Suppose an ACME client C issues an account recovery request for account A
> > with a new key K to the ACME server S.
> > A network attacker blocks this request and instead sends his own account
> > recovery request for account A (pretending to be C)
> > with his own key K’. The server S will then send C an email asking to
> > click on a link.
> > C will think this is a request in response to its own account recovery
> > request and will click on it.
> > S will think that C has confirmed account recovery and will transfer the
> > account A to the attacker’s key K’.
> >
> > In the above attack, the attacker did not need to compromise the contact
> > channel (or for that matter, the ACME channel).
> > This seems to directly contradict the security considerations in 9.3,
> > unless I am reading something wrong.
> > The key observation here is that on receiver-authenticated channels (e.g.
> > email) the receiver does not get to
> > bind the token provided by the server with its own account key.
> > Consequently, we need to add further checks.
> >
> > The email sent from S to C should contain a fresh token + C’s new account
> > key (e.g. within a key-authz field)
> > Instead of clicking on the link (out-of-band), C should cut and paste the
> > token into the ACME client which
> > can first check that the account key provided by the server matches the
> > one in the ACME client and only
> > then does it send the token back to the server.
> >
> > Alternatively, if we don’t want to change ACME too much, we must require
> > that the email recipient at C
> > visually confirms that the account key (thumbprint) provided by the server
> > matches the one displayed
> > in the ACME client.
> >
> > The attack described here is on account recovery, but a similar attack
> > appears if we allow email-based
> > domain validation. A malicious ACME server or man-in-the-middle can then
> > get certificate issued for C’s
> > domains with its own public key, without compromising the
> > contact/validation channel. The mitigation
> > for that attack would be very similar to the one proposed above.
> >
> > Emails with clickable links are *BAD*; we should enhance their security by
> > linking them better with
> > the ACME account key.
> >
> >
> > Proposal
> > ---------------
> >
> > I notice that -02 has removed account recovery completely. I would
> > recommend that we can
> > include account recovery, by piggybacking on the account roll-over
> > mechanism and using MACs
> > instead of bearer tokens sent in emails.
> >
> > The proposal that came up in discussions with Richard Barnes is as follows.
> >
> > Currently, account roll-over does something like the following: It signs
> > the roll-over request with the old key, where the request itself contains a
> > signature of the old key with the new key.
> > Note that it would be fine to flip the order of these signatures: It could
> > sign the roll-over request with the new key, where the request itself
> > contains a signature of the new key with the old key.
> >
> > We further observe that account recovery is a form of roll-over where you
> > are expected to know a secret that has been delivered out-of-band.
> > So, let’s assume that when the ACME client initiates account recovery, the
> > server will somehow out-of-band authenticate the user’s request
> > and issue the user with a MAC key (e.g. it may email a MAC key to the
> > contact email address, but it would be better advised to ask the user some
> > questions first.)
> >
> > Now, the ACME client can complete the account recovery by sending a
> > message as follows: It signs the recovery request with a new account key,
> > and the request itself
> > contains a MAC of the new key with the recovery MAC key.
> >
> > To make this fully uniform with account roll-over, it would also be
> > attractive to flip the order of signatures in the roll-over request, as
> > described above, so that the outer
> > signature is always with the new key, and the inner JWS is either a
> > signature with the old account key or a MAC with the recovery key.
> > account key, and the request itself contains a signature of the old key
> > with the new key.
> 
> I agree that this is worth doing.  It's worth having some recovery
> mechanism in here to avoid CAs having to invent their own (and possibly
> introduce vulns).  I would propose we do this in 2-3 pull requests:
> 
> 1. Swap the order of the signatures in account key roll-over
> 
> OLD: Sign(K_old_priv, Sign(K_new_priv, Fingerprint(K_old_pub)))
> NEW: Sign(K_new_priv, Sign(K_old_priv, Fingerprint(K_new_pub)))
> 
> 2. Add a section on how to do account recovery if you have a recovery key
> provisioned, namely:
> 
> NEW: Sign(K_new_priv, MAC(K_recovery, Fingerprint(K_new_pub)))
> 
> (We can benefit from JWS's conflation of signature and MAC here.)
> 
> 3. (Optional) Define a way to provision a client with a recovery key.
> 
> I mark (3) as optional because neither of the options for how to do it are
> especially nice.  On the one hand, if you do it in-band, then you have to
> add a lot of complexity to encrypt the recovery key so that only the client
> can read it (in order to keep it out of the hands of a TLS MitM).   On the
> other hand, if you do it out-of-band, then you're vulnerable to hijacking
> via compromise of the contact channel.  Between those two, my preference
> would be for the latter, just for simplicity, but I'm open to suggestions.

I am still fond of leveraging the existing PGP infrastructure for out of
band recovery.

That could work something like:

I register my PGP key fingerprint (or the key itself) as part of my
contact details.

In the event of out of band recovery, I request the server email me a
token.  It mails that to the registered recovery address (perhaps also
allowing it to be sent to the contact address registered with whois or
the role contact addresses accepted by CAB forum) - encrypted to my
PGP key, and signed with the CA's role key.

I then either follow the process above, using the ACME protocol with
that token, or alternatively, I email back a verification, signed with
my PGP key and encrypted to the CA's key.


This way, hijacking the contact channel is limited to someone who has
stolen my PGP key and been able to crack or otherwise bypass the strong
passphrase on it.

And if they've done that, then realistically, you've all already lost
because with that, they'd also be able to upload a trojaned ACME client
to Debian in my name, and compromise everyone who used it until that
got noticed ...  (among other packages, including some which could
potentially be used to compromise the CA's servers directly too!).


  Ron