Intel の CPU に遠隔操作が可能な脆弱性、下位レベルでの OS 修正が必要

2018.01.09

更新情報: 本記事の公開後にベンダー各社が発表した情報を追加しました。
追加した情報については本記事の末尾をご覧ください (最終更新: 2018-01-05T00:30Z)。


注: ソフォス製品に関する情報およびアドバイスについては、
ソフォスの Knowledgebase Article 128053(リンク先:英語) をご覧ください。


近い将来 (おそらく今月の後半には)、少なくとも Windows と Linux オペレーティングシステムについては、Intel プロセッサのメモリの管理方法を変更するセキュリティアップデートが公開されるでしょう。

これらの変更は非常に下位のレベルを対象にしたもので、パフォーマンスに影響する可能性があるため、多くの関心が集まっています。


どの程度パフォーマンスが低下するのかは多くの要因に左右されますが、影響を受けるハードウェアでデータベースサーバーを実行した場合、パフォーマンスが約 20% 低下する可能性があるとThe Register は推測しています(リンク先:英語)


「影響を受けるハードウェア」には、近年リリースされたほとんどの Intel CPU が含まれているようです。なお、AMD プロセッサは内部構造が異なるため、影響は受けますが、Intel ほど広範ではありません。

一体何が起きているのでしょうか?


リリース間近の Linux のパッチ(リンク先:英語)は、一般的に Kernel Page Table Isolation (KPTI) と呼ばれています (KAISER や F**CKWIT と呼ばれることもあります)。

後者は Forcefully Unmap Complete Kernel With Interrupt Trampolines の略で、前者は Kernel Address Isolation to have Side-channels Efficiently Removed の略です。


その理由は次のとおりです。


ほとんどの最新のオペレーティングシステムには、権限を付与されたコアであるカーネルが存在し、これが他のすべてを管理しています。カーネルはユーザープログラムを開始および停止し、セキュリティ設定を実施し、プログラムが別のプログラムによって上書きされないようにメモリを管理し、USB ドライブやネットワークカードなどのハードウェアへのアクセスを制御し、さまざまな規制を適用します。


一般的に「ユーザープログラム」と呼ばれる上記以外のすべてのものは、ユーザーランドで実行されます。ユーザーランドでは、合意がある場合に限りプログラム間の対話が可能です。


もしも、あるプログラムが他のプログラムのデータの読み取りや変更、あるいは動作への干渉が可能であった場合、セキュリティ上深刻な問題が発生します。さらに、ユーザーランドのプログラムがカーネルのデータにアクセスできてしまうと、コンピュータ全体のセキュリティおよび完全性が妨げられるため、問題は一層深刻です。


つまり、カーネルがすべき仕事の 1 つは、ユーザーランドとカーネルを適切に分離することです。こうすることで、ユーザーランドのプログラムはカーネルの権限を引き継いで、マルウェアを起動したり、データを盗み出したり、ネットワークトラフィックを盗聴したり、ハードウェアに問題を発生させたりするなどの操作ができなくなります。


このような分離を可能にするハードウェアサポートは CPU 自体に備わっており、x86 と x64 プロセッサは権限レベルと呼ばれる機能を提供しています。権限レベルはチップそのものによって実装・実行され、権限レベルを使用することでカーネルとカーネルによって起動されたユーザープログラムとを分離できます。


Intel がリングと呼ぶこの権限レベルには 4 段階あり、ほとんどのオペレーティングシステムは、最も高い権限である「リング 0」をカーネルに使用し、最も低い権限である「リング 3」をユーザーランドに使用しています。


大まかに言うと、「リング 0」のプロセスはリングの数字が 1 以上のプロセスおよびリソースを制御できますが、その反対は許可されません。


理論上、プロセッサ自体が「リング 3」プログラムによる「リング 0」メモリの読み込みをブロックするので、ユーザーランドプログラムがカーネルのアドレス空間に侵入するのを未然に防ぐことができます (アドレス空間に侵入された場合、システムそのものや他のプログラムに関する機密データ、あるいは他のユーザーのデータが漏洩する可能性があります)。


