人人, 你不要为了上市丧失了基本的道德!

昨天影响颇为强烈的人人网站内信漏洞导致大量用户隐私失窃的事让人很是震惊. 作为国内颇具影响力的SNS, 因为一个很低级的标签过滤问题, 导致如此严重的后果, 实在难以理解. 但事情到了这里, 还只是牵涉到人人的技术问题, 暂且没有上升到道德层面.

很快, 一些网友发表了关于此漏洞的文章, 希望可以引起大家的注意, 进而减小损失, 我也顺势发了一些相关的状态.但令人无法相信的是, 今天这些状态居然被删除了! 平时一些关于政治的状态, 人人你删除一些, 我鄙视你, 但不至于那么鄙视你. 但这个和政治毫无关系的状态, 仅因为陈述了一下这个事件, 就遭到删除, 我怎么就那么地鄙视你呢?

一个朋友提到人人要上市了, 于是似乎它们之间是有关联的. 或许这个事件本身就是竞争对手一首策划的, 人人你中招了就中招了, 居然期望通过阻止言论来保全自己的商业利益! 你这种行为与那什么东西有什么区别?! 那什么东西还可以说是为了和谐稳定, 而你呢? 你的商业道德哪儿去了?

事件发生的时候, 你没能尽快解决问题, 反而期望在之后通过这种侵犯用户权益的手段消除影响. 你让我情何以堪?

我承认因为有大量的同学朋友在人人网上, 我对人人网产生了一定的依赖, 但这并不妨碍我揭露你的行径! 技术赶不上Facebook, 道德又如此低劣! 看清你的前路在何方吧!

 

人人网站内信漏洞导致大量用户隐私泄露

昨天有个朋友给我看了一篇文章, 是关于一段出现在人人站内信中的JS.

当用户点开带有这段<script>的站内信时, 其中的代码将会自动运行, 并采集用户的好友名片信息, 发送到指定的服务器. 并且再给好友发送内容相同的站内信.

不得不说这是一个非常低级的漏洞, 人人的后台居然没有对站内信中的特定标签 (比如这里是script) 进行处理. 很不解的是, 人人的日志上都出现了大量关于此 “病毒” 的信息, 人人却依然没有修复此漏洞, 效率如此低下? 当时的 msg.renren.com 已经出现了不能访问的情况, 一开始我还以为是人人暂时关掉了相关服务并进行漏洞修复, 后来发现问题依旧, 于是之前的不能访问只能说明收到攻击的数量之大, 导致人人站内信的服务器超出负荷. 后来人人是有了一些举动, 但貌似并非是技术层面的, 只是将相关域名加成了关键字. 人人的技术人员哪儿去了?

那抛开这些不说, 谈谈这次攻击的技术方式.

因为一些安全问题, 浏览器对很多种方式的跨域访问进行了限制. 比如不同域的页面之间不能互相访问内容, XMLHttpRequest 跨域会有警告甚至根本不能跨域, 包括 HTML5 里面的 canvas 也做了类似限制. 不过还是有例外, 比如<script></script>, <img />就可以. script 可以获取跨域的信息, 而 img 可以通过 GET 方式发送跨域信息.

这也是这次攻击所利用到的主要信息交换方式.

所以人人的技术水平还有待提高啊, 包括在一些浏览器 (现代浏览器) 里显示也有小问题.

腾讯微博API OAuth验证及微博发送 (JavaScript)

首先, 道路是曲折的… 之前曾小试过 Basic 验证, 一开是也是不得要领, 不过悟透那个就显然快多了.

这是第一次做 OAuth 的验证, 在此实在想狠狠地骂腾讯的 API 说明文档, 不清不楚, 害得我到处查, 到处试… 总算, 经过一个上午的奋斗, 成功获取了 Request Token, 下午再稍加努力, 终于把 Access Token 拿到了手, 晚上又继续奋战, 搞定了微博发送, 至此, 也算对 OAuth 及腾讯微博的 API 有了个基本的了解.

JavaScript 实现腾讯微博的 OAuth 的难点在于 HMAC-SHA1 加密, 而且之后还得转换成 Base64, 最变态的是, 获取 Request Token 的时候, 加密时 AppKey 后面还得跟上个 “&”!!! 比如原来 AppKey 是 “123456”, 那么加密时的 Key 就是 “123456&”

好吧, 既然大家在看这篇文章, 相信关于 XMLHttpRequest 这些也比较熟悉了, 我就说说重点 (因为我是第一次真正接触 OAuth, 所以对里面一些约定俗成的东西可能还不清楚, 所以高手看了不要笑我这些 “重点” 太幼稚).

HMAC-SHA1 加密的 JavaScript 实现

在网上搜这个搜了很久, 最后找到了一个叫 Crypto-JS 的东西, 一看, 果然是好家伙, 里面提供了非常丰富的加密方式, 值得收藏. http://code.google.com/p/crypto-js/ 下载后引用 crypto.js, sha1.js, hmac.js 三个文件, 加密方式如下:

var message = “Message to be encoded”;
var secret = “Secret phrase”;

var bytes = Crypto.HMAC(Crypto.SHA1, message, secret, { asBytes: true }) ;
//但仅仅这样还不行, 还得转换成Base64.
//在Crypto.util下找到相应的方法.
var signature = Crypto.util.bytesToBase64(bytes);

