もはや『ブルー・フライデー』はない
(brendangregg.com)- 2024年7月19日に発生した世界的なWindows障害は、セキュリティ製品のカーネルドライバー更新が 不正なメモリ読み取り につながり、ブルースクリーンとブートループを引き起こした事例だった
- eBPF はカーネル内で実行されるが、検証器とサンドボックスによって危険なコードを拒否し、1つのプログラムがシステム全体をクラッシュさせられないよう設計されている
- LinuxにはすでにeBPFが組み込まれており、Microsoftの eBPF for Windows が本番運用可能な状態になれば、Windowsのセキュリティソフトウェアも同じ方式へ移行できる
- Google・Meta・Ciscoのような大手テック企業や、eBPFベースのセキュリティスタートアップは、速度、深い可視性、安全性保証を活用して、セキュリティ製品や検知体制を拡張している
- カーネルドライバーやカーネルモジュールを含む商用ソフトウェアを購入する企業は、Linuxでは今すぐ、Windowsでもまもなく eBPF対応 をベンダー要件にできる
7月19日のWindows障害が明らかにしたカーネルコードの危険性
- 2024年7月19日の障害は、カーネルプログラミングに内在する危険を示した前例のない事例だった
- 世界中のWindowsコンピューターが ブルースクリーン(blue screen of death) とブートループに見舞われ、病院・航空会社・銀行・食料品店・放送局などで障害が発生した
- 原因は広く使われているセキュリティ製品の 設定更新(config update) であり、その製品にはWindowsシステム向けのカーネルドライバーが含まれていた
- 更新後、カーネルドライバーが不正なメモリを読み取ろうとし、この種のエラーはカーネルをクラッシュさせる可能性がある
eBPFが防げるクラッシュ
- eBPF はもはや略語ではなく、Webブラウザーに組み込まれた安全なJavaScriptランタイムに似た 安全なカーネル実行環境 である
- Linuxユーザーは、すでに自分のシステムにeBPFを備えている可能性が高く、eBPFは数年前にLinuxカーネルへ組み込まれた
- eBPFプログラムは、システム全体をクラッシュさせられないよう制限されている
- ソフトウェア 検証器(verifier) が安全性を検査する
- プログラムは事実上サンドボックス内で実行される
- 検証器が安全でないコードを見つけると、そのプログラムは拒否され実行されない
- Linux実装の検証器は 2万行を超えるコード で構成されており、Meta・Isovalent・Googleなどの業界と、Rutgers University・University of Washingtonなどの学術界からの貢献がある
- 強化されたセキュリティ、低いリソース使用量、クラッシュ防止がeBPFの主要な利点である
LinuxとWindowsでの適用可能性
- 今回の障害を引き起こしたセキュリティ企業は、Linuxシステムではすでに eBPF導入の過程 にあった
- Microsoftの eBPF support for Windows が本番運用可能な状態になれば、WindowsのセキュリティソフトウェアもeBPFへ移植可能になる
- eBPFへ移行したWindowsセキュリティエージェントは、Windowsカーネルクラッシュを引き起こせない形になる
セキュリティ業界と大手テック企業の採用
- eBPFベースのセキュリティスタートアップである Oligo と Uptycs は、最近の障害をきっかけにeBPF移行の利点を強調している
- 大手テック企業もセキュリティ目的でeBPFを採用している
- CiscoはeBPFスタートアップのIsovalentを買収し、セキュリティ実行とモニタリングのためのファブリックである Cisco Hypershield を発表した
- Google と Meta は、eBPFの速度、深い可視性、安全性保証を基盤として、大規模環境で悪意ある挙動を検知・遮断している
- eBPFはセキュリティ以外にも ネットワーキング と オブザーバビリティ(observability) に使われている
eBPFの限界と運用上の補完策
- eBPFプログラムが起こしうる最悪の事態は、CPUサイクルやメモリのようなリソースを望ましくない水準で余分に消費することだ
- 無駄の多いコードまで防げるわけではないが、システムクラッシュにつながる深刻な問題は防止できる
- eBPFも新しい技術であるため管理コードにバグがあり、最近ニュースになった同じセキュリティ企業が発見した Linux kernel panic の事例もある
- こうしたバグをeBPF側で修正すれば、すべてのeBPFベンダーに修正が適用され、全体のセキュリティをより速く改善できる
- 展開リスクはeBPFだけで終わらず、併用できる運用手法も残っている
- カナリアテスト
- 段階的ロールアウト
- 一般的なレジリエンスエンジニアリング
購入者が求められる変化
- eBPF方式の重要な点は、LinuxとWindowsの両カーネルで基本提供されるソフトウェア的解決策であり、すでにこのユースケースで採用されていることにある
- 企業がカーネルドライバーやカーネルモジュールを含む商用ソフトウェアに費用を払うのであれば、eBPFを要件 にできる
- Linuxでは今日から可能で、Windowsでもまもなく可能になる
- 一部のベンダーはすでに先行してeBPFを採用しているが、他のベンダーには料金を支払う顧客からの要求が必要になるかもしれない
1件のコメント
Hacker News の意見
Windows 向け eBPF が提供する「フック」の一覧を見ると、現実とは距離があるように見える。現状では受信パケットとソケット操作程度なので、Microsoft は Berkeley Packet Filter を文字どおり パケットフィルタリング に使うことを期待している程度に思える
I/O フィルタリング、オブジェクトの作成・使用、CrowdStrike のようなドライバが NT カーネルに引っかける無数のポイントとは異なる
また、カーネル空間で動く他のサードパーティ製のゴミを監視するには、アンチマルウェアもカーネル内にいる必要がある。ELAM(early-launch anti-malware)はアンチマルウェアドライバを先にロードして他のドライバの動作を監視させるものだが、eBPF でこのようなことが可能かはかなり疑わしい
Microsoft が eBPF でカーネル空間のアンチマルウェアドライバを置き換えるには、まだ道のりは非常に長い
https://microsoft.github.io/ebpf-for-windows/ebpf__structs_8...
たとえるなら、人々が Google Chrome の JavaScript ウェブサイトで銀行業務をしているのに、Microsoft Edge では「JavaScript をサポートしていないので、この .EXE をダウンロードして実行してください」と言っているような状況だ。Microsoft が JavaScript や eBPF をサポートする「か」ではなく、「いつ」サポートするかを問う話に近い
Brendan Gregg のような人と議論したいわけではないが、この分野のベンダーには障害の連鎖全体をもっと 総合的に調査してほしい。障害発生から 3 日後に「x が y 日に発生した問題を解決する」という提案が出てくると、慎重になってしまう
正しい可能性もあるが、分析しなければ死角が残るかもしれないし、検討したうえで適切に捨てるべき代替案も多いかもしれない
特に「最悪の否定的結果は CPU の無駄遣いだけ」という部分には同意しにくい。特定のバグの種類ではそうかもしれないが、誤ったルールセットがシステムを深刻に文鎮化させ、復旧を難しくする障害モードは十分に多い
eBPF ベースのセキュリティモジュールが多くのベンダーにとって正しい選択ではないかもしれない、という意味ではなく、どのリスクを避けられ、どのリスクは避けられないのか、障害の連鎖のどの部分を扱うのかを理解しようという意味だ
https://opensource.microsoft.com/blog/2021/05/10/making-ebpf...
https://lwn.net/Articles/857215/
本当に懸念があるなら意見を出せる議論の場もあり、GitHub にまとまっている
https://github.com/microsoft/ebpf-for-windows
すでに答えがあるかもしれないし、なければそこで扱える
これは正しくない。システムが実行されるために何らかのコード片が必要な構造なら、そのコードが壊れたときシステムはそもそも実行されるべきではない。失敗を無視するのはおかしい。
たとえば、ある医療機器のドライバーコードが人を焼いてしまわないように安全ロックを保証しているなら、安全装置がオフのまま何事もないように動作するより、全体が停止するほうを選ぶ。
結局、下に降りても同じ問題が続くだけ。
Linux が実際にどうしているかは知らないが、不正な入力に対する動作を設定可能にする世界も想像できる。
また、その主張が常に真であるわけでもない。一般論としては共感するが、文脈によっては動き続けなければならないこともある。すぐ思い浮かぶ例は、自動火星着陸機の誘導コンピューターだ。地球との往復遅延が長すぎて、責任を先送りできない。
終了すれば墜落するが、破損した状態で最善を尽くせば、おそらく墜落するだけなので、そのほうがましな場合もある。
OS 全体が文鎮化すると、IT 技術者が直接修理しなければならず、はるかに大きな問題になる。そうでなければ、欠陥のあるドライバーだけを更新すれば済んだはずだ。
車もウォッシャー液がないからといってエンジンがかからないわけではない。
金曜日に影響を受けた組織の大半は、24時間のあいだマルウェア攻撃や不正利用のリスクが少し増えることのほうを、実際に経験した IT 全体の崩壊より好んだはずだ。
しかも、そのバグが必ずブルースクリーンを引き起こす必要があったわけでもない。システムが未定義の状態と無制限の結果を抱えたまま動き続けることもあり得た。
eBPF なら、少なくとも起こり得るエラーの一部を検出し、その結果に応じてリスク管理の判断を下せる。
更新するには呼び出し側が別の関数を呼び出す必要があるため、責任はカーネルを横からいじれる人ではなく、呼び出し側に置かれる。
表示されたハッシュに対応する関数がなければ呼び出せず、あったとしても意図された方法以外では呼び出せないので、望んでいる「完全に動作するか、まったく動作しないか」という性質が得られる。
また、不正な状態への反応が必ずしも「無視」である必要はない。制限付きのユーザーログインを無効化したり、画面を消したりすることもできる。
マルウェアがこれを悪用できるという懸念なら、マルウェアがすでにアンチウイルスのディスク上のファイルを書き換えられる状況で、システム自身がそれを処理できると信じるのがよい考えなのかは疑問だ。
セキュリティ上位の仕組みに報告し、外部システムがネットワークアクセスを無効化または制限する措置を取るようにするほうが安全かもしれない。さらに、こうした措置にはシステムへ介入する権限ではなく観察権限だけがあればよいので、アンチウイルスシステム自体がマルウェア経路やこの種のバグの原因になる可能性も下がる。
eBPF は優れており、さまざまな目的に使われて多くのことを改善できるが、「悪いソフトウェアアップデートのせいでコンピューターがクラッシュしなくなる」というのは誇張に見える。
BPF 自体にバグがないと仮定しても、カーネルフックの範囲はかなり広く、そのフックが eBPF コードを呼び出し、そのコードがさらにカーネルを呼び出せる。
https://www.man7.org/linux/man-pages/man7/bpf-helpers.7.html
特に bpf_probe_read_kernel() は非常によく使われるが、安全ではない。OOPS やクラッシュを避けるためにかなり努力しているものの、決して完全ではない。
残りのリストにも、実際に oops や panic を起こさなくてもシステムを簡単に壊せるものが多い。
そしてユーザー空間の「悪意ある行為」を検出して防ぐツールなら、あらゆるものを悪意あるものと判断し始めて、コンピューターを使いものにならなくすることもあり得る。
一方で eBPF には、ユーザー空間側の本当のセキュリティモデルがない。eBPF プログラムの実際のアタッチは、アタッチ先のカーネルオブジェクトに対する妥当な権限操作ではなく、bpf() システムコールを通じて行われ、コンテナが使う eBPF をそのコンテナ内に閉じ込める仕組みもまったくない。bpf_probe_read_kernel() は本質的にすべてのカーネルメモリを読める。
だから eBPF が通常のカーネル C コードより優れている点は、制限された unsafe API サーフェスを持つ安全な言語でコードを書くのに似ているところにある。この種の作業には大きな改善だが、決して完全ではない。
検証器が厳格で、Linux 実装が2万行を超えるという話もあるが、検証器は途方もなく複雑だ。手書きの2万行のロジックより、形式手法ベースのものを見たい。
「eBPFプログラムはソフトウェア検証器で安全性チェックを受け、事実上サンドボックス内で実行されるため、システム全体をクラッシュさせることはできない」という話には疑問を感じる
オペレーティングシステムの目的の一つは、ソフトウェアを監視することではないのか? これがOS自体に関わる問題だというのは分かるが、監視者を監視する層を追加すると、結局その層もまた監視しなければならないのではないか?
新たな複雑性が長期的にはより良いものになると無邪気に信じるより、複雑性の低減を選べないのか?
以前のやり方は、カーネルドライバをロードし、多数のシステムコールにフックを掛け、壊れないことを祈るというものだった。間違えればpanicが起きる可能性はあるが、Linuxはかなり堅牢である
eBPF方式は、欲しい情報をeBPF専用命令で要求するほうに近い
動作方式の概要はここにある: https://ebpf.io/what-is-ebpf/
素晴らしい技術のように聞こえるが、本当に深刻だった問題は「カナリアテスト、段階的ロールアウト、レジリエンスエンジニアリングのようなソフトウェア配布リスクの緩和策も使える」という部分である
基本的な業界標準の品質管理を実装するのに、新しい技術は必要ない
今回の事件を記念して、金曜日を休みにし始めてもよさそうだ。人々があまり追い立てられるように働かず、状況がどう進んでいるのか、その流れにどんな影響を与えられるのかを立ち止まって考える時間がもっとあったなら、被害は少なかった可能性がある
Linux実装の検証器が2万行を超え、産業界と学術界が貢献したという説明は、むしろ安心できない。追加の攻撃対象領域も問題だが、それほど大きなコードベースを誰が保証できるのか?
WebAssemblyの検証器ははるかに単純だという印象がある
フィルタが起動時にロードされ、あらゆるものにフックを掛けるなら、バグ一つでシステムが操作もパッチ適用も不可能なレベルまでロックされる可能性がある。たとえば空の許可リストをロードする場合がそうで、結局、ブートループを別の形のサービス拒否に変えてしまうことになり得る
Microsoftが復旧に必要な中核要素をハードコードされた許可リストに入れるなら、この種のツールのバグはより簡単に直せるかもしれないが、修正が配布されるまで、システムは起動していても使えない実質的なダウンタイムが発生し得る
ブログ記事には「eBPFはこの種のクラッシュに対して免疫がある」と書かれている
検索してみたが確かな内容は見つからず、依然として何かを壊せそうに見える。eBPFの専門家にこの主張について説明してほしい。見つけた中で最もよかった資料はこれである: https://stackoverflow.com/questions/70403212/why-is-ebpf-sai...