diff --git a/background/background.js b/background/background.js index 75fdae2..b083d9c 100644 --- a/background/background.js +++ b/background/background.js @@ -275,16 +275,8 @@ function parseServerHeader(serverHeader) { // 在 parseServerHeader 函数后添加 webpack 检测函数 function detectWebpack(pageContent) { - // 检查页面内容中的特征 - if (/(webpackJsonp|__webpack_require__|webpack-dev-server)/.test(pageContent)) { - return { - name: 'Webpack', - description: '通过页面特征识别到Webpack构建工具,用于前端资源打包', - version: 'Webpack' - }; - } // 检查 chunk 文件命名特征 - if (/(?:chunk|main|app|vendor|common)s?(?:[-.][a-f0-9]{8,20})*.(?:css|js)/.test(pageContent)) { + if (/(?:chunk|main|app|vendor|common)s?(?:[-.][a-f0-9]{8,20})+.(?:css|js)/.test(pageContent)) { return { name: 'Webpack', description: '通过文件命名特征识别到Webpack构建工具,用于前端资源打包', @@ -500,8 +492,32 @@ chrome.webRequest.onHeadersReceived.addListener( ['responseHeaders'] ); -// 添加消息监听器处理 popup 的请求 +// 添加构建工具更新消息处理 chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { + if (request.type === 'UPDATE_BUILDER') { + const fingerprints = serverFingerprints.get(sender.tab.id); + if (fingerprints && fingerprints.builder.name!=request.builder.name) { + fingerprints.builder = request.builder; + // 更新存储 + serverFingerprints.set(sender.tab.id, fingerprints); + // 通知更新 + try { + chrome.tabs.sendMessage(sender.tab.id, { + type: 'UPDATE_FINGERPRINTS', + fingerprints: { + server: fingerprints.server, + serverComponents: fingerprints.serverComponents, + headers: Object.fromEntries(fingerprints.headers), + technology: fingerprints.technology, + security: fingerprints.security, + analytics: fingerprints.analytics, + builder: fingerprints.builder + } + }).catch(() => {}); + } catch (e) {} + } + return true; + } if (request.type === 'GET_FINGERPRINTS') { // 获取当前标签页的指纹信息 const fingerprints = serverFingerprints.get(request.tabId); diff --git a/content/config/scanner.config.js b/content/config/scanner.config.js index 803d467..8502603 100644 --- a/content/config/scanner.config.js +++ b/content/config/scanner.config.js @@ -136,9 +136,17 @@ const SCANNER_CONFIG = { type: 'ID_KEY', patterns: SCANNER_CONFIG.ID_KEY.PATTERNS }; + }, + get FINGER() { + return { + type: 'FINGER', + + patterns: SCANNER_CONFIG.FINGER.PATTERNS + }; } }, + // 统一的黑名单配置 BLACKLIST: { // 值黑名单 - 从 ID_KEY 配置中移出 @@ -184,13 +192,20 @@ const SCANNER_CONFIG = { {name: 'GitHub Token2', pattern: /(?:ghp|gho|ghu|ghs|ghr|github_pat)_[a-zA-Z0-9_]{36,255}/g}, {name: 'Apple开发者密钥', pattern: /APID[a-zA-Z0-9]{32,42}/g}, {name: '企业微信密钥', pattern: /ww[a-z0-9]{15,18}/g}, - {name: 'key', pattern: /(?:['"]?(?:\w*(?:key|secret|oss|bucket)\w*)["']?)\s*[:=]\s*(?:"(?!\+)[^\,\s\"\(\>\<]*"|'(?!\+)[^\,\s\'\(\>\<]*'|[\d\s]+)/ig} + {name: 'key', pattern: /(?:['"]?(?:\w*(?:key|secret|oss|bucket)\w*)|ak["']?)\s*[:=]\s*(?:"(?!\+)[^\,\s\"\(\>\<]*"|'(?!\+)[^\,\s\'\(\>\<]*'|[\d\s]+)/ig} ], // 关键词黑名单 KEY_BLACKLIST: new Set([ 'size', 'row', 'dict', 'up', 'highlight', 'cabin', 'cross' ]) + }, + + // 添加构建工具配置 + FINGER: { + PATTERNS: [ + {name: 'Webpack页面特征', pattern: /(?:webpackJsonp|__webpack_require__|webpack-dev-server)/}, + ] } }; diff --git a/content/content.js b/content/content.js index 09ac616..1fb448b 100644 --- a/content/content.js +++ b/content/content.js @@ -15,7 +15,7 @@ const waitForDependencies = () => { ]; return new Promise(resolve => { (function check() { - deps.every(dep => window[dep]) ? resolve() : setTimeout(check, 50); + deps.every(dep => window[dep]) ? resolve() : setTimeout(check, 20); })(); }); }; @@ -41,8 +41,10 @@ const latestResults = { credentials: new Set(), // 用户名密码结果集 cookies: new Set(), // Cookie结果集 idKeys: new Set(), // ID密钥结果集 + fingers: new Set(), // 指纹结果集 }; + // 优化扫描函数 async function scanSources(sources, isHtmlContent = false) { try { @@ -112,6 +114,17 @@ async function scanSources(sources, isHtmlContent = false) { try { // 根据内容类型选择合适的模式 + if (key === 'FINGER') { + // 对每个模式进行匹配 + for (const {pattern: fingerPattern, name: fingerName} of pattern.patterns) { + if (latestResults.fingers.has(fingerName)) continue; + const matches = chunk.match(fingerPattern); + if (matches) { + filter(fingerName, latestResults); + } + } + continue; + } if (key === 'IP') { // 使用不同的IP匹配模式 const ipPattern = isHtmlContent ? pattern : SCANNER_CONFIG.PATTERNS.IP_RESOURCE; @@ -537,4 +550,4 @@ if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initScan); } else { initScan(); -} \ No newline at end of file +} \ No newline at end of file diff --git a/content/filters/scanner.filter.js b/content/filters/scanner.filter.js index 7cca924..35a2095 100644 --- a/content/filters/scanner.filter.js +++ b/content/filters/scanner.filter.js @@ -5,7 +5,7 @@ const regexCache = { chinesePattern: /^[\u4e00-\u9fa5]+$/, keywordPattern: /^func|variable|input|true|false|newline|null|http|unexpected|error|data|object|brac|beare|str|self|void|num|atom|opts|token|params|result|con|text|stor|sup|pun|emp|this|key|com|ent|met|opera|return|case|pare|ident|reg|invalid/i, camelCasePattern: /\b[_a-z]+(?:[A-Z][a-z]+)+\b/, - filterPattern: /请|输入|前往|整个|常用|咨询|为中心|以上|目前|任务|推动|需要|直接|识别|获取|用于|清除|遍历|一家|项目|等|造价|判断|通过|为了|可以|掌握|传统|杀毒|为了|允许|分析/ + filterPattern: /请|输入|前往|整个|常用|咨询|为中心|是否|以上|目前|任务|推动|需要|直接|识别|获取|用于|清除|遍历|一家|项目|等|造价|判断|通过|为了|可以|掌握|传统|杀毒|为了|允许|分析/ }; // 统一的扫描过滤器 @@ -251,7 +251,7 @@ const SCANNER_FILTER = { // 检查是否是空值 const valueMatch = match.replace(/\s+/g,'').split(/[:=]/); var key = valueMatch[0].replace(/['"]/g,'').toLowerCase(); - var value = valueMatch[1].replace(/['"\{\}\[\]\,\:\。\?\?\!\>\<]/g,'').toLowerCase(); + var value = valueMatch[1].replace(/['"\{\}\[\]\,\:\。\?\、\?\!\>\<]/g,'').toLowerCase(); if (!value.length) { return false; } @@ -321,6 +321,20 @@ const SCANNER_FILTER = { resultsSet?.idKeys?.add(match); return true; + }, + + // 构建工具检测过滤器 + finger: (match, resultsSet) => { + chrome.runtime.sendMessage({ + type: 'UPDATE_BUILDER', + builder: { + name: 'Webpack', + description: '通过页面特征识别到Webpack构建工具,用于前端资源打包', + version: 'Webpack' + } + }); + resultsSet?.fingers?.add(match); + return true; } };