[Json] Nested JSON encoding style too likely to be insecure

"Manger, James" <James.H.Manger@team.telstra.com> Tue, 23 February 2016 05:49 UTC

Return-Path: <James.H.Manger@team.telstra.com>
X-Original-To: json@ietfa.amsl.com
Delivered-To: json@ietfa.amsl.com
Received: from localhost (ietfa.amsl.com []) by ietfa.amsl.com (Postfix) with ESMTP id 0B70C1AC3A2 for <json@ietfa.amsl.com>; Mon, 22 Feb 2016 21:49:22 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: 1.799
X-Spam-Level: *
X-Spam-Status: No, score=1.799 tagged_above=-999 required=5 tests=[BAYES_50=0.8, HELO_EQ_AU=0.377, HOST_EQ_AU=0.327, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_LOW=-0.7, RELAY_IS_203=0.994] autolearn=no
Received: from mail.ietf.org ([]) by localhost (ietfa.amsl.com []) (amavisd-new, port 10024) with ESMTP id BJcq88tfZUMO for <json@ietfa.amsl.com>; Mon, 22 Feb 2016 21:49:19 -0800 (PST)
Received: from ipxcvo.tcif.telstra.com.au (ipxcvo.tcif.telstra.com.au []) by ietfa.amsl.com (Postfix) with ESMTP id 3C9081A92DC for <json@ietf.org>; Mon, 22 Feb 2016 21:49:18 -0800 (PST)
X-IronPort-AV: E=Sophos;i="5.22,488,1449493200"; d="scan'208,217";a="149830335"
Received: from unknown (HELO ipcavi.tcif.telstra.com.au) ([]) by ipocvi.tcif.telstra.com.au with ESMTP; 23 Feb 2016 16:49:16 +1100
X-IronPort-AV: E=McAfee;i="5700,7163,8083"; a="82226972"
Received: from wsmsg3757.srv.dir.telstra.com ([]) by ipcavi.tcif.telstra.com.au with ESMTP; 23 Feb 2016 16:49:15 +1100
Received: from WSMSG3153V.srv.dir.telstra.com ([]) by wsmsg3757.srv.dir.telstra.com ([fe80::b5b0:1190:625a:50ad%22]) with mapi; Tue, 23 Feb 2016 16:49:02 +1100
From: "Manger, James" <James.H.Manger@team.telstra.com>
To: "json@ietf.org" <json@ietf.org>
Date: Tue, 23 Feb 2016 16:49:00 +1100
Thread-Topic: Nested JSON encoding style too likely to be insecure
Thread-Index: AdFt/eCeCuwAKQZ4RlKTYc7/eVnwCA==
Message-ID: <255B9BB34FB7D647A506DC292726F6E13BBADBF674@WSMSG3153V.srv.dir.telstra.com>
Accept-Language: en-US, en-AU
Content-Language: en-US
acceptlanguage: en-US, en-AU
Content-Type: multipart/alternative; boundary="_000_255B9BB34FB7D647A506DC292726F6E13BBADBF674WSMSG3153Vsrv_"
MIME-Version: 1.0
Archived-At: <http://mailarchive.ietf.org/arch/msg/json/Dzspqf_NfQrG_sKQNxOYPglJRfE>
Subject: [Json] Nested JSON encoding style too likely to be insecure
X-BeenThere: json@ietf.org
X-Mailman-Version: 2.1.15
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: <https://mailarchive.ietf.org/arch/browse/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: Tue, 23 Feb 2016 05:49:22 -0000

I'm a bit late to the party on the "On flat vs nested JSON encoding style" thread...

The nested style that Phillip was encouraging is:

{ "A" :
   { "field1" : "value1", "field2" : "value2", "field3" : "value3" } }

It looks like messages in this style (requests and responses) would always have a top-level JSON object with a single member identifying the type of message ("A" in this example). An app might get this member from an iterator over the object (eg in Java when using a Map to represent a JSON object: op = map.entrySet().iterator().next();).

But what happens if a message (maliciously) has two elements in the top-level object?

{ "READ" :
   { "field1" : "value1", "field2" : "value2", "field3" : "value3" },
   { "field1" : "value1", "field2" : "value2", "field3" : "value3" } }

A receiving app (expecting 1 element) could easily pick either "READ" or "DELETE" and ignore the other. If an authorization layer picks "READ" and allows the message through, then the backend picks "DELETE" and acts accordingly... ouch.

This nested style looks cute, but is probably too cute as "obvious" ways to implement it can easily be insecure.
If we want to ensure a message type to come before its content then we should use a JSON array: [type, content].
James Manger