[Ace] 4.01 Get A Token From There, discovery-/form-driven applications and tokens opaque to the client

Christian Amsüss <christian@amsuess.com> Mon, 13 July 2020 15:12 UTC

Return-Path: <christian@amsuess.com>
X-Original-To: ace@ietfa.amsl.com
Delivered-To: ace@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id A7F703A132D for <ace@ietfa.amsl.com>; Mon, 13 Jul 2020 08:12:47 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -1.9
X-Spam-Level:
X-Spam-Status: No, score=-1.9 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001] autolearn=ham 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 mLidR5tduoNk for <ace@ietfa.amsl.com>; Mon, 13 Jul 2020 08:12:45 -0700 (PDT)
Received: from prometheus.amsuess.com (prometheus.amsuess.com [5.9.147.112]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id A17413A133C for <ace@ietf.org>; Mon, 13 Jul 2020 08:12:34 -0700 (PDT)
Received: from poseidon-mailhub.amsuess.com (095129206250.cust.akis.net [95.129.206.250]) by prometheus.amsuess.com (Postfix) with ESMTPS id 7E4284000F for <ace@ietf.org>; Mon, 13 Jul 2020 17:12:32 +0200 (CEST)
Received: from poseidon-mailbox.amsuess.com (hermes.amsuess.com [10.13.13.254]) by poseidon-mailhub.amsuess.com (Postfix) with ESMTP id 901A7AB for <ace@ietf.org>; Mon, 13 Jul 2020 17:12:31 +0200 (CEST)
Received: from hephaistos.amsuess.com (unknown [91.112.68.252]) by poseidon-mailbox.amsuess.com (Postfix) with ESMTPSA id 48FC264 for <ace@ietf.org>; Mon, 13 Jul 2020 17:12:31 +0200 (CEST)
Received: (nullmailer pid 1135105 invoked by uid 1000); Mon, 13 Jul 2020 15:12:26 -0000
Date: Mon, 13 Jul 2020 17:12:26 +0200
From: Christian Amsüss <christian@amsuess.com>
To: ace@ietf.org
Message-ID: <20200713151226.GA1047142@hephaistos.amsuess.com>
MIME-Version: 1.0
Content-Type: multipart/signed; micalg="pgp-sha256"; protocol="application/pgp-signature"; boundary="BOKacYhQ+x31HxR3"
Content-Disposition: inline
Archived-At: <https://mailarchive.ietf.org/arch/msg/ace/TLIbCfU0unm1el99Kjo2eoB37Qw>
Subject: [Ace] 4.01 Get A Token From There, discovery-/form-driven applications and tokens opaque to the client
X-BeenThere: ace@ietf.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: "Authentication and Authorization for Constrained Environments \(ace\)" <ace.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/ace>, <mailto:ace-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/ace/>
List-Post: <mailto:ace@ietf.org>
List-Help: <mailto:ace-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/ace>, <mailto:ace-request@ietf.org?subject=subscribe>
X-List-Received-Date: Mon, 13 Jul 2020 15:12:48 -0000

Hello ACE,

piecing together parts of the big picture of Resource Directory, CoRAL
forms and ACE, I was wondering where in the whole story the client
should tie its intention to the key material it uses to authorize an
action.

Take this -- admittedly contrived, but hopefully illustrative example:

* We have a device (C) inside example.com that coordinates a lot of
  actions (and thus has a good standing with the AS and gets almost all
  the tokens it asks for.

* The device would ike to register its management interface with the RD.

* A malicious attacker intercepts the discovery process, and tells C
  that there is an RD at
  `<coap://attack.example.com/launch-denial-of-service>;rt=core.rd`
  (which is a perfectly legitimate service we're running there for
  commercial purposes; its interface is that you submit POST a link
  there in link-format, and then it ties up the link target with endless
  requests).

* The device tries to register to the local RD by POSTing some data
  there, but as it has no token to the attack server, it receives a

  4.01 Unauthorized
  Get your token from coap://as.example.com, scope launch-attack,
  audience attack.example.com

* The client takes those pieces to the AS, which grants it a token
  (after all, C would be authorized to launch an attack, given it's
  known to be a coordinator -- it just doesn't mean to).

* C sends the token to the RS attack, and sends its POST again, with th
  link to its own management interface.

* The attack server brings C to a grinding halt, because it was tricked
  to shoot its own foot.

(Admittedly it's good practice for foot- and other guns to not just
silently ignore query parameters like ep=the-coordinator&lt=3600, but A)
other interfaces may be more accidentally-compatible, and B) CoRAL forms
would widen the range of craftable requests enormously).

My question here is: Where did this go wrong? Should C have verified
with attack.example.com that it really has the resource type core.rd?
Should it have understood the scope of the action? Should it have a
different security association with the AS for every action it asks
tokens for? And does the answer still hold if it has already obtained a
token to launch attacks (but just didn't notice that the RD it was sent
to happens to have the very URI its attack forces use)?

Kind regards
Christian

-- 
To use raw power is to make yourself infinitely vulnerable to greater powers.
  -- Bene Gesserit axiom