コンピュータシステムの階層を理解する
システムの脆弱性を悪用するには、コンピュータや電子システムがどのようなレベルに基づいて構築されているかを理解することが重要です。電子デバイスを構成する階層を表す方法はいくつもありますが、ここでは、設計全体がいくつかの異なる層に分かれていて、各層を異なる人たちが担当するという事実を念頭に置きながら話を進めることにします。
電子デバイスは対応する領域に基づき階層化されており、階層構造になっていることで、スタックの他の領域ごとの担当者にとっての複雑さが軽減されます。1 人の人間がコンピュータとその処理の隅から隅まで知ることは難しく、それを成し遂げようとすれば、かなりの努力が必要になるでしょう。最も単純化して言えば、ハードウェアエンジニアの場合は、システムボードの回路設計を担当し、電気、トランジスタ、論理ゲートなどを取り扱います。そして、完成した物理ハードウェアを次の担当者であるソフトウェアエンジニアに引き渡します。つまり、ハードウェアとソフトウェアという 2 つの主要ドメインが存在します。さらに抽象化することもできますが、このブログでは分かりやすさを優先し、ソフトウェアドメインに焦点を当てて話を進めます。
ソフトウェアドメインは、アプリケーション開発者、いくつかのプログラミング言語とその開発者、OS(オペレーティングシステム)のAPIによって提供されるライブラリなどで構成されます。当然ながら、ソフトウェア開発にもいくつかの分野があり、それぞれに事故やヒューマンエラーの可能性があります。品質保証がこれを解決する有効な手段となりますが、現実として、意図的ではない動作をすべて捕捉するのは難しく、潜在的なエクスプロイトや攻撃対象はかなり広いと考える必要があります。善意の研究者がこれらの攻撃対象を研究してバグとして開発者に報告しますが、その一方で、悪意の犯罪者はその攻撃対象を悪用しようとします。階層型のドメイン構造の理解を深めるには、具体的でわかりやすい例を参考にすると良いでしょう。
エクスプロイトを可能にする攻撃対象がそれぞれの層に存在するため、個々のレベルの詳細については、参考資料のセクションでご紹介する資料を参照してください。このブログでは前述のとおり、ソフトウェアドメインに焦点を当てて話を進めます。物理的な操作にはコンピュータシステムへの物理アクセスが必要とされますが、皆さんが利用しているサーバやネットワークデバイスは、物理的なアクセスを防ぐため、認証によって保護されたドアの後ろに置かれていることと思います。
ソフトウェアドメインにおいては、ソフトウェアアプリケーションを 4 つの異なるリング、すなわち、ユーザ空間(リング 3)からカーネル空間(リング 0)で表される空間に分類することができます。ユーザ空間のソフトウェアは、一般的にはエンドユーザがコンピュータシステムとやり取りする場所であり、ソフトウェアのこの部分が、ライブラリ関数やその他の低レベルのシステムコール(カーネル空間)を利用する目的で OS の API に対するシステムコールを実行します。こういったシステムコールの例としては、メモリの割り当て、新しいプロセスの実行、ハードディスクへのアクセスなどがあります。リングが上位になるほど特定のタスクや関数に対する権限が少なくなり、下位になるほど権限が多くなって、低いレベルの関数を利用できるようになります。全体をまとめると、次のようになります。
極めて単純化して言えば、ユーザ空間のアプリケーションとは、一般的にはエンドユーザがやり取りするものであり、そのアプリケーションの背後にあるタスクがカーネル空間に所定のシステムコールを実行します。そして、カーネル空間では、実行されたコールが正しく、使用できる範囲を逸脱していないことを確認するためのチェックが実行されます。
ところで、以上の説明が脆弱性やエクスプロイトとどう関係し、潜在的な脆弱性やエクスプロイトの特定にどのように役立つのかと疑問に思われたのではないでしょうか。説明が少し複雑になりますが、脆弱性の攻撃ベクトルを理解する上で重要であるため、さらに説明を続けることにします。
ISA(Instruction Set Architecture)と呼ばれる、単独で説明しても 1 つの記事になりそうな用語から話を始めましょう。これは、コンピュータによるデータビットの処理方法、すなわち、1 と 0 への変換方法と、マシン語のプログラミング / アセンブリを定義するプロトコルです。これも人間が開発するものであるため、エラーが発生する可能性があり、たとえば、Meltdown、Spectre、Lazy FPU などはこのエクスプロイトに分類されます。
「抽象化の階層」のグラフに描かれているどの階層にも、ヒューマンエラーに起因する脆弱性が存在する可能性があります。プログラミング言語によって、ユーザとやり取りするアプリケーションの開発の基礎が設定され、Java や Python / PHP などでアプリケーションが作成されますが、それが正しく開発されていないと、アプリケーションがクラッシュして入力がすべて失われてしまう可能性があります。あるいは、これらのアプリケーションによるシステムコールに不備があるために、任意コードのリモート実行が可能になる場合もあり、最近の Office のエクスプロイトや Flash Player などはこれに該当します。
以上のように、どのレベルでもかなりの部分に人が介在するため、何らかの事故が発生したり、誤りのあるコードが開発されたりする可能性があります。そういった不備を誰でも簡単に悪用できるわけではありませんが、抽象化の階層によって、攻撃ベクトルは広範囲にわたります。システムコールを評価したり却下したりする手段はありますが、そのような方法にもエラーが発生する可能性があります。我々にできるのは、偏りのない立場のセキュリティ研究者やユーザがバグや不備を正しい手順に従って報告し、報告された開発者がその脆弱性を修正してくれるのを期待することだけです。そして、仮にこの手順が守らなければ、犯罪者が脆弱性を先に発見して攻撃を開始し、疑いを持たない人たちが犠牲になる可能性があります。
参考資料
Atwood, J. 著(2008 年 1 月 3 日)、「ユーザとカーネルのモードを理解する」
出典:https://blog.codinghorror.com/understanding-user-and-kernel-mode/
Bansal, G. G. 著(2013 年 10 月 6 日)、「コンピュータ抽象化の概要:コンピュータ抽象化とテクノロジ」
出典:http://girdhargopalbansal.blogspot.com/2013/10/computer-abstractions-and-technology.html
[CSP-AIMS オンラインコース](2015 年 11 月 10 日)、「コンピュータサイエンスの抽象化」[動画ファイル]
出典:https://www.youtube.com/watch?v=i55nz9xAtJE
EDC.org の寄稿者による投稿、「コンピューティングの美しさと楽しさ – BJC:コンピュータの内側の抽象化」
出典:https://bjc.edc.org/bjc-r/cur/programming/6-computers/1-abstraction/01-abstraction.html?topic=nyc_bjc%2F6-how-computers-work.topic&course=bjc4nyc.html&novideo&noassignment
Hernandez, C. I. 著(2017 年 2 月 24 日)、「抽象化の階層:原子からアプリまで」
出典:https://medium.com/@carlos.i.hernandez011/abstraction-layers-from-atoms-to-apps-1888e7943f14
McCarty, S 著、(2015 年 7 月 29 日)、「コンテナを組み立てる(第 1 部):ユーザ空間とカーネル空間の違いの理解が重要である理由」
出典:https://rhelblog.redhat.com/2015/07/29/architecting-containers-part-1-user-space-vs-kernel-space/