NSS / browser-extension /content.js
Kshitijk20's picture
added extension and experimenting with prometheus
5a72624
// Content script - Runs on every page
console.log('Phishing Detector: Content script loaded');
// Extract page-level features from DOM
function extractPageFeatures() {
const features = {};
try {
// Favicon analysis
const favicon = document.querySelector('link[rel*="icon"]');
const currentDomain = window.location.hostname;
if (favicon) {
const faviconUrl = new URL(favicon.href, window.location.href);
features.Favicon = faviconUrl.hostname !== currentDomain ? 1 : -1;
} else {
features.Favicon = 1; // No favicon is suspicious
}
// Request_URL - Check if objects loaded from different domain
const images = document.querySelectorAll('img, video, audio');
let externalResources = 0;
images.forEach(img => {
try {
const imgUrl = new URL(img.src, window.location.href);
if (imgUrl.hostname !== currentDomain) externalResources++;
} catch (e) {}
});
const externalRatio = images.length > 0 ? externalResources / images.length : 0;
features.Request_URL = externalRatio > 0.22 ? 1 : (externalRatio > 0.61 ? 0 : -1);
// URL_of_Anchor - Check anchor tags
const anchors = document.querySelectorAll('a');
let suspiciousAnchors = 0;
anchors.forEach(a => {
const href = a.getAttribute('href');
if (!href || href === '#' || href.startsWith('javascript:')) {
suspiciousAnchors++;
} else {
try {
const anchorUrl = new URL(href, window.location.href);
if (anchorUrl.hostname !== currentDomain) suspiciousAnchors++;
} catch (e) {}
}
});
const anchorRatio = anchors.length > 0 ? suspiciousAnchors / anchors.length : 0;
features.URL_of_Anchor = anchorRatio > 0.31 ? 1 : (anchorRatio > 0.67 ? 0 : -1);
// Links_in_tags - Check meta, script, link tags
const metaLinks = document.querySelectorAll('meta, script[src], link[href]');
let externalMetaLinks = 0;
metaLinks.forEach(tag => {
const src = tag.getAttribute('src') || tag.getAttribute('href') || tag.content;
if (src) {
try {
const url = new URL(src, window.location.href);
if (url.hostname !== currentDomain) externalMetaLinks++;
} catch (e) {}
}
});
const metaRatio = metaLinks.length > 0 ? externalMetaLinks / metaLinks.length : 0;
features.Links_in_tags = metaRatio > 0.17 ? 1 : (metaRatio > 0.81 ? 0 : -1);
// SFH - Server Form Handler
const forms = document.querySelectorAll('form');
let suspiciousForms = 0;
forms.forEach(form => {
const action = form.getAttribute('action');
if (!action || action === '' || action === 'about:blank') {
suspiciousForms++;
} else {
try {
const formUrl = new URL(action, window.location.href);
if (formUrl.hostname !== currentDomain) suspiciousForms++;
} catch (e) {
suspiciousForms++;
}
}
});
features.SFH = forms.length > 0 && suspiciousForms > 0 ? 1 : -1;
// Submitting_to_email - Check if form submits to email
let hasEmailSubmit = false;
forms.forEach(form => {
const action = form.getAttribute('action');
if (action && action.startsWith('mailto:')) hasEmailSubmit = true;
});
features.Submitting_to_email = hasEmailSubmit ? 1 : -1;
// Redirect - Count meta redirects
const metaRefresh = document.querySelector('meta[http-equiv="refresh"]');
features.Redirect = metaRefresh ? 1 : -1;
// on_mouseover - Check for mouseover events that change status bar
let hasMouseoverStatusChange = false;
anchors.forEach(a => {
const mouseover = a.getAttribute('onmouseover') || a.getAttribute('onmouseout');
if (mouseover && (mouseover.includes('window.status') || mouseover.includes('location'))) {
hasMouseoverStatusChange = true;
}
});
features.on_mouseover = hasMouseoverStatusChange ? 1 : -1;
// RightClick - Check if right-click is disabled
const hasRightClickDisable = document.body.getAttribute('oncontextmenu') === 'return false' ||
document.oncontextmenu === null;
features.RightClick = hasRightClickDisable ? 1 : -1;
// popUpWidnow - Check for popup windows
const scripts = document.querySelectorAll('script');
let hasPopup = false;
scripts.forEach(script => {
if (script.textContent.includes('window.open') ||
script.textContent.includes('popup')) {
hasPopup = true;
}
});
features.popUpWidnow = hasPopup ? 1 : -1;
// Iframe - Check for iframes
const iframes = document.querySelectorAll('iframe');
features.Iframe = iframes.length > 0 ? 1 : -1;
return features;
} catch (error) {
console.error('Error extracting page features:', error);
return null;
}
}
// Listen for messages from popup or background
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === 'getCurrentURL') {
sendResponse({ url: window.location.href });
}
if (request.action === 'getPageFeatures') {
const features = extractPageFeatures();
sendResponse({ features: features });
}
if (request.action === 'showWarning') {
showPhishingWarning();
}
return true;
});
// Show warning banner on page
function showPhishingWarning() {
// Check if warning already exists
if (document.getElementById('phishing-warning-banner')) {
return;
}
const banner = document.createElement('div');
banner.id = 'phishing-warning-banner';
banner.style.cssText = `
position: fixed;
top: 0;
left: 0;
right: 0;
background: linear-gradient(135deg, #ff6b6b 0%, #c92a2a 100%);
color: white;
padding: 15px;
text-align: center;
font-family: Arial, sans-serif;
font-size: 16px;
font-weight: bold;
z-index: 999999;
box-shadow: 0 2px 10px rgba(0,0,0,0.3);
animation: slideDown 0.5s ease;
`;
banner.innerHTML = `
<div style="max-width: 1200px; margin: 0 auto; display: flex; align-items: center; justify-content: space-between;">
<div style="flex: 1;">
⚠️ <strong>WARNING:</strong> This site has been identified as potentially dangerous!
</div>
<button id="close-warning" style="
background: rgba(255,255,255,0.2);
border: 2px solid white;
color: white;
padding: 8px 20px;
border-radius: 5px;
cursor: pointer;
font-weight: bold;
margin-left: 20px;
">
Dismiss
</button>
</div>
`;
// Add animation
const style = document.createElement('style');
style.textContent = `
@keyframes slideDown {
from {
transform: translateY(-100%);
}
to {
transform: translateY(0);
}
}
`;
document.head.appendChild(style);
document.body.insertBefore(banner, document.body.firstChild);
// Close button
document.getElementById('close-warning').addEventListener('click', () => {
banner.remove();
});
// Blur page content
document.body.style.filter = 'blur(2px)';
// Remove blur when warning is dismissed
const observer = new MutationObserver(() => {
if (!document.getElementById('phishing-warning-banner')) {
document.body.style.filter = '';
observer.disconnect();
}
});
observer.observe(document.body, { childList: true });
}
// Auto-check on page load (optional - can be enabled in settings)
// Uncomment to enable automatic checking
/*
window.addEventListener('load', () => {
chrome.runtime.sendMessage({
action: 'checkPage',
url: window.location.href
});
});
*/