Develop with pleasure!

福岡でCloudとかBlockchainとか。

LND 0.18.5以下に存在した脆弱性

先日Matt Morehouseによって開示されたバージョン0.18.5以下のLNDに存在した脆弱性について↓

Disclosure: Critical vulnerabilities fixed in LND 0.19.0 - Implementation - Delving Bitcoin

この投稿ではLNDに存在した3つの脆弱性が開示されている。1つはDoSで残り2つは資金損失系。

DoS脆弱性

LND 0.18.5以下のバージョンに影響するDoS脆弱性。

morehouse.github.io

LNDは、ピアからメッセージを受信すると、メッセージを適切なサブシステムで処理できるようにキューに入れるようになっており、

  • サブシステムのgossiperchannel linkでは、ピアごとに最大1,000メッセージをキューイング可能
  • Lightningプロトコルのメッセージは最大64KBのサイズになり得る
  • LNDは利用可能なファイルディスクリプタ数まで多数のピア接続を許可していた(ちなみに自分のUmbrelのLNDプロセスにおけるファイルディスクリプタ数は1073741816だった)

のが問題となった。

攻撃者はターゲットノードに多数のピア接続をし、64KBのquery_short_channel_idsをスパム送信することで、ターゲットノードのメモリをOOMでクラッシュさせることができる。8GBのRAMを搭載するノードに対して、実験では5分以内にOOMを引き起こすことができたとのこと。

緩和策

この脆弱性への対応として、LND 0.19.0では、

  • キューのサイズが1,000メッセージから50メッセージに縮小し、
  • チャネルを開設していないピアからの接続を100件までに制限

するという緩和策が導入された

過剰フェイルバックによる資金喪失

2つめの脆弱性はこちら↓

morehouse.github.io

過剰フェイルバックの脆弱性は、もともとLND 0.17.5以下に存在していて、LND 0.18.0で修正された経緯がある↓

techmedia-think.hatenablog.com

今回報告されたのは、その亜種。

前回の脆弱性は、上記の記事のステップ⑩のレスポンスを下流ノードが返さずに⑨のコミットメントトランザクションをブロードキャストし、上流のLNDを再起動させることで、該当HTLCのさらに上流へのフェイルバックが行われるというもの。

今回の脆弱性は、下流の攻撃者が⑨のコミットメントトランザクションをブロードキャストするのではなく、被害者の上流ノードに⑦のコミットメントトランザクションをブロードキャストさせ、その後再起動させることで、該当HTLCのさらに上流へのフェイルバックが行われるというもの。これは、攻撃者のノードが被害者のノードにerrorメッセージを送信することでトリガーすることができる。

この亜種は、将来の過剰なフェイルバック脆弱性を防ぐためにBOLT 5をアップデートしていた際に発見され、プリイメージが既に判明しているHTLCはフェイルバックしないようにするチェックが追加され修正された

置換遅延攻撃

3つめの脆弱性は、LND 0.18.5以下のバージョンに影響するもので、トランザクションのバッチ処理およびその手数料の引き上げを管理するLNDのスイーパーシステムを狙ったもの↓

morehouse.github.io

このスイーパーシステムには2つの弱点がある:

  • バッチトランザクション内のインプットの内1つでも競合するトランザクションが承認されると、残ったインプットで再度バッチトランザクションを作成しなおすが、その際手数料が最小値にリセットされる。
  • 競合トランザクションによる二重使用後、再集約が次のブロックまで遅延される。

これらを悪用した攻撃のシナリオが↓

  1. 攻撃者は被害者と直接チャネルを開き、被害者が許容する最小のCLTVデルタ(デフォルトだと80ブロック)を使って、約40個のHTLCを自分宛にルーティングする。この時最後のHTLCを最大額とする。
  2. 攻撃者は、HTLCを期限切れになるまで保持し、被害者がチャネルを強制閉鎖する。ここで上流のHTLCのタイムアウトまで80ブロックのカウントダウンが始まる。
  3. 被害者のスイーパーは、40個のHTLCタイムアウトを1つのトランザクションに集約してブロードキャストする。
  4. 攻撃者はmempoolを監視して3のトランザクションを検知し、その内1つのインプットについてプリイメージを使って回収する競合トランザクションを作成し置換させる。
  5. 4のトランザクションが承認されると、被害者はそのプリイメージを使って上流のHTLCを解決できるが、残りの39個については、再集約は次のブロックまで遅延される。つまり競合トランザクションが承認されたブロック高をNとすると再集約されるのはN+1のブロックの承認後。
  6. N + 1ブロックが承認されると、被害者は残りのHTLCタイムアウトを含む新しいバッチトランザクションをブロードキャストする。この時、手数料は手数料関数の最小値にリセットされる。攻撃者は4以降の攻撃を繰り返す。
  7. 80ブロック経過後、攻撃者は残りのHTLCを窃取(下流はプリイメージで、上流はタイムアウトで)する。

再集約の遅延が+1ブロック分あるので、80ブロックの期限に対して40回の置換で済むようになってる。

攻撃コスト

攻撃者は最大40個のトランザクションを置換する必要があり、その際、バッチトランザクションの手数料を上回る手数料を支払う必要がある。

  • 攻撃全体の平均手数料率を1.4 sat/vBと仮定し、
  • バッチトランザクションに平均20個のHTLCが存在すると仮定すると(最初は40個で1つずつ減ってくため)

置換毎の平均コストは、HTLC 20個 × HTLCあたり166.5 vB × 1.4 sat/vB = 4,662 sats。

これが40回なので総コストは、40 × 4,662 sats = 186,480 sats。

つまり、20万sats未満のコストでチャネルの全資金を盗むことができる。

緩和策

LND 0l19.0では、

  • 再集約時の遅延をなくし、
  • 手数料値のリセットを修正し積極的にバンプし続ける

ように修正し、攻撃にかかるコストを引き上げた:

  • 2倍のHTLCと回数(最低80回)の置換が必要になり
  • 毎回、高騰した手数料を上回る必要がある