在安全测试工作中,针对web系统的访问url进行收集,不论是作为接口fuzz字典还是用来接口漏洞扫描检测都是非常关键的一步,因此一款适合自己的chrome插件可以帮助你获取自己需要的接口,并进行深入利用和漏洞挖掘,本篇文章主要介绍一款个人使用chrome插件的设计和详细代码。
一、插件功能概述
这款 Chrome 浏览器插件主要具备以下核心功能:
- URL 筛选:用户可以在插件弹出窗口的输入框中输入目标域名,点击 “开始” 按钮后,插件会监听所有网络请求,筛选出包含该域名的 URL。
- URL 去重:在筛选过程中,插件会自动对匹配到的 URL 进行去重处理,确保最终保存的 URL 列表中每个 URL 只出现一次。
- 排除特定后缀的URL:插件会排除以
.css
、.png
、.jpg
、.svg
、.gif
、.ico
、.woff2
为后缀的 URL,避免将这些静态资源的链接包含在结果中。 - URL 保存:点击 “结束” 按钮后,插件会将筛选并去重后的 URL 保存到本地的
urls.txt
文件中。 - 状态保持:在点击 “开始” 按钮后,即使关闭再打开插件窗口,输入框中的域名和按钮状态也会保持不变,方便用户继续操作。
二、代码结构与文件功能
整个插件由以下几个文件组成:
manifest.json
:插件的清单文件,用于声明插件的基本信息、权限、弹出窗口页面和后台脚本等。popup.html
:插件的弹出窗口页面,包含一个输入框用于输入目标域名,以及 “开始” 和 “结束” 按钮。popup.js
:负责处理弹出窗口的交互逻辑,包括按钮点击事件、状态保存和恢复等。background.js
:插件的后台脚本,负责监听网络请求、筛选和去重 URL、保存 URL 到本地文件等核心功能。
三、各文件详细设计思路与代码分析
1.manifest.json
{
"manifest_version": 3,
"name": "ASUrls",
"version": "1.0",
"description": "Filter URLs By Alan",
"permissions": ["webRequest", "storage", "downloads"],
"host_permissions": ["<all_urls>"],
"action": {
"default_popup": "popup.html"
},
"background": {
"service_worker": "background.js"
}
}
设计思路:
manifest_version
指定为 3,遵循 Chrome 扩展的最新规范。permissions
声明了插件所需的权限,包括webRequest
用于监听网络请求,storage
用于保存和恢复插件状态,downloads
用于将 URL 保存到本地文件。host_permissions
设置为<all_urls>
,表示插件可以监听所有域名的网络请求。action
字段指定了插件的弹出窗口页面为popup.html
。background
字段指定了插件的后台脚本为background.js
。
2.popup.html
<htmllang="en">
<head>
<metacharset="UTF-8">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>URL Filter</title>
</head>
<body>
<inputtype="text"id="domain-input"placeholder="输入域名">
<buttonid="start-button">开始</button>
<buttonid="end-button"disabled>结束</button>
<scriptsrc="popup.js"></script>
</body>
</html>
设计思路:
- 创建一个简单的 HTML 页面,包含一个输入框和两个按钮。
- 引入
popup.js
脚本,用于处理按钮的交互逻辑。
3.popup.js
document.addEventListener('DOMContentLoaded', function () {
const domainInput = document.getElementById('domain-input');
const startButton = document.getElementById('start-button');
const endButton = document.getElementById('end-button');
// 从存储中恢复状态
chrome.storage.local.get(['domain', 'isRecording'], function (result) {
const domain = result.domain;
const isRecording = result.isRecording;
if (domain) {
domainInput.value = domain;
}
if (isRecording) {
startButton.disabled = true;
endButton.disabled = false;
domainInput.disabled = true;
}
});
startButton.addEventListener('click', function () {
const domain = domainInput.value.trim();
if (domain) {
chrome.runtime.sendMessage({ action: 'start', domain: domain });
startButton.disabled = true;
endButton.disabled = false;
domainInput.disabled = true;
// 保存状态到存储
chrome.storage.local.set({ domain: domain, isRecording: true });
}
});
endButton.addEventListener('click', function () {
chrome.runtime.sendMessage({ action: 'end' });
startButton.disabled = false;
endButton.disabled = true;
domainInput.disabled = false;
domainInput.value = '';
// 清除存储的状态
chrome.storage.local.remove(['domain', 'isRecording']);
});
});
设计思路:
- 监听
DOMContentLoaded
事件,确保页面加载完成后再绑定事件。 - 从
chrome.storage.local
中获取之前保存的域名和记录状态,并恢复输入框和按钮的状态。 - 点击 “开始” 按钮时,获取输入框中的域名,向后台脚本发送
start
消息,禁用开始按钮和输入框,启用结束按钮,并将当前状态保存到chrome.storage.local
。 - 点击 “结束” 按钮时,向后台脚本发送
end
消息,恢复按钮和输入框的状态,清空输入框内容,并清除chrome.storage.local
中保存的状态。
4.background.js
let targetDomain = '';
let isRecording = false;
const matchedUrls = new Set();
const excludedExtensions = ['.css', '.png', '.jpg', '.svg', '.gif', '.ico', '.woff2'];
// 从存储中恢复状态
chrome.storage.local.get(['domain', 'isRecording'], function (result) {
const domain = result.domain;
const storedIsRecording = result.isRecording;
if (domain) {
targetDomain = domain;
}
if (storedIsRecording) {
isRecording = true;
}
});
// 监听所有 HTTP 请求
chrome.webRequest.onBeforeRequest.addListener(
function (details) {
if (isRecording && details.url.includes(targetDomain)) {
const url = details.url;
const hasExcludedExtension = excludedExtensions.some(ext => url.endsWith(ext));
if (!hasExcludedExtension &&!matchedUrls.has(url)) {
console.log('Matched URL:', url);
matchedUrls.add(url);
}
}
},
{ urls: ["<all_urls>"] }
);
// 监听来自弹出窗口的消息
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
if (message.action === 'start') {
targetDomain = message.domain;
isRecording = true;
// 保存状态到存储
chrome.storage.local.set({ domain: targetDomain, isRecording: true });
} else if (message.action === 'end') {
isRecording = false;
// 清除存储的状态
chrome.storage.local.remove(['domain', 'isRecording']);
saveUrlsToFile();
// 清空匹配的 URL 集合
matchedUrls.clear();
}
});
function saveUrlsToFile() {
const urlArray = Array.from(matchedUrls);
const urlText = urlArray.join('n');
const blob = new Blob([urlText], { type: 'text/plain' });
const reader = new FileReader();
reader.onload = function (event) {
const dataUrl = event.target.result;
chrome.downloads.download({
url: dataUrl,
filename: 'urls.txt',
saveAs: false
}, function (downloadId) {
if (chrome.runtime.lastError) {
console.error('Error downloading file:', chrome.runtime.lastError);
}
});
};
reader.readAsDataURL(blob);
}
设计思路:
- 状态管理:使用
targetDomain
存储目标域名,isRecording
标记是否正在进行 URL 筛选,matchedUrls
是一个Set
对象,用于存储筛选并去重后的 URL,excludedExtensions
数组存储要排除的文件后缀。 - 状态恢复:在脚本启动时,从
chrome.storage.local
中获取之前保存的域名和记录状态,并恢复相应的变量值。 - 网络请求监听:使用
chrome.webRequest.onBeforeRequest
监听所有网络请求,当处于记录状态且 URL 包含目标域名时,检查 URL 是否以排除的后缀结尾,若不是且 URL 不在matchedUrls
集合中,则将其添加到集合中并打印到控制台。 - 消息监听:使用
chrome.runtime.onMessage
监听来自弹出窗口的消息,根据消息的action
字段执行相应操作。收到start
消息时,更新目标域名和记录状态,并保存到chrome.storage.local
;收到end
消息时,停止记录,清除存储的状态,调用saveUrlsToFile
函数保存 URL 到本地文件,并清空matchedUrls
集合。 - 保存 URL 到文件:
saveUrlsToFile
函数将matchedUrls
集合转换为数组,将数组元素用换行符连接成字符串,创建Blob
对象,使用FileReader
将其转换为Data URL
,最后使用chrome.downloads.download
方法将 URL 保存到本地的urls.txt
文件中。
四、使用步骤
chrome://extensions/
。matchedUrls
集合中。urls.txt
文件,并清空 matchedUrls
集合,以便下次使用。通过结束按钮,即可实现对url中包含该域名的url进行了保存并下下载,当然,大家可以再次筛选,对获取的url中域名的位置进行限制,排除一些我们不需要的url信息,使工具更符合我们的需求。
原文始发于微信公众号(白帽少年):手搓chrome插件帮你实现url收集
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论