Preventing the Execution of Unauthorized Script in JSON

The JSON data set provides a couple of options for aiding in the prevention of executing unauthorized script that may have been injected by a 3rd party:


Example 1

This example loads some JSON that is preceded by a while(1);. The idea here is to force the client to remove the while(1); before eval'ing the JSON data. If they don't, the browser will hang due to the while(1); execution during the eval. This technique is used by Google applications like GMAIL to prevent the execution of unauthorized script. Here's what the actual JSON data looks like:

while(1);
[
	{
		"name": "Great Wall of China",
		"photo": "../../Spry/demos/gallery/galleries/china/images/china_01.jpg",
		"thumbnail": "../../Spry/demos/gallery/galleries/china/thumbnails/china_01.jpg"
	},
	{
		"name": "Hong Kong Skyline",
		"photo": "../../Spry/demos/gallery/galleries/china/images/china_24.jpg",
		"thumbnail": "../../Spry/demos/gallery/galleries/china/thumbnails/china_24.jpg"
	},
	{
		"name": "Great Pyramid of Giza",
		"photo": "../../Spry/demos/gallery/galleries/egypt/images/egypt_01.jpg",
		"thumbnail": "../../Spry/demos/gallery/galleries/egypt/thumbnails/egypt_01.jpg"
	},
	{
		"name": "Great Sphynx",
		"photo": "../../Spry/demos/gallery/galleries/egypt/images/egypt_07.jpg",
		"thumbnail": "../../Spry/demos/gallery/galleries/egypt/thumbnails/egypt_07.jpg"
	},
	{
		"name": "Eifel Tower",
		"photo": "../../Spry/demos/gallery/galleries/paris/images/paris_05.jpg",
		"thumbnail": "../../Spry/demos/gallery/galleries/paris/thumbnails/paris_05.jpg"
	},
	{
		"name": "Arc de Triomphe",
		"photo": "../../Spry/demos/gallery/galleries/paris/images/paris_10.jpg",
		"thumbnail": "../../Spry/demos/gallery/galleries/paris/thumbnails/paris_10.jpg"
	}
]

This is what the code to accomplish the preparsing looks like:

var dsExample1 = new Spry.Data.JSONDataSet("data/preparse-test-01.js", { preparseFunc: Example1PreparseFunc });

function Example1PreparseFunc(ds, jsonStr)
{
	return jsonStr.replace(/while\(1\);/g, "");
}

Which allows us to parse the JSON data and then display it:

{name} {name}

 


Example 2

This example loads some JSON data that is wrapped with C-Style comments. If this data is eval'd without removing the '/*' and '*/', nothing is executed, and no data is created. Here's what the actual JSON data looks like:

/*
[
	{
		"name": "Great Wall of China",
		"photo": "../../Spry/demos/gallery/galleries/china/images/china_01.jpg",
		"thumbnail": "../../Spry/demos/gallery/galleries/china/thumbnails/china_01.jpg"
	},
	{
		"name": "Hong Kong Skyline",
		"photo": "../../Spry/demos/gallery/galleries/china/images/china_24.jpg",
		"thumbnail": "../../Spry/demos/gallery/galleries/china/thumbnails/china_24.jpg"
	},
	{
		"name": "Great Pyramid of Giza",
		"photo": "../../Spry/demos/gallery/galleries/egypt/images/egypt_01.jpg",
		"thumbnail": "../../Spry/demos/gallery/galleries/egypt/thumbnails/egypt_01.jpg"
	},
	{
		"name": "Great Sphynx",
		"photo": "../../Spry/demos/gallery/galleries/egypt/images/egypt_07.jpg",
		"thumbnail": "../../Spry/demos/gallery/galleries/egypt/thumbnails/egypt_07.jpg"
	},
	{
		"name": "Eifel Tower",
		"photo": "../../Spry/demos/gallery/galleries/paris/images/paris_05.jpg",
		"thumbnail": "../../Spry/demos/gallery/galleries/paris/thumbnails/paris_05.jpg"
	},
	{
		"name": "Arc de Triomphe",
		"photo": "../../Spry/demos/gallery/galleries/paris/images/paris_10.jpg",
		"thumbnail": "../../Spry/demos/gallery/galleries/paris/thumbnails/paris_10.jpg"
	}
]
*/

This is what the code to accomplish the preparsing looks like:

var dsExample2 = new Spry.Data.JSONDataSet("data/preparse-test-02.js", { preparseFunc: Example2PreparseFunc });

