PaX
[Wikipedia|▼Menu]

PaX は、メモリに関する最小特権保護を実装したLinuxカーネル向けコンピュータセキュリティパッチである。最小特権の原則により、プログラムは正しい動作以外は何もできなくなる。PaX は2000年にリリースされた。

PaX はデータ用メモリページを実行不可とし、コード用メモリページを書き込み不可にすると共に無作為な配置を行う。これによりセキュリティを危険にさらす様々な動作が不可能になる(バッファオーバーランの一種など)。データページの実行不可設定により、データをコードとして実行できなくなる。コードページの書き込み不可設定により、不正なライブラリ実行が難しくなる。ただし、変数やポインタの書き換えは防げない。

PaX は The PaX Team が保守しているが、個々の開発者は匿名である。Linuxマスコットタックスの PaX 版
意義

コンピュータのセキュリティ問題の大半は、実行時に何かを書き換えられるような抜け穴(バグであることが多い)がプログラムにあることが原因である。Ubuntuの初期の44通の Security Notice を分類すると[1]、41%はバッファオーバーランを原因とする脆弱性、11.4%は整数オーバフロー、15.9%は不正データの処理上の問題であった。これらのバグを悪用すると、外部からコードを注入して実行させたり、既存コードを不正な順序で実行させることができる。なお、この分析は非常に簡単なものであって、詳細に脆弱性を分析すれば結果は変わってくるだろう。

ワームコンピュータウイルスなどの攻撃の多くは、メモリの内容を書き換えてマルウェアコードを実行できるようにすることで行われる。あるいは、データを実行するよう誘導するなどの手法がある。そのようなマルウェアの実行をブロックできれば、そのような侵入によって損害を被る可能性は激減する。Sasserのようなワームもそれによって対処可能である。

PaX は、そのような様々な攻撃を防ぐため、非常に汎用的な方法で防御するよう設計された。メモリのアクセス権(リード、ライト、実行の組合せ)を制御することで不正コードの実行を防ぎ、同時に正当なコードの実行には影響を与えないよう設計されている。若干のオーバーヘッドはあるが、PaX はDoS攻撃や外部からのコード注入制御の可能性を減らし、攻撃者にスーパーユーザー特権を与えるのを防ぎ、ハードディスク上の重要な情報へのアクセスを防ぎ、単に影響を受けたプログラムやプロセスがクラッシュするだけで済む。

DoS攻撃は、実行されるだけで迷惑であり、リソースや時間の浪費となる(企業のウェブサイトが攻撃された場合、ビジネス機会が失われる)。しかし、PaX があればデータを書き換えられたり、情報を外部にコピーされたりすることがなくなる。ただし環境によっては DoS 攻撃の類は攻撃されること自体が許容されない。サービス水準合意などの契約条件では、侵入者によるサービス低下が単なるコスト問題以上の契約違反として扱われる。それでも多くの場合、セキュリティを強化して重要な情報を保護することには意味がある。

多くのバグはメモリ破壊の原因となる。そのようなバグを利用して、プログラムが意図していない動作をさせることが可能となる。PaX はそのようなバグの検出や修正が可能なわけではなく、そのようなバグを利用した悪意ある攻撃を防ぐことにある。そのようなバグの一部は深刻度が減じられ、不正な動作をする代わりにプログラムを終了させる。

PaX はバッファオーバーフローを直接防ぐことはできないが、それを利用して不正なアクセスを行おうとするのを効果的に防ぐ。Stack Smashing Protector や StackGuard はバッファオーバフローそのものを検出し、そのような動作をしようとしたプログラムを終了させる。このような手法を Stack Smashing Protection と呼び、実際にオーバフロー状態となる前に防ぐ。一方 PaX はより汎用的な手法であり、オーバフローが発生してから実際のダメージが発生するのを防ぐ。どちらの手法でも結果的には同じ効果が得られるが、完全に重複する手法というわけではない。従って、両方の手法を同時に使うことで、システムをより安全にすることが(原理的には)可能である。一部のLinuxディストリビューションでは、PaX と Stack Smashing Protection の両方を採用している。

2004年中ごろ、PaXはLinuxカーネルのメインのソースツリーには含まれていなかった。これは、PaXチームがPaXを不完全であると考えていたためである。x86を含む多くのCPUアーキテクチャでは完全に機能しているが、いくつかのアーキテクチャでは部分的にしか実装されていないか、全く実装されていない。PaXが実装されているアーキテクチャとしては、IA-32 (x86)、AMD64IA-64AlphaPA-RISCMIPSPowerPCSPARC がある。
限界

PaXは実行ファイルやカーネルに潜在する基本的な設計ミスに対処することはできない。それは例えば、原理的に検出不可能な方法で攻撃可能とするような問題である。例えば、スクリプト言語インタプリタはファイルやネットワークにアクセスできるため、悪意あるスクリプトを使って特権ユーザーのアカウントを通して重要データを盗むことも可能である。PaXは書式文字列攻撃の一部も防げない。書式文字列攻撃では、既存のコードを使って任意のデータ位置の読み書きが可能であり、攻撃者は内部のアドレスを事前に知っておく必要がなく、攻撃用コードを注入する必要もない。

PaXの公式サイトにある文書[2]では、PaXが防ごうとしている攻撃を三種類としている。その文書によれば、PaX はそれらを効果的に防ぐことができるが、それ以外の攻撃は防ぐことはできない。実行コード領域の保護が可能で、そのベースを任意のアドレスにでき、完全なアドレス空間ランダム化が可能であることが前提である。防ぐことができる攻撃は大まかに言えば、次の通りである。
何らかのコードを導入し実行する攻撃。いわゆるシェルコードであることが多い。

