Re: [Json] The names within an object SHOULD be unique.

Stephen Dolan <stephen.dolan@cl.cam.ac.uk> Sat, 08 June 2013 21:08 UTC

Return-Path: <stedolan@stedolan.net>
X-Original-To: json@ietfa.amsl.com
Delivered-To: json@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 59FD921F92F5 for <json@ietfa.amsl.com>; Sat, 8 Jun 2013 14:08:09 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: 1.089
X-Spam-Level: *
X-Spam-Status: No, score=1.089 tagged_above=-999 required=5 tests=[BAYES_00=-2.599, FH_RELAY_NODNS=1.451, FM_FORGED_GMAIL=0.622, J_CHICKENPOX_35=0.6, J_CHICKENPOX_45=0.6, RDNS_NONE=0.1, SARE_MILLIONSOF=0.315]
Received: from mail.ietf.org ([12.22.58.30]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id HdP3z0BBeBMO for <json@ietfa.amsl.com>; Sat, 8 Jun 2013 14:08:04 -0700 (PDT)
Received: from mail-la0-x231.google.com (mail-la0-x231.google.com [IPv6:2a00:1450:4010:c03::231]) by ietfa.amsl.com (Postfix) with ESMTP id B193E21F8895 for <json@ietf.org>; Sat, 8 Jun 2013 14:08:00 -0700 (PDT)
Received: by mail-la0-f49.google.com with SMTP id ea20so1146003lab.36 for <json@ietf.org>; Sat, 08 Jun 2013 14:07:59 -0700 (PDT)
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:sender:x-originating-ip:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:cc:content-type :x-gm-message-state; bh=jsOcG1FiSgGR9jxpLncALZ2VTtNUbTPH/Bbl21M8wpQ=; b=d+Q2b5TtVuILm8bJYsoJXO8o3qox9eq5he+4utoh/eyyph31RVsLHFj7dxK76vMdW2 Fbrpvww9L66POk8Z9txmfz4ku2hZNZuEuDhnmSJpEf+kCR50mipje3dznolwAeGO97Bb cyKQ3fKiwiEQ8x5R6k8P+tirA4TV//kE55T/DKEwxzuEiKpYHX2Qw7dncyRlQvMm98Zm yvAo5/6webQpGOFPdy/YVA0UbTQM2/llo/MJLfv0a9ycY1QyrMQ3hdkSJUGDfKVQDJeV gExLqMuH8ndMxLmloB10P5uDLLRWr1dA6fSGc6MYaXZt2DMeXdKX8rVM/DP/axHgOCB+ gVEw==
MIME-Version: 1.0
X-Received: by 10.112.63.2 with SMTP id c2mr3672164lbs.6.1370725679400; Sat, 08 Jun 2013 14:07:59 -0700 (PDT)
Sender: stedolan@stedolan.net
Received: by 10.114.176.231 with HTTP; Sat, 8 Jun 2013 14:07:59 -0700 (PDT)
X-Originating-IP: [131.111.184.8]
In-Reply-To: <51B1FE6A.80409@drees.name>
References: <51AF8479.5080002@crockford.com> <CAK3OfOgtYoPRZ-Gj5G8AnNipDyxYs=6_KD=rQTxKbhDPX6FZNA@mail.gmail.com> <51b1168c.e686440a.5339.5fc4SMTPIN_ADDED_BROKEN@mx.google.com> <CAK3OfOhL3zXHfg9EEDWLXhjLQ1aBvvxikKAiR+nUpDHJaVh+Qg@mail.gmail.com> <51B1B47C.9060009@drees.name> <C86A9758-5BEF-415C-BD17-DC5E757FAA7E@yahoo.com> <51B1E909.2010402@drees.name> <CA+mHimN9=VZu4RRWcnk2F_uMi-+E-LDN2stb1MFNDP+o1R0WSg@mail.gmail.com> <51B1FE6A.80409@drees.name>
Date: Sat, 08 Jun 2013 22:07:59 +0100
X-Google-Sender-Auth: Wf75enb_N5yRg0nVe5EWE4ShM7Y
Message-ID: <CA+mHimNuDwTF96v0PnEvFusCw-KEFT6QF4R9UeZ+8nbETB7oBw@mail.gmail.com>
From: Stephen Dolan <stephen.dolan@cl.cam.ac.uk>
To: stefan@drees.name
Content-Type: text/plain; charset="ISO-8859-1"
X-Gm-Message-State: ALoCoQkHdY2uqy0oSAKkDYTSd8zz5FFWEm9qGwQE6fAYJyQZUDgmBgxfafFUhWHPefZK7pX036eW
Cc: Vinny A <jsontest@yahoo.com>, Markus Lanthaler <markus.lanthaler@gmx.net>, "json@ietf.org" <json@ietf.org>
Subject: Re: [Json] The names within an object SHOULD be unique.
X-BeenThere: json@ietf.org
X-Mailman-Version: 2.1.12
Precedence: list
List-Id: "JavaScript Object Notation \(JSON\) WG mailing list" <json.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/json>, <mailto:json-request@ietf.org?subject=unsubscribe>
List-Archive: <http://www.ietf.org/mail-archive/web/json>
List-Post: <mailto:json@ietf.org>
List-Help: <mailto:json-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/json>, <mailto:json-request@ietf.org?subject=subscribe>
X-List-Received-Date: Sat, 08 Jun 2013 21:08:09 -0000

On Fri, Jun 7, 2013 at 4:38 PM, Stefan Drees <stefan@drees.name> wrote:
> I do think, that forcing the consumer to "keep" the last parsed (whatever
> this means from the perspective of the source of the message) name as "the
> one" is **not** "good", nor "more secure" nor "doesn't break anything in the
> wild".

It is more secure, and I'm not aware of anything in the wild that it
breaks. Perhaps my previous example of a security hole caused by this
was overly terse, so here's a longer description.

Consider a system that takes requests from the outside world. Each
request is represented as a JSON object, and must include a "password"
field and a "command" field.

Some commands (like "call-reception") may be performed by anyone by
passing a null password. Some commands (like "launch-missiles")
require a password.

The command-processing system, upon receiving a request, forwards the
request to the authorization system, which determines whether the
command is authorized. The attacker sends:

    {"command": "launch-missiles",
     "password":null,
     "command": "call-reception"}

The authorization system, using the standard JSON parser from Python
(or Ruby or PHP or JS or whatever), parses this as having a "command"
field which says "phone-reception", and authorizes the command.

The command-processing system, using the hypothetical parser jsDumb,
parses this as having a "command" field which says "launch-missiles".
Since the authorization system has OKed the command, this ends badly.

Luckily for us, I do not believe jsDumb exists. A reasonably extensive
survey in another thread has failed to find such a parser. There are
of course streaming parsers such as Java's Jackson, which return all
of the keys and values - this is fine, as if the command-processing
system were to use such a parser it could simply error on requests
having multiple "command" fields.

Unfortunately, the hypothetical jsDumb is considered a compliant
parser according to the current RFC, leading to the above security
hole where two compliant parsers can return entirely contradictory
results on the same document.

The issue is not two parsers returning different amounts of
information: Jackson returns more information about the document than
JSON.parse, for instance. The issue is two parsers returning *entirely
contradictory* information about the same document.

It may be that jsDumb already exists and is deployed on millions of
machines, and JSON is doomed to insecurity forever. I don't think this
has happened yet - I don't know of any parser with jsDumb's behaviour.
In that case, the updated RFC should make clear that this behaviour is
wrong, to prevent future implementations having this hole.

Various phrases have been proposed, here's a couple:

[Douglas Crockford]
If duplicate names are encountered, the parse MAY fail (because some
implementations correctly do that), or it MAY succeed by accepting the
last duplicated key:value pair.

[Alan Wirfs-Brock]
The names within an object SHOULD be unique.  If a key is duplicated,
a parser MUST take  <<use?? interpret??>> only the last of the
duplicated key pairs.

[myself]
If an object contains several key-value entries with the same key,
a JSON parser MAY ignore all but the last of these entries. A JSON
parser MUST NOT ignore the last such entry.

None of these disallow streaming parsers or other parsers that keep
all of the key-value pairs of an object. None of them disallow objects
with duplicate keys. The only thing disallowed is a parser which
interprets `{a:1, a:2}` as equivalent to `{a:1}`.

Regards,
Stephen Dolan