复盘微博短链接盗窃门
Updated:
这不是意外,不是 bug,是蓄谋已久的阴谋! 不知道阅读完以后,你会不会和我一样心里发寒
事件背景
前两天传出了新浪微博利用短链接恶意盗取用户收益的事件,可能很多吃瓜群众还不是特别明白是咋回事。这里我简单复盘一下,顺便聊聊个人的见解。
事情最初由 @im61 的这张图片引起:
利益分析
首先要知道苹果的 iTunes 联盟,这个可以算是苹果官方的推广平台,具体介绍看这里,我没有用过,不过概括来说这个联盟就是一个平台,推广者帮忙推广 App,一旦有用户产生下载行为,推广者就可以获得收益。
这个联盟显然是一个三方平台,对推广者和应用开发者来说是双赢的局面,前者收获推广费用,后者获得下载流量,从而获得盈利。
为了标记某一次下载背后的推广者是谁(这样才好分成),苹果为每一个推广者提供了推广 ID(其实还有活动码,不过不是重点,所以略过),比如说某个应用的下载地址可能是:
那么带有推广码的下载地址就是:
可以看到 HTTP 请求多了一个参数,参数的值 1001|sTF
就是 @im61 同学的推广码, 一旦用户点击了带推广码的地址,@im61 同学就会产生收益。
短链接
由于 App 的下载地址本来就很长,再加上推广码和活动 ID,非常不利于阅读,因此微博提供了短链接生成器,比如通过微博的短链接生成器,我的长连接 会被转换成 http://t.cn/RJ8HDRC:
当你打开短链接的时候,实际上会经过一次 302 跳转,跳到原地址(也就是长连接的地址)。这个技术相当容易实现,因为理论上来说只要用一个字典来存储, 值是长连接,键是短链接(比如最简单的生成方法就是哈希一下)。
这样当你访问 http://t.cn/RJ8HDRC
这个网址时,服务器会拿到 RJ8HDRC
这个键,然后找到对应的值,也就是原始的 iTunes 长连接,再动态拼凑出一个 302 请求即可。302 请求表示页面临时被移动,根据 HTTP 规范,浏览器会重新请求新的临时地址。
我们可以验证一下:
新浪微博是如何作恶的
首先我们看到红色划线部分,有两个 at 参数,那么服务器以哪个为准呢,答案是不一定。HTTP 协议中并没有规定当 GET 方法的 Query 中出现重复的 key 怎么办,所以通常来说有三种解决方法:
- 以前面的为准,比如
&at=1&at=2
会被服务器当做&at=1
处理 - 以后面的为准,比如
&at=1&at=2
会被服务器当做&at=2
处理 - 以两者的拼接结果为准,比如
&at=1&at=2
会被服务器当做&at=[1,2]
处理
不同的 Web 服务器实现方法并不一样,比如 PHP 4.4 以后采用的是上述第二种方案。所以我们观察截图可以发现,
微博在原先的 at 字段后面新增了一个重复字段,填上了自己的推广码,一旦用户访问短链接,它返回的 302 重定向实际指向了微博自己的推广链接。
这也证明不管苹果使用的是哪种 Web 服务器,必然都是使用了第二种处理策略。
稍微一动脑子就可以想明白四件事情:
- 微博专门为窃取利益做了调试,它必须搞明白苹果 Web 服务器的处理逻辑。如果采用的是第一种策略,微博就不是在原先的 at 字段后面新增,而是在前面新增。
- 只要短链接控制权在微博手上,它就可以随意做出修改,当然如果苹果采用了第三种策略,微博是无能为力的(苹果表示这个锅我不背)。
- 显然并不是所有的链接都会被加上这样的参数,否则有相当多的地址都无法打开,比如我的博客
生成的短链接再解析回来依然正常。可见微博专门对短链接格式做了判断,如果是以 iTunes 开头才会做手脚。
- 这也是我觉得最可怕的一点,微博可以针对 iTunes 做专门处理,自然也可以针对其他推广链接做类似处理,至于微博偷走了多少钱,我们不得而知。
更让人气愤但是,@im61 同学的微博在 2017 年 2 月 16 日中午一点钟发出,而我写作本文的时间是 17 日晚上 10 点,接近一天半的时间内微博找出各种理由,但就是没有修改的意图。根据我的经验来看,这种策略的添加和删除都是极为容易的,开发者一定提供了良好的接口。
所以我猜测微博的管理层觉得事情还不够大,每拖延一分一秒,又是一大笔收入,年底的财报和股价会更好看。
我没有办法证明时间的准确性,不过希望看到本文的读者还有机会亲自体验一下微博做的恶。
如何防范
对于微博这种要钱不要脸的行为,如何防范呢,我想大概有两种方法。
第一种方法是利用第三方短链接服务,即先将自己的原始地址转换成安全的短链接,然后再将这个短链接转换成微博的短链接。这是原贴评论中有人提出的方案,我不知道为什么非要使用微博短链接(刚刚测了一下,使用别的短链接生成器似乎也可以),这里姑且认为是有什么限制吧。
这种方法是一种临时方法,并不保险,因为微博完全可以做一个递归判断,首先检查你的链接访问以后是不是 302,如果是 302 则抓取重定向的地址,直到找到 iTunes 为止。幸好暂时微博还没有这么做,不过为了钱,相信我,微博什么都做得出来。他们可以不让你提现,帮你自动发广告微博,乱插时间线。
自建服务器
最稳妥的方法还是使用自己的服务器,不过评论区中的 HTTPS 加密似乎用处不大。因为 HTTPS 加密只是请求过程加密,而你在发起请求时,必然走的是 GET 方法打开一个 URL,所以自己的推广码必然是明文放在请求头部,比如
1
|
HTTP GET https://bestswifter.com/promotion=我的推广码
|
然后我在自己的服务器上返回一个 302 重定向,带上推广码,重定向到 iTunes 上。
在我看来这种做法已经足够安全,因为微博没办法识别自己的 URL 特征,前文说过它只是依赖于 iTunes 开头的链接的识别。当我的域名和 query 键名都被混淆后,微博不可能再对我请求做任何修改,如果还不放心,还可以在服务器上对请求参数自行校验。
总的来说,控制权在自己手上才是最安全。
微博做了哪些恶
对于微博这样的中间平台来说,它本应该提供更好的安全保护服务,保护用户的合法利益不受侵犯。比如我们目前在做的广告和计费服务,客户端看到的并不是广告的真实地址, 也不会直接向服务器发送扣费请求。客户端能拿到的只是一个加了密的地址,在请求服务器时,一方面服务器对参数解密,进行扣费,另一方面返回 302,重定向到真正的广告地址。
而微博做的确实煞费苦心的调试广告平台存在的 bug,利用自身优势伪造请求数据(类似于 SQL 注入和 XSS 攻击),并针对不同目标平台做出区分,“优化” 自身收益。当恶行被曝光后,选择是找借口、拖时间而非及时承认错误,抓紧一分一秒从用户手上抢钱。
我想,微博欠无数像 @im61 这样的用户一个道歉。