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