├── README.md ├── background.js ├── content.js ├── icons ├── icon128.png ├── icon16.png └── icon48.png ├── img ├── image-20250206084931280.png └── image-20250206091434993.png ├── manifest.json ├── popup.html └── popup.js /README.md: -------------------------------------------------------------------------------- 1 | # Jssx 🚬🚬 by Yn8rt 2 | 3 | ## 写在前面 4 | 5 | **收啥费,不收费,这也能割?** 6 | 7 | **没事大家可以多分享一下,前几天想回去找一篇文章,结果发现撤回了,这搞的,越来越~~**😶 8 | 9 | **有什么不足的地方希望大家及时告诉我,或者有做二次开发记得@我一下** 10 | 11 | ## 项目简介 12 | 13 | 对 20 | - 分析页面可以利用的参数:有action属性的form表单,a标签herf属性值 21 | 22 | ## 安装与使用 23 | 24 | 1. **安装插件**:将插件**文件夹**托到浏览器的扩展程序中就ok了(目前只支持chrome内核的浏览器)。 25 | 2. **使用插件**:点击浏览器工具栏中的插件图标,输入自定义payload。 26 | 3. **查看结果**:扫描完成后,插件会在弹出窗口中显示检测结果,标明发现的敏感参数。 27 | 28 | ![image-20250206084931280](img/image-20250206084931280.png) 29 | 30 | ## 开发者 31 | 32 | 该插件由 Yn8rt 开发,旨在提高网页安全性,帮助开发者及时发现并修复敏感信息泄露问题。 33 | 34 | 如需更多信息或有任何疑问,请参阅项目文档或联系开发者。 -------------------------------------------------------------------------------- /background.js: -------------------------------------------------------------------------------- 1 | chrome.webRequest.onBeforeRequest.addListener(function (request) { 2 | console.log("Intercepted request URL:", request.url); 3 | if (!request.url.startsWith("chrome-extension://")) { 4 | { 5 | chrome.tabs.query({ 6 | active: true, 7 | currentWindow: true 8 | }, function (tabs) { 9 | chrome.tabs.sendMessage(tabs[0].id, { 10 | action: "addParameter", 11 | url: request.url 12 | }); 13 | }); 14 | } 15 | } 16 | }, { 17 | urls: [""] 18 | }, ["blocking"]); -------------------------------------------------------------------------------- /content.js: -------------------------------------------------------------------------------- 1 | const parametersSet = new Set(); 2 | let scanScheduled = false; 3 | 4 | //下面是针对的标签,这里只有a的herf标签和form标签 5 | function extractParameters() { 6 | const anchorElements = document.querySelectorAll("a[href]"); 7 | anchorElements.forEach((anchorElement) => { 8 | try { 9 | const urlObject = new URL(anchorElement.href); 10 | if (!urlObject.href.startsWith("chrome-extension://")) { 11 | const pathname = urlObject.pathname; 12 | const searchParams = new URLSearchParams(urlObject.search); 13 | for (const [key, value] of searchParams.entries()) { 14 | parametersSet.add( 15 | "" + 16 | urlObject.origin + 17 | pathname + 18 | "?" + 19 | key + 20 | "=" + 21 | value 22 | ); 23 | } 24 | } 25 | } catch (error) { 26 | console.error("处理 URL 时出错:", anchorElement.href, error); 27 | } 28 | }); 29 | 30 | const formElements = document.querySelectorAll("form"); 31 | formElements.forEach((formElement) => { 32 | try { 33 | const formData = new FormData(formElement); 34 | for (const [key, value] of formData.entries()) { 35 | if ( 36 | formElement.action && 37 | !formElement.action.startsWith("chrome-extension://") 38 | ) { 39 | parametersSet.add( 40 | formElement.action + "?" + key + "=" + value 41 | ); 42 | } 43 | } 44 | } catch (error) { 45 | console.error("处理表单时出错:", formElement, error); 46 | } 47 | }); 48 | 49 | // 发送所有收集到的参数 50 | chrome.runtime.sendMessage({ 51 | action: "sendParameters", 52 | parameters: Array.from(parametersSet), 53 | }); 54 | } 55 | 56 | function scheduleScan(delay) { 57 | if (!scanScheduled) { 58 | scanScheduled = true; 59 | setTimeout(() => { 60 | extractParameters(); 61 | scanScheduled = false; 62 | }, delay); 63 | } 64 | } 65 | 66 | // 初始扫描 67 | extractParameters(); 68 | 69 | // 延迟扫描(500ms 后) 70 | scheduleScan(500); 71 | 72 | // 再次延迟扫描(1s 后) 73 | scheduleScan(1000); 74 | 75 | // 使用 MutationObserver 监控文档变化 76 | const observer = new MutationObserver(extractParameters); 77 | observer.observe(document.body, { childList: true, subtree: true }); 78 | 79 | document.addEventListener("click", function (event) { 80 | if ( 81 | event.target && 82 | event.target.id === "forgotPassword" 83 | ) { 84 | setTimeout(extractParameters, 100); 85 | } 86 | }); 87 | 88 | chrome.runtime.onMessage.addListener(function ( 89 | message, 90 | sender, 91 | sendResponse 92 | ) { 93 | if (message.action === "getAllParameters") { 94 | sendResponse({ parameters: Array.from(parametersSet) }); 95 | } else if (message.action === "addParameter") { 96 | parametersSet.add(message.url); 97 | } 98 | }); -------------------------------------------------------------------------------- /icons/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yn8rt/Jssx/75bcd98cfd6b7d9c069f18d94ff37c8a18875d31/icons/icon128.png -------------------------------------------------------------------------------- /icons/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yn8rt/Jssx/75bcd98cfd6b7d9c069f18d94ff37c8a18875d31/icons/icon16.png -------------------------------------------------------------------------------- /icons/icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yn8rt/Jssx/75bcd98cfd6b7d9c069f18d94ff37c8a18875d31/icons/icon48.png -------------------------------------------------------------------------------- /img/image-20250206084931280.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yn8rt/Jssx/75bcd98cfd6b7d9c069f18d94ff37c8a18875d31/img/image-20250206084931280.png -------------------------------------------------------------------------------- /img/image-20250206091434993.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yn8rt/Jssx/75bcd98cfd6b7d9c069f18d94ff37c8a18875d31/img/image-20250206091434993.png -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "Js🚬XSS🚬Fuzzer", 4 | "version": "1.0", 5 | "description": "Jssx🚬🚬by Yn8rt", 6 | "permissions": ["activeTab", "declarativeContent", "storage", "webRequest", "webRequestBlocking", "*://*/*"], 7 | "background": { 8 | "scripts": ["background.js"] 9 | }, 10 | "browser_action": { 11 | "default_popup": "popup.html", 12 | "default_icon": { 13 | "16": "icons/icon16.png", 14 | "48": "icons/icon48.png", 15 | "128": "icons/icon128.png" 16 | } 17 | }, 18 | "icons": { 19 | "16": "icons/icon16.png", 20 | "48": "icons/icon48.png", 21 | "128": "icons/icon128.png" 22 | }, 23 | "content_scripts": [ 24 | { 25 | "matches": [""], 26 | "js": ["content.js"] 27 | } 28 | ] 29 | } -------------------------------------------------------------------------------- /popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Jssx🚬🚬 7 | 148 | 149 | 150 | 165 | 166 | 167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /popup.js: -------------------------------------------------------------------------------- 1 | document.addEventListener("DOMContentLoaded", function () { 2 | const resultsContainer = document.getElementById("results"), 3 | payloadInput = document.getElementById("payloadInput"), 4 | savePayloadBtn = document.getElementById("savePayloadBtn"); 5 | 6 | mainContainer.style.display = "block"; 7 | loadParameters(); 8 | 9 | function loadParameters() { 10 | chrome.tabs.query({ 11 | active: true, 12 | currentWindow: true 13 | }, function (tabs) { 14 | chrome.tabs.sendMessage(tabs[0].id, { 15 | action: "getAllParameters" 16 | }, function (response) { 17 | resultsContainer.innerHTML = ""; 18 | if (response && response.parameters && response.parameters.length > 0) { 19 | response.parameters.forEach(param => { 20 | const paramItem = document.createElement("li"); 21 | paramItem.className = "param-item"; 22 | if (typeof param === "string") { 23 | if (param.startsWith("http") || param.startsWith("https")) { 24 | paramItem.innerHTML = ` 25 | ${param} 26 | 27 | `; 28 | paramItem.querySelector(".open-btn").addEventListener("click", function () { 29 | chrome.tabs.create({ 30 | url: param 31 | }); 32 | }); 33 | } else { 34 | paramItem.textContent = param; 35 | } 36 | } else { 37 | paramItem.textContent = JSON.stringify(param); 38 | } 39 | resultsContainer.appendChild(paramItem); 40 | }); 41 | } else { 42 | const noParams = document.createElement("li"); 43 | noParams.className = "no-params"; 44 | noParams.textContent = "没找到参数,来一根吧🚬"; 45 | resultsContainer.appendChild(noParams); 46 | 47 | const spacer = document.createElement("div"); 48 | spacer.style.height = "100px"; 49 | resultsContainer.appendChild(spacer); 50 | } 51 | }); 52 | }); 53 | } 54 | 55 | chrome.storage.local.get("xssPayload", function (data) { 56 | if (data.xssPayload) { 57 | payloadInput.value = data.xssPayload; 58 | } 59 | }); 60 | 61 | savePayloadBtn.addEventListener("click", function () { 62 | const payload = payloadInput.value.trim(); 63 | if (payload) { 64 | chrome.storage.local.set({ 65 | xssPayload: payload 66 | }, function () { 67 | showNotification("Payload 已保存"); 68 | }); 69 | } 70 | }); 71 | 72 | document.querySelector(".refresh-btn").addEventListener("click", function () { 73 | chrome.tabs.query({ 74 | active: true, 75 | currentWindow: true 76 | }, function (tabs) { 77 | chrome.tabs.reload(tabs[0].id); 78 | }); 79 | }); 80 | 81 | document.querySelector(".xss-btn").addEventListener("click", function () { 82 | chrome.storage.local.get("xssPayload", function (data) { 83 | const xssPayload = data.xssPayload || ""; 84 | chrome.tabs.query({ 85 | active: true, 86 | currentWindow: true 87 | }, function (tabs) { 88 | chrome.tabs.sendMessage(tabs[0].id, { 89 | action: "getAllParameters" 90 | }, function (response) { 91 | if (response && response.parameters && response.parameters.length > 0) { 92 | response.parameters.forEach(param => { 93 | const url = new URL(param); 94 | const params = new URLSearchParams(url.search); 95 | for (const key of params.keys()) { 96 | params.set(key, xssPayload); 97 | } 98 | const newUrl = `${url.origin}${url.pathname}?${params.toString()}`; 99 | chrome.tabs.create({ 100 | url: newUrl 101 | }); 102 | }); 103 | } 104 | }); 105 | }); 106 | }); 107 | }); 108 | 109 | // 显示通知函数 110 | function showNotification(message) { 111 | const notification = document.createElement('div'); 112 | notification.className = 'notification'; 113 | notification.textContent = message; 114 | document.body.appendChild(notification); 115 | 116 | setTimeout(() => { 117 | notification.remove(); 118 | }, 3000); 119 | } 120 | }); --------------------------------------------------------------------------------