[Acme] Adam Roach's Discuss on draft-ietf-acme-acme-14: (with DISCUSS and COMMENT)

Adam Roach <adam@nostrum.com> Thu, 30 August 2018 04:50 UTC

Return-Path: <adam@nostrum.com>
X-Original-To: acme@ietf.org
Delivered-To: acme@ietfa.amsl.com
Received: from ietfa.amsl.com (localhost [IPv6:::1]) by ietfa.amsl.com (Postfix) with ESMTP id A2C631252B7; Wed, 29 Aug 2018 21:50:31 -0700 (PDT)
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit
From: Adam Roach <adam@nostrum.com>
To: The IESG <iesg@ietf.org>
Cc: draft-ietf-acme-acme@ietf.org, Yoav Nir <ynir.ietf@gmail.com>, acme-chairs@ietf.org, ynir.ietf@gmail.com, acme@ietf.org
X-Test-IDTracker: no
X-IETF-IDTracker: 6.83.1
Auto-Submitted: auto-generated
Precedence: bulk
Message-ID: <153560463159.14901.5253843942494748934.idtracker@ietfa.amsl.com>
Date: Wed, 29 Aug 2018 21:50:31 -0700
Archived-At: <https://mailarchive.ietf.org/arch/msg/acme/cGQzjW7WQQ5oS2nrnXCXZM-2Jn8>
Subject: [Acme] Adam Roach's Discuss on draft-ietf-acme-acme-14: (with DISCUSS and COMMENT)
X-BeenThere: acme@ietf.org
X-Mailman-Version: 2.1.27
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: Thu, 30 Aug 2018 04:50:32 -0000

Adam Roach has entered the following ballot position for
draft-ietf-acme-acme-14: Discuss

When responding, please keep the subject line intact and reply to all
email addresses included in the To and CC lines. (Feel free to cut this
introductory paragraph, however.)


Please refer to https://www.ietf.org/iesg/statement/discuss-criteria.html
for more information about IESG DISCUSS and COMMENT positions.


The document, along with other ballot positions, can be found here:
https://datatracker.ietf.org/doc/draft-ietf-acme-acme/



----------------------------------------------------------------------
DISCUSS:
----------------------------------------------------------------------

Thanks for all the work that everyone has put into this protocol. I'm excited by
what it's been able to do for the certificate issuance sector as a whole, and
truly appreciate all of the early implementors who have put both clients and
servers into active production. I'm definitely balloting YES once we get clarity
on my DISCUSS, below.

---------------------------------------------------------------------------

I've looked at this several different ways, and I must be missing something
obvious -- which should make this easy to clear.

§6.2:

>  Note that authentication via signed JWS request bodies implies that
>  GET requests are not authenticated.  Servers MUST NOT respond to GET
>  requests for resources that might be considered sensitive.  Account
>  resources are the only sensitive resources defined in this
>  specification.

This doesn't seem correct.

For example, let's imagine that I, as a user, get the directory for an ACME
server, the body of which is the example in §7.1.1. Then, I go through the
new-account process, and receive the Account object in §7.1.2:

   {
     "status": "valid",
     "contact": [
       "mailto:cert-admin@example.com",
       "mailto:admin@example.com"
     ],
     "termsOfServiceAgreed": true,
     "orders": "https://example.com/acme/acct/1/orders"
   }

Huh. Suddenly, I'm not so interested in *my* orders, because I've noticed that
different users' orders are apparently at a predictable URL that varies only by
a small integer. Curious, I change the "1" to a "2" and send:

  GET /acme/acct/2/orders HTTP/1.1
  Host: example.com

And get back not *my* orders, but someone *else's* orders.

   HTTP/1.1 200 OK
   Content-Type: application/json

   {
     "orders": [
       "https://example.com/acme/acct/2/order/1",
       "https://example.com/acme/acct/2/order/2",
       "https://example.com/acme/acct/2/order/3",
       "https://example.com/acme/acct/2/order/4"
     ]
   }

Interesting. So now I can do four more unauthenticated GETs and grab those order
objects.

   HTTP/1.1 200 OK
   Content-Type: application/json

   {
     "status": "valid",
     ...
     "identifiers": [
       { "type": "dns", "value": "smithforcongress.example" }
     ],
     ...
     "certificate": "https://example.com/acme/cert/1234"
   }
