要約

  • インターネットに露出したmemcachedのUDP機能は、被害者のIPアドレスを詐称した小さな要求を受け、要求していない被害者へ桁違いに大きな応答を送り返す反射器になり得た。
  • 恒久策は一つの管理者に集約されなかった。memcachedはUDPを初期状態で無効化し、接続元ネットワークは詐称を入口で拒否でき、GitHubは検知、BGP経路変更、選択した清浄化経路を自ら制御した。

GitHubが動かせたもの

2018年2月28日17時21分(UTC)、GitHubの監視は流入量と流出量の比率に異常を検知した。GitHub.comは17時26分まで利用不能となり、その後17時30分まで断続的に利用できなかった。同社は機密性と完全性に危険はなかったとしている。

攻撃は1,000を超える自律システムと数万のエンドポイントから到来し、ピークは1.35 Tbps、1秒当たり1億2,690万パケットだった。ある拠点でトランジット流入が100 Gbpsを超え、GitHubはAkamaiへトラフィックを移す判断をした。

17時26分、ChatOpsからトランジット事業者向けBGP広告を撤回し、AS36459をAkamaiとの接続だけで広告する命令が実行された。経路が再収束すると、Akamai境界のACLが攻撃を緩和した。GitHubは17時30分に完全復旧を確認した。17時34分にはインターネット交換点の経路も撤回し、さらに40 Gbpsを移した。18時過ぎには約400 Gbpsの第二波が来た。

この時系列で重要なのは、最大値の記録ではない。GitHubは反射元のサーバーを遠隔操作できなかったが、自社の監視、自社プレフィックスの広告、緩和事業者を使うタイミング、復旧判定は制御できた。事後に同社が緩和事業者の自動起動を検討するとしたのも、この局所的な決定時間を短くするためだった。ただし報告は計画を示すだけで、その後の実装完了までは証明しない。

小さな要求が第三者の帯域を使った

Memcachedは、本来は信頼されたアプリケーション網内で使う高速キャッシュである。UDPでは応答前に接続を確立しない。公開インターネットから到達できる設定になると、パケットに書かれた送信元アドレスを、応答先としてそのまま信じる性質が悪用可能になった。

Cloudflareが示した手順では、攻撃者はまず公開キャッシュに大きな値を置き、その後、被害者のIPアドレスを送信元に見せかけた小さなgetを送る。実験では15バイトが134 KBの応答を生んだ。別の観測では15バイトに対して750 KB、約51,200倍だった。

この倍率をすべての要求へ一般化してはいけない。GitHubの1.35 TbpsとCloudflareの実験も同一データではない。それでも構造は明瞭だ。攻撃者は小さな上りを使い、無関係なキャッシュ運用者の下りを消費させ、要求していない被害者へ届けた。

成立条件は二つある。UDPキャッシュが外部要求へ答えること。そして攻撃者側の経路が、攻撃者に属さない送信元アドレスを通すことである。

初期値の変更が新しい反射器を減らす

Memcached 1.5.6は事件前日の2月27日に公開された。リリースノートは、主な変更をUDPの初期無効化と説明する。実際のコミットではsettings.udpport = 11211settings.udpport = 0へ変わり、TCPポートだけを指定した際に同じUDPポートまで暗黙に開く処理が削除された。テストも同時に更新された。

UDPそのものは削除されていない。必要な運用者は-U 11211で明示的に有効化できた。この設計は、正当な局所利用を中央から禁じず、何も判断しないことが危険な許可になる状態を改めた。

ただし、1.5.6という表示だけでは安全を証明できない。OSパッケージ、サービス定義、運用パラメーターがUDPを再び有効にし得る。旧版でも私設アドレスへバインドし、外部ファイアウォールで閉じている場合がある。確認すべきなのは、実行中のサービスが外部からのUDP 11211へ答えるか、どれだけ返すかである。

Running-Code Primacyは、この差を重視する。文書は期待を記し、コードは初期動作を変え、テストは回帰を防ぐ。採用を証明するのは、実際のソケット、外部プローブ、パケット、送出量だ。

送信元の嘘はアクセス網で止める

反射器を閉じれば増幅能力が減る。送信元アドレス検証は、応答を被害者へ向ける嘘を止める。

RFC 2827、すなわちBCP 38は、下流の顧客から来るトラフィックを、顧客が正当に使う送信元プレフィックスに限定するよう推奨する。攻撃者の接続に近い場所で適用すれば、GitHubを名乗る偽パケットはキャッシュへ届かない。

もっとも、マルチホームと非対称経路を持つネットワークでは単一コマンドで済まない。RFC 3704は、入口ACL、厳格RPF、実行可能経路RPF、緩い方式を比較する。厳格方式を誤ると正当な非対称通信を捨てる。緩い方式は宛先への経路が存在することを見ても、その顧客が送信元を使う権利までは確認できない。

共通層が固定すべきなのは「顧客境界から権限のない送信元を出さない」という性質である。具体的な方式、経路情報の更新、例外、移行時期は各運用者が選ぶ。その自由は、結果を測定しなくてよいという意味ではない。

別々の境界に別々の証拠を置く

キャッシュ運用者は、待受設定、ファイアウォール、外部プローブ、送出量で露出がないことを示す。アクセス網は、顧客境界の詐称テストとフロー記録を示す。被害者は、異常検知、経路切替、緩和容量、復帰手順を演習する。

清浄化は、反射器がすでに放った帯域を被害者側で処理する。UDP無効化は一種類の反射器を消す。BCP 38は偽の要求を送信元近くで止める。三者は補完関係であって、どれか一つの証明書で代替できない。

AkamaiはGitHubが選んだ危機経路でフィルターを提供したのであり、GitHubの経路を恒久的に決める権利を得たわけではない。memcachedプロジェクトも、初期値を安全にしたが利用者ネットワークの統治者にはならなかった。この局所性が、復旧可能性を守る。

証拠の限界

資料は増幅機構、GitHubが測定したピーク、memcachedの初期値変更を裏付ける。すべてのmemcachedが公開されていたこと、GitHubの全パケットが51,200倍だったこと、すべての送信元ネットワークでBCP 38が欠けていたことまでは示さない。

より正確な教訓は、誰が何を拒否できたかにある。ソフトウェアの初期値は意図しない応答を拒否し、アクセス網は借り物の送信元を拒否し、被害者は耐えられない経路を撤回した。宣言ではなく、実行された拒否が攻撃面を縮めた。

情報源