Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jayus0821 committed Jun 19, 2021
1 parent d909902 commit d3cd80d
Show file tree
Hide file tree
Showing 8 changed files with 425 additions and 2 deletions.
94 changes: 92 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,92 @@
# Armor
Armor 浏览器反蜜罐插件
# 蜜罐溯源技术原理


蜜罐溯源这部分用到的技术主要是jsonp
jsonp全称是 JSON with Padding ,是基于 JSON 格式的为解决跨域请求资源而产生的解决方案。


如果某些站点存在jsonp劫持漏洞,如web1这个站点有个jsonp接口暴露者,功能就是返回用户的姓名:
```php
<?php
$callback = $_GET['callback'];
print $callback.'({"id" : "1","name" : "readname"});';
?>
```
正常的请求是这样的:
![image.png](https://cdn.nlark.com/yuque/0/2021/png/338445/1623051982711-1a18f09d-0833-4929-9c20-a931ef6cb8fc.png#align=left&display=inline&height=197&margin=%5Bobject%20Object%5D&name=image.png&originHeight=394&originWidth=823&size=31821&status=done&style=none&width=411.5)
这时候就可以在蜜罐中插入一个script脚本来跨域获取攻击者登陆的web1站点的姓名信息了
```html
<html>
<h1>jsonp窃取信息</h1>
<script type="text/javascript" src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript">
$.getJSON("http://127.0.0.1:91/getuser.php?callback=?", function(getUsers){
alert(getUsers.name);
});
</script>
</html>

```
![image.png](https://cdn.nlark.com/yuque/0/2021/png/338445/1623052379202-f1676578-9f8f-47d1-8972-c8fdbbeec8e8.png#align=left&display=inline&height=303&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1210&originWidth=1574&size=116802&status=done&style=none&width=394)
实际的蜜罐产品则是收集了非常多常用站点的jsonp漏洞,用来窃取攻击者的个人信息。
本文中的反蜜罐主要指的是,识别蜜罐、并且阻止蜜罐通过jsonp接口拿到攻击者的个人信息。反蜜罐插件更加强调的是后者,识别不到蜜罐问题不大,但是一旦信息被蜜罐窃取走,后果就很严重了。


# 反蜜罐浏览器插件Armor
被动探测主要是浏览器插件的形式,在访问的时候插件检测当前是否为蜜罐
目前github上比较好用的两款反蜜罐插件主要是:

- [https://github.com/cnrstar/anti-honeypot](https://github.com/cnrstar/anti-honeypot)

判断当前网页是否有跨域请求,且有黑白名单,黑名单主要就是蜜罐常用的jsonp劫持接口,匹配到则报蜜罐

- [https://github.com/iiiusky/AntiHoneypot-Chrome-simple](https://github.com/iiiusky/AntiHoneypot-Chrome-simple)

主要通过匹配js名称及内容来检测常见的蜜罐


这两个第一个存在漏报的可能,如果黑名单不全的话,还是会被蜜罐拿到信息
第二个也是一样的,不同蜜罐使用的js名称不一样,js内容不一样,比较难很全面的识别拦截
二者都很依赖规则库的完备性。


honpot-Armor里将二者结合起来进行改进,整体流程如下:
主要分三个阶段,分别是

- 探测白名单,由于检测的jsonp接口较多,在正常站点为了不影响使用,添加了白名单
- 对页面加载的js文件进行文件名和文件内容匹配,如Hfish蜜罐,特征就是**x.js**,且里面包含**sec_key**字段
- 对于页面发出的所有请求,对于源地址与目的请求地址,如果相同则忽略,如果不同则进入下一步
- 对于源地址,请求地址不同的请求,黑名单进行匹配,匹配到则直接拦截
- 对于黑名单未匹配到的,则检测请求路径中是否包含callback,cb等字符串,这是由jsonp的特性决定的,还有一些包含ooxx字段(默安的蜜罐),将这些请求进行拦截,标记为可疑请求。
- 为了减少规则匹配不完全导致漏报的危险,增加了jsonp跨域提醒,跨域请求仍然放行(数量比较多,如百度统计服务,很多网站都有,是正常的jsonp请求),但是会有通知提醒,用户可以自己选择开启提醒功能或关闭。



![Armor.png](https://cdn.nlark.com/yuque/0/2021/png/338445/1624036781615-2ecaf28a-e635-4942-b3f8-67e8212c2deb.png#align=left&display=inline&height=1399&margin=%5Bobject%20Object%5D&name=Armor.png&originHeight=1399&originWidth=2748&size=242213&status=done&style=none&width=2748)




# 使用
开发者模式,选择项目文件夹即可
![image.png](https://cdn.nlark.com/yuque/0/2021/png/338445/1624037689549-bf770eb6-00d6-453c-a1ad-f6f158aa6c23.png#align=left&display=inline&height=405&margin=%5Bobject%20Object%5D&name=image.png&originHeight=809&originWidth=2731&size=306757&status=done&style=none&width=1365.5)
![image.png](https://cdn.nlark.com/yuque/0/2021/png/338445/1624037744510-6ce6700a-f8e1-45bf-8ac0-025de4ef3bd7.png#align=left&display=inline&height=220&margin=%5Bobject%20Object%5D&name=image.png&originHeight=439&originWidth=1282&size=31967&status=done&style=none&width=641)
在一些正常网站上,黑名单导致一些正常功能不能使用,可以直接点击关闭反蜜罐功能
jsonp跨域提醒误报太多时,可以关闭jsonp跨域提示
如果识别到会以chrome通知的形式在右下角弹窗,自己会消失
![image.png](https://cdn.nlark.com/yuque/0/2021/png/338445/1624037735381-945f430f-c881-49d7-b268-7671e8abc05a.png#align=left&display=inline&height=803&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1605&originWidth=2982&size=238899&status=done&style=none&width=1491)
![image.png](https://cdn.nlark.com/yuque/0/2021/png/338445/1624037891295-afdb0ad0-2e30-4022-9062-ba0edaabe849.png#align=left&display=inline&height=784&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1567&originWidth=2974&size=221911&status=done&style=none&width=1487)
# todo

- 当前通知使用的是Notification函数,通知相对于检测延迟有点多,会导致开关切换之后,之前的通知还在弹
- 增加右键加入白名单之类的更多的交互
- 增加更多规则



# 参考
[https://juejin.cn/post/6844904127932137485](https://juejin.cn/post/6844904127932137485)
[https://github.com/sxei/chrome-plugin-demo](https://github.com/sxei/chrome-plugin-demo)
[http://www.ptbird.cn/chrome-extensions-storage.html](http://www.ptbird.cn/chrome-extensions-storage.html)


231 changes: 231 additions & 0 deletions background.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
'use strict'
var keyflag = 0; //是否提示有跨域的jsonp请求
var switchon = 1; //是否开启蜜罐
chrome.storage.sync.set({ keyflag: 0, switchon: 1 });
const manifest = chrome.runtime.getManifest();
var honeypotUrlCache = {};
var http = {};
var ruleStr = `
{
"默安幻阵": [
{
"filename": "record.js",
"content": "document[__Ox3f21b[0xd]](__Ox3f21b"
}
],
"HFish": [
{
"filename": "x.js",
"content": "sec_key"
}
]
}
`
var rule = JSON.parse(ruleStr);
const {
version
} = manifest;


// 给数组添加push2方法,用于向数组push不重复的数据
Array.prototype.push2 = function() {
for (var i = 0; i < arguments.length; i++) {
var ele = arguments[i];
if (this.indexOf(ele) == -1) {
this.push(ele);
}
}
};

// 规则匹配,匹配成功将数据放入缓存
function checkForRule(url, content) {
for (var item in rule) {
for (var r1 in rule[item]) {
if (rule[item][r1]["filename"] === '{{honeypotAny}}' && content.indexOf(rule[item][r1]["content"]) != -1) {
honeypotUrlCache[url] = item;
return
} else if (url.indexOf(rule[item][r1]["filename"]) != -1) {
if (rule[item][r1]["content"] === '{{honeypotAny}}') {
honeypotUrlCache[url] = item;
return
} else if (content.indexOf(rule[item][r1]["content"]) != -1) {
honeypotUrlCache[url] = item;
return
}
}
}
}
}


// 传入 URL 检查是否为蜜罐
function checkHoneypot(url) {

console.log("[Honeypot] check url:" + url)
let status = false

// 判断是否在历史检测出来中的缓存中存在
//console.log(honeypotUrlCache)
if (honeypotUrlCache.hasOwnProperty(url)) {
status = true
} else {
// 不存在就进行请求,然后解析内容用规则去匹配
$.ajax({
type: "get",
async: false,
url: url,
success: function(data) {
checkForRule(url, data)
console.log("[Honeypot] checkForRule over.")
}
});
}

// 再次从缓存中检查
if (honeypotUrlCache.hasOwnProperty(url)) {
status = true
}

return status
}

var count = 0
//每次请求前触发,可以拿到 requestBody 数据,同时可以对本次请求作出干预修改
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
chrome.storage.sync.get('keyflag', (res) => {
keyflag = res.keyflag;
});
chrome.storage.sync.get('switchon', (res) => {
switchon = res.switchon;
});
console.log(switchon, keyflag);
if (switchon == 0) {
return;
}
// console.log(details);
if (details.type == 'script') { //
if (checkHoneypot(details.url)) {
new Notification("当前为" + honeypotUrlCache[details.url] + "蜜罐,快跑,当前蜜罐脚本已屏蔽!");
return { cancel: true };
}
}

//url:当前的url;initiator:浏览器状态栏里的domain
let {
url,
initiator
} = details;
// console.log(url, initiator); //http://mbd.baidu.com/newspage/api/getusername?cb=jQuery15204197566477288597_1623140159838&_=1623140160171 http://103.43.19.111

//如果发起者为空,直接赋值url
if (initiator == "undefined" || initiator == "null" || typeof(initiator) == "undefined") {
initiator = url;
}
const protocal = url.split("://")[0];

//根据url返回域名和对应的path
function GetHostAndPath(url) {
var arrUrl = url.split("//"); // http://mbd.baidu.com/newspage/api/getusername?cb=jQuery15204197566477288597_1623140159838&_=1623140160171
var start = arrUrl[1].indexOf("/");
var host = arrUrl[1].substring(0, start);
var path = arrUrl[1].substring(start); //stop省略,截取从start开始到结尾的所有字符

var result = new Array(host, path);
return result
}
//根据url获取主域名
function get_domain(url) { //http://103.43.19.111
var domain = url.split("://")[1];
if (domain.includes('/')) {
domain = domain.split('/')[0];
}
// var re_domain = /([a-zA-Z0-9-]+)(.com\b|.net\b|.edu\b|.miz\b|.biz\b|.cn\b|.cc\b|.org\b){1,}/g;
// domain = url.match(re_domain);
return domain;

}
//判断host是否在黑名单内
function inBlackList(host) {
//黑名单host来自长亭D-sensor的溯源api,共47个
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", "mbd.baidu.com", "wapsite.baidu.com", "zhifu.baidu.com", "m.iask.sina.com.cn", "mooc1-1.chaoxing.co", "myjr.suning.com", "mooc1-1.chaoxing.com", "my.zol.com.cn", "passport.tianya.cn", "account.cnblogs.com", "passport2.chaoxing.com", "zhifu.duxiaoman.com"];
for (const BlackSite of BlackList) {
if (host == BlackSite) {
return true
}
}
return false
}

var mainDomain = get_domain(initiator); //发起者的主域名
var targetHost = GetHostAndPath(url)[0]; //跨域或本域访问的目标主机
var targetPath = GetHostAndPath(url)[1]; //跨域或本域访问的目标路径
console.log(mainDomain, targetHost, targetPath);

const WhiteList = ['www.baidu.com', 'www.qq.com', 'www.csdn.net', 'www.weibo.com', 'www.cnblogs.com', 'www.aliyun.com', 'www.ctrip.com', 'www.weibo.cn', 'www.iqiyi.com', 'www.163.com', 'www.126.com', 'www.51cto.com', 'www.taobao.com', 'www.sogou.com', 'www.iteye.com', 'www.58.com', 'www.google.com', 'www.fofa.so', 'www.jd.com', 'www.tmall.com', 'www.github.io', 'www.github.com', 'www.sina.com.cn', 'www.mi.com', 'www.zhihu.com', 'quake.360.cn', 'www.bilibili.com', 'www.csdn.com'] //白名单
for (var WhiteSite of WhiteList) {
if (mainDomain == WhiteSite) {
console.log('命中白名单' + mainDomain); // 访问这些网站时退出
return;
}
}

let redirectUrl;
let cancel;

if (mainDomain == targetHost) { //如果相等表示正常域内访问
return;
} else { //如果不相等,可能是跨域访问,需要继续判断
let flag = 0;
const blockQueryStringList = ['callback', 'jsonp', 'javascript', 'cb=', 'xxoo']; //如果url中存在这些字段,说名可能时jsonp请求,归类为可疑请求,进行拦截
// `默安蜜罐特征:xxoo=chrome-extension`
if (protocal == 'http' || protocal == 'https') {
if (inBlackList(targetHost)) {
// 黑名单拦截
count += 1;
flag = 1;
new Notification('拦截黑名单' + count + '次:' + targetHost + '\n建议立即关闭页面 => ' + mainDomain);
console.log('拦截黑名单' + count + '次:' + targetHost + '\n建议立即关闭页面 => ' + mainDomain);
} else {
for (const q of blockQueryStringList) {
if (q && targetPath.includes(q)) {
redirectUrl = 'data:text/javascript;charset=UTF-8;base64,' + btoa(`;`); //拦截
new Notification('拦截可疑溯源请求:' + targetHost + targetPath + '\n建议立即关闭页面 => ' + mainDomain);
console.log('拦截可疑溯源请求:' + targetHost + targetPath + '\n建议立即关闭页面 => ' + mainDomain);
flag = 1;
}
}
}
if (keyflag == 1) {
if (flag == 0) { //黑名单不一定全,如果callback关键字匹配也失效的话,就可能拦截失败,通过提示存在所有jsonp跨域请求,让用户自己来判断
const jsonp_WhiteList = [".css", ".js", ".png", ".jpg", ".gif", "api.map.baidu.com", "miao.baidu.com", "img", "imges"] //path中含有这些字符串的被划分为正常的jsonp请求//会比较多
let flag2 = 1;
for (const q of jsonp_WhiteList) {
let request_url = targetHost + targetPath;
if (request_url.includes(q)) {
flag2 = 0;
}
}
if (flag2 == 1) {
new Notification('存在跨域jsonp:\n' + targetHost + targetPath);
console.log('存在跨域jsonp:\n' + targetHost + targetPath);
}

}
}


}
}

if (cancel) return {
cancel
};
else if (redirectUrl) return {
redirectUrl
}
else return {};
}, {
urls: ["<all_urls>"]
}, ["blocking"]
);
Binary file added chrome反蜜罐插件-Armor.pdf
Binary file not shown.
Binary file added img/bee.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 33 additions & 0 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "Armor - antiHoneyPot",
"version": "1.0.0",
"manifest_version": 2,
"description": "Armor反蜜罐",
"icons": {
"128": "/img/bee.png"
},
"browser_action": {
"default_popup": "popup.html",
"default_title": "Armor - antiHoneyPot",
"default_icon": "/img/bee.png"
},
"background": {
"persistent": true,
"scripts": [
"background.js",
"thirdParty/jquery-3.5.1.min.js"
]
},
"permissions": [
"notifications",
"activeTab",
"tabs",
"storage",
"https://*/*",
"http://*/*",
"webRequest",
"webRequestBlocking"
],
"web_accessible_resources": ["*"],
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
}
29 changes: 29 additions & 0 deletions popup.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Armor蜜罐检测插件</title>
<script src="./thirdParty/jquery-3.5.1.min.js"></script>
<style>
body {
width: 200px;
height: 140px;
}
</style>

</head>


<body>
<div class="jumbotron">
<p>反蜜罐功能: <input id="switch1" type="checkbox"></p>
<p>jsonp跨域提示: <input id="switch2" type="checkbox"></p>
</div>

<script src="popup.js"></script>
</body>


</html>
Loading

0 comments on commit d3cd80d

Please sign in to comment.