WebSth 指纹识别插件简要分析

浏览:
字体:
发布时间:2013-12-20 16:18:22
来源:
今天才在某个论坛上看到这个网站:http://websth.com/, 深感所知甚晚啊,自己一直想做的web指纹识别,已经有童鞋做成chrome插件发布了,并且功能还算比较强大,不过准确性确实有待提高。于是我下载了其源码并开始围观一下。

    先看看识别效果:

    2.png

    之前接触过chrome插件的开发(只是看过一部分文档),所以对插件的运行流程有所了解。

    代码的文件结构是这样:

    1.png

    其中有一个manifest.json,一个json格式的文件,读过文档的就知道这个文件其实是chrome加载插件的主文件,里面配置了一些关于插件的信息。我们打开参观一下:



{  "name": "__MSG_extName__",  "description": "__MSG_extDescription__",  "permissions": [ "http://*/*", "https://*/*", "tabs", "storage" ],  "version": "1.1.0",  "manifest_version": 2,  "default_locale": "en",  "icons": {    "128": "icon-128x128.png"  },  "background": {    "scripts": [      "js/web_technologies.js",       "js/web_servers.js",       "js/oses.js",       "js/web_front_libraries.js",       "js/web_apps.js",      "js/background.js"    ],    "persistent": true    },  "content_scripts": [ {    "js": ["js/website_analyzer.js"],    "matches": [ "http://*/*", "https://*/*" ],    "run_at": "document_end"  } ],  "options_page": "options.html",  "page_action": {    "default_popup": "popup.html"  }}
 
    不长,里面有一个content_scripts字段,这个字段表示在web页面内运行的javascript脚本。chrome插件其实就是javascript脚本,所有的功能用脚本的形式执行。每当打开匹配url的页面时,就执行content_scripts里指定的脚本,这里是js/website_analyzer.js。

 

    于是我们跟踪一下,打开js/website_analyzer.js。,发现其中代码功能是ajax获取当前访问的网页内容,并传递给扩展。其中定义了这样一个对象:

 
var data = {            "header"    : this.getAllResponseHeaders(),            "dom"       : covertNodes(document),            "hostname"  : hostname,            "port"      : document.location.port        };

这个对象就保存了http头、DOM对象、域名和端口。然后通过 chrome.extension.sendMessage(data) 传递给我们的插件。

 

    返回到我们的manifest.json中,还能找到一个background字段,里面保存了不止一个的js文件,这些js文件就是运行在我们插件整个生命周期中的脚本。其中有一个background.js,它接受到了浏览器页面传递来的data数据,然后对它进行处理。

    打开background.js文件,略长,我们只分析web指纹那个部分。

 

// match web appsvar apps = []for (var i in web_apps) {  for (var j in web_apps[i]['rules']) {    if (findNode(root, web_apps[i]['rules'][j].type, web_apps[i]['rules'][j].match, web_apps[i]['rules'][j].name, web_apps[i]['rules'][j].attributes)) {      apps.push(web_apps[i]);      break;    }  }}technologyData[sender.tab.id]['web_apps'] = apps;
 
    因为在加载background.js之前加载了一个web_apps.js,里面定义了一个web_apps对象,就类似一个数据库,保存着很多指纹信息。我们这里就用一个for in循环,遍历web_apps对象,在其中匹配查找。内层还有一个for in循环,进行多个条件下的匹配。比对用到findNode这个函数,这个函数在background.js中:
 