function Example2PreparseFunc(ds, jsonStr)
{
	return jsonStr.replace(/\/\*|\*\//g, "");
}

Which allows us to parse the JSON data and then display it:

{name} {name}

 


Example 3

This example loads some JSON that is wrapped in a function call. The idea here is that the client must remove the "results(" and ")" before doing the eval, or it will fail the JSON.org parser test. Here's what the actual JSON data looks like:

results([
	{
		"name": "Great Wall of China",
		"photo": "../../Spry/demos/gallery/galleries/china/images/china_01.jpg",
		"thumbnail": "../../Spry/demos/gallery/galleries/china/thumbnails/china_01.jpg"
	},
	{
		"name": "Hong Kong Skyline",
		"photo": "../../Spry/demos/gallery/galleries/china/images/china_24.jpg",
		"thumbnail": "../../Spry/demos/gallery/galleries/china/thumbnails/china_24.jpg"
	},
	{
		"name": "Great Pyramid of Giza",
		"photo": "../../Spry/demos/gallery/galleries/egypt/images/egypt_01.jpg",
		"thumbnail": "../../Spry/demos/gallery/galleries/egypt/thumbnails/egypt_01.jpg"
	},
	{
		"name": "Great Sphynx",
		"photo": "../../Spry/demos/gallery/galleries/egypt/images/egypt_07.jpg",
		"thumbnail": "../../Spry/demos/gallery/galleries/egypt/thumbnails/egypt_07.jpg"
	},
	{
		"name": "Eifel Tower",
		"photo": "../../Spry/demos/gallery/galleries/paris/images/paris_05.jpg",
		"thumbnail": "../../Spry/demos/gallery/galleries/paris/thumbnails/paris_05.jpg"
	},
	{
		"name": "Arc de Triomphe",
		"photo": "../../Spry/demos/gallery/galleries/paris/images/paris_10.jpg",
		"thumbnail": "../../Spry/demos/gallery/galleries/paris/thumbnails/paris_10.jpg"
	}
])

This is what the code to accomplish the preparsing looks like:

var dsExample3 = new Spry.Data.JSONDataSet("data/preparse-test-03.js", { preparseFunc: Example3PreparseFunc });

function Example3PreparseFunc(ds, jsonStr)
{
	return jsonStr.replace(/results\(|\)\s*$/g, "");
}

Which allows us to parse the JSON data and then display it

{name} {name}

 


Example 4

This example demonstrates how to turn on the JSON.org parser within the JSONDataSet to avoid executing JSON that has embedded function calls:

[
	{
		name: "Great Wall of China",
		photo: "../../Spry/demos/gallery/galleries/china/images/china_01.jpg",
		thumbnail: "../../Spry/demos/gallery/", foo: alert("This is code that was inserted but should never be executed!!"), bar: "galleries/china/thumbnails/china_01.jpg"
	},
	{!
		name: "Hong Kong Skyline",
		photo: "../../Spry/demos/gallery/galleries/china/images/china_24.jpg",
		thumbnail: "../../Spry/demos/gallery/galleries/china/thumbnails/china_24.jpg"
	},
	{
		name: "Great Pyramid of Giza",
		photo: "../../Spry/demos/gallery/galleries/egypt/images/egypt_01.jpg",
		thumbnail: "../../Spry/demos/gallery/galleries/egypt/thumbnails/egypt_01.jpg"
	},
	{
		name: "Great Sphynx",
		photo: "../../Spry/demos/gallery/galleries/egypt/images/egypt_07.jpg",
		thumbnail: "../../Spry/demos/gallery/galleries/egypt/thumbnails/egypt_07.jpg"
	},
	{
		name: "Eifel Tower",
		photo: "../../Spry/demos/gallery/galleries/paris/images/paris_05.jpg",
		thumbnail: "../../Spry/demos/gallery/galleries/paris/thumbnails/paris_05.jpg"
	},
	{
		name: "Arc de Triomphe",
		photo: "../../Spry/demos/gallery/galleries/paris/images/paris_10.jpg",
		thumbnail: "../../Spry/demos/gallery/galleries/paris/thumbnails/paris_10.jpg"
	}
]

This is what the code to accomplish the preparsing looks like:

var dsExample4 = new Spry.Data.JSONDataSet("data/preparse-test-04.js", { useParser: true });

Which should result in an error being thrown because invalid JS was detected. The table below should not render anything:

{name} {name}

 


Example 5

This example demonstrates that you can use both the preparsing hook and the JSON.org parser at the same time. It uses the JSON data from Example 1:

var dsExample5 = new Spry.Data.JSONDataSet("data/preparse-test-01.js", { useParser: true, preparseFunc: Example1PreparseFunc });

The data that is loaded in this example is passing through both the preparsing function and the JSON.org parser, and since it is valid JSON data, we are able to render the data:

{name} {name}