Skip to content

Commit

Permalink
machine-learning-variant
Browse files Browse the repository at this point in the history
Integrate ML & URL Whitelisting
  • Loading branch information
RootUp authored Jan 1, 2025
2 parents 76a6be6 + d1604e5 commit e8866d2
Show file tree
Hide file tree
Showing 10 changed files with 1,294 additions and 401 deletions.
49 changes: 32 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,45 @@
# SmuggleShield
***Beta Version***
***Stable Version (2.0)***

[![CodeQL Advanced](https://github.com/RootUp/SmuggleShield/actions/workflows/codeql.yml/badge.svg)](https://github.com/RootUp/SmuggleShield/actions/workflows/codeql.yml)

SmuggleShield is an experimental browser extension that aims to prevent **basic** HTML smuggling attacks by detecting common patterns. While this is not a comprehensive or bulletproof solution, it is an attempt to provide an additional layer of security during browsing. **The project is still in the testing phase!**
SmuggleShield is a browser extension that aims to prevent **basic** HTML smuggling attacks by detecting common patterns. While this is not a comprehensive or bulletproof solution, it is an attempt to provide an additional layer of security during browsing or during your red/puprle team exercise.

The extension is compatible both on Chrome and Edge for Mac and Windows OS. Enable developer mode under extension settings and click on "Load unpacked" in the "SumggleSheild" folder. The extension would be up and running. Blocked URLs are stored in extension cache up to 10 days with blocked pattern, URL, and timestamp, which can be reviewed by clicking on extension then "Export Blocked Content Logs.". 
The extension is compatible both on Chrome and Edge for Mac and Windows OS. Enable developer mode under extension settings and click on "Load unpacked" in the "SumggleSheild" folder. The extension would be up and running. Blocked URLs are stored in extension cache up to 10 days with blocked pattern, URL, and timestamp, which can be reviewed by clicking on extension then "Export Blocked Content Logs", the current stable version also has key fatures such as "URL Whitelisting" because sometimes SmuggleShield could take few seconds extra to load a page because it scans every elements of the webpage but with this key feature (URL Whitelisting) you can reduce the overhead

## Incognito Mode Support
SmuggleShield can protect against HTML smuggling attempts in incognito mode, but requires manual activation. To enable incognito protection: open Chrome's extension management page (`chrome://extensions/`), click "Details" on SmuggleShield, and toggle "Allow in incognito". Note: This setting is disabled by default as per Chrome's security policy. When enabled, the extension will maintain separate states for normal and incognito sessions to preserve privacy, while providing the same level of protection against HTML smuggling attempts in both modes.
## Extension Workflow

## **Install from Chrome Web Store**
- [SmuggleShield](https://chromewebstore.google.com/detail/SmuggleShield/lglilndcogcapdkpfllcdlopgffbepce) - Currently, the GH version of this extension is more better than the one published on Chrome webstore.
![SmuggleShield-Workflow](https://github.com/user-attachments/assets/a42d9f8d-3968-42c8-b0e8-a9507defa197)

![SmuggleShield_POC](https://github.com/user-attachments/assets/c8602882-cd1b-48fb-9512-642993aadf88)
[Watch on Youtube](https://youtu.be/6x0Fe_63qxA)
## Machine Learning Integration & Workflow

I have taken multiple code references from StackOverflow/Github and file smuggling samples from delivr[dot]to. Hence, special thanks to them!
First, the `HTMLSmugglingBlocker` analyzes webpage content and combines both pattern-based detection and ML-based analysis. The MLDetector then extracts six key features (`base64Length`, `blobUsage`, `downloadAttr`, `scriptDensity`, `encodingFunctions`, `binaryManipulation`) and makes predictions using a **0.75** confidence threshold. Then its a continuous learning loop where the `MLMonitor` tracks performance metrics and feeds results back to improve detection accuracy, with all learned patterns persisted in `chrome.storage.local` for adaptation to new threats.

![SmuggleShield-ML](https://github.com/user-attachments/assets/043b9f32-b28f-437f-a7c6-1f59e705dc22)

https://github.com/user-attachments/assets/8b8f1333-6a99-4979-bc17-56026a048ba8

## In Action

## **Privacy Policy**
- [Privacy Policy for SmuggleShield](https://www.inputzero.io/p/smuggelsheild.html)
https://github.com/user-attachments/assets/8d97fdcf-b3d2-4ddb-a846-0900e333b7fe

## **SmuggleShield could have prevented**
## Incognito Mode Support
SmuggleShield can protect against HTML smuggling attempts in incognito mode, but requires manual activation. To enable incognito protection: open Chrome's extension management page (`chrome://extensions/`), click "**Details**" on SmuggleShield, and toggle "**Allow in incognito**". Note: This setting is disabled by default as per Chrome's security policy. When enabled, the extension will maintain separate states for normal and incognito sessions to preserve privacy, while providing the same level of protection against HTML smuggling attempts in both modes.

## Install from Chrome Web Store
[SmuggleShield](https://chromewebstore.google.com/detail/SmuggleShield/lglilndcogcapdkpfllcdlopgffbepce) - Currently, the GitHub version is more better than the one published on Chrome webstore.

## SmuggleShield Could Have Prevented

- [Quakbot- 14072022](https://github.com/0xToxin/Malware-IOCs/blob/main/Quakbot/Quakbot-%2014072022)
- [Pikabot | TA577 | 1.1.15-ghost](https://github.com/pr0xylife/Pikabot/blob/main/Pikabot_01.11.2023.txt)
- [A malspam campaign delivering AsyncRAT](https://x.com/RandomDhiraj/status/1854182495337476211)
- [HTML smuggling is delivering DCRat malware, bypassing traditional security controls by embedding malicious payloads in HTML files. This advanced technique poses a global threat to unsuspecting users](https://x.com/RandomDhiraj/status/1839717748970021027)
| **Sr. No.** | **Details** | **Reference** |
|-------------|--------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|
| 1 | Quakbot campaign (14th July 2022) | [GitHub](https://github.com/0xToxin/Malware-IOCs/blob/main/Quakbot/Quakbot-%2014072022) |
| 2 | DCRat malware via HTML Smuggling | [X (Twitter)](https://x.com/RandomDhiraj/status/1839717748970021027) |
| 3 | Pikabot (TA577, Version 1.1.15-ghost) | [GitHub](https://github.com/pr0xylife/Pikabot/blob/main/Pikabot_01.11.2023.txt) |
| 4 | AsyncRAT delivered via malspam campaign | [X (Twitter)](https://x.com/RandomDhiraj/status/1854182495337476211) |

## Special Thanks
I have taken multiple code references from StackOverflow/Github and file smuggling samples from delivr[dot]to. Hence, special thanks to them!

## Privacy Policy
[Privacy Policy for SmuggleShield](https://www.inputzero.io/p/smuggelsheild.html)
117 changes: 94 additions & 23 deletions SmuggleShield/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const config = {
suspiciousHeaders: ['content-disposition', 'content-type'],
logRetentionDays: 10,
cacheDurationMs: 5 * 60 * 1000,
whitelistEnabled: true
};

class WeakLRUCache {
Expand Down Expand Up @@ -79,6 +80,68 @@ function debounce(func, delay) {

const debouncedLogBlockedContent = debounce(logBlockedContent, 1000);

async function isWhitelisted(url) {
try {
const hostname = new URL(url).hostname;
const result = await chrome.storage.local.get('whitelist');
const whitelist = result.whitelist || [];
console.log('Background checking whitelist for:', hostname, 'Whitelist:', whitelist);
return whitelist.includes(hostname);
} catch (error) {
console.error('Error checking whitelist:', error);
return false;
}
}

chrome.webNavigation.onCommitted.addListener(async (details) => {
if (details.frameId === 0) { // Main frame only
const isWhitelistedUrl = await isWhitelisted(details.url);
if (isWhitelistedUrl) {
chrome.tabs.sendMessage(details.tabId, {
action: "setWhitelisted",
value: true
}).catch(error => console.debug('Tab not ready yet:', error));
}
}
});

chrome.webRequest.onBeforeRequest.addListener(
async (details) => {
if (await isWhitelisted(details.url)) {
console.log('URL is whitelisted, allowing request:', details.url);
return { cancel: false };
}

const isSuspiciousUrl = checkSuspiciousURL(details.url);

if (isSuspiciousUrl) {
console.log('Suspicious URL detected:', details.url);
return { cancel: true };
}

return { cancel: false };
},
{urls: ["<all_urls>"]},
["blocking"]
);

chrome.webRequest.onHeadersReceived.addListener(
async (details) => {
if (await isWhitelisted(details.url)) {
return { responseHeaders: details.responseHeaders };
}

const hasSuspiciousHeaders = checkSuspiciousHeaders(details.responseHeaders);
if (hasSuspiciousHeaders) {
chrome.tabs.sendMessage(details.tabId, {action: "suspiciousHeadersDetected"})
.catch(error => console.error('Error sending message:', error));
}
return {responseHeaders: details.responseHeaders};
},
{urls: ["<all_urls>"]},
["responseHeaders"]
);

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
console.log('Received message:', request);
switch (request.action) {
Expand All @@ -87,13 +150,19 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
console.warn(request.message);
break;
case "analyzeURL":
const result = memoizedAnalyzeURL(request.url);
if (Date.now() - result.timestamp < config.cacheDurationMs) {
sendResponse({isSuspicious: result.isSuspicious});
} else {
const newResult = memoizedAnalyzeURL(request.url);
sendResponse({isSuspicious: newResult.isSuspicious});
}
isWhitelisted(request.url).then(whitelisted => {
if (whitelisted) {
sendResponse({isSuspicious: false, whitelisted: true});
} else {
const result = memoizedAnalyzeURL(request.url);
if (Date.now() - result.timestamp < config.cacheDurationMs) {
sendResponse({isSuspicious: result.isSuspicious, whitelisted: false});
} else {
const newResult = memoizedAnalyzeURL(request.url);
sendResponse({isSuspicious: newResult.isSuspicious, whitelisted: false});
}
}
});
return true;
case "exportLogs":
chrome.storage.local.get(['blockedLogs'], result => {
Expand Down Expand Up @@ -134,21 +203,6 @@ const checkSuspiciousHeaders = memoize((headers) => {
);
}, (headers) => JSON.stringify(headers));

chrome.webRequest.onHeadersReceived.addListener(
(details) => {
const hasSuspiciousHeaders = checkSuspiciousHeaders(details.responseHeaders);

if (hasSuspiciousHeaders) {
chrome.tabs.sendMessage(details.tabId, {action: "suspiciousHeadersDetected"})
.catch(error => console.error('Error sending message:', error));
}

return {responseHeaders: details.responseHeaders};
},
{urls: ["<all_urls>"]},
["responseHeaders"]
);

const memoizedAnalyzeURL = memoize((url) => {
const isSuspicious = checkSuspiciousURL(url);
return {isSuspicious, timestamp: Date.now()};
Expand All @@ -160,7 +214,7 @@ class ContentAnalyzer {
this.analysisQueue = new Set();
this.isProcessing = false;
this.lastAnalysis = 0;
this.minAnalysisInterval = 300; // ms between analyses
this.minAnalysisInterval = 300;
}

queueForAnalysis(element) {
Expand Down Expand Up @@ -296,3 +350,20 @@ function setupObserver() {

contentAnalyzer.queueForAnalysis(document.documentElement);
}

chrome.action.onClicked.addListener((tab) => {
chrome.tabs.create({
url: chrome.runtime.getURL('main.html'),
active: true
});
});


chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
if (request.action === "whitelistUpdated") {
const result = await chrome.storage.local.get('whitelist');
const whitelist = result.whitelist || [];
console.log('Whitelist updated:', whitelist);
return true;
}
});
Loading

0 comments on commit e8866d2

Please sign in to comment.