[OAUTH-WG] potential issues in draft-ietf-oauth-signed-http-request?

Brian Campbell <bcampbell@pingidentity.com> Tue, 21 July 2015 14:20 UTC

Return-Path: <bcampbell@pingidentity.com>
X-Original-To: oauth@ietfa.amsl.com
Delivered-To: oauth@ietfa.amsl.com
Received: from localhost (ietfa.amsl.com [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id D92041A8868 for <oauth@ietfa.amsl.com>; Tue, 21 Jul 2015 07:20:37 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -1.378
X-Spam-Level:
X-Spam-Status: No, score=-1.378 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, FM_FORGED_GMAIL=0.622, HTML_MESSAGE=0.001, SPF_PASS=-0.001] autolearn=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 dZlQtSo1DNUh for <oauth@ietfa.amsl.com>; Tue, 21 Jul 2015 07:20:35 -0700 (PDT)
Received: from mail-ig0-x22d.google.com (mail-ig0-x22d.google.com [IPv6:2607:f8b0:4001:c05::22d]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 41DA61B2E6E for <oauth@ietf.org>; Tue, 21 Jul 2015 07:20:13 -0700 (PDT)
Received: by igr7 with SMTP id 7so41785453igr.0 for <oauth@ietf.org>; Tue, 21 Jul 2015 07:20:12 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pingidentity.com; s=gmail; h=mime-version:from:date:message-id:subject:to:content-type; bh=db6vJqELfqyjEvT+Co8AIcZg56YEbWmb2GSkI2Z99C8=; b=HwkSSKy7cBCn0XqfJTD0om6oBKGchmx4DyzQC/NlYzW1Krj8vZlnDUKOOMNEfjeVhc FLMS4Qh6cx/COBIZB0rSfv0WqzerfBUq7+S+q1zuXnQDKCfbp3aiDS9MWVlXzUgSB4Wv qB6ftUrnTX/yvQt+Bs1gBsyiINgfkKdM3hW9I=
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:from:date:message-id:subject:to :content-type; bh=db6vJqELfqyjEvT+Co8AIcZg56YEbWmb2GSkI2Z99C8=; b=lLjanVSWkBcQnR696xM8Q/9CONBL/O424SKIVq1P08T269BMnnjWxF7EBgjYiC7HoO 0ssYHpp5l9HUajNUdfMw9OZKUXGzThWF00dAS2ZjhYvWgo3bvrfciJjwj3ndnj5u+YZz j2xmHMuynEINzO1kDjfmGraxawIrTi9wAfc+hVkkIwJE4mrXcd45w4PBQ74sl6muzuXg GNVhjWHjHXZyK4zV31XW4XDSIN5t4FlfWd7y4nN0Y6nn7IUWt+D8Ydaa1QS47BKun5a4 TQUbXGBvnoJKNf+mFGuRQ/Jwon7FaW5lozt4fOSWGWqKzWb+5zAvX4RXa27uxHeetJ9d 5XJg==
X-Gm-Message-State: ALoCoQkNWPURBk5kuPAWPpDQkmPmZEFrLhsXt/MMRSVWPOW87o1z3cAjRYCLcEr7iOO8FlKo5x3+
X-Received: by 10.107.159.66 with SMTP id i63mr49767926ioe.68.1437488412688; Tue, 21 Jul 2015 07:20:12 -0700 (PDT)
MIME-Version: 1.0
Received: by 10.79.96.199 with HTTP; Tue, 21 Jul 2015 07:19:43 -0700 (PDT)
From: Brian Campbell <bcampbell@pingidentity.com>
Date: Tue, 21 Jul 2015 16:19:43 +0200
Message-ID: <CA+k3eCQJxzjJ1RSuBRqdT77sj7JiLPHnJc=odO-020jk1n--wQ@mail.gmail.com>
To: oauth <oauth@ietf.org>
Content-Type: multipart/alternative; boundary="001a1141b960352952051b635a75"
Archived-At: <http://mailarchive.ietf.org/arch/msg/oauth/AK_4YiQOmGxpN0DaZ0z_y7ry2r8>
Subject: [OAUTH-WG] potential issues in draft-ietf-oauth-signed-http-request?
X-BeenThere: oauth@ietf.org
X-Mailman-Version: 2.1.15
Precedence: list
List-Id: OAUTH WG <oauth.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/oauth>, <mailto:oauth-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/oauth/>
List-Post: <mailto:oauth@ietf.org>
List-Help: <mailto:oauth-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/oauth>, <mailto:oauth-request@ietf.org?subject=subscribe>
X-List-Received-Date: Tue, 21 Jul 2015 14:20:38 -0000

I think I said, at the last meeting, that I would review
draft-ietf-oauth-signed-http-request, which was maybe foolish of me, but I
thought I should be timely and send something before the meeting tomorrow.
Even though the document isn't on the agenda.

Let me first say that I honestly don't know if this HTTP signing is the
right approach or not for presenting some kind of 'better than bearer'
access tokens to the RS. As such, I don't intend my reading/review of the
document as either an endorsement of it or opposition to it.

That said, I did notice a couple of potential security or interoperability
issues that I wanted to raise.

Following the description of calculating the query parameter list and hash
<https://tools.ietf.org/html/draft-ietf-oauth-signed-http-request-01#section-3.2>
and validating the query parameter list and hash
<https://tools.ietf.org/html/draft-ietf-oauth-signed-http-request-01#section-4.1>
(text of both copied below) it seems like different query strings could
result in the same hash value. For example,

The query string ?foo=bar%3D&bar= processed in order shown there would have
a names list of ["foo", "bar"] and parameters of
 foo=bar=
 bar=
and the hash would be of
 foo=bar=bar=

While the different query string ?foo=&bar=bar%3D processed in the same
order, left to right, would have the same names list of ["foo", "bar"] and
parameters of
 foo=
 bar=bar=
and the hash would be of
 foo=bar=bar=

It's a made up example but seems to show that different content in the
query string can sometimes be manipulated to produce the same hash. I don't
have an exploit in mind but the bad guys are smarter than me. And it's
probably just generally the kind of thing a security related protocol
shouldn't allow for.

Or am I misunderstanding something?

Seems like encoding and delimitation need to be explicitly handled in
whatever way the query parameters are dealt with. There's already a [[]] in
there that hints at the possibility.

The text also says "repeated parameter names are processed separately with
no special handling" but, for that to work, doesn't it require that the
client and server process repeated parameters in the same order?

I think the header list and hash likely has similar issues as it's
basically the same approach.

As I look at the text again, shouldn't the 4.x sections talk about the
server or resource server rather than the client?



3.2 <https://tools.ietf.org/html/draft-ietf-oauth-signed-http-request-01#section-3.2>.
Calculating the query parameter list and hash

   To generate the query parameter list and hash, the client creates two
   data objects: an ordered list of strings to hold the query parameter
   names and a string buffer to hold the data to be hashed.

   The client iterates through all query parameters in whatever order it
   chooses and for each query parameter it does the following:


   1.  Adds the name of the query parameter to the end of the list.

   2.  Encodes the name and value of the query parameter as "name=value"
       and appends it to the string buffer.  [[Separated by an
       ampersand?  Alternatively we could have this also pulled into an
       ordered list and post-process the concatenation, but that might
       be too deep into the weeds. ]]

   Repeated parameter names are processed separately with no special
   handling.  Parameters MAY be skipped by the client if they are not
   required (or desired) to be covered by the signature.

   The client then calculates the HMAC hash over the resulting string
   buffer.  The list and the hash result are added as the value of the
   "p" member.



4.1 <https://tools.ietf.org/html/draft-ietf-oauth-signed-http-request-01#section-4.1>.
Validating the query parameter list and hash

   The client has at its disposal a map that indexes the query parameter
   names to the values given.  The client creates a string buffer for
   calculating the hash.  The client then iterates through the "list"
   portion of the "p" parameter.  For each item in the list (in the
   order of the list) it does the following:

   1.  Fetch the value of the parameter from the HTTP request parameter
       map.  If a parameter is found in the list of signed parameters
       but not in the map, the validation fails.

   2.  Encode the parameter as "name=value" and concatenate it to the
       end of the string buffer. [[same separator issue as above.]]

   The client calculates the hash of the string buffer and base64url
   encodes it.  The client compares that string to the string passed in
   as the hash.  If the two match, the hash validates, and all named
   parameters and their values are considered covered by the signature.

   There MAY be additional query parameters that are not listed in the
   list and are therefore not covered by the signature.  The client MUST
   decide whether or not to accept a request with these uncovered
   parameters.