Skip to content

Instantly share code, notes, and snippets.

@mathiasbynens
Last active June 25, 2016 02:03
Show Gist options
  • Save mathiasbynens/5547352 to your computer and use it in GitHub Desktop.
Save mathiasbynens/5547352 to your computer and use it in GitHub Desktop.
Basic JSON/JSON-P service in PHP
<?php
// Prevent content sniffing attacks such as http://mths.be/bst.
header('X-Content-Type-Options: nosniff');
// Note: The user-provided callback name must be filtered to prevent attack
// vectors. This script simply removes any symbols other than `[a-zA-Z0-9$_]`
// from the input. Sadly, this blocks the use of some valid JavaScript
// identifiers, and also accepts a few invalid ones. See
// http://mathiasbynens.be/notes/javascript-identifiers for details.
// The callback name is prefixed with an empty multi-line comment (`/**/`) to
// prevent content sniffing attacks in browsers without `nosniff` support.
$callback = isset($_GET['callback'])
? '/**/' . preg_replace('/[^a-zA-Z0-9$_.]/s', '', $_GET['callback'])
: false;
// Send the appropriate MIME type: JSON or JSON-P/JavaScript?
header('Content-Type: ' .
($callback ? 'application/javascript' : 'application/json') .
';charset=UTF-8');
// There’s no reason not to allow CORS for public APIs.
// See http://annevankesteren.nl/2012/12/cors-101 for details.
header('Access-Control-Allow-Origin: *');
// Your data goes here. It’s recommended to always use an associative array
// here, so that the resulting JSON represents a non-array object, as this
// prevents JSON hijacking attacks. See http://mths.be/bss for details.
$data = array('some-key' => 'some-value');
// Output the end result.
echo ($callback ? $callback . '(' : '') .
json_encode($data, JSON_UNESCAPED_SLASHES) . // ≥ PHP 5.4.0
($callback ? ')' : '');
?>
@mathiasbynens
Copy link
Author

This used to be a comment over at https://gist.github.com/cowboy/1200708#comment-49498, but I’ve made it a proper gist for future reference.

I’ve added the JSON_UNESCAPED_SLASHES bit, too. There’s no need to escape / unless the JSON-formatted data is inserted as part of an HTML <script> element, and the / in question is part of the sequence </script. Since this is code for a stand-alone JSON/JSON-P service, this context doesn’t apply here.

Attack vectors such as http://homakov.blogspot.be/2013/02/are-you-sure-you-use-jsonp-properly.html?showComment=1374935144243#c3257897429883603211 or http://lcamtuf.coredump.cx/postxss/ (see Abuse of JSONP). An XSS vulnerability in a JSON-P service can be used to bypass CSP on the same origin, as part of a bigger attack .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment