[Acme] On multiple CAs and contact-based recovery

Karthik Bhargavan <karthikeyan.bhargavan@inria.fr> Wed, 23 March 2016 22:33 UTC

Return-Path: <Karthikeyan.Bhargavan@inria.fr>
X-Original-To: acme@ietfa.amsl.com
Delivered-To: acme@ietfa.amsl.com
Received: from localhost (localhost []) by ietfa.amsl.com (Postfix) with ESMTP id 0619612DA03 for <acme@ietfa.amsl.com>; Wed, 23 Mar 2016 15:33:56 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -5.899
X-Spam-Status: No, score=-5.899 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, FORM_FRAUD=1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_HI=-5, T_FILL_THIS_FORM_SHORT=0.01, T_RP_MATCHES_RCVD=-0.01] autolearn=ham autolearn_force=no
Received: from mail.ietf.org ([]) by localhost (ietfa.amsl.com []) (amavisd-new, port 10024) with ESMTP id HYmH_3NsPo-R for <acme@ietfa.amsl.com>; Wed, 23 Mar 2016 15:33:53 -0700 (PDT)
Received: from mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr []) (using TLSv1.2 with cipher RC4-SHA (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 0B4FF12D0B2 for <acme@ietf.org>; Wed, 23 Mar 2016 15:33:51 -0700 (PDT)
X-IronPort-AV: E=Sophos;i="5.24,383,1454972400"; d="scan'208,217";a="170482442"
Received: from 89-156-8-219.rev.numericable.fr (HELO []) ([]) by mail3-relais-sop.national.inria.fr with ESMTP/TLS/DHE-RSA-AES256-SHA; 23 Mar 2016 23:33:49 +0100
From: Karthik Bhargavan <karthikeyan.bhargavan@inria.fr>
Content-Type: multipart/alternative; boundary="Apple-Mail=_47052A7D-AA5C-42BE-8669-87CF8315A547"
Message-Id: <B594A7FA-1F8B-489C-8A7D-328BCD60C79A@inria.fr>
Date: Wed, 23 Mar 2016 23:33:49 +0100
To: acme@ietf.org
Mime-Version: 1.0 (Mac OS X Mail 9.2 \(3112\))
X-Mailer: Apple Mail (2.3112)
Archived-At: <http://mailarchive.ietf.org/arch/msg/acme/9HX2i0oGyIPuE-nZYAkTTYXhqnk>
Subject: [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: Wed, 23 Mar 2016 22:33:56 -0000

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.


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.


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.

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

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/ <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.

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)

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.


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.