内容简介:作者:sunsama@知道创宇404区块链安全研究团队为了迎合以太坊区块链[1]发展需求,Microsoft Azure[2]早在2016年9月九推出了以太坊节点走自动部署的模块。部署情况如下:登陆Microsoft Azure:
作者:sunsama@知道创宇404区块链安全研究团队
背景介绍
为了迎合以太坊区块链[1]发展需求,Microsoft Azure[2]早在2016年9月九推出了以太坊节点走自动部署的模块。部署情况如下:
登陆Microsoft Azure:
部署Ethereum Proof-of-Work Consortium:
访问建立的“ADMIN-SITE”可以看到一个“Blockchain Admin”界面:
我们注意到这个管理接口提供了一个“转账”功能并且整个页面缺少鉴权机制任何人都可以访问,这样就导致恶意攻击者可以通过该接口提交钱包地址和转账数量进行转账。
Web3.js 是⼀个兼容了以太坊核心功能的JavaScript库[3],很多以太坊客户端及DApp都是通过调用Web3.js的API接⼝来实现。 以太坊客户端开发库主要是提供了两种类型的API接口:RPC(Remote Procedure Call)及IPC(Inter-process Communications),在以往的攻击事件里很多关注点都在RPC接口上,而很少关注IPC接口,在本文的涉及“Blockchain Admin”的问题就发生在IPC接口上,由此下面做了详细的代码分析:
代码分析
在分析之前我们先介绍下PRC及IPC接口区别:
IPC与RPC简介
IPC(Inter-process Communications)进程间通信,是指在不同进程之间传播或交换信息,IPC的方式通常有管道、消息队列、信号量、共享存储、Socket、Stream等。对于geth来说IPC的方式更为高效,在安装geth之后 IPC socket不会自动创建,并且他也不是一个永久的资源,只有在启动geth时才会创建一个IPC Socket。
有以下几个参数可以在启动geth时配置IPC相关服务,其他参数可以使用geth —help查看。
--ipcdisable Disable the IPC-RPC server --ipcapi "admin,eth,debug,miner,net,shh,txpool,personal,web3" API's offered over the IPC-RPC interface --ipcpath "geth.ipc" Filename for IPC socket/pipe within the datadir (explicit paths escape it)
在geth启动时使用 --ipcpath来指定一个IPC路径,会有一段信息指明IPC的相关信息。例如
IPC endpoint opened: /Users/username/Library/Ethereum/geth.ipc
Web3.js中提供了使用IPC通信的方法。
// Using the IPC provider in node.js var net = require('net'); var web3 = new Web3('/Users/myuser/Library/Ethereum/geth.ipc', net); // mac os path // or var web3 = new Web3(new Web3.providers.IpcProvider('/Users/myuser/Library/Ethereum/geth.ipc', net)); // mac os path // on windows the path is: "\\\\.\\pipe\\geth.ipc" // on linux the path is: "/users/myuser/.ethereum/geth.ipc"
node_modules/web3/lib/web3/ipcprovider.js
var IpcProvider = function (path, net) { var _this = this; this.responseCallbacks = {}; this.path = path; this.connection = net.connect({path: this.path}); ............... };
https://github.com/ethereum/go-ethereum/wiki/Management-APIs 中给出了在命令行使用IPC的例子
RPC(Remote Procedure Call)远程过程调用,指通过网络从远程计算机的程序上请求服务。geth为RPC提供了两种方法,分别是HTTP JSON RPC API(默认8545端口)和WebSocket JSON RPC API(默认8546端口)。
在命令行中可以使用以下参数配置RPC服务。
--rpc 启用HTTP-RPC服务器 --rpcaddr value HTTP-RPC服务器接口地址(默认值:“localhost”) --rpcport value HTTP-RPC服务器监听端口(默认值:8545) --rpcapi value 基于HTTP-RPC接口提供的API WebSocket --ws 启用WS-RPC服务器 --wsaddr value WS-RPC服务器监听接口地址(默认值:“localhost”) --wsport value WS-RPC服务器监听端口(默认值:8546) --wsapi value 基于WS-RPC的接口提供的API --wsorigins value websockets请求允许的源
同样的在Web3.js中也提供了使用RPC的方法。
Http Api var Web3 = require('web3'); var web3 = new Web3('http://localhost:8545'); // or var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); WebSocket Api // change provider web3.setProvider('ws://localhost:8546'); // or web3.setProvider(new Web3.providers.WebsocketProvider('ws://localhost:8546'));
/** * HttpProvider should be used to send rpc calls over http */ var HttpProvider = function (host, timeout) { this.host = host || 'http://localhost:8545'; this.timeout = timeout || 0; };
以太坊黑色情人节事件中,攻击者就是利用了RPC接口进行恶意转账。
流程分析
我们在Blockchain Admin页面的两个输入框中输入转账地址和转账数量并提交。
/home/ethtest/etheradmin/app.js定义了提交后服务器处理的方法。
命令行中的参数 var listenPort = process.argv[2] var gethIPCPath = process.argv[3]; var coinbase = process.argv[4]; var coinbasePw = process.argv[5]; var consortiumId = process.argv[6]; var registrarHostEndpoint = process.argv[7]; var registrarConnectionString = process.argv[8]; var registrarDatatbaseId = process.argv[9]; var registrarCollectionId = process.argv[10]; 定义了使用IPC服务 var web3IPC = new Web3(new Web3.providers.IpcProvider(gethIPCPath, require('net'))); ·············· app.post('/', function(req, res) { var address = req.body.etherAddress;//转账地址 var amount = req.body.amount;//转账数量 if(web3IPC.isAddress(address)) { //如果提交的地址是以太坊地址则解锁账号 web3IPC.personal.unlockAccount(coinbase, coinbasePw, function(err, res) { console.log(res); //通过ipc方法发送一笔交易 web3IPC.eth.sendTransaction({from: coinbase, to: address, value: web3IPC.toWei(amount, 'ether')}, function(err, res){ console.log(address)}); }); req.session.isSent = true; } else { req.session.error = "Not a valid Ethereum address"; } res.redirect('/'); });
使用POST方法提交后,会判断我们输入的地址是否是合法的以太坊地址。默认情况下我们的账号是处于锁定状态的,这里判断地址正确后使用 personl.unlockAccount() 方法解锁账号。该方法需要的参数coinbase和coinbasePw在启动服务时已经在命令行中作为参数传递过来了,使用ps命令查看该服务的进程。
其中 f9cdc590071d9993b198b08694e5edf376979ce6 是我们的钱包地址, 123qweasdZXC 是解锁钱包需要的密码, /home/ethtest/.ethereum/geth.ipc 是 getIPCPath 参数的内容。
personal.js中的 unlockAccount 方法。
var unlockAccount = new Method({ name: 'unlockAccount', call: 'personal_unlockAccount', params: 3, inputFormatter: [formatters.inputAddressFormatter, null, null] });
IpcProvider.js中对发送方法的定义。
IpcProvider.prototype.send = function (payload) { if(this.connection.writeSync) { var result; // try reconnect, when connection is gone if(!this.connection.writable) this.connection.connect({path: this.path}); var data = this.connection.writeSync(JSON.stringify(payload)); try { result = JSON.parse(data); } catch(e) { throw errors.InvalidResponse(data); } return result; } else { throw new Error('You tried to send "'+ payload.method +'" synchronously. Synchronous requests are not supported by the IPC provider.'); } };
ipcprovider会调用JSONRPC.js将 unlockAccount 方法中的参数格式化为JSON格式。
在node_modules/web3/lib/web3/ipcprovider.js中下断点跟踪一下数据流。
然后将数据通过socket写入。
接下来 geth 通过 IPC 接收到了请求的方法和参数,然后使用 UnlockAccount 函数进行账户解锁,解锁账户后使⽤eth.sendTransaction⽅法发送交易。
sendTransaction方法会使用已经解锁后的本地账户的私钥进行签名,并使用 SignedTransaction 方法进行发送签名后的交易。
我们通过geth日志获取交易hash,在console中查看详细信息。
- 下面是从提交交易请求到生成交易并发送的流程图。
值得一提的是:在我们分析过程发现通过Microsoft Azure提供的以太坊节点自动化部署方案仍然使用的1.7.3版本的geth ⽽这个版本里UnlockAccount函数:
func (s *PrivateAccountAPI) UnlockAccount(addr common.Address, password string, duration *uint64) (bool, error) { const max = uint64(time.Duration(math.MaxInt64) / time.Second) var d time.Duration if duration == nil { d = 300 * time.Second } else if *duration > max { return false, errors.New("unlock duration too large") } else { d = time.Duration(*duration) * time.Second } err := fetchKeystore(s.am).TimedUnlock(accounts.Account{Address: addr}, password, d) return err == nil, err }
wiki中对personal_unlockAccount方法的定义:
从keystore中解锁账户并获得私钥,并把已经解锁的私钥放到内存中。解锁账户的api允许传入超时时间,默认超时为300秒,如果传⼊入的超时时间为0,则是永久不不会超时,账户⼀直处于解锁状态,直到节点进程退出。这也是“以太坊【偷渡】漏洞事件[5]”发生的主要原因。
风险评估
在以往的关于以太坊攻击案例里更多的是发生在暴露在互联网的RPC接口上,⽽基于本地进程通讯的IPC接口 被认为是相对安全可靠的,但是如果类似于Microsoft Azure提供的以太坊节点⾃动化部署⽅案里 的“Blockchain Admin”基于IPC调⽤程序,本身没有任何认证直接暴露在互联网上无疑是巨大的安全风险。(注:通过ZoomEye⽹路空间搜索引擎[7]可以看到曾经暴露在互联网上的目标。)
在实际测试分析过程发现使用Microsoft Azure提供的以太坊节点自动化部署方案更多的是联盟链或私有链,部署共有链的情况较少,所以这个安全事件实际可能给共有链的带来的影响相对不大。对于联盟链或私有链的影响需要根据其本身的情况去衡量量评估。
报告流程
针对以上问题我们第一时间联系了微软:
- 2018年5月21日 相关问题描叙报告给MSRC邮件 secure@microsoft.com
- 2018年5月22日 收到MSRC邮件反馈并按要求补充了相关技术细节
- 2018年5月24日 收到MSRC Case分配确认邮件
- 2018年5月31日 收到MSRC关于ZoomEye搜索引擎相关细节询问并反馈
- 2018年7月6日 邮件MSRC追问相关问题修复进展
- 2018年7月10日 收到MSRC反馈邮件称:他们认为这个是设计考虑的问题,用户可以选择对管理页面进行限制,另外升级了Geth版本
总结
区块链虚拟货币安全事件频发,安全刻不不容。通过这次的案例可以得几点建议:
-
尽量避免使用这种自动化部署区块链应用的方案,如果必须使用的话,请仔细查看该方案使用的程序是否存在安全缺陷与漏洞。
-
修改默认端口,关闭对外的高权限接口,如果必须暴露在互联网,请对接口进行鉴权。
-
关注官方发布的更新日志,及时更新代码。
针对目前主流的以太坊应用,知道创宇提供专业权威的智能合约审计服务,规避因合约安全问题导致的财产损失,为各类以太坊应用安全保驾护航。
知道创宇404智能合约安全审计团队: https://www.scanv.com/lca/index.html
联系电话:(086) 136 8133 5016(沈经理,工作日:10:00-18:00)
参考
[1] https://baike.baidu.com/item/%E4%BB%A5%E5%A4%AA%E5%9D%8A/20865117?fr=aladdin
[2] https://azure.microsoft.com/en-us/
[3] https://github.com/ethereum/web3.js/
[4] https://github.com/ethereum/go-ethereum/wiki/Management-APIs
[5] https://paper.seebug.org/547/
[6] https://mp.weixin.qq.com/s/Kk2lsoQ1679Gda56Ec-zJg
[7] https://www.zoomeye.org/searchResult?q=%22Blockchain%20Admin%22
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 闪电网络最新漏洞分析:仅需攻击85个节点便可窃取闪电节点通道资金
- xml创建节点(根节点、子节点)
- Vultr VPS 节点选择方法 | 各节点延迟一览
- 1.19 JQuery2:节点插入与节点选取
- POC分布式节点算法机制下的超级节点计划
- tikv节点下线缩容后改造成tidb节点记录
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Developing Large Web Applications
Kyle Loudon / Yahoo Press / 2010-3-15 / USD 34.99
As web applications grow, so do the challenges. These applications need to live up to demanding performance requirements, and be reliable around the clock every day of the year. And they need to withs......一起来看看 《Developing Large Web Applications》 这本书的介绍吧!