プログラマが意図していない不正な順序で既存のコードを実行させる攻撃。return-to-libc攻撃と呼ばれる。

既存のコードを正しい順序で実行させるが、適当なデータを与えることで望みの動作をさせる攻撃。1.1.4-a 以前の zlib にこの問題があることが知られている。

PaX はこれらの攻撃の元となるバグを検出・対処できるわけではなく、単に攻撃によるダメージを防ぐものであるため、あらゆる攻撃を防ぐことができるわけではない。実際、ライスの定理により、あらゆる攻撃を防ぐことは不可能とされている。

3つ目の攻撃は、攻撃対象のアドレスを知る必要がない場合、PaXを使っても全く防ぐことができない。また、2つ目と3つ目の攻撃は、攻撃対象のアドレス空間配置を知る必要がある場合、それを攻撃対象のアドレス空間を読み取ることで知ることができるなら、PaX を使っても防ぐことができない。これは、攻撃対象が /proc/(pid)/maps にあるような情報を漏らすようなバグを持っていると可能になる。ユーザーランドでプロセスのアドレス空間配置などの情報を見えないようにするパッチもあるが、それは PaX には含まれていない。

事前にアドレス空間配置に関する知識が必要なら、2つ目と3つ目の攻撃は推測や力ずくの探索を行わなければ、ほとんど不可能である。ASLRの文書[3]には、そのような攻撃が成功する「小さな可能性」をさらに詳しく解説している。

1つ目の攻撃は、攻撃者が攻撃対象のタスクを生成でき、それに書き込むことができ、mmap()でファイルをマッピングできる場合に可能となる。すると、二次攻撃が可能でなければ攻撃は成功しないため、そこまで分析する必要がある。PaX には含まれないが、この種の攻撃の可能性を減じるには、アクセス制御を正しく設定しておく必要がある。

PaXを使ったとしてもシステムアドミニストレータによる管理は必要である。PaXはメモリ破壊バグを利用した攻撃を防ぐ。PaXが防ぐことができる攻撃の多くは、バッファオーバーフローを起こすバグに関連している。これは、メモリ管理関連の問題を利用した攻撃の典型的な部分を占める。ただし、PaXは全てのそのような攻撃を防ぐわけではない。
PaX が提供する機能

PaX が提供するのはNXビット(あるいはそれに相当する各CPU/MMUアーキテクチャにある機能)の機能を使った(あるいはそれをOSでエミュレートした)メモリ保護機能である。また、return-to-libc攻撃や、メモリ空間配置に関する知識に依存した攻撃を防ぐため、アドレス空間配置のランダム化を行う。
実行空間保護図1 プログラム内のメモリセグメント群。青はコード、緑はデータを表す。

PaX の主要機能は実行空間保護である。一部プロセッサにあるNXビットの機能を用いて任意のコードの実行を防ぐ。それによって、コード注入やシェルコードといった攻撃を防ぐ。NXビットを持たないIA-32CPUでは、PaX はその機能を様々な手段でエミュレートできる。

Linuxを含む多くのOSでは、ハードウェアのNXビットの機能を利用して、メモリのアクセス権を適切に設定する。図1は、1つのロードされたライブラリのあるプログラムのメモリセグメント群を簡単に図示したものである。緑のセグメントはデータで、青のセグメントはコードである。一般に、AMD64なども含めたプロセッサでのアドレス空間は、デフォルトでは図1のように明確にデータ部とコード部が定義されている。しかし、Linux ではデフォルトではアプリケーションが自身のメモリ保護設定を変更することを防ぐことができず、コード部を書き込み可能にしたり、データ部をコードとして実行することが可能となっている。PaX はそのような変更を防ぐとともに、典型的な操作に最適な最も制限のきつい保護設定を保証する。

実行空間保護が起動しているとき、mprotect() 制限も含まれ、PaX は本来コード部でなかった領域を実行可能にするような操作を不可能にする。これにより、書き込み可能だったことのある領域に存在するコードは実行不能となり、悪意があるかどうかとは関係なく、コードを後から注入することが不可能となる。

すると、Javaジャストインタイムコンパイル方式のように、実行時にコードを生成して実行する必要のあるアプリケーションは動作できなくなる。しかし多くの場合、そのような機能を必要としているプログラムは、それに依存しないように書き換えることが可能である。根本的に実行時のコード生成が必要なものについては、システムアドミニストレータがその実行ファイルに印を付け、その実行ファイルについては制限が課せられないようにすることができる。

PaX チームは mmap() システムコールをどう扱うかを決定する必要に迫られた。mmap は共有メモリのマッピングや共有ライブラリのロードに使われる。そのため、使われている状況によっては書き込み可能なページや実行可能なページを生成できるようにしなければならない。PaX の現在の実装では、デフォルトで書き込み可能な無名メモリページのマッピングが可能となっている。ファイルのマッピングは mmap() コールが書き込みのパーミッションを指定している場合のみ書き込み可能にできる。


次ページ
記事の検索
おまかせリスト
▼オプションを表示
ブックマーク登録
mixiチェック!
Twitterに投稿
オプション/リンク一覧
話題のニュース
列車運行情報
暇つぶしWikipedia

Size:30 KB
出典: フリー百科事典『ウィキペディア(Wikipedia)
担当:undef