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.

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


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.


Best,
Karthik
_______________________________________________
Acme mailing list
[email protected]
https://www.ietf.org/mailman/listinfo/acme

Reply via email to