はじめに
ParityMultisigWalletとは、イーサリアムのマルチシグウォレットの一つです。最近Parityチームから、マルチシグのセキュリティハッカー達によって、Parity1.5のクライアントのマルチシグ・ウォレットのコントラクトがハッキングされたということが報告されています。ハッカー達はICOのプロジェクトのEdgeless Casino, Swarm City, and æternityの3つのプロジェクトから、ICOプロジェクトに投資した人の持分を合わせ、153,037Ether(当時の価値で3000万ドル)を奪いました。
MultisigExploit-Hacker(MEH: マルチシグ専門のハッカー)は、Parityのクライアントのmultisig wallet contractの脆弱性を悪用しています。
第1回では「ParityWalletの脆弱性と技術的な攻撃の仕組み」を説明しました。第2回では、「攻撃に使用される関数delegatecall,ParityMultisigWalletへの2度目の攻撃について、ParityMultisigWalletの今後開発者が気をつけるべき点」に分けて説明していきます
本記事は、過去にコンセンサス・ベイスが主宰していたオンラインサロンの記事です。記事は2017年~2018年にかけて執筆されたため、一部は、既に古くなっている可能性があります。あらかじめご了承ください。
第1章 攻撃に使用される関数delegatecall
delegatecall関数について
delegatecall関数は、呼び出し元のWalletのコントラクト(または環境)でdelegatecall関数を実行することにより、動作します。これはライブラリのコードを読みこみ実行はしますが、ライブラリを呼び出した人によって直接データを変更することができることを意味します。基本的にはdelegatecall関数を実行することによって、ライブラリのコード(送金や管理者権限移行など)が簡単に実行できたということになります。delegatacallのストレージの書き込みは、ライブラリのストレージではなくWalletのコントラクトのストレージに書き込みがされます。delegatecall関数とは、コントラクトの実行時に別のアドレスから動的にコードをロードすることができます。今回の場合その際に攻撃者のアドレスでロードされ、ウォレットのストレージやアドレス、残高などが容易に参照できたため、被害が大規模になりました。
EVMのコントラクトについて
EVMでのコントラクトは、可変長バイナリを入力として受け取り、その出力として、可変長バイナリのデータを生成するプログラムです。そのコントラクトを用いたトランザクションでは、アドレスと複数のデータを扱うことが多いです。このアドレスにコードが格納されている場合、一部のデータがどこのindexに対応してるかは、標準のエンコードが使用されており、異なるコントラクトのコードにジャンプするジャンプテーブルという構造が使われています。
第1回第2章技術的な攻撃の仕組みのコードのアドレスを引数とするinitWalletという関数を呼び出すためのに必要なindexの値は、bytes4(sha3(“initWallet(address)”))と表せます。今回このジャンプテーブル構造を使って、攻撃されました。
第2章 ParityMultisigWalletへの2回目の攻撃
2回目の攻撃の内容
11月6日に、7月2日以降に導入されたすべてのParityMultisigWalletの資金が凍結しました。一部分の人はこれは150万ETHに影響を及ぼしていると推測しています。この攻撃が注目されているのは、攻撃された時期にParityMultisigWalletを用いて、資金を集めていたファンドやICOに資金を使っていたその顧客の資金がすべて凍結した為です。今回問題となったのは、ParityMultisigWalletを普通のParityWalletに戻すことによって、initWalletを呼ぶことができるようになったことです。この攻撃は2回の取引によって行われました。1つ目の取引は、7月19日のParityライブラリのトランザクション(0xae7168deb525862f4fee37d987a971b385b96952)を用いてinitWallet()関数の所有者を初期化しました。所有者はParityライブラリを自由に変更できるようになったので、Parityのライブラリを以前のMultisigWalletの状態にすることを可能にしました。下記に初期化のソースコードを記します。
//コントラクトが初期化されていない場合例外でスルーする
modifier only_uninitialized { if (m_numOwners > 0) throw; _; }
//オーナーと日付の制限の引数を渡すことで、権限を移行する
function initWallet(address[] _owners, uint _required, uint _daylimit) only_uninitialized {
initDaylimit(_daylimit);
initMultiowned(_owners, _required);
}
2つめは、通常のライブラリに初期化された後、攻撃者によって、3つ目のParityライブラリにある全てのWalletの機能を止める事ができるkill関数を呼ぶ事ができました。これは7月20日以降に作られた全てのWalletに影響を与えます。その為、このWalletは今なお使う事ができないのです。kill関数のソースコードを以下に記します。
function kill(address _to) onlymanyowners(sha3(msg.data)) external {
suicide(_to);
}
etherscan.ioのログから、消されたコードが他のParityMultisigWalletからコントラクトが呼び出されているのがわかっています。そして攻撃者自身をライブラリのコントラクトの所有者にすることができ、コントラクトを初期化しながらwalletを自由に扱うことができるようになりました。攻撃者はコントラクトを削除し、delegatecall関数を呼ぶことにより、開発用のテストを全て使えなくしたので、「isowner(
以上のコードは_toに機能をetherを奪いたいWalletのアドレスを設定する事でそのWalletのコントラクトの機能を停止する事ができます。
影響
脆弱なスマートコントラクトはParityTeamによって脆弱性が発見されました。影響を受けたマルチシグウォレットは全部で151アドレス( https://github.com/elementus-io/parity-wallet-freeze )にも及びます。crypto eli5によって集められた、152百万ドル(当時レートで513,743eth)が影響を受けてしまったのです。一番影響を受けたICOは、1億3千万ドル調達したPolkadot ICOだと言われています。3番目のParityライブラリは簡単にアップデートできないため、もし脆弱性が見つかった時にライブラリに依存することになり、対処が難しい状況にあります。セキュリティ対策ではNX, KASLR 等が実装されているため、過去20年間でかなりのセキュリティ改善が施されています。これらのセキュリティは新しいクラスのバグが見つかるとハードウェアとOSがバグを防いでくれます。その為、非常事態が起こったからハードフォークする、というのが唯一つの解決策ではなくなっています。
第3章 今後、開発者が気をつけるべき点
第1回目まとめ
今までのParityWalletの脆弱性と攻撃の仕組みから、第1回目では、ParityWalletから資金を引き出すことは比較的に容易であったということがわかります。ParityWalletでのinitWallet関数はWalletコントラクタでのみ実行され、ウォレット自身にはinitWallet関数はありません。つまり、トランザクションのデータのindexに対応させてウォレットに送信する呼び出しは全てが一致するとは限りません。したがって攻撃者にとっては、Wallet.initWallet(攻撃者のアドレス)を実行して呼び出すことは限りなく困難でした。
contract Wallet {
address _walletLibrary;
address owner;
function Wallet(address _owner) {
_walletLibrary = ;
_walletLibrary.delegatecall(bytes4(sha3("initWallet(address)")), _owner);
}
function withdraw(uint amount) returns (bool success) {
return _walletLibrary.delegatecall(bytes4(sha3("withdraw(uint)")), amount);
}
function initWallet(address[] _owners, uint _required, uint _daylimit) {
initDaylimit(_daylimit);
initMultiowned(_owners, _required);
}
// fallback function gets called if no other function matches
call
function () payable {
_walletLibrary.delegatecall(msg.data);
}
}
しかし、fallback関数によってテーブル内のデータが一致しない場合に応答するために作られた関数を用いることで、資金の受領及び予期しないデータの受け渡しを可能にしました。これにより、ウォレット内のライブラリを容易に呼び出すことができるようになっていました。ParityMultisigWalletではアドレスを別のものに変更しながら、同じウォレットに異なるアドレスを保管することができました。
この時ParityMultisigWalletは全てのトランザクション内容が誰でも見ることができた可能性があり、ガス費用を節約するために送金の取り消しなどの特定の機能を公開するために使用されていました。
したがって攻撃者がWallet.initWallet(address)を呼び出すと、fallback関数が呼び出されジャンプテーブルの参照に失敗します。Walletのfallback関数は、ウォレットライブラリをdelegatecallしてプロセス内のすべての呼び出しデータを転送します。この呼び出されたデータは、initWallet(address)と攻撃者のアドレスで構成されています。initWallet関数が呼び出されたデータを受け取ると、トランザクションの値と一致しWalletの所有者が攻撃者に変更されます。
第2回目まとめ
ParityMultisigWalletの問題点は、initWallet関数が直接呼び出された為、共有ライブラリが破壊されたことで、他のウォレットをライブラリの機能により使用できるようにしてしまったことです。投資した人たちにはEtherが凍結したように見えますが、実はコントラクトの所有者が全て保有していました。攻撃者がライブラリのコードを削除したことで、資金を引き出す為の必要なwithdraw関数が削除されてしまい、そこから引き出すこともできなくなってしまったのです。
技術的解決策
initWalletが内部的に記録されていた場合、ジャンプテーブルに対応するコントラクトが存在しないため、コントラクトの外部からinitWalletを呼び出すことが不可能になります。initWalletが二重初期化をチェックしていれば、問題はありませんでした。helper関数であるmodiferを用いることにより厳重な所有権制御を施す必要があります。また、今後はinternal を用いて外部参照ができないような仕組みづくりが重要であると言えます。また、スマートコントラクトでの脆弱性が発見された時に、ソースコードの書き換えが容易ではありません。その為ブロックチェーン上の貯蓄している資金の持続可能性を上げるべく、今後ソフトウェアレイヤー(APIなど)のセキュリティにも重点を置くことで、脆弱性を防げる可能性が高いです。
参考資料:
・The Parity Wallet Hack Explained
https://blog.zeppelin.solutions/on-the-parity-wallet-multisig-hack-405a8c12e8f7
・Parity Wallet Security Alert — Vulnerability in the Parity Wallet library contract
https://medium.com/crypt-bytes-tech/parity-wallet-security-alert-vulnerability-in-the-parity-wallet-service-contract-1506486c4160
・The $280M Ethereum’s Parity bug.
https://blog.comae.io/the-280m-ethereums-bug-f28e5de43513
免責事項
本記事に掲載されている記事の内容につきましては、正しい情報を提供することに務めてはおりますが、提供している記事の内容及び参考資料からいかなる損失や損害などの被害が発生したとしても、弊社では責任を負いかねます。実施される際には、法律事務所にご相談ください。
技術・サービス・実装方法等のレビュー、その他解説・分析・意見につきましてはblock-chani.jp運営者の個人的見解です。正確性・正当性を保証するものではありません。本記事掲載の記事内容のご利用は読者様個人の判断により自己責任でお願いいたします。
ブロックチェーン学習に最適の書籍の紹介
図解即戦力 ブロックチェーンのしくみと開発がこれ1冊でしっかりわかる教科書
本書は、ブロックチェーン技術に興味を持ったエンジニアや、その仕組みを学び、自分の仕事に活かしたいビジネスパーソンを対象にして、ブロックチェーンのコア技術とネットワーク維持の仕組みを平易な言葉で解説しています。この本を読んだうえで、実際にコードを書くような専門書、ブロックチェーンビジネスの解説書を読むことで、理解度が飛躍的に高まるでしょう。(はじめにより)
会社紹介
弊社(コンセンサス・ベイス株式会社)は、2015年設立の国内で最も古いブロックチェーン専門企業です。これまでに、大手企業の顧客を中心に、日本トップクラスのブロックチェーンの開発・コンサルティング実績があります。ブロックチェーンに関わるビジネスコンサル・システム開発・教育・講演などご希望でしたら、お気軽にお問い合わせください。
会社ホームページ
https://www.consensus-base.com/