这样就搞定啦. 需要注意的是 (前面我也有提到), 在获取 Request Token 的时候, secret需要在 App Secret 后面加上 “&”. 获取 Access Token 的时候, 则是用 “&” 把 App Secret 和 Token Secret连起来.

参数编码

按说这个是算不上重点的, 不过实在找不到东西写, 就把这个算上去吧.

方法很简单, 使用JavaScript内置的encodeURIComponent()方法即可.

看来这里还真是重点, 编码要求要什么 [RFC3986], 在 encodeURIComponent() 的基础上, 还要额外编码 ! * ( ) ‘ 这5个字符.

否则当添加微博的内容中出现这些字符的时候, oauth_signature 参数会有误, 导致鉴权失败.

时间戳

注意单位是哦! new Date().getTime()的单位是毫秒, 所以注意先除以1000再取整.

要签名的Base String

里面的参数要排序, 当然这个文档中也强调了. 另外就是这些参数中是不包括 oauth_signature 的. 显然, 也没法包含这个参数, 不过我这样点明下, 免得大家心生疑惑.

 

最后, 这个是我用 HTA (JavaScript) 实现的一个验证和发微博的小Demo, http://www.vilic.info/demo/vt.rar . 源码是基于 vejis 的, 如果有看不太明白的可以参考 vejis.js 文件中的说明. (补充, 后来发现有个小Bug, 其实不算Bug, 我一开始以为所有的API都可以用POST方法, 就全部使用的是POST, 对应的稍微小改就可以了)

原来JavaScript也可以有属性的get和set

今天在群里和大大们讨论问题, 顺便就谈到了开发 Prever 2 的时候遇到的一个. 归结下来, 就是希望能保护一些对象, 使之不能被修改.
后来Franky大神提到一个方法, Object.defineProperty, 据说是IE8部分支持, 其他浏览器的最新应该都是支持的. 因为我现在不求兼容很多浏览器, 所以对我来说, 这自然是非常有用的东西了.
查了查MSDN和MDC, 解释如下(翻译得不恰当的地方请见谅):

语法

Object.defineProperty(obj, prop, descriptor)

参数

obj
要定义属性的对象
prop
要修改或者定义的属性名称
descriptor
属性定义和修改的描述符

描述

这个方法允许对象属性的严格添加和修改. 普通的属性添加创建的属性可以在属性枚举(for…in 循环)中枚举, 这时候, 值可能被改变或者删除. 这个方法允许修改这些额外的特性(即可改变或可删除).

属性描述符是对象形式的, 它可以由两种方式表示: 数据描述符和访问描述符. 数据描述符是一个有值, 可写或者不可写的属性. 访问描述符是通过一个getter和setter函数对来描述的. 一个描述符必须是这两种之一, 不能掺杂. 这两种描述符都可以使用configurable和enumerable.

一个属性描述符是一个具有以下字段的对象:

value
属性的值. (仅限数据描述符). 默认为undefined.

writable
如果值为true, 属性的值可以被改变. (仅限数据描述符). 默认是false.

get
属性的getter, undefined表示没有getter. (仅限访问描述符). 默认是undefined.

set
属性的setter, undefined表示没有setter. (仅限访问描述符). 默认是undefined.

configurable
如果值为true, 则该属性的描述符可以被修改并且该属性可以从相关对象上删去. 默认为false.

enumerable
如果只为true, 则该属性可以从相关对象上枚举. 默认是false.

JavaScript 能有多快?

最近想玩一玩HTML5, 特别是canvas和CSS3的3D transform. 不过3D transform貌似只有Safari支持比较正常, 之前的Chrome也可以, 现在不知道怎么的好像不行了. 那自然就把重心落到了canvas上.

想用canvas实现一些3D的效果, 但却无从下手. 一方面是因为自己算法方面的知识匮乏, 另一方面, 则是不清楚JavaScript究竟能有多快. 毕竟一牵涉到图形处理, 计算量就摊在了那里.

各大浏览器都陆陆续续地支持硬件加速了, 所以渲染应该不是问题, 今天便做了个小测试, 想看看JS的效率. 内容比较简单:

//JavaScript:
var l = 100000000;
var o = [];
for (var i = 0; i < l; i++) {
    if (o.length == 100000)
        o.length = 0;
    o.push(i);
}

//C++ (vector)
int l = 100000000;
for (int i = 0; i < l; i++) {
    if (vct.size() == 100000)
        vct.clear();
    vct.push_back(i);
}

//C++ (原生数组)
int vct[100000];
int vi = 0;
int l = 100000000;
for (int i = 0; i < l; i++)
{
    if (vi == 100000)
    {
        vi = 0;
        memset(vct, 0, sizeof(int) * 10000);
    }
    vct[vi] = i;
}

最后, C++ vector耗费的时间最长, 接近一分钟; JavaScript Array在Chrome 10中耗时3s多一点; C++原生数组最快, 不到1s.

当然, 我也不指望JavaScript的Array能快过C++的原生数组, 但取得了这样的成绩也是令人惊讶的. 原来一直觉得脚本语言和被编译为机器码的语言速度上肯定不在一个数量级, 而且可能会差很多个数量级, 现在看来, 似乎并非如此. 虽然可能一个for循环和一个数组操作没有暴露JavaScript速度上的弱点, 但也足以改变我的看法. JavaScript速度的提升, 也意味着Web与我们生活的又一次靠近!