Encode "<" and ">" in JSON/Ajax responses to prevent content-sniffing attacks

Summary:
Some browsers will still sniff content types even with "Content-Type" and
"X-Content-Type-Options: nosniff". Encode "<" and ">" to prevent them from
sniffing the content as HTML.

See T865.

Also unified some of the code on this pathway.

Test Plan: Verified Opera no longer sniffs the Conduit response into HTML for
the test case in T865. Unit tests pass.

Reviewers: cbg, btrahan

Reviewed By: cbg

CC: aran, epriestley

Maniphest Tasks: T139, T865

Differential Revision: https://secure.phabricator.com/D1606
This commit is contained in:
epriestley
2012-02-14 14:51:51 -08:00
parent 8da4f981fb
commit c8b4bfdcd1
14 changed files with 143 additions and 16 deletions
+33 -1
View File
@@ -70,6 +70,37 @@ abstract class AphrontResponse {
return $this;
}
protected function encodeJSONForHTTPResponse(
array $object,
$use_javelin_shield) {
$response = json_encode($object);
// Prevent content sniffing attacks by encoding "<" and ">", so browsers
// won't try to execute the document as HTML even if they ignore
// Content-Type and X-Content-Type-Options. See T865.
$response = str_replace(
array('<', '>'),
array('\u003c', '\u003e'),
$response);
// Add a shield to prevent "JSON Hijacking" attacks where an attacker
// requests a JSON response using a normal <script /> tag and then uses
// Object.prototype.__defineSetter__() or similar to read response data.
// This header causes the browser to loop infinitely instead of handing over
// sensitive data.
// TODO: This is massively stupid: Javelin and Conduit use different
// shields.
$shield = $use_javelin_shield
? 'for (;;);'
: 'for(;;);';
$response = $shield.$response;
return $response;
}
public function getCacheHeaders() {
$headers = array();
if ($this->cacheable) {
@@ -94,7 +125,8 @@ abstract class AphrontResponse {
// IE has a feature where it may override an explicit Content-Type
// declaration by inferring a content type. This can be a security risk
// and we always explicitly transmit the correct Content-Type header, so
// prevent IE from using inferred content types.
// prevent IE from using inferred content types. This only offers protection
// on recent versions of IE; IE6/7 and Opera currently ignore this header.
$headers[] = array('X-Content-Type-Options', 'nosniff');
return $headers;