ユーザーランドで実行されるこのようなマシンコード命令のシーケンスは、次のようにステップ 1 でブロックされます。

mov rax, [kernelmemory]   ; これはブロックされる - メモリは保護されている
mov rbx, [usermemory]     ; これは許可されている - メモリは「あなたのもの」

同様に、命令をスワップすると、このシーケンスは次のようにステップ 2 でブロックされます。

mov rbx, [usermemory]     ; これは許可されている - メモリは「あなたのもの」
mov rax, [kernelmemory]   ; これはブロックされる - メモリは保護されている

Intel と AMD の最新の CPU は、投機的実行と呼ばれる機能をサポートしています。この機能では、プロセッサが次のいくつかの命令で実行されるべきことを把握し、小さな命令 (サブ命令) に分割して、プログラム上の順序とは異なる順序で処理します。


これはスループット向上のために行われるため、中間結果に影響を及ぼさない低速な処理はパイプラインの早い段階で開始されます。一方、その他の処理は、遅い命令が最後に実行された場合に発生したであろう待ち時間 (「デッドタイム」) を使って実行されます。


たとえば、上記の 2 つの命令は計算上独立してるため、実行する順序は関係ありません (ただし、順番を入れ替えることによって、カーネルからメモリを読み込もうとする問題のある命令がプロセッサによってブロックされるタイミングは変わります)。


順序の重要性

2017 年 7 月、順序が本当に関係ないのかどうかをドイツのセキュリティ研究者が調査しました(リンク先:英語)


この研究者は、プロセッサが不正な命令 X の一部として内部結果を計算し、その内部結果を正規の命令 Y を処理する際に使用し、その後 X だけに禁止フラグを立てた場合に何が起こるのだろうか、と疑問に思いました。


結果 X と Y の両方がキャンセルされた場合であっても、不正な命令 X が投機的実行されたことを示す内部結果の痕跡は残されるのだろうか?

残されているのであれば、その痕跡から何かを解明できるだろうか?

この研究者は次のような例から調査を開始しました。


1.  mov rax, [K]      ; K は禁止されているカーネルアドレス
and rax, 1
mov rbx, [U+rax]  ; U は許可されているユーザーアドレス

アセンブラをご存知なくても大丈夫です。このコードは次の処理を実行します。

  • カーネルメモリからレジスタ A を読み込みます。
  • A が偶数ならば 0 に変更し、奇数ならば 1 に変更します (これは思考実験を分かりやすくするためです)。
  • A に応じて、メモリ位置 U+0 または U+1 からレジスタ B を読み込みます。

投機的実行とは理論上、命令1 における権限違反が原因で命令のシーケンス全体が最終的に無効化され、ブロックされたとしても、CPU が命令 1 を終了する前に命令 3 で内部処理を終了できることを意味します。


しかし、もしかしたら命令 3 がもたらす副作用について、CPU のどこか別の場所から推察できるのではないでしょうか?

結局のところ、投機的に実行された命令 3 がメモリ位置 U または U+1 を参照したかどうかによって、プロセッサの挙動はわずかに異なるはずです。


たとえば、この差異は CPU のメモリキャッシュに現れることがあります。メモリキャッシュは、最近参照されたメモリアドレスと、パフォーマンス向上の目的で CPU 自体の内部で保持されている値のリストです。


つまり、このキャッシュが「密告者」の役割を果してサイドチャネルとなり、CPU 内部の秘密情報 (この場合は、メモリ位置 K の権限値が奇数であるか偶数であるか) が漏洩する可能性があるということです。


(CPU キャッシュ内のメモリを参照するほうが、実際のメモリチップからメモリをフェッチするよりも約 40 倍高速です。したがって、よく使用されている値に対してこのような「近道」を設けることによって、パフォーマンスは大幅に向上します。)


要するに、研究者は上記の場合の A が偶数A が奇数の差 (あるいは、CPU が U でピークしたのかそれとも CPUが U+1 でピークしたのか) を測定できなかったということです。

