原创 标题:  以太币被盗问题解答

以太币被盗问题解答

最近在技术讨论群(QQ群: 659809063)和网上遇到很多以太坊被盗的问题,这种盗窃场景往往发生在初次接触以太坊的同学身上。今天就简单总结一下这种被盗的原因和场景。

被盗场景

下面是一段网上论坛寻求解答的一个提问,也正是我们今天要讲的典型的以太币被盗场景。

1、前一天晚上,我们用本地代码去连接阿里云以太坊节点(公链)服务器做交易,私钥文件(A地址)保存在服务器上,交易时,失败了,到etherscan查交易时发现以太币被转到一个不认识的地址(H地址),这时尚未意识到被盗,怀疑代码存在问题。

2、第二天,往A地址转了点以太币,然后在服务器上的命令行做交易,命令行查询帐户以太币正常,解锁帐户后,交易失败,到etherscan查交易时发现以太币被转到昨天的地址(H地址),pending。

3、我们分析可能是私钥泄漏、密码简单,于是在服务器上新创建了一个地址(B地址),密码变复杂了,又转了点以太币,更新的了以太坊客户端(从1.7.3更新到1.8.1),同样在服务器上的命令行做交易,命令行查询帐户以太币正常,解锁帐户后,交易又失败了,查得以太币被转走(H地址),pending。

4、这次分析可能是服务器感染病毒,于是格式化服务器,重新搭建环境,创建帐户,转以太币,还是在命令行做交易,又发生了同样的问题,以太币被转走(K地址),pending
这到底是什么问题,哪位大神遇到过,帮忙解答下,小弟不胜感激!!!

问题还原及解答

看到这里很多掉进此坑的朋友可能已经知道了被盗的原因,现在我们就分析一下,让后来者避免再重蹈覆辙。

其实,这个问题的原因很简单,问题就出在以太坊的转账时的解锁机制。很明显,这位同学的以太坊节点是可以公网访问,没有限制入网ip。我们都知道,当发起转账交易时是需要进行解锁,看一下解锁的代码:

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
}

通过源代码我们可以看到,如果没有传递解锁时间参数,系统会默认将发起交易的账号解锁300秒。而以太币被盗就发生在这恐怖的300秒,在没有一点安全防护的节点服务器,这意味着在5分钟内,任何人都可以调用转账方法将此账户的以太币转到其他账户。黑客通过工具监听到某个地址被解锁,马上就调用该服务的该地址出高价手续费将余额全部转走。

小结

以上就是新手常见的被盗场景之一,或许你还正在疑惑为什么我发出交易的时候代码报转账手续费不足,而在这之前你的以太币已经不翼而飞。针对这个问题最简单的防护措施就是确保服务器的访问限制。至于更高级的安全防护新手很难做的,也是一个很大的课题,后面的文章中会陆续讲解。

END
朱智胜的个人博客-微信公众号