揭秘以太坊中潜伏多年的“偷渡”漏洞,全球黑客正在疯狂偷币

世界上有一群人,互联网对于他们来讲就是提款机。html

是的,过去是,如今更是,由于电子货币的出现,他们提款的速度变得更疯狂。node

在2017年,咱们的蜜罐监测到一块儿针对以太坊的全球大规模攻击事件,咱们将其命名为以太坊“偷渡”漏洞。python

经过该漏洞,黑客能够在没有服务器权限、没有keystore密码权限的状况下,转走钱包中的全部余额。nginx

而如此严重的漏洞,1年前就在reddit.com被曝光有黑客在利用,而且最先可追溯到2016年的2月14号就有黑客经过此漏洞窃取到比特币:git

www.reddit.com/r/ethereum/…github

近期也有中国的慢雾安全团队揭露了这种攻击手法:web

mp.weixin.qq.com/s/Kk2lsoQ16…数据库

在长达2年的时间里,并无多少用户关注到,以太坊也没有进行针对性的防御措施,直到今日,以太坊的最新代码中依然没有可以抵御这种攻击。json

所以咱们决定将咱们所掌握的详细数据公布给全部人,但愿能促使以太坊的开发者认可并修复该漏洞。api

漏洞成因

(如下的代码分析基于https://github.com/ethereum/go-ethereum的当前最新提交:commit b1917ac9a3cf4716460bd53a11db40384103e5e2)

以太坊目前最流行的节点程序(Geth/Parity )都提供了RPC API,用于对接矿池、钱包等其余第三方程序。

默认状况下,节点的RPC服务是无需密码就能够进行接口调用,官方实现的RPC API也并未提供设置RPC链接密码的功能,所以,一旦将RPC端口暴露在互联网,将会很是危险。

而咱们所捕获的以太坊“偷渡”漏洞,正是利用了以太坊默认对RPC不作鉴权的设计。

被攻击的用户,须要具有如下条件:

  1. 节点的RPC端口对外开放
  2. 节点的RPC端口可直接调用API,未作额外的鉴权保护(如经过nginx等方式进行鉴权保护)
  3. 节点的区块高度已经同步到网络的最新高度,由于须要在该节点进行转帐,若是未达到最高度,没法进行转帐

当用户对本身的钱包进行了解锁(unlockAccount函数),在解锁超时期间,无需再输入密码,即可调用RPC API的eth_sendTransaction进行转帐操做。

漏洞的关键组成,由未鉴权的RPC API服务及解锁帐户后有必定的免密码时间相结合,如下是解锁帐户的unlockAccount函数:

代码路径:go-ethereum/internal/jsre/deps/api.go

经过函数的实现代码可见,解锁帐户的api容许传入超时时间,默认超时为300秒,

真正进行解锁的函数TimedUnlock实现以下:

代码路径:go-ethereum/accounts/keystore/keystore.go

当传入的超时大于0时,会发起一个协程进行超时处理,若是传入的超时时间为0,则是永久不会超时,帐户一直处于解锁状态,直到节点进程退出。

详细的用法参考官方文档:https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_unlockaccount

攻击手法揭秘

1. 寻找对外开放以太坊RPC端口的服务器,确认节点已经达到以太坊网络的最高区块高度

黑客经过全球的端口服务扫描,发现RPC服务为以太坊的RPC接口时,调用eth_getBlockByNumber(‘last’, false),获取最新的区块高度。

可是因为有些以太节点是以太坊的分叉币,高度与以太坊的不同,所以黑客即便发现节点高度与以太坊的高度不同,也不会放弃攻击。

2. 调用eth_accounts,获取该节点上的全部帐户。

eth_accounts的请求将返回一个帐户地址列表:[0x1834axxxxxxxxxxxxxxxxxxxxxxxxxxx, 0xa13jkcxxxxxxxxxxxxxxxxxxxxxxxxxxx,…… ]

3. 调用eth_getBalance,查询地址余额。

这个过程黑客可在本身的服务器完成以太坊的余额查询,由于以太坊的区块链帐本数据库是随意公开获取的。

有部分黑客没有搭建以太坊的全节点,没有自行查询余额,所以也会在被攻击服务器进行eth_getBalance操做。

4. 持续调用转帐操做,直到恰好用户用密码解锁了钱包,完成非法转帐操做的“偷渡”

黑客会构造eth_sendTransaction的转帐操做,并填写余额、固定的手续费:

{“jsonrpc”:”2.0″,”id”:2,”method”:”eth_sendTransaction”,”params”:[{“from”:”受害者钱包地址1″,”gas”:”0x55f0″,”to”:”0xdc3431d42c0bf108b44cb48bfbd2cd4d392c32d6″,”value”:”0x112345fc212345000″}]}
{“jsonrpc”:”2.0″,”id”:2,”method”:”eth_sendTransaction”,”params”:[{“from”:”受害者钱包地址2″,”gas”:”0x55f0″,”to”:”0xdc3431d42c0bf108b44cb48bfbd2cd4d392c32d6″,”value”:”0x112345fc212345000″}]}
{“jsonrpc”:”2.0″,”id”:2,”method”:”eth_sendTransaction”,”params”:[{“from”:”受害者钱包地址3″,”gas”:”0x55f0″,”to”:”0xdc3431d42c0bf108b44cb48bfbd2cd4d392c32d6″,”value”:”0x112345fc212345000″}]}

其中的value的单位是以太的最小单位:wei,计算为以太的话须要除10的18次方:

>>> 0x112345fc212345000
19758522752314920960L
>>> 19758522752314920960L/1000000000000000000
19L

黑客会持续发转帐操做,并按期监控余额变化,更新转帐的金额,直到用户使用钱包,输入密码解锁了钱包,此时钱包余额会当即被转走。

快速漏洞测试

安装python的web3库,而后链接RPC端口,发起请求,若是获取到返回结果,即可能存在该漏洞。

参考:http://web3py.readthedocs.io/en/stable/quickstart.html

from web3 import Web3, HTTPProvider, IPCProvider
web3 = Web3(HTTPProvider(‘http://ip:port’))
print web3.eth.blockNumber

黑客解密及IOCs情报

黑客钱包

目前咱们掌握了3个黑客的钱包收款地址,未转走的帐户余额为2220万美金:

https://etherscan.io/address/0x957cD4Ff9b3894FC78b5134A8DC72b032fFbC464,余额为38,076 ETH(未统计erc20 token),最先进帐为2016-2-14,最新进帐为2018-3-21(当前还在持续入帐)

https://etherscan.io/address/0x96a5296eb1d8f8098d35f300659c95f7d6362d15,余额为321 ETH(未统计erc20 token),最先进帐为2016-8-10,最新进帐为2017-11-28。

https://etherscan.io/address/0xdc3431d42c0bf108b44cb48bfbd2cd4d392c32d6,余额为330 ETH(未统计erc20 token),最先进帐为2018-2-06,最新进帐为2018-3-20。

黑客攻击源IP

146.0.249.87(德国黑森州法兰克福)
162.251.61.133(加拿大)
190.2.133.114(库拉索)
85.14.240.84(德国北莱茵)

目前大部分的黑客使用https://github.com/regcostajr/go-web3进行频繁API请求,若是有看到大量user-agent为“Go-http-client/1.1”的POST请求时,请记录下请求内容,确认是否为恶意行为。

紧急响应及修复建议

  1. 关闭对外暴露的RPC端口,若是必须暴露在互联网,请使用鉴权:https://tokenmarket.net/blog/protecting-ethereum-json-rpc-api-with-password/
  2. 借助防火墙等网络防御软件,封堵黑客攻击源IP
  3. 检查RPC日志、web接口日志,是否有异常大量的频繁请求,检查请求内容是否为eth_sendTransaction
  4. 等待以太坊更新最新代码,使用修复了该漏洞的节点程序

文章来源:BLS区块链安全实验室官方网站

官网地址:http://www.sec-lab.io/

​​​​​


转载于:https://juejin.im/post/5ab87cdd6fb9a028ca52f539