あのんちゃんのセキュリティ奮闘記

気になったコトをかいていきます

ぼくらの七日間戦争 -YentenとBitZenyを襲った不正増殖事件- その1

仮想通貨のYentenとBitZenyで起きた不正増殖事件を後世に残すべく記事を書きました。
この記事が今後のブロックチェーンセキュリティの参考になれば嬉しいです(๑´ڡ`๑)

今回は事件の超まとめと、攻撃に使われた脆弱性「CVE-2018-17144」についてです。
Yenten、BitZenyのそれぞれの詳細な話はまた今度かくのでお楽しみに!

※間違いがあれば「あのん (@anon_secchan)」に連絡ください。

忙しい人向け!1分でわかる不正増殖事件

Yenten

f:id:anon_secchan:20181128020144p:plain:w100

2018年11月、Yenten は攻撃者によって、2億5千万YTNという、Yentenの今までの採掘量を大きく超える不正増殖の被害を受けました。
やがて取引所は攻撃者による増殖したコインの大量の売り注文を受け、通貨の価値が崩壊し、相場が一瞬で 1 Satoshi に張り付きました。

f:id:anon_secchan:20181128034347p:plain
複数回の不正増殖被害を受けて最終的に1Satoshiに張り付いたYentenのチャート

現在、Yentenユーザが脆弱性の影響を受けなかった古いバージョンでの通貨の再スタートを模索しています。

BitZeny

f:id:anon_secchan:20181128020255p:plain:w100

2018年11月、Yentenを襲った不正増殖から日も経たず、BitZeny は攻撃者によって、2000万ZNYという不正増殖被害を受けました。
しかし、攻撃者は(幸運にも)何故か不正増殖したコインを売りに出さず、沈黙を保っていました。

その間に BitZeny の開発チームは利用者・プールに広く注意喚起を行い、バージョンのアップデートを促しました。
結果、利用者のコンセンサスによって不正増殖はブロックチェーンのシステム上なかったことになり、事件も収束しました。


CVE-2018-17144 の解説レポート

CVE-2018-17144 は 9/18 に公開・修正された、BitcoinおよびBitcoinをフォークした仮想通貨に影響が発生する脆弱性で、 当初 Bitcoin Coreグループにより以下のような説明がなされました。

したがって、Bitcoin Core 0.14.Xでは、ブロック内の単一のトランザクション内でトランザクションアウトプットを二重使用しようとすると、報告されていたようにアサーションエラーとクラッシュが発生します。 - https://bitcoincore.org/notice/

これが何を意味しているかというと、
ブロックチェーンに参加しているノードに対して不正なトランザクションを送りつけることで、0.14.X で稼働しているノードを停止させることができ、ハッシュレートを下げることで結果として 51% attack が成功しやすくなる
ということです。
確かにこのバグを利用することでそのような行為の足掛けにすることは可能になります。

ただこの脆弱性の本当の脅威はこれだけではありません。

数日間隠蔽された、本脆弱性の恐るべき脅威

本来の脅威は上記のリリースのあと2日後の9/20に公表されました。

Bitcoin Core 0.15では、未使用のトランザクションアウトプットの追跡を簡略化し、リソース枯渇攻撃への脆弱性を修正するための、より大きな再設計の一環としてアサーションが僅かに変更されました。アウトプットが未使用から使用済みにマークされたか検証する代わりに、存在するかどうか検証するだけになりました。 したがって、Bitcoin Core 0.15.X, 0.16.0, 0.16.1および0.16.2では、使用されているアウトプットを同じブロック内に作成されたブロック内の単一のトランザクション内で二重使用しようとすると、同じアサーションエラーが発生します(0.16.3のパッチに含まれているテストケースに存在します)。ただし、前のブロックで二重使用されたアウトプットが作成された場合でも、エントリーはDIRTYフラグがセットされたままCCoin mapに残っており、使用済みとマークされているため、アサーションは発生しません。これによりマイナーがBitcoinの供給量を増やすことが可能になり、増やした値で二重使用する可能性があります。

つまり、わかりやすくいうと
Bitcoin Core 0.15 - 0.16.2 とそれをフォークして作成された仮想通貨はコインの不正増殖を受け入れる」
ということです。これは本当に恐るべき脆弱性です。

※本脆弱性ソースコードベースで深く知りたい方は下記レポートを参照してください。
https://hackernoon.com/bitcoin-core-bug-cve-2018-17144-an-analysis-f80d9d373362

攻撃の実証

脆弱性を悪用する攻撃はとても容易で、修正コミットに再現方法が記載されています。
さらに Pythonですぐ使えるPoCもインターネット上に公開されています。

  • BitCoin Core 0.16.3 修正コミットのテストケース

https://github.com/MarcoFalke/bitcoin/blob/master/test/functional/p2p_invalid_block.py

https://github.com/hikame/CVE-2018-17144_POC/blob/master/cve-2018-17144-Double_Spend.py

また、Bitcoin の Testnet でも9/26 の時点で実証として不正トランザクションを含んだブロックが追記されました。
(ただし承認されずOrphan Blockとなっています)

不正トランザクションの詳細を確認すると、確かにvinの部分に同一トランザクションが2回使われていることがわかります:

$ bitcoin-cli -testnet getrawtransaction fb7a8658ec015133e36e2cf7ddf7e8c887c3a5becec2f30f24ebfe43e72f4b59
    {
      "txid": "fb7a8658ec015133e36e2cf7ddf7e8c887c3a5becec2f30f24ebfe43e72f4b59",
      "hash": "fb7a8658ec015133e36e2cf7ddf7e8c887c3a5becec2f30f24ebfe43e72f4b59",
(...)
      "vin": [
        {
          "txid": "6a08723bc717e1ddf91fa60fde25784ef66952e8687f3bffe391fc2c819dbfd9",
(...)
        },
        {
          "txid": "6a08723bc717e1ddf91fa60fde25784ef66952e8687f3bffe391fc2c819dbfd9",
(...)

※この事例ではUTXOが2回だけ使われていますが、トランザクションのサイズが許す限りは何回でも重複利用することが可能ということに注意してください。

ブロックチェーン分裂という副作用

f:id:anon_secchan:20181128022830p:plain
不正ブロックを受け取った際のBitcoin Coreの各バージョンの挙動

脆弱性でコイン不正増殖の影響を受けるバージョンは 0.15 - 0.16.2 です。
不正トランザクションを含むブロックを各バージョンのノードが受け取った場合、以下のような挙動を示します。

  • 0.14.X -> クラッシュ
  • 0.15-0.16.2 -> ブロックを受け入れる
  • その他 -> ブロックを拒否する

これは実際のところ、ブロックチェーンにどんな影響が出るでしょうか?
答えはチェーンのフォークです。

ブロックチェーンに貢献しているハッシュレートの多数が影響を受けないバージョンの場合、汚れたブロックチェーンと綺麗なブロックチェーンとでフォークされたとしても、影響を受けないバージョンによる圧倒的なハッシュレートにより綺麗なブロックチェーンにすぐに収束します。
しかし、ハッシュレートの多数が脆弱ノードによるものの場合、汚れたチェーンがメインチェーンとなりずっと継続することになります。
前者の実際の事例が上に記載したBitcoinのTestnetで、後者の実際の事例がYentenとBitZenyです。

ただ、ここで強く言っておかないといけない注意点があります。
攻撃によって起きる"フォーク"は、影響を受けるバージョンである0.15-0.16.2だけの話であるということです。

f:id:anon_secchan:20181128022936p:plain
汚れたチェーンと綺麗なチェーン
不正なトランザクションはそもそも受け入れられるものではないため、それを受け入れている汚れたブロックチェーンは、影響を受けないノードから見ると最初から存在しないチェーンです。
これが通常行われる短期的なフォークと全く異なる点です。
ただ見方を変えれば、影響を受けないノードは不正なトランザクションを受け容れないということで、実質ハードフォークをしているともいえなくもないです。ここが大変ややこしい・・・。

チェーン分裂によるBAN大会

f:id:anon_secchan:20181128023301p:plain
不正なチェーンを広報し続ける脆弱ノードをBANしまくっているログ
脆弱ノードによるハッシュレートが過半数を超えている場合、汚れたブロックチェーンを伸ばしている脆弱ノードから見ると汚れたチェーンは正当なメインチェーンと認識されています。しかしながら、影響を受けないノードから見るとそもそも存在しないチェーンとされます。

これはどんな事態を引き起こすでしょうか?

少数の影響を受けないノードは綺麗なチェーンを伸ばします。しかし脆弱なノードは"本来なら"存在しないチェーンを広報し続けます。影響を受けないノードは不正なブロックを受け入れることがないので、受け入れを拒否し、広報してきたノードのBANスコアが上昇します。さらにいうと不正トランザクションはBAN判定の中でも一発BAN対象(banlevel=100)なので、影響を受けないノードは脆弱なノードを即座にBANしてしまいます。

f:id:anon_secchan:20181128033312p:plain
不正なブロックを広報してDoS認定される脆弱ノード

なお、少数のノードが広報する綺麗なチェーンは脆弱なノードからしたらどう扱われるでしょうか。影響を受けないノードから綺麗なチェーン(しかしブロック高は小さい)のブロックを受け取った時、別のチェーンが存在したということで、脆弱なノードは「自分が持っているチェーンはもしかしたらもう切り捨てられた古いチェーンなのではないか」と判断します。そうすると自分の知らないメインチェーンを探しにさらに色んなノードに接続しにいきます(これは正しい動作です)。しかし、汚れたチェーンが一番伸びているチェーンなので、いくら探しても汚れたチェーンを超えるチェーンはありません。結果として脆弱なノードがわざわざBANをされに影響を受けないノードに接続しにいくことになるんです。悲しい物語ですね。

不正増殖の増幅量

不正増殖はトランザクションのvinに利用するUTXOの数値に依存します。
攻撃に利用するUTXOが10コインだった場合、そのUTXOを100回利用したとしても1000コインにしかなりません。
しかし、UTXOが1万コインだったらどうでしょうか?100回利用したら100万コインになります。
100万コインに増殖したUTXOをさらに何十回・何百回も利用した場合は・・・?
この脆弱性がいかに危険なものかがわかるでしょうか。

51% Attack は不要

事件当初、BitCoin Coreチームによる不正確な情報があったため、YentenとBitZenyが51% attackを受けたのではないかという混乱が一部で起きました。
しかし、上で説明しているように、不正増殖については原理上、攻撃者が1ブロックを生成するだけで実現可能です。
攻撃者のハッシュレートが既に51%を超えている場合なら確かにすぐに不正増殖が可能ですが、少ないハッシュレートであっても、確率上、下記の時間で攻撃が成功します。

(( All_Hashrate - Atk_Hashrate) * block_time) / Atk_Hashrate (単位:秒)

まとめ

脆弱性ブロックチェーンにどれだけのインパクトを与えるものなのかご理解いただけたでしょうか。
このような脆弱性は今回のみならず、仮想通貨に価値がある限り今後も見つかると思います。 開発者が行方不明であったり、コミュニティが小さくメンテナンスが困難なアルトコインは非常に危険であると言わざるを得ません。
なんとかして開発者を確保した方がいいですし、開発者が出てこないならそのアルトコインから手を引くのも考えたほうがいいですね・・・。


アルトコインへの注意喚起

下記に該当する仮想通貨は、不正増殖攻撃を実際に受ける可能性があります!!

・多数のノードが Bitcoin Core 0.15 から 0.16.2 を元にしたウォレットを使用している
・ハッシュレートが攻撃のコストパフォーマンスに見合う数値
・取引所に上場している

上記に該当している仮想通貨の開発者・開発コミュニティは、早急に利用者に対して脆弱性解消バージョンのウォレットの利用を促してください。
あなたが単なる仮想通貨の参加者である場合は、開発者・開発コミュニティに対して脆弱性解消バージョンの提供を依頼してください。

なお、脆弱性解消ノードによるハッシュレートが全体の 51% を超えるまでは引き続きの警戒が必要です。
万が一不正増殖攻撃を受けた場合においても、解消ノードによるハッシュレートが過半数を超えていれば汚れたブロックチェーンが綺麗なブロックチェーンへすぐに収束するため、攻撃者の狙いである取引所での売却は困難となります。

攻撃の確認方法

自分が利用している仮想通貨が CVE-2018-17144 の攻撃を受けていないかどうか確認するには、 影響を受けないノードでのdebug.logの出力で判断が可能です。

Bitcoin Core 0.14 以前のバージョン

f:id:anon_secchan:20181128021206p:plain
Yenten 1.3.1 で 不正ブロックを含む汚れたチェーンを受け取ったときのエラーログ

debug.log に「ERROR: CheckTransaction() : duplicate inputs」という文字列が存在するかどうかでおおよその判断が可能です。

Bitcoin Core 0.16.3 以降のバージョン

f:id:anon_secchan:20181128022314p:plain
BitZeny 2.0.2 で 不正ブロックを含む汚れたチェーンを受け取ったときのエラーログ

debug.log に「ERROR: ProcessNewBlock: AcceptBlock FAILED」という文字列が大量に存在するかどうかでおおよその判断が可能です。


次は Yenten を襲った不正増殖攻撃についてかきます。
近いうちに投稿するのでお楽しみに❗