├── .DS_Store
├── img
└── logo.png
├── README.md
├── manifest.json
├── popup.js
├── popup.html
└── background.js
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cnrstar/anti-honeypot/HEAD/.DS_Store
--------------------------------------------------------------------------------
/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cnrstar/anti-honeypot/HEAD/img/logo.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 更新
2 | V1.0.2:
3 | 增加个启动/暂定按钮
4 | 优化了一些代码实现逻辑
5 | 加个版本更新提示
6 | # 背景
7 | + 在真实攻防演习中,蓝队不再像以前只是被动防守,而是慢慢开始转变到主动出击的角色。对蓝队反制红队帮助最大的想来非蜜罐莫属,现在的商业蜜罐除了会模拟一个虚拟的靶机之外,还承担了一个很重要的任务:溯源黑客真实身份。相当一部分黑客因为浏览器没开隐身模式导致被利用jsonhijack漏洞抓到真实ID,虽然可以反手一个举报到src换积分,但是在漏洞修复之前,又是一批战友被溯源。相信很对已经被溯源的红方选手对此更有体会。
8 | + 在这种背景下,各位红方老司机应当很需要一个能自动识别这种WEB蜜罐,因此我们写了个简单的chrome插件,用来帮助我们摆脱被溯源到真实ID的困境。插件有两个功能,一是识别当前访问的网站是否是蜜罐,是的话就弹框预警;二是对访问的jsonp接口进行重置,防止对方获取到真实ID。所采用的原理非常简单粗暴,就是判断当前网站域和jsonp接口的域是否是同一个,是的话就预警并阻断。比如我访问一个`http://1.2.3.4/`的网站,结果这个网站里的js去请求了一个baidu.com的api,那妥妥的有问题了。但是粗暴判断也会带来误报,比如我正常访问`baidu.com`,但是其引用了个`apibaidu.com`的jsonp,就一样也会报警和拦截,这种情况下就暂时用白名单来解决了。
9 | # 使用
10 | + 打开chrome的插件管理 chrome://extensions/。
11 | + 打开开发者模式,并点击”加载已解压的扩展程序”,选择对应的目录导入即可
12 |
13 | # TODO
14 | + 加入jsonp漏洞的自动挖掘
15 | + 借鉴另外一个[项目](https://github.com/iiiusky/AntiHoneypot-Chrome-simple)的通过特定js脚本名称和内容识别已知厂商的蜜罐
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Anti-HoneyPot[By-MegaVector]",
3 | "version": "1.0.2",
4 | "manifest_version": 2,
5 | "description": "",
6 | "icons": {
7 | "128": "/img/logo.png"
8 | },
9 | "browser_action": {
10 | "default_popup": "popup.html",
11 | "default_title": "Anti-HoneyPot[By-MegaVector]",
12 | "default_icon": "./img/logo.png"
13 | },
14 | "background": {
15 | "persistent": true,
16 | "scripts": [
17 | "background.js"
18 | ]
19 | },
20 | "permissions": [
21 | "notifications",
22 | "activeTab",
23 | "tabs",
24 | "storage",
25 | "https://*/*",
26 | "http://*/*",
27 | "webRequest",
28 | "webRequestBlocking"
29 | ],
30 | "web_accessible_resources": ["*"],
31 | "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
32 | }
--------------------------------------------------------------------------------
/popup.js:
--------------------------------------------------------------------------------
1 | // popup.js
2 |
3 | // 初始化插件状态为已启动
4 | let isEnabled = true;
5 |
6 | // 从 storage 中读取插件状态
7 | chrome.storage.sync.get('isEnabled', function(data) {
8 | // 如果之前存储了状态,则使用该状态,否则默认为已启动
9 | isEnabled = data.isEnabled !== undefined ? data.isEnabled : true;
10 | updateButtonAndStatus();
11 | });
12 |
13 | // 更新按钮文本和状态显示
14 | function updateButtonAndStatus() {
15 | const toggleButton = document.getElementById('toggleButton');
16 | const statusElement = document.getElementById('status');
17 | if (isEnabled) {
18 | toggleButton.textContent = '暂停插件';
19 | statusElement.textContent = '当前状态: 运行中';
20 | } else {
21 | toggleButton.textContent = '启动插件';
22 | statusElement.textContent = '当前状态: 已暂停';
23 | }
24 | }
25 |
26 | // 切换插件状态
27 | function toggleExtension() {
28 | isEnabled = !isEnabled;
29 | updateButtonAndStatus();
30 | // 存储新的插件状态
31 | chrome.storage.sync.set({isEnabled: isEnabled}, function() {
32 | // 发送消息给 background.js 更新插件状态
33 | chrome.runtime.sendMessage({action: "toggleExtension", enabled: isEnabled});
34 | });
35 | }
36 |
37 | // 为按钮添加点击事件监听器
38 | document.getElementById('toggleButton').addEventListener('click', toggleExtension);
39 |
--------------------------------------------------------------------------------
/popup.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 蜜罐检测插件
7 |
47 |
48 |
49 |
50 |
蜜罐检测插件
51 |
已拦截蜜罐数量: 0
52 |
53 |
当前状态: 已启动
54 |
版本 V1.01
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/background.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | // 初始化插件状态和计数器
3 | let isEnabled = true;
4 |
5 | const currentVersion = chrome.runtime.getManifest().version;
6 | // 更新检查地址
7 | const updateUrl = 'http://chatcs.megavector.cn/antihonypot.txt';
8 |
9 | // 当插件安装或更新时,或者Chrome启动时,检查更新
10 | chrome.runtime.onInstalled.addListener(() => {
11 | checkForUpdate();
12 | });
13 |
14 | chrome.runtime.onStartup.addListener(() => {
15 | checkForUpdate();
16 | });
17 |
18 | // 检查更新的函数
19 | function checkForUpdate() {
20 | fetch(updateUrl)
21 | .then(response => response.text())
22 | .then(text => {
23 | // 假设txt文件内容是形如 "1.0.0" 的版本号字符串
24 | const latestVersion = text.trim();
25 | const v2 = parseInt(latestVersion.replace(/\./g, ''));
26 | const v1 = parseInt(currentVersion.replace(/\./g, ''));
27 | // 比较版本号,这里使用了简单的字符串比较,实际应用中可能需要更复杂的版本比较逻辑
28 | if (v2 > v1) {
29 | notifyUserToUpdate(latestVersion);
30 | }
31 | })
32 | .catch(error => {
33 | console.log('Error checking for update:', error);
34 | });
35 | }
36 |
37 | // 通知用户更新的函数
38 | function notifyUserToUpdate(latestVersion) {
39 | const options = {
40 | type: 'basic',
41 | iconUrl: 'img/logo.png', // 插件的图标
42 | title: '插件更新可用',
43 | message: `发现新版本 ${latestVersion},请访问插件页面下载更新。`
44 | };
45 |
46 | chrome.notifications.create('updateNotification', options, () => {});
47 | }
48 |
49 | // 监听通知点击事件,当用户点击通知时,可以打开插件的页面
50 | chrome.notifications.onClicked.addListener(notificationId => {
51 | if (notificationId === 'updateNotification') {
52 | chrome.tabs.create({ url: 'chrome://extensions/' });
53 | }
54 | });
55 |
56 |
57 | // 假设这是你用于处理网络请求的监听函数
58 | function handleWebRequest(details) {
59 | //url:当前的url;initiator:浏览器状态栏里的domain
60 | let {
61 | url,
62 | initiator
63 | } = details;
64 |
65 | //如果发起者为空,直接赋值url
66 | if (typeof (initiator) == "undefined") {
67 | initiator = url;
68 | }
69 | const protocal = url.split("://")[0];
70 |
71 | //根据url返回域名和对应的path
72 | function GetHostAndPath(url) {
73 | const urlObj = new URL(url);
74 | return [urlObj.hostname, urlObj.pathname + urlObj.search];
75 | }
76 |
77 | //根据url获取主域名
78 | function get_domain(url){
79 | if (!url) return null;
80 | var re_domain = /([a-zA-Z0-9-]+)(?:.com\b|.net\b|.edu\b|.miz\b|.biz\b|.cn\b|.cc\b|.org\b)/;
81 | var domain = url.match(re_domain);
82 | return domain ? domain[0] : null;
83 | }
84 | //判断host是否在黑名单内
85 | function inBlackList(host) {
86 | //黑名单host来自长亭D-sensor的溯源api,共47个
87 | const BlackList = ["account.itpub.net", "accounts.ctrip.com", "ajax.58pic.com", "api.csdn.net", "api.ip.sb", "api.passport.pptv.com", "bbs.zhibo8.cc", "bit.ly", "blog.csdn.net", "blog.itpub.net", "c.v.qq.com", "chinaunix.net", "cmstool.youku.com", "comment.api.163.com", "databack.dangdang.com", "dimg01.c-ctrip.com", "down2.uc.cn", "github.com", "hd.huya.com", "home.51cto.com", "home.ctfile.com", "home.zhibo8.cc", "hudong.vip.youku.com", "i.jrj.com.cn", "iask.sina.com.cn", "itunes.apple.com", "m.ctrip.com", "m.game.weibo.cn", "mapp.jrj.com.cn", "my.zol.com.cn","passport.ctrip.com", "passport.game.renren.com", "passport.iqiyi.com", "playbill.api.mgtv.com", "renren.com", "skylink.io", "u.faloo.com", "ucenter.51cto.com", "v.huya.com", "v2.sohu.com", "vote2.pptv.com", "wap.sogou.com", "webapi.ctfile.com", "weibo.com", "www.58pic.com", "www.iqiyi.com", "www.iteye.com", "www.zbj.com", "www.cndns.com", "mozilla.github.io", "www.sitestar.cn", "api.fastadmin.net", "m.site.baidu.com", "restapi.amap.com", "login.sina.com.cn", "now.qq.com", "message.dangdang.com", "musicapi.taihe.com", "api-live.iqiyi.com", "api.m.jd.com", "tie.163.com", "pcw-api.iqiyi.com", "so.v.ifeng.com", "passport.baidu.com", "wz.cnblogs.com", "passport.cnblogs.com", "hzs14.cnzz.com", "mths.be", "validity.thatscaptaintoyou.com", "stc.iqiyipic.com", "s14.cnzz.com", "sb.scorecardresearch.com", "js.cndns.com", "datax.baidu.com", "assets.growingio.com", "www.gnu.org", "wappassalltest.baidu.com", "baike.baidu.com", "ka.sina.com.cn", "p.qiao.baidu.com", "map.baidu.com", "www.dangdang.com", "g.alicdn.com", "s.faloo.com", "msg.qy.net", "morn.cndns.com", "i.qr.weibo.cn", "github.comgithub.com", "uis.i.sohu.com", "www.tianya.cn", "passport.mop.com", "commapi.dangdang.com", "comment.money.163.com", "chaxun.1616.net", "tieba.baidu.com", "remind.hupu.com", "service.bilibili.com", "node.video.qq.com", "api.weibo.com", "www.jiyoujia.com"];
88 | for (const BlackSite of BlackList) {
89 | if (host == BlackSite) {
90 | return true;
91 | }
92 | }
93 | return false;
94 | }
95 |
96 | var mainDomain = get_domain(initiator); //发起者的主域名
97 | var targetHost = GetHostAndPath(url)[0]; //跨域或本域访问的目标主机
98 | var targetPath = GetHostAndPath(url)[1]; //跨域或本域访问的目标路径
99 | var targetDomain = get_domain(url) //目标主域名
100 |
101 | const WhiteList = ['baidu.com', 'qq.com', 'csdn.net', 'weibo.com', 'cnblogs.com','aliyun.com','ctrip.com','weibo.cn','iqiyi.com','163.com','126.com','51cto.com','taobao.com','sogou.com','iteye.com','58.com','google.com','fofa.so','jd.com','tmall.com','github.io','github.com','sina.com.cn','mi.com'] //白名单
102 | for (var WhiteSite of WhiteList) {
103 | if (mainDomain == WhiteSite) {
104 | console.log('命中白名单'+mainDomain);
105 | return;
106 | }
107 | }
108 |
109 | let redirectUrl;
110 |
111 | if (mainDomain == targetDomain) { //如果相等表示正常域内访问
112 | console.log(targetDomain);
113 | } else { //如果不相等,可能是跨域访问,需要继续判断
114 | const blockQueryStringList = ['callback', 'jsonp', 'javascript'];
115 | for (const q of blockQueryStringList) {
116 | if (protocal == 'http' || protocal == 'https') {
117 | if (q && targetPath.includes(q)) {
118 | redirectUrl = 'data:text/javascript;charset=UTF-8;base64,' + btoa(`;`);
119 | if (inBlackList(targetHost)) {
120 | // 黑名单拦截
121 | new Notification('拦截黑名单' + targetHost);
122 | } else {
123 | // 普通拦截
124 | new Notification('拦截可疑溯源请求:' + targetHost);
125 | }
126 | }
127 | }
128 | }
129 |
130 | }
131 | if (redirectUrl) return {
132 | redirectUrl
133 | }
134 | else return {};
135 | }
136 |
137 |
138 | // 设置监听器
139 | chrome.webRequest.onBeforeRequest.addListener(
140 | handleWebRequest,
141 | {
142 | urls: [""]
143 | },
144 | ["blocking"]
145 | );
146 |
147 |
148 | // 接收来自 popup.html 的消息
149 | chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
150 | if (message.action === "toggleExtension") {
151 | isEnabled = message.enabled;
152 | if (isEnabled) {
153 | // 如果插件之前被禁用,重新添加监听器
154 | chrome.webRequest.onBeforeRequest.addListener(
155 | handleWebRequest,
156 | {
157 | urls: [""]
158 | },
159 | ["blocking"]
160 | );
161 | } else {
162 | // 如果插件被禁用,移除监听器
163 | chrome.webRequest.onBeforeRequest.removeListener(handleWebRequest);
164 | }
165 | }
166 | });
167 |
168 | // 其他 background.js 代码逻辑...
169 |
--------------------------------------------------------------------------------