はじめに
こんにちは。新規事業開発室の山口 (@yamarkz) です。
ERC20に準拠したトークンコントラクトの脆弱性問題について4/25辺りからSNS上で大きな話題になりました。
ERC20速報:イーサリアムベースのプロジェクトが使用するERC20準拠のコントラクトのBatch Transfer関数のバグで取扱い数を超えるトークンをコスト0で生成し送金できるバグが発見される。実際にBeautyChainトークンの $BEC が数十兆を優に超える数が送金される #イーサリアム #ERC20 #仮想通貨 https://t.co/wy7eF7zFx5
— 墨汁うまい(BlockchainUmai) (@bokujyuumai) 2018年4月25日
今回はこの脆弱性問題について技術的な観点からどういった問題なのかを解説していきたいと思います。
ERC20やトークンコントラクトの解説は下記記事で行なっています。参考にして見てください
BatchOverFlowと呼ばれる脆弱性問題に対する結論
まず、結論を先に述べます。
このBatchOverFlowと呼ばれる脆弱性問題はERC20に準拠した処理で発生したものではなく、トークンコントラクトに独自実装された batchTransfer
と呼ばれる関数で発生した脆弱性問題です。
なので、この batchTransfer
と呼ばれる処理が含まれていないERC20に準拠したトークンでは何ら問題はなく、batchTransfer
の処理が含まれたトークンコントラクトが問題となっています。
SNS上で情報を追っていると、「ERC20準拠のトークンに問題があり、Ethereum史上最大の事件だ!」という様な情報が見受けられました。
この文脈から、あたかもERC20準拠トークン全てに問題が起きている様な状況が想像されますが。この問題はERC20に準拠したトークンの中で、batchTransferという機能を含んだトークンコントラクトで脆弱性が見つかったというのが正しい認識です。なので、Ethereum全体から見ると問題自体は局所的で、ERC20に準拠したトークン全ての価値が脅かされるという問題ではありません。
とはいえ、この問題によりいくつかのトークン価値が失われており、資産価値的観点から見ると大きな損失が生まれてしまっているのは事実です。
この問題について技術的観点からより深く仕組みを見ていきたいと思います。
BatchOverFlowの仕組み
今回話題になったトークンコントラクトのバグは「BatchOverFlow」と呼ばれるもので、この問題に対する詳細な解説は4/23にMedium上で紹介されています。(1次情報は下記リンクを参照)
このバグはBeutyChainと呼ばれるプロジェクトのERC20に準拠したトークンコントラクトで見つかりました。 実際にライブネットにデプロイされたソースコードはこちらから確認することができます。
トークンホルダーのリストを見ると特定のアドレスが保有するトークン量がものすごい額になっています。これが今回の問題で発生した現象です。参考
脆弱性があった batchTransfer
という関数は以下です。
この関数は、関数を呼び出したアカウントから複数の送信先アカウントに対して同一量のトークンを1度に送信するための処理です。
関数の引数は2つ
_receivers
送信先アカウントアドレスの配列_value
送信トークン量
上記の処理ではamount変数に送信先アドレス数(receivers) * 送信トークン数(value)で算出した値を代入しています。 次に、「amount額を送信主が保有するトークンより超えないか」「0より大きい額で20より小さい額のトークンを送信しているか」を判定しています。 2つの判定をrequireでバリデート処理し、失敗した場合例外エラーが発生処理が終了します。成功した場合、処理実行が続きます。
そして、実際にアカウントが保有するトークン量をシフトチェンジする処理です。 amout額を送信元のアカウントから差し引き(.sub)、for文で_valueの額をreciversのアカウントアドレスに追加(.add)します。 送信先アカウントに対して送信が完了した事を伝えるEvent(Transfer)を発行し、処理が終了した事を伝えるtrueを返して処理が終了します。
この処理の流れで今回脆弱性の問題となったのは uint256 amount = uint256(cnt) * _value;
の部分で、送信元アカウントからの送信総額を算出処理です。
valueはuint256型です。仮に送信者が5トークン保有しており、receiverに2つ以上のアドレスと_valueに2以上で乗算し5以下のになる大きな数を渡したとします。
2つ以上のアドレスとvalueに乗算した結果、オーバーフローが発生し数が5以下0以上になる。このオーバーフローの発生により数字が変わることでバリデーションが通ることになります。その結果、本来想定していない大きな額(_value)がreciverのアドレスに付与されます。
※ オーバーフロー問題に関するわかりやすい解説はこちらを参考。
これにより攻撃者は特定のアカウントが所有するトークン量を簡単に増やすことができるようになり。結果、トークン全体の供給量が壊れてしまいトークンの価値がなくなってしまいます。
価値がなくなる事で、トークンを購入し保有していたユーザーは損失が生まれることになります。また、この脆弱性を含んだトークンが取引所に上場していた場合も問題があります。
トークンの供給量が壊れている状況で、仮に取引所が取引許可していた場合。上記の仕組みを利用して、悪意のあるユーザーが不正に供給したトークンを取引所に空売りすることが可能になります。トークンの空売りにより取引所からは多額の資金が流出する自体が起こることが想定されます。
問題による影響
上記で示した状況が想定されたため、今回の問題が発生したトークンを取り扱っていた取引所は急遽、この事態が収束するまでERC20の取引を一時停止するという対応を行なっています。
ERC20トークンの取引を一時停止している主要な取引所
↓okexの取引アナウンス
問題に対する解決策
この脆弱性問題に対する解決策はオーバーフローが起きる算出処理が行われた場合に、処理を中断し例外エラーを発生させることです。
算出処理よるオーバーフローは既知の問題で、解決アプローチも明確にされています。
算出処理はzeppelin-solidityというコントラクト開発ライブラリ群のSafeMath.sol を利用することが定石となっています。
今回のBeutyChainのトークンコントラクトを見ると全体的に、このSafeMathのような算出処理関数を利用していました。(.add / .sub etc..) しかし、なぜかbatchTransactionの乗算処理ではmul関数が使われていませんでした。
このmul関数を採用しなかった背景は調べても見つけることができませんでした。。。 >< おそらく、レビューで抜け漏れていたのではないかと想像します。
問題に対する有識者の反応
この問題に対して、正確に問題を理解し正しい意見を述べている方々の意見を紹介しておきます。
ALIS CTOのIshiiさん
重用なこと箇条書き:
— Sota Ishii (@sot528) 2018年4月26日
- ALISに影響なし
- ERC20のバグではない
- Ethereumのバグではない
- ほとんどのERC20トークンに影響なし
- 影響は数種類のトークンのみ https://t.co/9K8tGwT5pw
Solidity開発Tips イチローのnakajoさん
そもそもbatchTransferメソッドはerc20 standardじゃないし、独自に拡張してやらかしてる感じなんだよね。
— Yukishige Nakajo (@nakajo) 2018年4月26日
erc-20 token全部がやばい見たいな風潮になってるのがまたなんとも。。。。https://t.co/6EswGzXpBF https://t.co/IkzE0eDspT
Hi-Ether Organizerのamachinoさん
batchTransfer() という、特定のプロジェクトが独自に書いたコードのバグが、「ERC20 規格のバグ」のようなデマに変わって拡散してるのか。。
— Akinori Machino (@amachino) 2018年4月26日
SafeMath ライブラリを使いましょう、Mythril でセキュリティチェックしましょう、というようなことを啓蒙するだけかなぁ。
自分もつぶやきました
これはERC20の規格の問題ではなく、独自実装した部分に脆弱性があったという話 https://t.co/Pup7Rv2RbH
— yamarkz (@yamarkz) 2018年4月26日
まとめ
- バグが生まれない様、質が担保されたコードを採用する (SafeMathなど)
- 多額の資産が絡むコードは必ず外部の厳密なコードレビューを入れよう
- できればバグバウンティなども実施して事前にバグを発見し潰す努力を
SafeMathを使うことが定石であるということが、今回の脆弱性問題を実際に分析し学ぶことができました。 トークンホルダーからすると痛い代償ではあるもの、Ethereum全体としての教訓は得られたのかなと個人的には思っています。
宣伝
Gunosyではブロックチェーンを始めとしてスマートスピーカー、VR/ARと言った新規領域での研究・開発を進めており、メンバーを募集しています。
少し話を聞いてみたい!という方も歓迎していますので、下記のリンクからの応募お待ちしております。
また弊社Gunosyでは、blockchain.tokyo を主催するなど、ブロックチェーンや仮想通貨に関する調査を行っています。
次回は来月に開催する予定です。イベントグループへメンバー登録をしていただくとイベント参加者募集の通知が来るので、こちらもぜひ登録してみてください。