しかし、最終的にこの思考実験は成功しました。


この研究者は、この種のアドレス計算方法を用いてカーネルメモリに関する情報を盗み出すことができる同様のコード構造を発見しました。

つまり、Intel の CPU は、権限のあるメモリを権限のないプログラムにリークする可能性のあるハードウェアレベルのサイドチャネルの問題を抱えているということです。


後はご存知の通り

この後の話は、皆様がご存知の通りです。

少なくとも Linux と Windows については、KAISER (Kernel Address Isolation to have Side-channels Efficiently Removed: 効率的にサイドチャネルを除去するためのカーネルアドレス分離 (KPTI)) を提供するパッチが間もなくリリースされる予定です。


これで、KAISER という名前の由来がお分かりになったのではないでしょうか。このパッチによってカーネルとユーザーランドメモリはより厳密に分離されるため、投機的実行手法による副作用は測定できなくなっています。


このセキュリティ修正プログラムは、複数の仮想マシンを実行しているサーバーなどのマルチユーザーコンピュータにとって特に重要です。このような環境では、個々のユーザーやゲストオペレーティングシステムが上記の手法を使って、システムの他の部分 (ホストオペレーティングシステムなど)、あるいは同じ物理サーバー上の他のゲストに不正にアクセスできる可能性があります。


しかし、CPU キャッシュはパフォーマンス向上のために存在しており、キャッシュ機能の効果を低下させるものはパフォーマンスも低下させる可能性があります。


単純なログインよりも 2FA (2 要素認証) の方が面倒であったり、普通の HTTP よりも HTPS の方がコストがかかったりするのと同様に、セキュリティの進化にはほんの少しの不便さも必要です。


チーム全体のために嫌なことを引き受ける時がやって来たということです。


今後の展望

パッチに関する詳細の多くが、現時点 [2018-01-03T16:30Z] では秘密のベールに隠されています。

秘密にされているのは、修正プログラムを準備している複数のベンダーによって課せられた機密保持条項が理由のようです。データ漏洩や権限昇格の新たな手法に対する関心の高さを考えれば、それも当然かもしれません。


とは言え、パッチの正式な公開と同時に秘密主義ではなくなることが期待されます。


なお、希望される方は今すぐに Linux 用のパッチを入手してテストすることができます。(ただし、最終版ではないためテスト以外の目的にはお勧めできません。)

現時点では、この脆弱性の危険性はアプライアンスなどの専用サーバーやノート PC などのパーソナルデバイスでは比較的小さいことが分かっています (攻撃者がこの脆弱性を悪用するには、まずユーザーのコンピュータ上でコードを実行する必要があります)。


マルチユーザー型のビルドサーバーや、同じ物理ハードウェア上で複数の顧客の仮想マシンを実行するホスティングサービスなどの共有コンピュータにおいては、リスクが非常に大きくなります。このような環境のホストカーネルは、1 人のユーザーが実行する複数のプログラムを分離するためだけではなく、複数のユーザーを分離するために存在しているからです。


したがって、今回のような脆弱性が存在していると、不正なユーザーが同時にログインしている他のユーザーの情報を入手したり、同じサーバー上にホストされている他の仮想マシンに影響を及ぼしたりできる可能性があります。


この脆弱性は何年も前から存在しており、少なくとも数か月間前から報告されているものであるため、パニックに陥る必要はありません。とは言え、お使いのオペレーティングシステム用のパッチがおそらく 2018 年 1 月には公開されると思われるので、できるだけ早く適用することをお勧めします。

更新情報

[2018-01-04T01:00Z]

Google の脆弱性追跡チームである Project Zero が、ここ数か月間行っていた調査の詳細を公開しました(リンク先:英語)。この報告書は技術的で専門用語が多用されていますが、ポイントは次のとおりです。


  • 理論上、Intel、AMD、および ARM のさまざまなプロセッサが、上記のように悪用可能な投機的実行およびキャッシングに関連する機能を有しています。
  • AMD のチップはこれまでのところ、デフォルト以外のカーネル機能が有効になっている Linux を使用した場合に限り、攻撃が可能です。
  • Intel のチップが悪用され、権限のないログイン済みのユーザーがゆっくりだが確実にカーネルデータを読み取ることに成功しています。
  • Intel のチップが悪用され、ゲスト仮想マシンの root ユーザーがゆっくりだが確実にホストのカーネルデータを読み取ることに成功しています。

