This commit is contained in:
sickle committed 2025-01-13 12:25:34 +08:00
1 parent 8c528c18c8
commit c72f580320
6 files changed
+451 -613

No files matched your search

+22 -2
View File
@@ -1,8 +1,28 @@
// 统一的扫描器配置
const SCANNER_CONFIG = {
// API 相关配置 - 只保留正则表达式
// 白名单配置
WHITELIST: [
'github.com',
'stackoverflow.com',
'npmjs.com',
'google.com',
'youtube.com',
'microsoft.com',
'apple.com',
'mozilla.org',
'cdn.jsdelivr.net',
'cdnjs.cloudflare.com',
'unpkg.com',
'jquery.com',
'bootstrapcdn.com',
'fontawesome.com'
],
// API 相关配置
API: {
PATTERN: /['"](?:\/|\.\.\/|\.\/)[^\/\>\< \)\(\{\}\,\'\"\\]([^\>\< \)\(\{\}\,\'\"\\])*?[\'"]/g
PATTERN: /['"](?:\/|\.\.\/|\.\/)[^\/\>\< \)\(\{\}\,\'\"\\]([^\>\< \)\(\{\}\,\'\"\\])*?[\'"]/g,
// 静态文件后缀
STATIC_FILE_PATTERN: /\.(js|css|ico|png|webp|jpg|jpeg|gif|svg|woff|woff2|ttf|eot|map|json)$/i
},
// 域名相关配置
+38 -15
View File
@@ -26,6 +26,7 @@ const waitForDependencies = () => {
const latestResults = {
domains: new Set(), // 域名结果集
apis: new Set(), // API 结果集
staticFiles: new Set(), // 静态文件结果集
ips: new Set(), // IP 地址结果集
internalIps: new Set(), // 内网 IP 结果集
phones: new Set(), // 手机号结果集
@@ -292,12 +293,27 @@ function scanSources(sources) {
sendUpdate();
}
// 检查域名是否在白名单中
function isInWhitelist(hostname) {
return SCANNER_CONFIG.WHITELIST.some(domain => {
// 完全匹配或者是子域名
return hostname === domain || hostname.endsWith('.' + domain);
});
}
// 初始化扫描
async function initScan() {
try {
await waitForDependencies();
window.logger.info('开始扫描...');
// 检查当前域名是否在白名单中
const currentHostname = window.location.hostname.toLowerCase();
if (isInWhitelist(currentHostname)) {
window.logger.info('当前域名在白名单中,跳过扫描');
return;
}
// 清空之前的结果
Object.keys(latestResults).forEach(key => {
if (key === 'hashes') {
@@ -447,11 +463,23 @@ async function collectAndScanResources() {
// 监听来自 popup 的消息
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.type === 'GET_RESULTS') {
// 检查是否在白名单中
const currentHostname = window.location.hostname.toLowerCase();
if (isInWhitelist(currentHostname)) {
sendResponse('WHITELISTED');
return;
}
// 返回当前的扫描结果
sendResponse(Object.fromEntries(
Object.entries(latestResults).map(([key, value]) => [key, Array.from(value)])
));
} else if (request.type === 'REFRESH_SCAN') {
// 检查是否在白名单中
const currentHostname = window.location.hostname.toLowerCase();
if (isInWhitelist(currentHostname)) {
sendResponse('WHITELISTED');
return;
}
// 重新执行扫描
initScan().then(() => {
sendResponse(Object.fromEntries(
@@ -462,23 +490,18 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
} else if (request.type === 'GET_CONFIG') {
// 返回配置信息,将正则表达式转换为字符串
const config = {
WHITELIST: SCANNER_CONFIG.WHITELIST,
API: {
PATTERN: SCANNER_CONFIG.API.PATTERN.toString()
PATTERN: SCANNER_CONFIG.API.PATTERN.toString(),
STATIC_FILE_PATTERN: SCANNER_CONFIG.API.STATIC_FILE_PATTERN.toString()
},
PATTERNS: {
DOMAIN: SCANNER_CONFIG.PATTERNS.DOMAIN.toString(),
IP: SCANNER_CONFIG.PATTERNS.IP.toString(),
PHONE: SCANNER_CONFIG.PATTERNS.PHONE.toString(),
EMAIL: SCANNER_CONFIG.PATTERNS.EMAIL.toString(),
IDCARD: SCANNER_CONFIG.PATTERNS.IDCARD.toString(),
URL: SCANNER_CONFIG.PATTERNS.URL.toString(),
JWT: SCANNER_CONFIG.PATTERNS.JWT.toString(),
AWS_KEY: SCANNER_CONFIG.PATTERNS.AWS_KEY.toString(),
HASH: {
MD5: SCANNER_CONFIG.PATTERNS.HASH.MD5.toString(),
SHA1: SCANNER_CONFIG.PATTERNS.HASH.SHA1.toString(),
SHA256: SCANNER_CONFIG.PATTERNS.HASH.SHA256.toString()
}
DOMAIN: {
BLACKLIST: SCANNER_CONFIG.DOMAIN.BLACKLIST,
SPECIAL_DOMAINS: SCANNER_CONFIG.DOMAIN.SPECIAL_DOMAINS
},
IP: {
PRIVATE_RANGES: SCANNER_CONFIG.IP.PRIVATE_RANGES.map(pattern => pattern.toString()),
SPECIAL_RANGES: SCANNER_CONFIG.IP.SPECIAL_RANGES.map(pattern => pattern.toString())
}
};
sendResponse({ config });
+6 -2
View File
@@ -6,8 +6,12 @@ const SCANNER_FILTER = {
// 去除首尾的引号
match = match.slice(1, -1);
// 只添加到结果集
resultsSet?.apis?.add(match);
// 检查是否是静态文件
if (SCANNER_CONFIG.API.STATIC_FILE_PATTERN.test(match)) {
resultsSet?.staticFiles?.add(match);
} else {
resultsSet?.apis?.add(match);
}
return true;
};
})(),
+222 -188
View File
@@ -1,39 +1,68 @@
/* 基础页面布局 */
/* 基础样式 */
body {
width: 400px;
height: 600px;
margin: 0;
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
padding: 0;
font-size: 14px;
line-height: 1.5;
background: #fff;
color: #333;
overflow: hidden;
}
/* 导航栏样式 */
.nav {
.nav-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
padding: 0;
border-bottom: 1px solid #e9ecef;
background: #fff;
border-bottom: 1px solid #eee;
height: 40px;
flex-shrink: 0;
}
/* 导航栏标题 */
.nav-title {
font-size: 16px;
font-weight: 600;
color: #2c2c2c;
.nav-left {
display: flex;
}
.nav-right {
padding-right: 10px;
}
.nav-tab {
padding: 10px 20px;
border: none;
background: none;
color: #495057;
font-size: 14px;
cursor: pointer;
position: relative;
}
.nav-tab.active {
color: #228be6;
font-weight: 500;
}
.nav-tab.active::after {
content: '';
position: absolute;
bottom: -1px;
left: 0;
right: 0;
height: 2px;
background: #228be6;
}
/* 刷新按钮样式 */
.refresh-btn {
padding: 4px 12px;
font-size: 13px;
padding: 6px 12px;
color: #5c7cfa;
background: #edf2ff;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 13px;
transition: all 0.2s;
}
@@ -41,138 +70,204 @@ body {
background: #dbe4ff;
}
/* 主容器样式 */
.container {
padding: 8px 16px 12px;
height: calc(100% - 50px);
/* 页面容器样式 */
.page {
height: calc(100vh - 40px);
overflow-y: auto;
padding: 10px 10px 10px 12px;
width: 400px;
box-sizing: border-box;
}
/* 自定义滚动条样式 */
.container::-webkit-scrollbar {
width: 6px;
height: 6px;
.page.active {
display: block;
}
.container::-webkit-scrollbar-track {
background: #f1f3f5;
border-radius: 3px;
}
.container::-webkit-scrollbar-thumb {
background: #dee2e6;
border-radius: 3px;
}
.container::-webkit-scrollbar-thumb:hover {
background: #ced4da;
/* 内容容器样式 */
.container {
height: 100%;
overflow: hidden;
width: 100%;
}
/* 结果区域样式 */
.section {
margin-bottom: 12px;
margin-bottom: 8px;
}
/* 结果区域标题栏 */
.section-header {
margin-bottom: 6px;
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 4px;
}
/* 标题文本样式 */
.title {
font-size: 15px;
font-weight: 600;
color: #495057;
letter-spacing: 0.3px;
}
/* 结果数量样式 */
.count {
font-size: 13px;
color: #868e96;
margin-left: 2px;
font-weight: normal;
letter-spacing: 0.2px;
}
/* 结果内容区域 */
.section-content {
background: #f8f9fa;
border-radius: 4px;
padding: 8px;
display: block;
padding: 6px 10px 6px 6px;
max-height: 300px;
overflow-y: auto;
width: 100%;
box-sizing: border-box;
margin-right: 2px;
}
/* 结果区域滚动条样式 */
.section-content::-webkit-scrollbar {
width: 6px;
height: 6px;
}
.section-content::-webkit-scrollbar-track {
background: #f1f3f5;
border-radius: 3px;
}
.section-content::-webkit-scrollbar-thumb {
background: #dee2e6;
border-radius: 3px;
}
.section-content::-webkit-scrollbar-thumb:hover {
background: #ced4da;
}
/* 结果项包装器 */
.content-wrapper {
display: flex;
flex-wrap: wrap;
gap: 8px;
padding: 4px;
width: 100%;
box-sizing: border-box;
}
/* 单个结果项样式 */
/* 结果项样式 */
.item {
display: inline-flex;
align-items: center;
padding: 6px 12px;
padding: 4px 10px;
background: #fff;
border-radius: 4px;
font-size: 13px;
color: #495057;
cursor: pointer;
position: relative;
box-shadow: 0 1px 2px rgba(0,0,0,0.03);
transition: all 0.15s ease;
width: fit-content;
min-width: unset;
max-width: calc(100% - 16px);
white-space: normal;
margin: 3px;
box-shadow: 0 1px 2px rgba(0,0,0,0.05);
}
.item:hover {
background: #f8f9fa;
}
/* 配置页面样式 */
.config-section {
padding: 8px;
}
.config-group {
margin-bottom: 16px;
}
.config-group h3 {
font-size: 14px;
color: #495057;
margin-bottom: 8px;
font-weight: 600;
}
.config-content {
background: #f8f9fa;
padding: 10px;
border-radius: 4px;
font-size: 12px;
color: #495057;
word-break: break-all;
margin-right: 8px;
line-height: 1.5;
}
/* 白名单项样式 */
.whitelist {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
gap: 6px;
}
.whitelist-item {
background: #e9ecef;
padding: 4px 8px;
border-radius: 4px;
text-align: center;
font-size: 12px;
color: #495057;
}
/* 配置项样式 */
.config-item {
margin-bottom: 8px;
}
/* 添加悬停效果 */
.item:hover {
background: #f8f9fa;
transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
.config-item:last-child {
margin-bottom: 0;
}
/* 点击效果 */
.item:active {
transform: scale(0.98);
.config-label {
font-weight: 500;
margin-bottom: 4px;
color: #495057;
}
.config-value {
font-family: monospace;
word-break: break-all;
line-height: 1.5;
}
/* 黑名单项样式 */
.blacklist {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
gap: 4px;
}
.blacklist-item {
background: #f1f3f5;
padding: 3px 6px;
border-radius: 3px;
font-size: 11px;
text-align: center;
}
/* 状态提示样式 */
.loading, .error {
padding: 20px;
text-align: center;
color: #666;
}
.error {
color: #ff6b6b;
}
/* 白名单提示样式 */
.whitelisted {
padding: 20px;
text-align: center;
color: #2b8a3e;
background: #ebfbee;
border-radius: 4px;
margin: 10px;
font-size: 14px;
}
/* 复制提示样式 */
.copy-tooltip {
position: fixed;
background: rgba(0, 0, 0, 0.8);
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
z-index: 1001;
}
/* 计数样式 */
.count {
font-size: 13px;
color: #868e96;
margin-left: 4px;
font-weight: normal;
}
/* 无结果提示样式 */
.no-results {
padding: 20px;
text-align: center;
color: #868e96;
font-style: italic;
}
/* 内容包装器样式 */
.content-wrapper {
display: flex;
flex-wrap: wrap;
gap: 4px;
}
/* 为不同类型的结果添加左侧彩色边框 */
@@ -182,7 +277,7 @@ body {
left: 0;
top: 0;
bottom: 0;
width: 2.5px;
width: 3px;
border-radius: 4px 0 0 4px;
}
@@ -195,12 +290,12 @@ body {
background: #b197fc; /* 紫色 - API */
}
.ip-list .item::before {
background: #ffd43b; /* 黄色 - IP */
.static-list .item::before {
background: #20c997; /* 青绿色 - 静态文件 */
}
.port-list .item::before {
background: #868e96; /* 灰色 - 端口 */
.ip-list .item::before {
background: #ffd43b; /* 黄色 - IP */
}
.phone-list .item::before {
@@ -219,14 +314,6 @@ body {
background: #4dabf7; /* 浅蓝 - URL */
}
.btc-list .item::before {
background: #fab005; /* 金色 - 比特币地址 */
}
.eth-list .item::before {
background: #7950f2; /* 深紫 - 以太坊地址 */
}
.jwt-list .item::before {
background: #ff922b; /* 橙色 - JWT Token */
}
@@ -247,92 +334,39 @@ body {
background: #82c91e; /* 黄绿色 - SHA256哈希 */
}
/* 复制按钮样式 */
.copy-all-btn {
padding: 4px;
background: none;
border: none;
cursor: pointer;
color: #868e96;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
transition: all 0.2s;
position: relative;
/* 自定义滚动条样式 */
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
.copy-all-btn:hover {
background: #f1f3f5;
color: #495057;
::-webkit-scrollbar-track {
background: transparent;
}
.copy-all-btn:active {
transform: translateY(1px);
::-webkit-scrollbar-thumb {
background: #e9ecef;
border-radius: 3px;
transition: background 0.2s;
}
/* 复制提示动画 */
@keyframes fadeInOut {
0% {
opacity: 0;
transform: translate(-50%, -40%);
}
20% {
opacity: 1;
transform: translate(-50%, -50%);
}
80% {
opacity: 1;
transform: translate(-50%, -50%);
}
100% {
opacity: 0;
transform: translate(-50%, -60%);
}
/* 当鼠标悬停在页面上时,滚动条变深 */
.page:hover::-webkit-scrollbar-thumb {
background: #adb5bd;
}
/* 复制提示样式 */
.copy-tooltip {
position: fixed;
background: rgba(33, 37, 41, 0.9);
color: white;
padding: 6px 12px;
border-radius: 4px;
font-size: 12px;
pointer-events: none;
white-space: nowrap;
z-index: 1000;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
animation: fadeInOut 1s ease;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
/* 结果区域的滚动条样式 */
.section-content::-webkit-scrollbar {
width: 4px;
height: 4px;
}
/* 状态提示样式 */
.loading, .error, .no-results {
padding: 8px;
text-align: center;
color: #868e96;
font-style: italic;
font-size: 13px;
.section-content::-webkit-scrollbar-thumb {
background: #e9ecef;
}
.error {
color: #ff6b6b;
}
/* 优化标签间距 */
.content-wrapper {
gap: unset;
}
/* 移除结果项间的分隔符 */
.item::after {
content: none;
}
.item:last-child::after {
content: none;
/* 当鼠标悬停在结果区域时,滚动条变深 */
.section-content:hover::-webkit-scrollbar-thumb {
background: #adb5bd;
}
+14 -238
View File
@@ -2,219 +2,24 @@
<html>
<head>
<meta charset="UTF-8">
<!-- 引入样式文件 -->
<link rel="stylesheet" href="highlight.css">
<style>
/* 基础样式设置 */
body {
width: 400px; /* 固定弹出窗口宽度 */
margin: 0;
padding: 0;
font-size: 14px;
line-height: 1.5;
background: #f8f9fa;
}
/* 主容器样式 */
.container {
width: 400px; /* 与body同宽 */
max-height: 600px; /* 最大高度限制 */
overflow-y: auto; /* 内容超出时显示滚动条 */
padding: 15px;
margin: 0;
box-sizing: border-box;
}
/* 结果区域样式 */
.result-section {
width: 370px; /* 考虑内边距的容器宽度 */
margin: 10px 0;
padding: 10px;
border: 1px solid #8f8c8c;
border-radius: 4px;
background: #f2eeee;
box-sizing: border-box;
}
/* 结果列表样式 */
.result-list {
width: 350px;
margin: 0;
padding: 0;
}
/* 结果项样式 */
.result-item {
width: 350px;
padding: 8px;
border-bottom: 1px solid #eee;
box-sizing: border-box;
}
/* 结果项包装器样式 */
.result-wrapper {
width: 334px;
position: relative;
padding-right: 30px; /* 为复制按钮预留空间 */
box-sizing: border-box;
overflow: hidden;
}
/* URL 内容样式 */
.url-content {
width: 304px;
display: inline-block;
padding: 8px;
margin: 0;
background: #f5f5f5;
border-radius: 3px;
font-family: monospace;
font-size: 12px;
line-height: 1.4;
overflow-wrap: anywhere;
word-break: break-all;
white-space: pre-wrap;
box-sizing: border-box;
overflow: hidden;
text-overflow: ellipsis;
}
/* 复制按钮样式 */
.copy-btn {
position: absolute;
right: 0;
top: 8px;
padding: 4px;
border: none;
background: transparent;
cursor: pointer;
opacity: 0.6;
transition: opacity 0.2s;
}
.copy-btn:hover {
opacity: 1;
}
/* 导航栏样式 */
.nav {
width: 400px;
position: sticky;
top: 0;
background: white;
z-index: 1000;
padding: 10px 15px;
border-bottom: 1px solid #eee;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
}
/* 标题样式 */
h3 {
margin: 0 0 10px 0;
font-size: 14px;
color: #333;
}
/* 按钮通用样式 */
button {
padding: 6px 12px;
border: 1px solid #ddd;
border-radius: 4px;
background: #fff;
cursor: pointer;
font-size: 12px;
}
button:hover {
background: #f5f5f5;
}
/* 状态提示样式 */
.loading, .error {
padding: 20px;
text-align: center;
color: #666;
}
/* 复制提示工具提示样式 */
.copy-tooltip {
position: fixed;
background: rgba(0, 0, 0, 0.8);
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
z-index: 1001;
}
/* 导航栏样式 */
.nav-tabs {
display: flex;
background: #fff;
border-bottom: 1px solid #ddd;
padding: 0;
height: 600px;
margin: 0;
height: 40px;
justify-content: space-between; /* 两端对齐 */
align-items: center; /* 垂直居中 */
}
.nav-left {
display: flex; /* 左侧标签容器 */
}
.nav-right {
padding-right: 10px; /* 右侧按钮容器 */
}
.nav-tab {
padding: 10px 20px;
cursor: pointer;
border: none;
background: none;
color: #666;
font-size: 14px;
position: relative;
}
.nav-tab.active {
color: #1a73e8;
font-weight: 500;
}
.nav-tab.active::after {
content: '';
position: absolute;
bottom: -1px;
left: 0;
right: 0;
height: 2px;
background: #1a73e8;
}
/* 刷新按钮样式 */
.refresh-btn {
padding: 6px 12px;
color: #5c7cfa;
background: #edf2ff;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 13px;
transition: all 0.2s;
}
.refresh-btn:hover {
background: #dbe4ff;
padding: 0;
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
background: #fff;
color: #333;
display: flex;
flex-direction: column;
}
/* 页面容器样式 */
.page {
display: none;
height: calc(100vh - 40px); /* 减去导航栏高度 */
flex: 1;
overflow-y: auto;
}
@@ -222,41 +27,16 @@
display: block;
}
/* 配置页面样式 */
.config-page {
padding: 15px;
}
.config-section {
margin-bottom: 20px;
}
.config-section h4 {
margin: 0 0 10px 0;
color: #333;
font-size: 14px;
}
.config-item {
background: #f5f5f5;
padding: 10px;
border-radius: 4px;
margin-bottom: 10px;
font-family: monospace;
font-size: 12px;
word-break: break-all;
white-space: pre-wrap;
}
/* 内容容器样式 */
.container {
padding: 15px;
height: 100%;
overflow-y: auto;
}
</style>
</head>
<body>
<!-- 导航栏 -->
<div class="nav-tabs">
<div class="nav-bar">
<div class="nav-left">
<button class="nav-tab active" data-page="scanner">信息搜集</button>
<button class="nav-tab" data-page="config">配置</button>
@@ -266,18 +46,14 @@
</div>
</div>
<!-- 信息搜集页面 -->
<!-- 扫描页面 -->
<div class="page scanner-page active">
<div class="container">
<!-- 内容将由 JavaScript 动态生成 -->
</div>
<div class="container"></div>
</div>
<!-- 配置页面 -->
<div class="page config-page">
<div class="config-container">
<!-- 配置内容将由 JavaScript 动态生成 -->
</div>
<div class="container"></div>
</div>
<script src="popup.js"></script>
+149 -168
View File
@@ -7,10 +7,7 @@ function switchPage(pageName) {
// 更新页面显示状态
document.querySelectorAll('.page').forEach(page => {
const isScanner = page.classList.contains('scanner-page');
const isConfig = page.classList.contains('config-page');
if ((isScanner && pageName === 'scanner') || (isConfig && pageName === 'config')) {
if (page.classList.contains(`${pageName}-page`)) {
page.classList.add('active');
} else {
page.classList.remove('active');
@@ -25,88 +22,91 @@ function switchPage(pageName) {
// 显示配置信息
function displayConfig() {
const configContainer = document.querySelector('.config-container');
configContainer.innerHTML = '<div class="loading">加载配置中...</div>';
// 获取当前标签页
const container = document.querySelector('.config-page .container');
container.innerHTML = '<div class="loading">加载配置中...</div>';
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
if (tabs[0]) {
// 向content script发送消息获取配置
chrome.tabs.sendMessage(tabs[0].id, {type: 'GET_CONFIG'}, response => {
if (response && response.config) {
const config = response.config;
// 构建配置页面内容
let html = '';
// API 配置
html += `
<div class="config-section">
<h4>API 路径匹配</h4>
<div class="config-item">${config.API.PATTERN}</div>
</div>
`;
// 域名配置
html += `
<div class="config-section">
<h4>域名匹配</h4>
<div class="config-item">${config.PATTERNS.DOMAIN}</div>
</div>
`;
// IP 配置
html += `
<div class="config-section">
<h4>IP 地址匹配</h4>
<div class="config-item">${config.PATTERNS.IP}</div>
</div>
`;
// 其他敏感信息匹配
html += `
<div class="config-section">
<h4>手机号码匹配</h4>
<div class="config-item">${config.PATTERNS.PHONE}</div>
</div>
<div class="config-section">
<h4>邮箱匹配</h4>
<div class="config-item">${config.PATTERNS.EMAIL}</div>
</div>
<div class="config-section">
<h4>身份证号匹配</h4>
<div class="config-item">${config.PATTERNS.IDCARD}</div>
</div>
<div class="config-section">
<h4>URL 匹配</h4>
<div class="config-item">${config.PATTERNS.URL}</div>
</div>
<div class="config-section">
<h4>JWT Token 匹配</h4>
<div class="config-item">${config.PATTERNS.JWT}</div>
</div>
<div class="config-section">
<h4>AWS Key 匹配</h4>
<div class="config-item">${config.PATTERNS.AWS_KEY}</div>
</div>
<div class="config-section">
<h4>哈希值匹配</h4>
<div class="config-item">MD5: ${config.PATTERNS.HASH.MD5}</div>
<div class="config-item">SHA1: ${config.PATTERNS.HASH.SHA1}</div>
<div class="config-item">SHA256: ${config.PATTERNS.HASH.SHA256}</div>
</div>
`;
configContainer.innerHTML = html;
} else {
configContainer.innerHTML = '<div class="error">无法加载配置</div>';
if (chrome.runtime.lastError) {
container.innerHTML = '<div class="error">无法获取配置信息</div>';
return;
}
const { config } = response;
if (!config) {
container.innerHTML = '<div class="error">配置信息为空</div>';
return;
}
// 构建配置展示HTML
let html = '<div class="config-section">';
// 添加白名单展示
html += `
<div class="config-group">
<h3>白名单域名</h3>
<div class="config-content whitelist">
${config.WHITELIST.map(domain => `<div class="whitelist-item">${domain}</div>`).join('')}
</div>
</div>
`;
// API 配置展示
html += `
<div class="config-group">
<h3>API 配置</h3>
<div class="config-content">
<div class="config-item">
<div class="config-label">路径匹配模式:</div>
<div class="config-value">${config.API.PATTERN}</div>
</div>
<div class="config-item">
<div class="config-label">静态文件模式:</div>
<div class="config-value">${config.API.STATIC_FILE_PATTERN}</div>
</div>
</div>
</div>
`;
// 域名配置展示
html += `
<div class="config-group">
<h3>域名配置</h3>
<div class="config-content">
<div class="config-item">
<div class="config-label">黑名单:</div>
<div class="config-value blacklist">
${config.DOMAIN.BLACKLIST.map(domain => `<div class="blacklist-item">${domain}</div>`).join('')}
</div>
</div>
<div class="config-item">
<div class="config-label">特殊域名:</div>
<div class="config-value">${config.DOMAIN.SPECIAL_DOMAINS.join(', ')}</div>
</div>
</div>
</div>
`;
// IP 配置展示
html += `
<div class="config-group">
<h3>IP 配置</h3>
<div class="config-content">
<div class="config-item">
<div class="config-label">内网 IP 范围:</div>
<div class="config-value">${config.IP.PRIVATE_RANGES.join('<br>')}</div>
</div>
<div class="config-item">
<div class="config-label">特殊 IP 范围:</div>
<div class="config-value">${config.IP.SPECIAL_RANGES.join('<br>')}</div>
</div>
</div>
</div>
`;
html += '</div>';
container.innerHTML = html;
});
}
});
@@ -118,89 +118,56 @@ function displayResults(results) {
const sections = [
{ id: 'domain-list', data: results.domains, title: '域名' },
{ id: 'api-list', data: results.apis, title: 'API接口' },
{ id: 'static-list', data: results.staticFiles, title: '静态文件' },
{ id: 'ip-list', data: results.ips, title: 'IP地址' },
{ id: 'port-list', data: results.ports, title: '端口号' },
{ id: 'phone-list', data: results.phones, title: '手机号码' },
{ id: 'email-list', data: results.emails, title: '邮箱' },
{ id: 'idcard-list', data: results.idcards, title: '身份证号' },
{ id: 'url-list', data: results.urls, title: 'URL' },
{ id: 'jwt-list', data: results.jwts, title: 'JWT Token' },
{ id: 'aws-list', data: results.awsKeys, title: 'AWS Key' },
{ id: 'hash-md5-list', data: results.hashes.md5, title: 'MD5哈希' },
{ id: 'hash-sha1-list', data: results.hashes.sha1, title: 'SHA1哈希' },
{ id: 'hash-sha256-list', data: results.hashes.sha256, title: 'SHA256哈希' }
{ id: 'hash-md5-list', data: results.hashes?.md5, title: 'MD5哈希' },
{ id: 'hash-sha1-list', data: results.hashes?.sha1, title: 'SHA1哈希' },
{ id: 'hash-sha256-list', data: results.hashes?.sha256, title: 'SHA256哈希' }
];
// 获取或创建容器
const container = document.querySelector('.container');
// 获取容器
const container = document.querySelector('.scanner-page .container');
let html = '';
// 遍历所有部分
sections.forEach(({ id, data, title }) => {
// 如果数据存在且不为空
if (data && data.length > 0) {
// 检查section是否已存在
let section = document.getElementById(`section-${id}`);
if (!section) {
// 如果section不存在,创建新的section
section = document.createElement('div');
section.className = 'section';
section.id = `section-${id}`;
section.innerHTML = `
html += `
<div class="section">
<div class="section-header">
<div>
<span class="title">${title}</span><span class="count">(${data.length})</span>
<span class="title">${title} <span class="count">(${data.length})</span></span>
</div>
<div class="section-content">
<div class="content-wrapper ${id}">
${Array.from(data).map(item => `
<div class="item" title="${item}">
${item}
</div>
`).join('')}
</div>
<button class="copy-all-btn" title="复制所有${title}">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16 3H4C3.45 3 3 3.45 3 4V16C3 16.55 3.45 17 4 17H16C16.55 17 17 16.55 17 16V4C17 3.45 16.55 3 16 3ZM15 15H5V5H15V15Z" fill="currentColor"/>
<path d="M20 7H18V19H6V21C6 21.55 6.45 22 7 22H20C20.55 22 21 21.55 21 21V8C21 7.45 20.55 7 20 7Z" fill="currentColor"/>
</svg>
</button>
</div>
<div class="section-content ${id}" id="${id}">
<div class="content-wrapper"></div>
</div>
`;
container.appendChild(section);
// 添加复制所有按钮功能
section.querySelector('.copy-all-btn').addEventListener('click', () => {
const allText = data.join('\n');
copyText(allText, section.querySelector('.copy-all-btn'), '已复制全部');
});
} else {
// 如果section已存在,更新计数
section.querySelector('.count').textContent = `(${data.length})`;
}
// 更新内容
const contentWrapper = section.querySelector('.content-wrapper');
const existingItems = new Set(Array.from(contentWrapper.children).map(el => el.getAttribute('data-full-text')));
// 添加新项
data.forEach(item => {
if (!existingItems.has(item)) {
const itemDiv = document.createElement('div');
itemDiv.className = 'item';
itemDiv.setAttribute('data-full-text', item);
itemDiv.title = item;
itemDiv.textContent = item;
// 添加右键复制功能
itemDiv.addEventListener('contextmenu', (e) => {
e.preventDefault();
copyText(item, itemDiv, '已复制');
});
contentWrapper.appendChild(itemDiv);
}
});
</div>
`;
}
});
// 移除loading状态
const loading = container.querySelector('.loading');
if (loading) {
loading.remove();
// 如果没有任何结果
if (!html) {
html = '<div class="no-results">未发现敏感信息</div>';
}
// 更新容器内容
container.innerHTML = html;
// 处理长文本
handleLongText();
}
// 显示复制成功的提示框
@@ -249,6 +216,18 @@ function copyText(text, element, message) {
// 页面加载完成时的初始化
document.addEventListener('DOMContentLoaded', () => {
// 获取当前激活的页面
const activePage = document.querySelector('.nav-tab.active').dataset.page;
// 初始化页面显示
document.querySelectorAll('.page').forEach(page => {
if (page.classList.contains(`${activePage}-page`)) {
page.classList.add('active');
} else {
page.classList.remove('active');
}
});
// 添加导航标签点击事件
document.querySelectorAll('.nav-tab').forEach(tab => {
tab.addEventListener('click', () => {
@@ -256,8 +235,28 @@ document.addEventListener('DOMContentLoaded', () => {
});
});
// 添加刷新按钮点击事件
document.querySelector('.refresh-btn').addEventListener('click', () => {
const container = document.querySelector('.scanner-page .container');
container.innerHTML = '<div class="loading">正在扫描...</div>';
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
if (tabs[0]) {
chrome.tabs.sendMessage(tabs[0].id, {type: 'REFRESH_SCAN'}, response => {
if (chrome.runtime.lastError) {
container.innerHTML = '<div class="error">无法连接到页面</div>';
} else if (response === 'WHITELISTED') {
container.innerHTML = '<div class="whitelisted">当前域名在白名单中,已跳过扫描</div>';
} else if (response) {
displayResults(response);
}
});
}
});
});
// 初始化扫描页面
const container = document.querySelector('.container');
const container = document.querySelector('.scanner-page .container');
container.innerHTML = '<div class="loading">正在扫描...</div>';
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
@@ -265,32 +264,14 @@ document.addEventListener('DOMContentLoaded', () => {
chrome.tabs.sendMessage(tabs[0].id, {type: 'GET_RESULTS'}, response => {
if (chrome.runtime.lastError) {
container.innerHTML = '<div class="error">无法连接到页面</div>';
} else if (response === 'WHITELISTED') {
container.innerHTML = '<div class="whitelisted">当前域名在白名单中,已跳过扫描</div>';
} else if (response) {
displayResults(response);
}
});
}
});
window.addEventListener('resize', handleLongText);
});
// 刷新按钮点击事件处理
document.querySelector('.refresh-btn').addEventListener('click', () => {
const container = document.querySelector('.container');
// 显示加载状态
container.innerHTML = '<div class="loading">正在扫描...</div>';
// 触发重新扫描
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
if (tabs[0]) {
chrome.tabs.sendMessage(tabs[0].id, {type: 'REFRESH_SCAN'}, response => {
if (response) {
displayResults(response);
}
});
}
});
});
// 监听来自 content script 的消息