----------
   HTTP/1.1 200 OK
   Content-Type: application/json

   {
     "status": "valid",
     ...
     "identifiers": [
       { "type": "dns", "value": "something-embarassing-with-goats.example" }
     ],
     ...
     "certificate": "https://example.com/acme/cert/5678"
   }
----------
   HTTP/1.1 200 OK
   Content-Type: application/json

   {
     "status": "valid",
     ...
     "identifiers": [
       { "type": "email", "value": "smith-personal@obscure-domain.example" }
     ],
     ...
     "certificate": "https://example.com/acme/cert/9abc"
   }
----------
   HTTP/1.1 200 OK
   Content-Type: application/json

   {
     "status": "valid",
     ...
     "identifiers": [
       { "type": "tn", "value": "+12025550172" }
     ],
     ...
     "certificate": "https://example.com/acme/cert/defg"
   }

So now I've learned that the same account has pulled certs for both
"smithforcongress.example" and "something-embarassing-with-goats.example"; that
they have control over the email address
"smith-personal@obscure-domain.example," and that their phone number is +1 202
555 0172. There's a pretty good chance that... someone didn't want all of that
to be generally known.

And... huh... that's interesting.

     GET /acme/cert/9abc HTTP/1.1
     Host: example.com

     HTTP/1.1 200 OK
     Content-Type: application/pem-certificate-chain
     Link: <https://example.com/acme/some-directory>;rel="index"

     -----BEGIN CERTIFICATE-----
     [X.509 Cert for smith-personal@obscure-domain.example]
     -----END CERTIFICATE-----
     -----BEGIN CERTIFICATE-----
     [Issuer certificate contents]
     -----END CERTIFICATE-----
     -----BEGIN CERTIFICATE-----
     [Other certificate contents]
     -----END CERTIFICATE-----

Whoa. That's cool. The next thing I'm doing is configuring Thunderbird to forge
mail from smith-personal@obscure-domain.example and going on an email spree
admitting to owning a rather embarrassing domain name, in which I ask concerned
constituents to call me on my unlisted phone number to discuss the issue.

Clearly I've missed something, because this just seems way too obvious. What
prevents this attack (or a similar one from observing that the order URLs are
predictable?)

If I *haven't* missed something, then there appears to have been an assumption
here, never written into the document, that the URLs generated for the orders
list and for the order objects are unguessable. If that's the case, I would:

(1) Expect this to be stated in section 7.1.2.1 and 7.1.3

(2) Expect a specification of a reasonable number of bits of entropy to use in
    orders list and order object URLs.

