Skip to content

Commit 2bf1c29

Browse files
committed
Remove blocking HTTP header listener
After thinking about this more, this function seems insane. I think we should remove it for a lot of reasons. Here are the big ones: 1. Performance We want wider HTTPS Everywhere adoption, and performance is the big limiting factor here. The biggest complaints are still "it's slow," and blocking all HTTP request headers to loop over & reconstruct cookies is nuts. Testing on a CR-48 & other CPU-limited machines, HTTPS Everywhere still causes a significant performance/battery hit (*especially* this single function). 2. It doesn't really work right If the comments are any indication ("XXX I have no idea..."): The if(ruleset) code doesn't actually secure any cookies -- it just adds the ruleset to the tab, but doesn't append a new secure cookie to the newCookies array. 3. The race condition this "prevents" seems just silly The old justification for this function is it prevents a race-condition, but wow, that's insanely hard to replicate. After running with some alert()s for some time, I can't even get the warning in question to trigger. To really steal a cookie here, you'd need: - A site that supports HTTPS - and is in our rulesets - and has appropriately scoped, secureable cookies - and sets them without the HTTPS Only flag - and they're interesting enough to steal AND - An active, MITM attacker that controls a subdomain of interest - with the ability force the user to visit an HTTP page - with millisecond-level timing precision This just seems silly to me. If you're controlling HTTP subdomains & any sites the end-user is visiting, this seems like it's simultaneously the most complex and also most meaningless attack you could mount. Signed-off-by: Nick Semenkovich <semenko@alum.mit.edu>
1 parent 9d0af02 commit 2bf1c29

File tree

1 file changed

+1
-48
lines changed

1 file changed

+1
-48
lines changed

chromium/background.js

Lines changed: 1 addition & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -342,47 +342,6 @@ function onCookieChanged(changeInfo) {
342342
}
343343
}
344344

345-
// This event is needed due to the potential race between cookie permissions
346-
// update and cookie transmission (because the cookie API is non-blocking).
347-
// Without this function, an aggressive attacker could race to steal a not-yet-secured
348-
// cookie if they controlled & could redirect the user to a non-SSL subdomain.
349-
// WARNING: This is a very hot function.
350-
function onBeforeSendHeaders(details) {
351-
// TODO: Verify this with wireshark
352-
for (var h in details.requestHeaders) {
353-
if (details.requestHeaders[h].name == "Cookie") {
354-
// Per RFC 6265, Chrome sends only ONE cookie header, period.
355-
var uri = new URI(details.url);
356-
var host = uri.hostname();
357-
358-
var newCookies = [];
359-
var cookies = details.requestHeaders[h].value.split(";");
360-
361-
for (var c in cookies) {
362-
// Create a fake "nsICookie2"-ish object to pass in to our rule API:
363-
var fake = {domain:host, name:cookies[c].split("=")[0]};
364-
// XXX I have no idea whether the knownHttp parameter should be true
365-
// or false here. We're supposedly inside a race condition or
366-
// something, right?
367-
var ruleset = all_rules.shouldSecureCookie(fake, false);
368-
if (ruleset) {
369-
activeRulesets.addRulesetToTab(details.tabId, ruleset);
370-
log(INFO, "Woah, we lost the race on updating a cookie: "+details.requestHeaders[h].value);
371-
} else {
372-
newCookies.push(cookies[c]);
373-
}
374-
}
375-
details.requestHeaders[h].value = newCookies.join(";");
376-
log(DBUG, "Got new cookie header: "+details.requestHeaders[h].value);
377-
378-
// We've seen the one cookie header, so let's get out of here!
379-
break;
380-
}
381-
}
382-
383-
return {requestHeaders:details.requestHeaders};
384-
}
385-
386345
function onResponseStarted(details) {
387346

388347
// redirect counter workaround
@@ -394,11 +353,6 @@ function onResponseStarted(details) {
394353

395354
wr.onBeforeRequest.addListener(onBeforeRequest, {urls: ["https://*/*", "http://*/*"]}, ["blocking"]);
396355

397-
// This watches cookies sent via HTTP.
398-
// We do *not* watch HTTPS cookies -- they're already being sent over HTTPS -- yay!
399-
wr.onBeforeSendHeaders.addListener(onBeforeSendHeaders, {urls: ["http://*/*"]},
400-
["requestHeaders", "blocking"]);
401-
402356
wr.onResponseStarted.addListener(onResponseStarted,
403357
{urls: ["https://*/*", "http://*/*"]});
404358

@@ -416,8 +370,7 @@ chrome.tabs.onReplaced.addListener(function(addedTabId, removedTabId) {
416370
displayPageAction(addedTabId);
417371
});
418372

419-
// Listen for cookies set/updated and secure them if applicable. This function is async/nonblocking,
420-
// so we also use onBeforeSendHeaders to prevent a small window where cookies could be stolen.
373+
// Listen for cookies set/updated and secure them if applicable. This function is async/nonblocking.
421374
chrome.cookies.onChanged.addListener(onCookieChanged);
422375

423376
function disableSwitchPlannerFor(tabId) {

0 commit comments

Comments
 (0)