function findNode(root, type, text, name, attr){  // type = [  //  1, // element   //  3, // text  //  8  // comment  // ]  // text = reg to search  // name = element tagName  // attr = element attr to search  for (var node in root){    if(type == 1 && root[node].nodeType == type){ // element      if (root[node].nodeName.toUpperCase() == name.toUpperCase()){        var search_str = root[node].attributes[attr.toLowerCase()];        if (search_str.match(text)){          return true;        }      }    }else if(root[node].nodeType == type){ // text & comment      if (root[node].nodeValue.match(text)) {        return true;      }    }  }  return false;}


  第一个参数root是DOM,后面几个参数表示比对的内容。这个函数用一个for in循环遍历了整个DOM,如果是元素(element,type=1)节点,就比较其name元素的attr属性是否和text匹配(type/name/attr/text是传入的参数),如果是文本(TEXT/COMMENT, type=3 or 8)节点,就直接比较该文本是否和text匹配。

 

    我们举个例子,比如discuz的规则:

 

{        "icon": "discuz.jpg",        "title": "Discuz!",        "url"  : "http://www.discuz.net",        "rules": [            {                "type": 1,                "name": "SCRIPT",                "attributes": "src",                "match": "logging//.js"            },            {                "type": 1,                "name": "META",                "attributes": "content",                "match": "Discuz//!"            },            {                "type": 3,                "name": "TITLE",                "attributes": "",                "match": "Powered by Discuz//!"            },            {                "type": 1,                "name": "A",                "attributes": "href",                "match": "^home.php//?mod=space"            }        ]    },
 
    我们看rules的第一项,type=1,表示元素节点,也就是说我们查找,如果找到“script”元素的“src”属性和"logging//.js"匹配(通俗来说就是找到<script src="...logging.js"></script>),这里就返回true.

 

    因为discuz的规则有四个,我们看代码发现,只要有一个满足就跳出,匹配下一个web app,所以准确度不高,只能说是疑似discuz。像我之前那个截图一样,出现了dedecms和pwiki两个可能,还需要进一步的确认才行。

    填充了apps这个对象以后,把它保存 technologyData[sender.tab.id]['web_apps'] = apps;

    主目录下还有一个popup.html,作用就是我点击插件的按钮,弹出的那个小框的html代码。打开发现就是一个什么内容都没有的html,但最后加载了js/popup.js这个脚本。这个脚本就是把technologyData中的内容取出来,写到popup.html里,让用户看。

    打开popup.js,看到web指纹那个部分。

    找到如下代码:




if (data['web_apps'].length != 0) {        var tr = document.createElement('tr');        var td1 = document.createElement('td');        td1.innerHTML =  "<strong>";        td1.innerHTML += chrome.i18n.getMessage("webApps");        td1.innerHTML += "</strong>";        var td2 = document.createElement('td');        td2.setAttribute("colspan", "2");        for (var i in data['web_apps']) {            if (data['web_apps'][i].url){                // td2.innerHTML += "<a href=/"" + data['web_apps'][i].url + "/" target=/"_blank/"><img class=/"img/" width=/"19px/" hight=/"19px/" src=/"icons/" + data['web_apps'][i].icon + "/" />&nbsp;&nbsp;" + data['web_apps'][i].title + "</a>";                td2.innerHTML += "<a href=/"" + data['web_apps'][i].url + "/" target=/"_blank/"><img class=/"img/" width=/"19px/" hight=/"19px/" src=/"icons/" + data['web_apps'][i].icon + "/" title=/"" + data['web_apps'][i].title + "/" />&nbsp;" + data['web_apps'][i].title + "</a>&nbsp;&nbsp;";            }else{                td2.innerHTML += "<img class=/"img/" width=/"19px/" hight=/"19px/" src=/"icons/" + data['web_apps'][i].icon + "/" />&nbsp;" + data['web_apps'][i].title + "&nbsp;&nbsp;";            }        }        tr.appendChild(td1);        tr.appendChild(td2);        document.getElementById("detail").appendChild(tr);    }
 
    没什么好说的,就是一个一个取出来,加进html里。

 

    最后,我们梳理一遍流程:

    1.打开浏览器,预先加载插件的javascript,比如background.js等

    2.进入一个网站:discuz.net

    3.加载js/website_analyzer.js,通过ajax获得所访问网站的DOM和其他信息

    4.background.js获取到DOM,执行一个for in 循环,遍历web_apps对象,对其中每一个web app类型做比对。比对过程是遍历DOM,发现匹配就退出,执行下一次比对。

    5.返回比对结果。如果此时用户点击插件按钮,即弹出popup.html,其中执行popup.js,该js把相关信息写入popup.html让用户查看。

 

    读过代码后知道这个插件是靠DOM元素的匹配来识别某个web指纹,相比于其他一些比如md5指纹识别要更适合javascript,可扩展性也好(我们可以修改web_apps.js来手工添加一些web指纹信息)。


>更多相关文章
24小时热门资讯
24小时回复排行
资讯 | QQ | 安全 | 编程 | 数据库 | 系统 | 网络 | 考试 | 站长 | 关于东联 | 安全雇佣 | 搞笑视频大全 | 微信学院 | 视频课程 |
关于我们 | 联系我们 | 广告服务 | 免责申明 | 作品发布 | 网站地图 | 官方微博 | 技术培训
Copyright © 2007 - 2024 Vm888.Com. All Rights Reserved
粤公网安备 44060402001498号 粤ICP备19097316号 请遵循相关法律法规
');})();