(3) Expect the examples to show appropriately random URLs (e.g.
    https://example.com/acme/acct/9258fac3-7866-4922-90e6-bbd0c89e751a/orders)


(4) Expect a treatment in section 10 of the risks that might arise from third
    parties gaining access to orders, as doing so provides free-and-clear access
    to private certificates (which, for dns, can be trivially used to
    revoke certs; and for other types, can be used for impersonation as well)

Again, I'm still expecting that I've simply missed something obvious -- I just
can't for the life of me figure out what it is.


----------------------------------------------------------------------
COMMENT:
----------------------------------------------------------------------

I have a small handful of substantive comments, and several editorial nits.

---------------------------------------------------------------------------

General:

This protocol specifies the use of RFC 3339 time formats in several places. Most
modern protocols that reference RFC 3339 choose to place further restrictions on
the format; commonly, the time-secfrac portion is required to be omitted, and
the time-offset portion is required to be "Z". In addition to making parsing
easier, these restrictions have the property of any given time having only one
possible string representation.

My suggestion would be for ACME to include similar restrictions. Alternately, if
the full range of optionality allowed by RFC 3339 is actually intended, please
adjust the examples so that at least a few of them include fractional seconds
and non-UTC timezones.

---------------------------------------------------------------------------

§5:

For avoidance of doubt, this section should probably indicate that values that
will appear in certificates will be used and conveyed in the form present in
certificates, possibly with a reference to RFC 5280 section 7.

---------------------------------------------------------------------------

§6.4.1:

>  The server MUST generate the value provided in
>  Replay-Nonce in such a way that they are unique to each message, with
>  high probability.  For instance, it is acceptable to generate Replay-
>  Nonces randomly.

It's not clear whether the values need to also be unpredictable; e.g., would it
be okay if the value of the nonce for operation n+1 could be easily derived or
guessed from the nonce for operation n?

---------------------------------------------------------------------------

§7.4.2:

>  GET /acme/cert/asdf HTTP/1.1
>  Host: example.com
>  Accept: application/pkix-cert
>
>  HTTP/1.1 200 OK
>  Content-Type: application/pem-certificate-chain

This pairing of "Accept: application/pkix-cert" with "Content-Type:
application/pem-certificate-chain" seems to be at odds with the description in
RFC 7231 §5.3.2. I know that proactive negotiation is optional in HTTP, but it
seems that it would be much better to show this as something like:

   GET /acme/cert/asdf HTTP/1.1
   Host: example.com
   Accept: application/pkix-cert, application/pem-certificate-chain;q=0.5

===========================================================================

All of my remaining comments are editorial in nature, and most of those are
minor editorial nits.


i-d nits reports:

  ** There are 3 instances of too long lines in the document, the longest one
     being 15 characters in excess of 72.

I'm not sure it's reasonable to expect the RFC editor to have enough knowledge
to know how to best split the key authorization across lines (or to elide
portions of it, whichever makes more sense).

---------------------------------------------------------------------------

i-d nits also reports:

  -- The exact meaning of the all-uppercase expression 'NOT REQUIRED' is not
     defined in RFC 2119.  If it is intended as a requirements expression, it
     should be rewritten using one of the combinations defined in RFC 2119;
     otherwise it should not be all-uppercase.

---------------------------------------------------------------------------

§1:

>  Existing Web PKI certificate authorities tend to use a set of ad hoc
>  protocols for certificate issuance and identity verification.  In the
>  case of DV certificates, a typical user experience is something like:

I expect this text won't age gracefully. Even at the time of publication of
this document, over 64% of all certificates issued on the web have been issued
using the ACME protocol, arguably making it the "typical user experience." (see
https://censys.io/certificates/report?q=tags%3Atrusted&field=parsed.issuer.organization.raw&max_buckets=50)

I suggest caveating this paragraph with text along the lines of "prior to the
advent of the protocol described by this document, the typical user experience
was..."

---------------------------------------------------------------------------

§1:

>  For example, as of this writing, there is
>  ongoing work to use ACME for issuance of Web PKI certificates
>  attesting to IP addresses [I-D.ietf-acme-ip] and STIR certificates
>  attesting to telephone numbers [I-D.ietf-acme-telephone].

Suggestion: consider including [draft-ietf-acme-email-smime] in this list.

---------------------------------------------------------------------------

§6.2:

>  These intermediaries can also change values in the request that are
>  not signed in the HTTPS request, e.g., the request URL and headers.

Nit: "...header fields."

---------------------------------------------------------------------------

§6.4:

>  An error response with the
>  "badNonce" error type MUST include a Replay-Nonce header with a fresh
>  nonce.

Nit: "...header field..."

---------------------------------------------------------------------------

§6.5:

>  "urn:ietf:params:acme:error:rateLimited".  Additionally, the server
>  SHOULD send a "Retry-After" header [RFC7231] indicating when the
>  current request may succeed again.

Nit: "...header field..."

>  In addition to the human-readable "detail" field of the error
>  response, the server MAY send one or multiple link relations in the
>  "Link" header  [RFC8288] pointing to documentation about the specific
>  rate limit that was hit, using the "help" link relation type.

Nit: "...header field..."

---------------------------------------------------------------------------

§7.1:

>  The "->" is a mnemonic for a Location
>  header pointing to a created resource.

Nit: "...header field..."

---------------------------------------------------------------------------

§7.1.2.1:

>  The server MAY
>  return an incomplete list, along with a Link header with a "next"
>  link relation indicating where further entries can be acquired.

Nit: "...header field..."

---------------------------------------------------------------------------

§7.3.4:

>  This response MUST
>  include a Link header with link relation "terms-of-service" and the
>  latest terms-of-service URL.

Nit: "...header field..."

---------------------------------------------------------------------------

§7.4.2:

>  Because certificate resources are immutable once issuance is
>  complete, the server MAY enable the caching of the resource by adding
>  Expires and Cache-Control headers specifying a point in time in the
>  distant future.  These headers have no relation to the certificate's
>  period of validity.

Nit: "...header fields..." (twice)

>  The ACME client MAY request other formats by including an Accept
>  header [RFC7231] in its request.

Nit: "...header field..."

>  provide one or more "Link: rel="up"" headers pointing to an issuer or

Nit: "...header fields..."

---------------------------------------------------------------------------

§7.5:

>  When a client receives an order from the server it downloads the
>  authorization resources by sending GET requests to the indicated
>  URLs.

Nit: "...from the server, it downloads..."