--------------------------------- LIDS Trusted Path Execution (TPE) --------------------------------- Yusuf Wilajati Purna (ywpurna@users.sourceforge.net) March 09, 2004 INTRODUCTION ============ "Trusted Path" はセキュリティモデルの中で、伝統的な保護機能として知られています。 これは、ユーザーが、その他のプロセスやユーザーからの妥協が無い、信頼できるソフトウェアに アクセス出来ることを、確実にし、またそのソフトウェアが本当に意図されたとおりにに実行されてい ることを確実にする、簡単なメカニズムです。 ([1], [2]) にある、標準や文書では、より正確にこの単語を定義しています。 任意のユーザーが任意のコードを実行することを防止することを主目的とした 、信頼できるメカニズムを提供しようとするコンセプトは、「Trusted Path Execution」、あるいは省略して「TPE」と 呼ばれます。 このメカニズムを取り込むために、Linux や*BSD カーネルでは、多くのセキュリティの拡張や、 パッチが存在しています。これらの導入により、一般的に、TPE は次の3 つの主なコンポーネントを ベースにして作られると考えられます: - Trusted Path. (信頼できるPath ) -------------      これは狭い意味での、信頼できるPath です。通常、Path は親ディレクトリが 'root' により所有されていて、その他のGroup やAnonymous がWrite 権限を 持っていない場合に、信頼できると考えられます。 - Trusted ACL. (信頼できるACL ) ------------ これは、信頼できるユーザーのリストです。このリストに載っているユーザーが、 'root' もですが、信頼できると考えられます。 - Rule. (ルール) ----- これは実行可能なファイルが信頼できるPath と信頼できるACL の情報/状態で ある場合に、実行させるかどうか決定するための、ポリシーやルールです。 例えば、[7] では、その機能は次のように定義されています: 信頼できるPath と信頼できるACL は上のように定義され、実行可能なファイルが実行で きるかどうかを、次のようなルールにより決定します: - 信頼できるuser で、信頼できるpath -> user はそのファイルを実行できる。 - 信頼できるuser で、信頼できないpath -> user はそのファイルを実行できる。 - 信頼できないuser で、信頼できるpath -> user はそのファイルを実行できる。 - 信頼できないuser で、信頼できるpath -> user はそのファイルを実行できない。 したがって、この機能の導入により、理論上は、user が信頼できない場合(すなわち、 信頼できないACL の場合)かつ、その処理が信頼できるpath で無い場合のみ、 そのファイルを実行できなくすることが出来ます。 しかしながら、実際には、この導入には未だ少し抜け落ちがあります。例えば、 LD_PRELOAD/LD_LIBRARY_PATH(library) タイプの攻撃や、 '/lib/ld-linux.so.X ' タイプの攻撃からの保護メカニズムが 導入されていないため、信頼できないuser は、そんなに多くの努力を必要としなくても 信頼できないファイル(すなわち、信頼できないpath のファイル)を、これらの弱点を突く 攻撃をすることにより、実行することが可能です。 上記の、ほとんど一般的なTPE のコンセプトに基づき、現在のLIDS をTPE モードLIDS と してバイナリやライブラリを実行したり、保護されている限りは、カーネルモジュール をロードさせるように拡張してみます。 アプローチ ======== LIDS をTPE として拡張するために、次の3 つの一般的なTPE コンポーネントを定義する必要が あります: - Trusted Path. (信頼できるPath ) -------------- LIDS では、root がオーナーになっていて、group もanonymous も write 権限が与えられていない親ディレクトリを、信頼できるpath として 定義することは、有効ではありません。なぜなら、LIDS の役割の一つとして root の権限を制限するということがあるからです。 代わりに、バイナリ/カーネルモジュール/ライブラリ のパスがLIDS で 最低でもREADONLY に保護されている状態を、「信頼できる」と定義します。 したがって、デフォルトのルールは最低でもREADONLY になっている必要が あります。 例: - lidsconf -A -o /sbin -j READONLY -> /sbin 以下の実行可能ファイルは信頼できます。 - lidsconf -A -o /lib -j READONLY -> /lib 以下のライブラリは信頼できます。 - lidsconf -A -o /lib/modules -j READONLY -> /lib/modules 以下のモジュールは信頼できます。 - lidsconf -A -o /var/workdir -j READONLY lidsconf -A -o /sbin/application_a -j READONLY lidsconf -A -s /sbin/application_a -o /var/workdir -j WRITE -> 更に、保護されたappication_a が/var/workdir に対して WRITE 権限を持っているときには、/var/workdir 以下のファイル も信頼できると考えます。 - Trusted ACL. (信頼できるACL ) ------------ 仮に信頼できるユーザーのリストを信頼できるACL として定義したとしても、 有効ではありません。LIDS はユーザーがプログラムを実行することに対しての 制限よりも、むしろバイナリー/プログラムの方に焦点を当てています。 既にLIDS ACL がありますので、ここではLIDS ACL を信頼できるACL として 定義します。 - Rule. (ルール) ----- 簡単なルールを次のように定義します: 信頼できるバイナリーのみが実行を許可され、信頼できるライブラリ/カーネルモジュール のみがロードすることを許可されます。 待ってください! こうしてみるとLIDS では既に同様のメカニズムを持っているようです。 実際、そのとおりです。現時点では、カーネルのConfig 中にCONFIG_LIDS_NO_EXEC_UP を "Y" にしておくと、LIDS はカーネルが封印される(lidsadm -I) 前は、保護されていない プログラムの実行を拒否します。従って、LIDS には既に基本的なメカニズムが存在しています。 更に、LIDS 自身での大局的な見地からすると、LIDS は実際大きいフレームワークとして TPE の導入と似たことを行っています。 導入 ============== カーネルスペース ------------ カーネルスペースでは、path が保護されているかのチェック機能は、既にLIDS の中に 基本的な機能として存在しています。従って、基本的な機能と、どこでいつパフォーマンス チェックをするべきかを定義する関数を作成すること作業が必要になります。 TPE 拡張では、次の3 つの関数が導入されます: - lids_exec_tpe_permission(brpm) ------------------------------ この関数は、バイナリーが保護されているかどうかをチェックします。 - lids_mmap_tpe_permission(file, protection) ------------------------------------------ この関数は、ライブラリが保護されているかどうかをチェックします。 - lids_module_tpe_permission(module) ---------------------------------- これはモジュールがロードされる前に、それが保護されているかどうかをチェックします。 これらの関数が呼び出されるべき場所は、殆どがLSM フックから導き出されます。 lids_exec_tpe_permission(brpm) 用に、fs/exec.c:do_exec()内にその関数を呼び出すための フックをセットできます。基本的なアルゴリズムは、次のようになります: --------------------------------------------------------------------- lids_exec_tpe_permission(bprm) { int error = 0 if (!lids_check_base(bprm->file->dentry, LIDS_APPEND)) error = -EACCES; return error; } --------------------------------------------------------------------- これは本当のコードではないことに注意してください。これは擬似コードだと思ってください。 ファイルのdentry が保護されているかどうかをチェックするだけのものです。 保護されていないときは、関数はエラーコードとして-EACCESS と供にエラーコードを 返します。 殆どのライブラリがmmap() によってロードされているので、 mm/mmap.c:do_mmap_pgoff() にライブラリをチェックする関数呼び出しのための フックをセットすることが出来ます。 次に、 lids_mmap_tpe_permission() の簡単なアルゴリズムを:お見せします --------------------------------------------------------------------- lids_mmap_tpe_permission(file, protection) { int error = 0; if (!file) return 0; if (!(protection & PROT_EXEC)) return 0; if (!lids_check_base(file->dentry, LIDS_APPEND)) error = -EPERM; return error; } --------------------------------------------------------------------- ファイルシステム上に、本当に存在しているかについては、ファイルについてPROT_EXEC で メモリ保護属性をチェックしているだけです。もしこのファイルが保護されていなければ、 関数は単純に、-EPERM をエラーコードとしてエラーを返してきます。 モジュールが保護されているかどうかをチェックするために、モジュールのシンボル情報を 使用することが出来ます。シンボル情報をモジュールのpath から得ることが出来ます。 この関数を呼ぶためのフックは、したがってkernel/module.c:sys_init_module() の中に あります。この関数の基本的なアルゴリズムは次のようになります: --------------------------------------------------------------------- lids_module_tpe_permission(module) { int error = 0; modpath = get_module_path(module); if (!lids_check_base(modpath->dentry, LIDS_APPEND)) error = -EPERM; return error; } --------------------------------------------------------------------- シンボルからモジュールのpath 情報を得た後、前に出てきた他の2 つの関数と同じように、 lids_module_tpe_permission() により、path が保護されているかどうかをチェックします。 path が保護されていない場合には、単純に-EPERM を返します。 これらがLIDS TPE メカニズムでの、チェックに使用する、基本的な3 つの関数になります。 メカニズムそれ自身はLIDS カーネルの設定パラメーターにより、オプションとして取り込みが 可能です。カーネルのCONFIG_LIDS_TPE で'Y' を選択することにより、LIDS TPE 機能が有効に なります。 ユーザー空間 ---------- ACL_DISCOVERY モードと同じように、'TCP モード' ターミナルはオペレーション時の、 LIDS のステートを記述するために使われます。 このモードをコントロールしやすくするために、lidstools に新しいフラグ: TPE フラグを追加しました。このフラグの状態により、システムがTPE モードか、 そうでないのかを判断します。 また、このフラグを用いてシステムのTPE モードをON/OFF に出来ます。つまり: # lidsadm -S -- +TPE /* これでTPE mode になります*/ # lidsadm -S -- -TPE /* これでTPE mode をオフにします*/ また、TPE モードをカーネル封印のときと同時に、次のように変更できます: # lidsadm -I +TPE 。 ACL_DISCOVERYモードにをON にすると、最初のうちは、アプリケーションがTPE モードで 動くときに、どのライブラリが保護されてなくてはいけないかを調べるための、良いツールに なるでしょう。 LIDS TPE が出来ること、出来ないこと =================================== これまで説明した手順により、LIDS TPE は実際には何を出来るのでしょうか? 簡単に説明すると、次のようになります: - root 特権を含む、任意のユーザーが, 保護されていないライブラリを含む任意のファイル (保護されていないバイナリ) を実行することを防止します。 - root 特権を含む任意のユーザーが、保護されていないカーネルモジュールを 読み込むことを防止する - システムをLD_PRELOAD/LD_LIBRARY_PATH タイプの攻撃から守ります。 - システムを'/lib/ld-linux.so.X ' タイプの攻撃から守ります。(*) (*) 2.4.25/2.6.0 以前のカーネルに対しては、mount を'noexec' オプションを つけて使用しても、この保護メカニズムは動作しません。しかしながら、今のところ、 2.4.25/2.6.0 に対しては、'/lib/ld-linux.so.X ' タイプの攻撃から保護する ことが可能です。いずれにせよ、LIDS TPE はよりフレキシブルに動作します。 しかしながら、非保護場合には動作は完璧です。そして、LIDS TPE は未だ完璧ではありません。 現在は、LIDS TPE は信頼されているインタープリター、すなわちsh 、perl などを通して 起動された、信頼されていないスクリプトを防ぐことは出来ません。 従って、信頼されていないスクリプトは、それらのインタープリターを通して動作することが 可能です。バッファーオーバーフローの脆弱性を用いて実行される任意のコードを防ぐことは 出来ません。 注意 ======= もともとルールによるアプローチのため、LIDS TPE を用いることにより、実行の際にテンポラリの スクリプト/実行ファイルをテンポラリのディレクトリ(/tmp など)に作成して、それを実行する ようなアプリケーションの動作に問題が生じます。これらのようなアプリケーションは、きっと 動かないでしょう。 開発環境でLIDS をLIDS TPE モードで用いると、単にコンパイルしたりプログラムをテストしたりする ことが出来なくなるため、非常にイライラするでしょう。LIDS TPE は開発環境で用いるのには 適していません。 結論 ======= LIDS TPE は任意の(root を含んだ)ユーザーが、任意の実行ファイル/ライブラリを実行したり、 保護されていない/信頼されていないカーネルモジュールがロードされるのを防ぐことが出来ます。 とはいえ、LIDS TPE は開発環境で用いるには適しておらず、プロダクションサーバーでセキュリティ の品質を高めるために使用することが出来ます。 カーネル2.4 に関しては、LIDS TOP は他のセキュリティプロジェクト、たとえば Openwall [9] や PaX [10] プロジェクトなどに統合されていて、任意のバッファーオーバーフロー 脆弱性を用いるコードや、タスクのアドレス空間を用いる任意のコードの実行を防ぐことが 期待されています。 最後に、楽しんで、試してみて、バグを見つけたら報告してください:-) 確認 =============== TPE メカニズムはSony Corp. で行ったプロジェクトの一部として提供されました。 LIDS チームに代わって、Sony Corp. の、LIDS コミュニティに対しての貢献に対して 感謝します。 入手 ============ LIDS TPE はLIDS 1.2.0 からインプリメントされています。この機能を制御するためには、 lidstools 0.5.4 以上を用いる必要があります。ソースコードはhttp://www.lids.org から 自由にダウンロードできます。 リファレンス ========== 1. US DoD, "Trusted Computer System Evaluation Criteria (DOD 5200.28-std)", 1985. 2. Loscocco, Smalley, et al, NSA, "The Inevitability of Failure: The Flawed Assumption of Security in Modern Computing Environment", 1998. http://www.nsa.gov/selinux/papers/inevitability/ 3. route|daemon9 , "Trusted Path Execution Patch fo Linux 2.0.0+", 1998. https://www.phrack.com/phrack/52/P52-06 4. Krzysztof G. Baranowski , "Linux Trusted Patch Execution Redux", https://www.phrack.com/phrack/53/P53-08, 1998. 5. route|Mike Schiffman|daemon9 , "Trusted Path/ACL Execution Patches for OpenBSD 2.4-SNAP", 1998. https://www.phrack.com/phrack/54/P54-06 6. Brian , "TPE in Stephanie for OpenBSD 3.4", 2003. http://kaizo.org/mirrors/stephanie/ 7. Niki Rahimi "TPE LSM module for Linux 2.5.59 (2.6)", 2003. http://www-124.ibm.com/developer/opensource/linux/patches/?patch_id=770 8. LSM Developers/Community , "LSM Linux Security Modules". http://lsm.immunix.org/ 9. Solar Designer et al, "Openwall Project". http://www.openwall.com/ 10. PaX Team, "PaX Project". http://pax.grsecurity.net/