summaryrefslogtreecommitdiff
path: root/devtools
diff options
context:
space:
mode:
authorGaming4JC <g4jc@bulletmail.org>2018-09-25 23:03:28 -0400
committerGaming4JC <g4jc@bulletmail.org>2018-09-25 23:03:28 -0400
commit8a93466ffb43dd7e7e1252359eb79fa379f8ff0e (patch)
treecf7aa42302515fe1792fd9c3230c6fd7ae3325fc /devtools
parent9958caa9295a4dcfbd47e0d745c4fe77c7a98734 (diff)
downloaduxp-8a93466ffb43dd7e7e1252359eb79fa379f8ff0e.tar.gz
backport mozbug 1334776 - CVE-2017-7797 Header name interning leaks across origins
Potential attack: session supercookie. [Moz Notes](https://bugzilla.mozilla.org/show_bug.cgi?id=1334776#c5): "The problem is that for unknown header names we store the first one we see and then later we case-insensitively match against that name *globally*. That means you can track if a user agent has already seen a certain header name used (by using a different casing and observing whether it gets normalized). This would allow you to see if a user has used a sensitive service that uses custom header names, or allows you to track a user across sites, by teaching the browser about a certain header case once and then observing if different casings get normalized to that. What we should do instead is only store the casing for a header name for each header list and not globally. That way it only leaks where it's expected (and necessary) to leak." [Moz fix note](https://bugzilla.mozilla.org/show_bug.cgi?id=1334776#c8): "nsHttpAtom now holds the old nsHttpAtom and a string that is case sensitive (only for not standard headers). So nsHttpAtom holds a pointer to a header name. (header names are store on a static structure). This is how it used to be. I left that part the same but added a nsCString which holds a string that was used to resoled the header name. So when we parse headers we call ResolveHeader with a char*. If it is a new header name the char* will be stored in a HttpHeapAtom, nsHttpAtom::_val will point to HttpHeapAtom::value and the same strings will be stored in mLocalCaseSensitiveHeader. For the first resolve request they will be the same but for the following maybe not. At the end this nsHttpAtom will be stored in nsHttpHeaderArray. For all operation we will used the old char* except when we are returning it to a script using VisitHeaders."
Diffstat (limited to 'devtools')
-rw-r--r--devtools/client/netmonitor/filter-predicates.js4
-rw-r--r--devtools/client/netmonitor/test/browser_net_copy_headers.js16
-rw-r--r--devtools/client/netmonitor/test/browser_net_timing-division.js4
-rw-r--r--devtools/client/shared/AppCacheUtils.jsm8
-rw-r--r--devtools/client/shared/curl.js8
-rw-r--r--devtools/client/webconsole/net/test/mochitest/browser_net_headers.js4
-rw-r--r--devtools/client/webconsole/test/browser_webconsole_bug_630733_response_redirect_headers.js2
-rw-r--r--devtools/shared/webconsole/test/test_network_get.html8
-rw-r--r--devtools/shared/webconsole/test/test_network_longstring.html4
-rw-r--r--devtools/shared/webconsole/test/test_network_post.html8
10 files changed, 33 insertions, 33 deletions
diff --git a/devtools/client/netmonitor/filter-predicates.js b/devtools/client/netmonitor/filter-predicates.js
index 9c8e49c622..75ee422aad 100644
--- a/devtools/client/netmonitor/filter-predicates.js
+++ b/devtools/client/netmonitor/filter-predicates.js
@@ -72,7 +72,7 @@ function isWS({ requestHeaders, responseHeaders }) {
// Find the 'upgrade' header.
let upgradeHeader = requestHeaders.headers.find(header => {
- return (header.name == "Upgrade");
+ return (header.name.toLowerCase() == "upgrade");
});
// If no header found on request, check response - mainly to get
@@ -81,7 +81,7 @@ function isWS({ requestHeaders, responseHeaders }) {
if (!upgradeHeader && responseHeaders &&
Array.isArray(responseHeaders.headers)) {
upgradeHeader = responseHeaders.headers.find(header => {
- return (header.name == "Upgrade");
+ return (header.name.toLowerCase() == "upgrade");
});
}
diff --git a/devtools/client/netmonitor/test/browser_net_copy_headers.js b/devtools/client/netmonitor/test/browser_net_copy_headers.js
index 36ce2fb347..bb582c8e13 100644
--- a/devtools/client/netmonitor/test/browser_net_copy_headers.js
+++ b/devtools/client/netmonitor/test/browser_net_copy_headers.js
@@ -49,12 +49,12 @@ add_task(function* () {
const EXPECTED_RESPONSE_HEADERS = [
`${httpVersion} ${status} ${statusText}`,
- "Last-Modified: Sun, 3 May 2015 11:11:11 GMT",
- "Content-Type: text/html",
- "Content-Length: 465",
- "Connection: close",
- "Server: httpd.js",
- "Date: Sun, 3 May 2015 11:11:11 GMT"
+ "last-modified: Sun, 3 May 2015 11:11:11 GMT",
+ "content-type: text/html",
+ "content-length: 465",
+ "connection: close",
+ "server: httpd.js",
+ "date: Sun, 3 May 2015 11:11:11 GMT"
].join("\n");
yield waitForClipboardPromise(function setup() {
@@ -62,8 +62,8 @@ add_task(function* () {
}, function validate(result) {
// Fake the "Last-Modified" and "Date" headers because they will vary:
result = String(result)
- .replace(/Last-Modified: [^\n]+ GMT/, "Last-Modified: Sun, 3 May 2015 11:11:11 GMT")
- .replace(/Date: [^\n]+ GMT/, "Date: Sun, 3 May 2015 11:11:11 GMT");
+ .replace(/last-modified: [^\n]+ GMT/, "last-modified: Sun, 3 May 2015 11:11:11 GMT")
+ .replace(/date: [^\n]+ GMT/, "date: Sun, 3 May 2015 11:11:11 GMT");
return result === EXPECTED_RESPONSE_HEADERS;
});
info("Clipboard contains the currently selected item's response headers.");
diff --git a/devtools/client/netmonitor/test/browser_net_timing-division.js b/devtools/client/netmonitor/test/browser_net_timing-division.js
index 0114ba2355..ff2379dc28 100644
--- a/devtools/client/netmonitor/test/browser_net_timing-division.js
+++ b/devtools/client/netmonitor/test/browser_net_timing-division.js
@@ -48,9 +48,9 @@ add_task(function* () {
let lastRequest = RequestsMenu.getItemAtIndex(1);
info("First request happened at: " +
- firstRequest.attachment.responseHeaders.headers.find(e => e.name == "Date").value);
+ firstRequest.attachment.responseHeaders.headers.find(e => e.name == "date").value);
info("Last request happened at: " +
- lastRequest.attachment.responseHeaders.headers.find(e => e.name == "Date").value);
+ lastRequest.attachment.responseHeaders.headers.find(e => e.name == "date").value);
ok(secDivs.length,
"There should be at least one division on the seconds time scale.");
diff --git a/devtools/client/shared/AppCacheUtils.jsm b/devtools/client/shared/AppCacheUtils.jsm
index a2beca993c..9fd4d0541e 100644
--- a/devtools/client/shared/AppCacheUtils.jsm
+++ b/devtools/client/shared/AppCacheUtils.jsm
@@ -86,7 +86,7 @@ AppCacheUtils.prototype = {
_parseManifest: function ACU__parseManifest(uriInfo) {
let deferred = defer();
let manifestName = uriInfo.name;
- let manifestLastModified = new Date(uriInfo.responseHeaders["Last-Modified"]);
+ let manifestLastModified = new Date(uriInfo.responseHeaders["last-modified"]);
if (uriInfo.charset.toLowerCase() != "utf-8") {
this._addError(0, "notUTF8", uriInfo.charset);
@@ -158,7 +158,7 @@ AppCacheUtils.prototype = {
// Check that the resource was not modified after the manifest was last
// modified. If it was then the manifest file should be refreshed.
let resourceLastModified =
- new Date(uriInfo.responseHeaders["Last-Modified"]);
+ new Date(uriInfo.responseHeaders["last-modified"]);
if (manifestLastModified < resourceLastModified) {
this._addError(parsedUri.line, "fileChangedButNotManifest",
@@ -230,12 +230,12 @@ AppCacheUtils.prototype = {
result.requestHeaders = {};
request.visitRequestHeaders(function (header, value) {
- result.requestHeaders[header] = value;
+ result.responseHeaders[header.toLowerCase()] = value;
});
result.responseHeaders = {};
request.visitResponseHeaders(function (header, value) {
- result.responseHeaders[header] = value;
+ result.responseHeaders[header.toLowerCase()] = value;
});
deferred.resolve(result);
diff --git a/devtools/client/shared/curl.js b/devtools/client/shared/curl.js
index 420fe6aa5c..6d33ad9717 100644
--- a/devtools/client/shared/curl.js
+++ b/devtools/client/shared/curl.js
@@ -81,14 +81,14 @@ const Curl = {
postDataText = data.postDataText;
postData.push("--data");
postData.push(escapeString(utils.writePostDataTextParams(postDataText)));
- ignoredHeaders.add("Content-Length");
+ ignoredHeaders.add("content-length");
} else if (multipartRequest) {
postDataText = data.postDataText;
postData.push("--data-binary");
let boundary = utils.getMultipartBoundary(data);
let text = utils.removeBinaryDataFromMultipartText(postDataText, boundary);
postData.push(escapeString(text));
- ignoredHeaders.add("Content-Length");
+ ignoredHeaders.add("content-length");
}
// Add method.
@@ -125,11 +125,11 @@ const Curl = {
}
for (let i = 0; i < headers.length; i++) {
let header = headers[i];
- if (header.name === "Accept-Encoding") {
+ if (header.name.toLowerCase() === "accept-encoding") {
command.push("--compressed");
continue;
}
- if (ignoredHeaders.has(header.name)) {
+ if (ignoredHeaders.has(header.name.toLowerCase())) {
continue;
}
command.push("-H");
diff --git a/devtools/client/webconsole/net/test/mochitest/browser_net_headers.js b/devtools/client/webconsole/net/test/mochitest/browser_net_headers.js
index 4a47074ee1..14cde846c2 100644
--- a/devtools/client/webconsole/net/test/mochitest/browser_net_headers.js
+++ b/devtools/client/webconsole/net/test/mochitest/browser_net_headers.js
@@ -26,11 +26,11 @@ add_task(function* () {
// Select "Headers" tab
let tabBody = yield selectNetInfoTab(hud, netInfoBody, "headers");
let paramName = tabBody.querySelector(
- ".netInfoParamName > span[title='Content-Type']");
+ ".netInfoParamName > span[title='content-type']");
// Verify "Content-Type" header (name and value)
ok(paramName, "Header name must exist");
- is(paramName.textContent, "Content-Type",
+ is(paramName.textContent, "content-type",
"The header name must have proper value");
let paramValue = paramName.parentNode.nextSibling;
diff --git a/devtools/client/webconsole/test/browser_webconsole_bug_630733_response_redirect_headers.js b/devtools/client/webconsole/test/browser_webconsole_bug_630733_response_redirect_headers.js
index 5097499538..da4bdcf122 100644
--- a/devtools/client/webconsole/test/browser_webconsole_bug_630733_response_redirect_headers.js
+++ b/devtools/client/webconsole/test/browser_webconsole_bug_630733_response_redirect_headers.js
@@ -87,7 +87,7 @@ function getContent() {
function performTest() {
function readHeader(name) {
for (let header of headers) {
- if (header.name == name) {
+ if (header.name.toLowerCase() == name.toLowerCase()) {
return header.value;
}
}
diff --git a/devtools/shared/webconsole/test/test_network_get.html b/devtools/shared/webconsole/test/test_network_get.html
index 710c9b0d75..c2313be12a 100644
--- a/devtools/shared/webconsole/test/test_network_get.html
+++ b/devtools/shared/webconsole/test/test_network_get.html
@@ -196,13 +196,13 @@ function onResponseHeaders(aState, aResponse)
ok(!!aResponse.rawHeaders, "response rawHeaders available");
checkHeadersOrCookies(aResponse.headers, {
- "Content-Type": /^application\/(json|octet-stream)$/,
- "Content-Length": /^\d+$/,
+ "content-type": /^application\/(json|octet-stream)$/,
+ "content-length": /^\d+$/,
});
checkRawHeaders(aResponse.rawHeaders, {
- "Content-Type": /^application\/(json|octet-stream)$/,
- "Content-Length": /^\d+$/,
+ "content-type": /^application\/(json|octet-stream)$/,
+ "content-length": /^\d+$/,
});
onResponseCookies = onResponseCookies.bind(null, aState);
diff --git a/devtools/shared/webconsole/test/test_network_longstring.html b/devtools/shared/webconsole/test/test_network_longstring.html
index d551368969..9e6ea7771b 100644
--- a/devtools/shared/webconsole/test/test_network_longstring.html
+++ b/devtools/shared/webconsole/test/test_network_longstring.html
@@ -212,8 +212,8 @@ function onResponseHeaders(aState, aResponse)
ok(aResponse.headersSize > 0, "response headersSize > 0");
checkHeadersOrCookies(aResponse.headers, {
- "Content-Type": /^application\/(json|octet-stream)$/,
- "Content-Length": /^\d+$/,
+ "content-type": /^application\/(json|octet-stream)$/,
+ "content-length": /^\d+$/,
"x-very-short": "hello world",
"x-very-long": {
"type": "longString",
diff --git a/devtools/shared/webconsole/test/test_network_post.html b/devtools/shared/webconsole/test/test_network_post.html
index d96b9b0b7c..a0b8edb648 100644
--- a/devtools/shared/webconsole/test/test_network_post.html
+++ b/devtools/shared/webconsole/test/test_network_post.html
@@ -204,13 +204,13 @@ function onResponseHeaders(aState, aResponse)
ok(!!aResponse.rawHeaders, "response rawHeaders available");
checkHeadersOrCookies(aResponse.headers, {
- "Content-Type": /^application\/(json|octet-stream)$/,
- "Content-Length": /^\d+$/,
+ "content-type": /^application\/(json|octet-stream)$/,
+ "content-length": /^\d+$/,
});
checkRawHeaders(aResponse.rawHeaders, {
- "Content-Type": /^application\/(json|octet-stream)$/,
- "Content-Length": /^\d+$/,
+ "content-type": /^application\/(json|octet-stream)$/,
+ "content-length": /^\d+$/,
});
onResponseCookies = onResponseCookies.bind(null, aState);