(「ゆっくり」とは、攻撃者が毎秒 1,000 バイト、すなわち 1 日あたり約 100 メガバイトのデータを盗み出せることを意味します。)

「攻撃者は攻撃をどこに集中させればよいのか分からず、カーネルデータをランダムにつかみ取ることしかできないはずだ」と思われているのであれば、Heartbleed に似た問題だと考えるとよいかもしれません。Heartbleed 攻撃で入手できるデータの多くはゴミのようなものですが、時折パスワードや復号鍵などの秘密データを入手できることがあります。


Heartbleed と異なるのは、攻撃者が脆弱性のあるサーバーにすでに足跡を残している必要がある点です。たとえば、すでにログインしているユーザーでコマンドシェルが開いた状態になっていたり、ホスティングサーバー上で実行されている仮想マシン (VM) の所有者であったりする必要があります (どちらのケースも、ユーザーは自分のアカウントまたは自分の VM に完全に制約されていなければなりません)。


Intel は、短い公式コメント(リンク先:英語)を発表しています。Intel Responds to Security Research Findings (セキュリティ調査結果に対するインテルの回答) と題されたこの声明は多くを語っていません。主なポイントは次のとおりです。


  • 「Intel は、これらのエクスプロイトによってデータが破損、改ざん、または削除される可能性はないと考えています。」確かに、これまで報告された攻撃およびエクスプロイトは、データをカーネルから吸い取ることができても、カーネル領域にデータを戻すことはできていません。
  • 「これらのエクスプロイトが「バグ」または「脆弱性」によって引き起こされ、インテル製品に固有のものであるとする最近の報告は正しくありません。」本記事はタイトルに「脆弱性」という言葉を使用していますが、今後も使用し続けます。投機的実行が理想的な形で実装されていれば、投機的実行がセキュリティに違反したことが判明した後に副作用は検出されないはずだ、というのがソフォスの見解です。
  • 「一部の報告に反して、パフォーマンスへの影響はワークロードに左右されるものであり、平均的なコンピュータユーザーにとっては重要な影響ではありません。」この点については、皆様がご自身で解釈してください。

[2018-01-04T17:40Z]

AMD は、An Update on AMD Processor Security (AMD プロセッサのセキュリティに関する最新情報)と題した声明を発表しました。(リンク先:英語) Intel の声明と同様に、あまり多くは語られていませんが、AMD の CPU がこれらの攻撃の影響を全く受けない訳ではないことを認めています。


さまざまな F**CKWIT エクスプロイトに 3 つの CVE 脆弱性番号 (CVE-2017-5753、CVE-2017-5715、CVE-2017-5754) が割り当てられています。

AMD は、-5733 に対して脆弱であるが、-5754 の影響は受けないと主張しています。また、理論上は -5715 のリスクがあるが、「アーキテクチャが異なることから、この攻撃を受けるリスクはほぼゼロ」であると主張しています。


[2018-01-05T00:30Z]

Firefox は先ほど、これらの攻撃を緩和するためのブラウザアップデート(リンク先:英語)を公開しました。Firefox はバージョン 57.0.4 に移行します。

このアップデートにより、Firefox ブラウザで実行される JavaScript が短い時間間隔を正確に測定するのが大幅に難しくなりました (これらの攻撃では、キャッシュされたメモリアドレスとキャッシュされなかったメモリアドレスを把握するうえで、メモリアクセスの速さのタイミングを測る必要があります)。


現在キャッシュされているメモリアドレスは、最近アクセスされている必要があります。これは、(最終的にキャンセルされたとしても) 命令が投機的に実行された場合に何が起こったのかを把握するのに役立ちます。

おすすめの記事はこちら