Skip to content
Snippets Groups Projects
Commit b61a2454 authored by Anton Bershanskiy's avatar Anton Bershanskiy
Browse files

Started webRequest code

Added basic webRequest code, capable to detect when cookies are set and leaked
parent 211eee65
No related branches found
No related tags found
No related merge requests found
# How this extension works
## Detecting cookie operations
This extension aims to detect improper use of cookies by observing
the cookie modifications and use. So it relies on browser APIs
`cookies` (to detect changes in cookie store and write cookies) and
`webRequest` (to detect cookie writes via `Set-Cookie` response header
and cookie disclosure via `Cookie` request header), as well as some
injected code into the page (`content_scripts` and `web_accessible_resources`).
### `webRequst`
`webRequest` API has two modes of operation: asynchronous and
synchronous (blocking). Currently, extension blocks on `webRequest`
to maintain the smallest amount of internal datastructures. So far,
I didn't see any slowdowns. However, this is a known *tradeoff*,
which will be reversed if needed.
\ No newline at end of file
Options UI can be too tall (long vertically) for the provided pace. In that case, window can't resolve th right heght and scroll thing and just starts shaking. Fixed by setting body{height:700px}.
\ No newline at end of file
# TODO list
## Priority
* Collect sufficient information about cookies, store it properly
* `webRequest` code is funky
## Later
* Make `webRequest` optional.
## Fixed?
* Options UI can be too tall (long vertically) for the provided pace. In that case, window can't resolve th right heght and scroll thing and just starts shaking. Fixed by setting body{height:700px}.
......@@ -2,18 +2,99 @@
// Initialize the cookie database upon extension installation
const platform = chrome;
// TODO: make an actual datasructure.
var cookieDatabase = {}
var cookieObservations = {}
/*
* Prepare datastructures of the newly installed extension
*/
chrome.runtime.onInstalled.addListener (function() {
platform.runtime.onInstalled.addListener (function() {
// Setup default extension settings
chrome.storage.local.set({DevTools: true});
// if (browser.permissions.contains({permissions:["cookies"]})
// chrome.cookies.onChanged.addListener(recordCookieChange));
// if (browser.permissions.contains({permissions:["webRequest"]})
// chrome.cookies.onChanged.addListener(recordCookieChange))
});
platform.storage.local.set({DevTools: true})
// Setup Cookies change listener
// TODO: what if user gives permission later?
platform.permissions.contains({permissions:["cookies"]}, function(result){
if (result)
platform.cookies.onChanged.addListener(recordCookieChange)
})
// Setup webRequest listener
platform.permissions.contains({permissions:["webRequestBlocking"]}, function(result){
if (result)
onPermissionWebRequestGranted()
})
})
/*
* Observe the network activity around coookies
*/
function onPermissionWebRequestGranted(){
const urls = ["http://*/*", "https://*/*"]
/*
* Observe the Cookie header containing cookies being sent to the server
*/
function watchCookiesSent(details){
const protocol = details.url.substring(0, details.url.indexOf("://"))
for (var i = 0; i < details.requestHeaders.length; ++i) {
if (details.requestHeaders[i].name === "Cookie") {
const cookies = details.requestHeaders[i].value.split("; ")
for (var cookie of cookies){
// Split the cookie in name and value
const index = cookie.indexOf("=")
const name = cookie.substr(0, index)
const value = cookie.substr(index + 1)
if (protocol === "http" && (cookieDatabase[name] === undefined || cookieDatabase[name].secureOrigin === true)){
console.log("LEAK", name)
}
// console.log("Cookie sent: ", cookie, name, value)
// if (details.initiator.startsWith
}
// details.requestHeaders.splice(i, 1);
break
}
}
return {requestHeaders: details.requestHeaders}
}
/*
* Observe the Set-Cookie header in response from the server
*/
// TODO: Difference between "set-cookie" and "Set-Cookie"
// TODO: support protocols other than HTTP(S)
function watchCookiesSet(details){
// console.log(details)
// Get additional parameters
const protocol = details.url.substring(0, details.url.indexOf("://"))
for (var i = 0; i < details.responseHeaders.length; ++i) {
if (details.responseHeaders[i].name === "set-cookie"){//"Set-Cookie") {
const value = details.responseHeaders[i].value
const name = value.substring(0, value.indexOf("="))
console.log("Cookie set: ", name)
cookieDatabase[name] = {secureOrigin: protocol === "https", httpOrigin: true}
}
} /*else {
console.log(details.responseHeaders[i].name)
}*/
return {responseHeaders: details.responseHeaders}
}
platform.webRequest.onBeforeSendHeaders.addListener (watchCookiesSent,
{urls: urls}, ["blocking", "requestHeaders"])
platform.webRequest.onHeadersReceived.addListener (watchCookiesSet,
{urls: urls}, ["blocking", "responseHeaders"])
}
function recordCookieChange(/*object*/ changeInfo){
chrome.storage.local.set({last: changeInfo.cookie, lastReason: changeInfo.cause});
chrome.storage.local.set({last: changeInfo.cookie, lastReason: changeInfo.cause})
}
......@@ -11,10 +11,11 @@
},
"permissions": [
"storage",
"cookies"
"cookies",
"webRequest",
"webRequestBlocking"
],
"optional_permissions": [
"webRequest",
"http://*/",
"https://*/"
],
......
......@@ -38,7 +38,7 @@ document.addEventListener("DOMContentLoaded", function () {
// Attach all the click handlers
DevTools.addEventListener ("click", choiceHandlerDevTools);
WebRequest.addEventListener("click", choiceHandlerWebRequest);
newOriginForm.onsubmit = function(evt) {addOrigin(evt.target.elements['newOrigin'].value);return false;};
newOriginForm.onsubmit = function(evt) {addOrigin(evt.target.elements["newOrigin"].value);return false;};
originsList.addEventListener("click",originsListDeleteHandler);
// Display current settings
......@@ -56,7 +56,7 @@ document.addEventListener("DOMContentLoaded", function () {
var permissionsLength = permissions.permissions.length;
for (var i = 0; i < permissionsLength; i++) {
switch (permissions.permissions[i]){
case "webRequest":
case "webRequestBlocking":
WebRequest.checked = true;
break;
/* TODO: add every optional permission here */
......@@ -132,7 +132,7 @@ function choiceHandlerWebRequest(evt){
if (checked){
// WebRequest integration requested
platform.permissions.request({
permissions: ["webRequest"]
permissions: ["webRequestBlocking"]
}, function(granted) {
// The callback argument will be true if the user granted the permissions.
if (granted) {
......@@ -147,7 +147,7 @@ function choiceHandlerWebRequest(evt){
// WebRequest integration disabled
// Remove permission
platform.permissions.remove ({
permissions: ["webRequest"]
permissions: ["webRequestBlocking"]
}, function(removed) {
if (removed) {
// The permissions have been removed.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment