• 注册
  • 综合生活 综合生活 关注:37 内容:287

    Parity钱包被盗事件

  • 查看作者
  • 打赏作者
  • 拉黑名单
    • 综合生活
    •  井底望天:大家知道上次parity那个钱包被盗了3000万美元,是啥回事吗? 

       井底望天: @蝙蝠猫 懂不懂multi-sign呢? 

       多重签名 

       单签名钱包,就是你有一个私人钥匙 

       多签名钱包,就是应对你公司账号,要几个人一起签名才行 

       这个明白吗? 

       好了,现在我一个多签名钱包,好比说,我有三个钱包主人,每个人有不同的私钥 

       那么需要至少两个私钥签名才行 

       才可以动用里面的钱 

       好了,那现在搞初始化 

       我们创建一个多签名钱包,然后把我们仨个人的地址放进去,规定2/3的签名才有效 

       但是,后来发觉这个初始化加人的功能,被错误地写成了一个公开public的function 

       什么意思呢?就是任何外人,都可以调用这个功能,去添加地址 

       现在黑客来了,自己加了4个新地址进去了 

       那么就变成如果你有7个主人,4/7的签名就有效了 

       所以黑客就签了4个签名,把里面的以太币给发走了 

       就这么简单,呵呵 

       我们这里有没有专业软件高手? 

       如果有,我可以说得更具体,呵呵 

       这么说吧,因为你在以太坊上面部署合约 

       用的时候,会调用里面的程序,肯定就要交gas 

       那么节省的一个办法,就是去调用已经部署的公共库 

       Parity的多签名钱包,也是这样干的,去调用了一个公共库 

       

      程序代码: [url=][选择][/url]

      addressconstant_walletLibrary=0xa657491c1e7f16adb39b9b60e87bbb8d93988bc3; 

       那么调用方法,就是用delegatecall 

       不懂程序的,就这么说,你反正传一个名字过去,它就会调用同名的程式 

       一个例子 

       

      程序代码: [url=][选择][/url]

      function isOwner() constant returns(bool){

        return_walletLibrary.delegatecall(msg.data);

       这个就是去调用库里面的isOwner 

       但是Solidity干了一个错误的事情,就是让你可以自己设计一个后备程式 

       就是任何找不到同名的程式,都来这里 

       结果Parity的同学们就写了一个程式,让你找不到名字的送以太币的程式,全部去一个自己设定的程式 

       

      程序代码: [url=][选择][/url]

      function() payable {

        //justbeingsentsomecash?

        if(msg.value>0)

          Deposit(msg.sender,msg.value);

        elseif(msg.data.length>0)

          _walletLibrary.delegatecall(msg.data);

       这个,就是被人攻击了 

       这个程序是什么意思? 

       1.首先,你去调用一个程式,它的名字,在你的合约里面没有,就进这个地方了 

       2.如果你这个程式,里面发送以太币,就走第一个分叉,如果没有 

       3.如果没有以太币发送,但是有数据,就去第二个分叉,去调用公共库 

      井底望天:那么黑客就写了这么一个程式 

      程序代码: [url=][选择][/url]

      functioninitWallet(address[]_owners,uint_required,uint_daylimit)

      {

        initDaylimit(_daylimit);

        initMultiowned(_owners,_required);

      }

       结果这个initWallet,没有在多签名合约里面,但是在公共库里面 

       里面就调用了initMultiowned这个程式 

       

      程序代码: [url=][选择][/url]

      functioninitMultiowned(address[]_owners,uint_required

      {

        m_numOwners=_owners.length+1;

        m_owners[1]=uint(msg.sender);

        m_ownerIndex[uint(msg.sender)]=1;

        for(uinti=0;i<_owners.length;++i

        {

            m_owners[2+i]=uint(_owners);

            m_ownerIndex[uint(_owners)]=2+i;

        }

        m_required=_required;

       发生了什么? 

       就是现有钱包的主人,就被全部替换掉了,呵呵 

       大家明白点了吧? 

       问题在哪里? 

       1.库里面的initWallet和initMuitiWallet,应该标上intenal,就是作为私人程式,不能允许外面调用 

       internal 

       2.你应该至少检查一下,人家这个钱包是不是已经有了啊 

       如果有了,就拒绝初始化,新钱包才可以做 

       这个是Solidity这边的问题 

       那么在Parity这边,你不应该盲目让delegatecall干所有事情 

       你应该有个白名单限制哪些功能可以做 

       结果就是这次的黑客水平也不算高 

       他们只是直接找到最有钱的三个账号,去手动攻击了 

       结果白帽子们,才可以用脚本,把其他账号,给先攻击掉 

       如果黑客水平高一点 

       直接用脚本攻击,呵呵 

       那就不是这三家了额,呵呵 

       最后搞掉3100万美元,呵呵 

       白帽子好像最后救了1.8亿美元下来,呵呵 

       也不行啊,没有其他的保护手法 

       关键是区块链的码农,不少是是网络码农转过来的

       不是安全系统码农

      请登录之后再进行评论

      登录
    • 做任务
    • 实时动态
    • 偏好设置
    • 返回顶部
    • 帖子间隔 侧栏位置: