主页 > imtoken在新手机上登录 > 以太坊“后走私时代”盗币“扫码攻击”
以太坊“后走私时代”盗币“扫码攻击”
0x00 前言
2018年08月01日,智造创域404区块链安全研究团队发布了后走私时代的走私漏洞及盗币方式介绍,并公开了后走私时代的三种盗币方式:线下攻击、重释放攻击和爆炸攻击。
在进一步的研究中,我们发现了这些攻击的补充:清除攻击。 攻击者要么诉诸矿工,要么拥有一定的算力,以获得将交易打包成块的权利。 在偷渡漏洞中,攻击者在被攻击节点上构造一个gasPrice为0的交易,等待用户解锁账户并签名广播。 攻击者还设置了一个恶意节点来接收交易。 攻击者可以将符合条件的交易打包,零手续费完成转账。 通过这种攻击,攻击者可以获得节点上余额不足以支付转账手续费或勉强支付手续费的所有以太币,在一定程度上可以防止其他攻击者的竞争,可以被描述为羊毛的典范。
此外,在收集到足够多的以太坊剩余物后,攻击者将目标锁定在这些被盗但仍留在账户中的代币上。 直到现在,很多智能合约发行的代币,部分被攻击账户中的代币,仍然被攻击者通过扫码攻击少量盗取。
本文将从一笔零手续费交易入手,模拟被盗币再现的实际过程,分析扫码攻击成功的关键点。
0x01 从零手续费交易开始
在区块链系统中,每笔交易都应附带一部分gas和相应的gasPrice作为服务费。 当交易被打包成区块时,这笔服务费将用于奖励完成打包的矿工。
在 中,我们提到了一个利用以太坊 JSON-RPC 接口的攻击者帐户 0x957cD4Ff9b3894FC78b5134A8DC72b032fFbC464()。 攻击者扫描公网开放的RPC端口,构造高额手续费的交易请求。 一旦用户解锁账户,用户的余额将转移到攻击者账户或攻击者创建的合约账户中。
在分析该账户的交易信息时,我们发现了一笔不符合常识的交易,我们先从这笔交易说起。
交易地址:0xb1050b324f02e9a0112e0ec052b57013c16156301fa7c894ebf2f80ac351ac22()
函数:转移(地址_TO,UINT256 _VALUE)方法ID:0xA9059CBB [0]:0000000000000000000000000000000000957CD4FF9B3894FC78B5134A8DC78DC72B032B032B032FFBC464 [1]:000000000000000000000000000000000000000000000000000000000000000000000000倍:000000000000000000000000000000000000000000000000000000000000000000倍:000000000000000000000000000000000000000000000000000000000000000000倍[1]
从0x00a329c0648769a73afac7f9381e08fb43dbea72()到合约MinereumToken(攻击者的合约)的交易,虽然用户余额很小,但是这个交易使用账户的所有余额作为价值与合约进行交互。 这笔交易使用了正常数量的 gas,但它的 gasPrice 被设置为 0。
如前所述,攻击者会用更高的费用来保证他的交易成功,而矿工会在节点的txpool中倒序排列每笔交易的gasPrice,并优先将gasPrice高的交易打包到后续区块中。 这个世界上每时每刻都在发生着无数的交易。 最近7天,一笔交易的最低gasPrice为3Gwei。 这笔零手续费交易是如何发生的以太坊rpc节点,又是如何打包到区块中的?
0x02 思路分析
在区块链系统中,任何人都可以加入区块链网络,成为节点之一,参与记账、挖矿等操作。 保证区块链的可信性和去中心化的核心是共识机制。
共识机制
在以太坊中,矿工将前一个区块的hash值、txpool中手续费高的交易、时间戳等数据打包,不断计算nonce进行挖矿。 最先获得符合条件的nonce值的矿工将拥有记账权,并获得手续费和挖矿奖励。 矿工将获得的区块进行广播,其他节点对这个区块进行验证。 如果没有错误,则认为新区块生成以太坊rpc节点,区块链高度增加。 这是每个节点生成新块以维持共识的过程。
完成0 gasPrice交易需要确认两个问题
接下来我们测试一下0 gasPrice交易的相关操作。 了解零手续费交易是如何产生的,它是如何被txpool接受的,包含零手续费交易的区块是否可以被识别,并确认以上问题的答案。
0x03 零手续费交易测试
一种。 单节点测试
首先我们确认一下这笔交易是否可以进入节点的交易池并启用测试链。 默认rpc端口为8545,使用python的web3包发起0gasPrice转账。
geth --networkid 233 --nodiscover --verbosity 6 --ipcdisable --datadir data0 --rpc --rpcaddr 0.0.0.0 控制台
节点1发起转账脚本,转账前需要解锁账户
from web3 import Web3, HTTPProviderweb3 = Web3(HTTPProvider("http://localhost:8545/"))print(web3.eth.accounts)#转账前必须解锁账户 web3.eth.sendTransaction({
“来自”:web3.eth.accounts[0],
“至”:web3.eth.accounts[1],
“价值”:10,
“气体”:21000,
“gasPrice”:0,
})
交互结果
> 交易池。 内容
{
待办的: {},
排队:{}
}
> eth.getBalance(eth.accounts[0])
80亿
> personal.unlockAccount(eth.accounts[0],'sissel')
真的
> INFO [08-14|11:20:14.972] 提交的交易 fullhash=0x72e81751d2517807cabad24102d3cc2f0f4f2e8b92f1f106f1ee0bf6be734fe4 收件人=0x92636b225F148e24407CfB2F2
> 交易池。 内容
{
待办的: {
0x092fda221a114FA702e2f59C217C92cfEB63f5AC:{
3:{
块哈希:“0x0000000000000000000000000000000000000000000000000000000000000000”,
块号:空,
来自:“0x092fda221a114fa702e2f59c217c92cfeb63f5ac”,
气体:“0x5208”,
气体价格:“0x0”,
散列:“0x72e81751d2517807cabad24102d3cc2f0f4f2e8b92f1f106f1ee0bf6be734fe4”,
输入:“0x”,
随机数:“0x3”,
r: "0x1eca20e3f371ed387b35ca7d3220789399a3f64c449a825e0fa7423b96ce235c",
s: "0x35a58e5cb5027c7903c1f1cc061ae846fb5150186ebbabb2b0766e4cbfc4aee6",
至:“0x92636b228148e2824cb8d472ef2f4e76f2f5059c”,
交易索引:“0x0”,
五:“0x42”,
值:“0xa”
}
}
},
排队:{}
}
> miner.start(1)
INFO [08-14|11:20:35.715] 更新的挖掘线程 threads=1
INFO [08-14|11:20:35.716] 交易池价格阈值更新价格=18000000000
无效的
INFO [08-14|11:20:35.717] 开始采矿作业
> INFO [08-14|11:20:35.719] 提交新的挖矿工作 number=115 txs=1 uncles=0 elapsed=223µs
> mINFO [08-14|11:20:36.883] 成功封新区块 number=115 hash=ce2f34…210039
信息 [08-14|11:20:36.885] ? 块达到规范链号=110 哈希=2b9417…850c25
信息 [08-14|11:20:36.886] ? 挖掘出的潜在区块数=115 hash=ce2f34…210039
INFO [08-14|11:20:36.885] 提交新的挖矿工作 number=116 txs=0 uncles=0 elapsed=202µs
> miner.stop()
真的
> eth.getBalance(eth.accounts[0])
799999990
节点 1 发起的零手续费交易成功,交易被挖矿成功打包入块。
b. 多节点共识测试
现在加入另一个节点
geth --datadir "./" --networkid 233 --rpc --rpcaddr "localhost" --port 30304 --rpcport "8546" --rpcapi "db,eth,net,web3" --verbosity 6 --nodiscover安慰
使用这些方法添加节点
> admin.nodeInfo
> admin.addPeer()
> admin.peers
节点1仍然使用刚才的脚本发起零手续费交易,成功添加到节点1的txpool中,但是节点2因为gasPrice不合法拒绝了交易。
TRACE[08-15|10:09:24.682] 丢弃无效交易 hash=3902af...49da03 err="transaction underpriced"
> 交易池。 内容
[]
在geth的配置中找到了一个与此相关的参数
--txpool.pricelimit value 强制接受池中的最低 gas 价格限制(默认值:1)
启动时将其更改为0,但交易仍然没有出现在节点二的txpool中。
看了源码,这个参数确实是控制txpool添加交易的最小gasPrice,但是不能小于1。
如果确认。 限价 < 1 {
log.Warn("清理无效的 txpool 价格限制", "provided", conf.PriceLimit, "updated", DefaultTxPoolConfig.PriceLimit)
conf.PriceLimit = DefaultTxPoolConfig.PriceLimit
}
让节点1(txpool中gasPrice为0)开始挖矿,将交易打包成一个区块,发现节点2认可了这个区块,达成共识,两个节点的高度都增加了。
得出结论:
我们将执行一个简短的源代码分析来支持我们的结论。
0x04 源码分析
(以下代码分析基于最新commit:commit 6d1e292eefa70b5cb76cd03ff61fc6c4550d7c36)
目前以太坊中最流行的节点程序(Geth/Parity)都提供了RPC API,用于连接矿池、钱包等第三方程序。 首先确认节点打包txs时代码的实现。
一世。 交易池
代码路径:./go-ethereum/core/tx_pool.go
// TxPool 包含所有当前已知的交易。 交易//在从网络接收或//在本地提交时进入交易池。 当它们被包含在区块链中时,它们就会退出池。 输入 TxPool 结构 {
配置 TxPoolConfig
chainconfig *params.ChainConfig
chain区块链
gasPrice *big.Int //最低GasPrice限制
/* 其他参数*/}
生成tx实例时,发现有最低要求gasPrice。 具体来说,这个函数会拒绝接受这个交易。
// validateTx 根据共识// 规则检查交易是否有效,并遵守本地节点的一些启发式限制(价格和大小)。func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
// 这是 gasPrice 的检查
if !local && pool.gasPrice.Cmp(tx.GasPrice()) > 0 {
返回错误定价过低
}
/* ... */
返回零}
二. 删除低于阈值的交易
代码路径:./go-ethereum/core/tx_list.go 并且在处理txs时,会删除低于阈值的交易,但不会删除本地交易。
// Cap 找到所有低于给定价格阈值的交易,将它们// 从定价列表中删除并返回它们以进一步从整个池中删除。func (l *txPricedList) Cap(threshold *big.Int, local *accountSet)类型。 交易{
drop := make(types.Transactions, 0, 128) // 要删除的远程低价交易
save := make(types.Transactions, 0, 64) // 要保留的本地低价交易
对于 len(*l.items) > 0 {
// 如果在清理过程中发现,则丢弃过时的事务
tx := heap.Pop(l.items).(*types.Transaction)
如果 _,好的 := (*l.all)[tx.Hash()]; !行 {
// 如果找到一个被删除的,更新状态计数器
湖。 陈皮——
继续
}
// 如果达到阈值则停止丢弃
如果 tx.GasPrice().Cmp(阈值) >= 0 {
// 如果价格不低于阈值,则退出
保存=追加(保存,TX)
休息
}
// 发现非陈旧事务,丢弃除非本地
if local.containsTx(tx) { //本地交易不会被删除
保存=追加(保存,TX)
} 别的 {
drop = 追加(drop,tx)
}
}
对于 _, tx := 范围保存 {
堆。 推送(l。项目,tx)
}
回落}
以上部分是区块链网络中的一个节点。 当尝试接收或加入 gasPrice 为 0 的交易时,会有一些过滤或规则限制。 但是通过修改源码,我们仍然可以合法地将gasPrice为0的交易添加到区块中,然后进行nonce计算。 接下来继续源码分析,检验这样得到的区块是否能被其他节点接受并达成共识。
三. 共识验证
代码路径:./go-ethereum/consensus/consensus.go 这是geth提供的共识算法引擎接口
类型引擎接口{
// 符号
Author(header *types.Header) (common.address, 错误)
/* 校验header、seal、processing difficulty等函数... */
// 预处理区块头信息,修改难度等
Prepare(chain ChainReader, header *types.Header) 错误
// 区块奖励等,区块被挖出后的事情
Finalize(chain ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction,
uncles []*types.Header, receipts []*types.Receipt) (*types.Block, 错误)
// 计算nonce,如果收到更高的链,退出
Seal(chain ChainReader, block *types. Block, stop
// 计算难度值
CalcDifficulty(chain ChainReader, time uint64, parent *types.Header) *big.Int
// APIs 返回此共识引擎提供的 RPC API。
APIs(chain ChainReader) []rpc.API
// Close 终止由共识引擎维护的任何后台线程。
关闭()错误}
查看VerifySeal(),发现验证了以下内容:
可以看出,其他节点对共识的签名、nonce等进行了校验,对零手续费交易没有进行校验。 换句话说,虽然零手续费交易不会激励矿工,但它仍然是合法的。
0x05 开发过程
攻击者首先利用偷渡漏洞构造一个零手续费的正常转账交易。 用户解锁账户后,广播交易。 具体过程如下图所示:
0x06 摘要
由此,我们可以得出结论,对于像0 gasPrice这样的特殊交易,可以得出以下结论:
因为json-rpc接口的攻击方式,攻击者可以签署一个0gasPrice的交易,并通过偷渡漏洞进行广播。 通过收集这样的0gasPrice交易并加入到一些矿工的txpool中,当矿工挖出新的区块时,这些交易也会被打包。 即攻击者可能与部分矿工联手,或者攻击者本身具有一定的算力,使得矿工不再遵循诚实挖矿的原则来维护区块链系统。
0x07 利用价值和防御计划
因为零手续费交易的出现,很多低收益的攻击都会有意义。
增加收入
攻击者可以利用该方法,结合其他攻击手段,将被攻击账户内的余额全部转出,实现利润最大化。
羊毛用尽
根据上文提到的攻击方式,如果账户余额较小,甚至不足以支付转账手续费,则可以通过上述的羊毛攻击方案将账户中的剩余部分收入囊中。 由于本次交易的gasPrice为0,因此可以在一个区块中同时打包多笔此类交易,例如本合约下的多笔交易:0x1a95b271b0535d15fa49932daba31ba612b52946(),本区块中的几笔交易:4788940()
走私代币
在被盗账户没有以太坊的情况下,攻击者发现这些账户中仍然存在部分智能合约发行的代币。 没有以太坊就无法为转账支付gas,而零手续费交易可以完美解决这个问题。 直到现在,还有很多没有以太坊的被攻击账户,还在以这种方式转移代币。
防御计划
由于0gasPrice交易只是扩展其他攻击方案的一种方式,因此防御也应着眼于之前json-rpc接口的使用。
0x08 影响规模
我们从上面提到的 0 gasPrice 交易开始。 调查发现,近期仍有不少gasPrice为0的交易。 大部分零手续费交易来自矿池:0xb75d1e62b10e4ba91315c4aa3facc536f8a922f5()和0x52e44f279f4203dcf680395379e5f9990a69f13c(),如区块6161214()、6160889()等。
我们注意到这些0gasPrice的交易,只是前期的少量交易,会携带较少的ETH,符合我们对其羊毛特性的预期。 据统计,自2017年6月以来,共计748个账户共计24.2eth零手续费转账。
还发现了中提到的重放攻击,导致的账号丢失:0x682bd7426ab7c7b4b5beed331d5f82e1cf2cecc83c317ccee6b4c4f1ae34d909()
0.05eth被盗
在这0个gasPrice中,更多的是对合约发行的TOKEN的转账请求,将用户账户中的token转入合约所有者的账户(),例如:
此帐户的 tx 记录。
攻击者拥有多个矿池的算力,将多个被攻击账户拥有的各种代币转移到相应的账户中。 虽然单笔交易金额不大,但是可以进行这种攻击方式的账户却很多。 更多,且无手续费。 加起来,直到现在,攻击者仍在清除这些令牌。
0x09 结语
区块链系统是基于去中心化才能实现交易的共识。 一个前提是绝大多数矿工将通过诚实的挖矿来维护整个比特币系统。 当矿工不再诚实时,区块链的可信度和去中心化程度都会大大降低。 当黑客与矿工结合,或者黑客本身拥有算力成为矿工时,他们会在现有攻击方式的基础上提供更多扩展的攻击方案。
0 gasPrice 交易的出现违背了区块链设计的初衷,即矿工应该支付手续费作为激励。 区块链技术和虚拟货币的普及,赋予了链上货币巨大的经济价值,人人都想在区块链浪潮中分一杯羹。 对于黑客来说尤其如此。 作为窃取者,他们绞尽脑汁从各个角度攻击区块链和合约。 当黑客寄居矿工时,他们不仅可以挖出区块,还可以挖出漏洞。
▼智能合约审计服务▼
针对目前主流的以太坊应用,智创宇提供专业、权威的智能合约审计服务,避免因合约安全问题造成的财产损失,为各类以太坊应用的安全保驾护航。
知乎创宇404智能合约安全审计团队: