Working MVP

This commit is contained in:
Darryl Nixon 2023-06-17 15:45:09 -07:00
parent 396ba90c7e
commit 74cb8d47b2

View file

@ -26,39 +26,39 @@ async function process_request(details) {
try { try {
let hostname = (new URL(details.url)).hostname; let hostname = (new URL(details.url)).hostname;
let securityInfo = await browser.webRequest.getSecurityInfo(details.requestId, { certificateChain: true, rawDER: true }); let securityInfo = await browser.webRequest.getSecurityInfo(details.requestId, { certificateChain: true, rawDER: true });
if (securityInfo.state !== "insecure") { if (securityInfo.certificates.length > 0) {
const fingerprint = securityInfo.certificates[0].fingerprint.sha256;
let fpData = localStorage.getItem(fingerprint);
const currentTime = Date.now(); const currentTime = Date.now();
if (fpData) {
fpData = JSON.parse(fpData);
// If the last request was less than 10 minutes ago, don't spam the API
if (fpData.lastCheck && currentTime - fpData.lastCheck < 10 * 60 * 1000) {
return;
}
// If the last response was less than 12 hours ago, don't check again
if (fpData.lastResponse && currentTime - fpData.lastResponse < 12 * 60 * 60 * 1000) {
return;
}
} else {
fpData = {};
}
fpData.lastCheck = currentTime;
localStorage.setItem(fingerprint, JSON.stringify(fpData));
const tab = details.tabId;
if (!send_buffer[tab]) {
send_buffer[tab] = {};
}
if (!send_buffer[tab][hostname]) {
send_buffer[tab][hostname] = {};
}
securityInfo.certificates.forEach(cert => { securityInfo.certificates.forEach(cert => {
send_buffer[tab][hostname][cert.fingerprint.sha256] = cert.rawDER; const fingerprint = cert.fingerprint.sha256;
let fpData = localStorage.getItem(fingerprint);
if (fpData) {
fpData = JSON.parse(fpData);
// If the last request was less than 10 minutes ago, don't spam the API
if (fpData.lastCheck && currentTime - fpData.lastCheck < 10 * 60 * 1000) {
return;
}
// If the last response was less than 12 hours ago, don't check again
if (fpData.lastResponse && currentTime - fpData.lastResponse < 12 * 60 * 60 * 1000) {
return;
}
} else {
fpData = {};
}
fpData.lastCheck = currentTime;
localStorage.setItem(fingerprint, JSON.stringify(fpData));
const tab = details.tabId;
if (!send_buffer[tab]) {
send_buffer[tab] = {};
}
if (!send_buffer[tab][hostname]) {
send_buffer[tab][hostname] = {};
}
send_buffer[tab][hostname][fingerprint] = cert.rawDER;
}); });
} }
} catch (error) { } catch (error) {
@ -66,6 +66,20 @@ async function process_request(details) {
} }
} }
function generate_alerts(fingerprints) {
fingerprints.forEach(fingerprint => {
let fpData = localStorage.getItem(fingerprint);
fpData = JSON.parse(fpData);
if (fpData.alert === true) {
browser.notifications.create({
"type": "basic",
"iconUrl": browser.runtime.getURL("icons/crowdtls-48.png"),
"title": "CrowdTLS Alert",
"message": fpData.alertMsg
});
}
});
}
/** /**
* Checks the fingerprint and sends a REST GET request to the API. * Checks the fingerprint and sends a REST GET request to the API.
@ -95,12 +109,28 @@ async function do_checks(buffer) {
const data = await response.json(); const data = await response.json();
if (data["anomalies"]) {
const currentTime = Date.now();
Object.keys(data["anomalies"]).forEach(fingerprint => {
let fpData = localStorage.getItem(fingerprint);
fpData = JSON.parse(fpData);
fpData.lastCheck = currentTime;
fpData.lastResponse = currentTime;
fpData.alert = true;
fpData.alertTime = currentTime;
fpData.alertMsg = data["anomalies"][fingerprint];
localStorage.setItem(fingerprint, JSON.stringify(fpData));
});
generate_alerts(Object.keys(data["anomalies"]));
}
Object.keys(buffer).forEach(hostname => { Object.keys(buffer).forEach(hostname => {
if (!data[hostname]) { if (!data[hostname]) {
delete buffer[hostname]; delete buffer[hostname];
} }
}); });
send_certificate_chain(buffer); await send_certificate_chain(buffer);
} }
catch (error) { catch (error) {
console.error(error); console.error(error);
@ -182,7 +212,7 @@ browser.webRequest.onHeadersReceived.addListener(
// When a tab update happens (i.e., page load complete), send the buffered data // When a tab update happens (i.e., page load complete), send the buffered data
browser.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => { browser.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
if (changeInfo.status === "complete" && send_buffer[tabId]) { if ((changeInfo.status || tab.status) == 'complete' && send_buffer[tabId]) {
await do_checks(send_buffer[tabId]); await do_checks(send_buffer[tabId]);
delete send_buffer[tabId]; delete send_buffer[tabId];
} }