Grsecurity
Grsecurity プロジェクトは Linux カーネルのセキュリティを高めるためのパッチを提供しています。一般的な攻撃ベクトルに対してカーネルを強固にし、絶え間なく生まれる脆弱性によってカーネルが危ない状態になるのを防ぎます。楽チンな自動学習モードがあるパワフルな強制アクセス制御 (Mandatory Access Control) システムが含まれています。また、PaX パッチも含まれており、強力なメモリー保護や ASLR によってエクスプロイトに対してユーザースペースのアプリケーションを強固にします。
- 既知の脆弱性のパッチや、シグネチャベースの検出、その他の反応的な方法を使ってセキュリティを高めているようなふりをする他の高価なセキュリティ"ソリューション"とは異なり、grsecurity は本当の率先的なセキュリティを提供します。アプリケーションとオペレーティングの両方を強固にする唯一の方法として、grsecurity は公に公開するサーバーや共用のホスティング環境で必須と言えるでしょう。
目次
インストール
公式リポジトリの linux-grsec パッケージは grsecurity によって強化されたカーネルを提供します。AUR の linux-grsec-ltsAUR パッケージには 3.14 長期サポート版が入っています。基本的には、標準カーネルと完全に互換があり問題は発生しません。デフォルトで、ユーザーが使える機能はほとんど無効になっていますが、それでも攻撃に対するカーネルの著しい強化がなされます。
任意で paxd パッケージをインストールすることで PaX による脆弱性攻撃の弱体化が有効にされ、ユーザースペースのプロセスが保護されます。/etc/paxd.conf
設定ファイルで指定したリポジトリのパッケージや一般的なサードパーティ製のソフトウェアの必要な例外を設定するデーモンが入っています。これらの例外は Pacman の処理や設定ファイルを変更した後に再度適用されます。再起動後に自動で起動します (無効にするようマスクすることも可能です)。
さらに checksec, pax-utils, paxtest パッケージには PaX を使用したりエクスプロイト攻撃弱体化技術が有効かどうか検証するのに便利なツールが含まれています。
任意の gradm パッケージには RBAC ポリシーを管理するためのユーザースペースツールが入っています。RBAC はデフォルトで無効になっており、重要な設定をしないかぎりサンプルのポリシーは使い物になりません (学習モードを多用するなど)。
カスタムカーネル
公式パッケージをベースにしてカスタムカーネルを ABS でコンパイルすることは考慮に値します。パフォーマンスとセキュリティのバランスを取るための様々な妥協があり、公式設定は頑丈ではありますが、あらゆるユースケースにうってつけとは言えません。/proc
と /sys
の制限はあまりに多くのソフトウェアを破壊してしまうため汎用なパッケージとしては受け入れられませんが、有効にすることで情報の漏洩の危険性を減らすのに役立つ可能性があります。使われているオプションの理論的な根拠については DeveloperWiki:Security#grsecurity を見て下さい。
RANDSTRUCT プラグインやシンボルのアドレスの秘匿などの機能はカスタムカーネルでのみ意味を成し得ます、攻撃者はビルド済みのカーネルならば解析することができるからです。linux-grsec パッケージは CONFIG_RANDOMIZE_BASE
を有効にしていますが、ランダマイズベースに加えて CONFIG_GRKERNSEC_HIDESYM
を利用してカスタムビルドではユニークシンボルオフセットを使うことができます。
ユーザーの分離にも基づく /proc
の強化は /proc
に hidepid
マウントオプションを使うことで可能で、あまり大きなロスはありません。AUR のオリジナルの linux-grsec
では他のグループベースのホワイトリストモデルを使って厳格な /proc
制限を有効にしていました。これは arsch リポジトリ や 手動 でインストールできます。
互換性
以下の非互換機能を使うには有効にする機能を減らしたカスタムカーネルをビルドする必要があります:
- ハイバネーションはサポートされていません (
CONFIG_GRKERNSEC_KMEM
,CONFIG_PAX_MEMORY_SANITIZE
,CONFIG_RANDOMIZE_BASE
と衝突) - Xen はサポートされていません (
CONFIG_PAX_KERNEXEC
,CONFIG_PAX_MEMORY_UDEREF
と衝突)
以下のパッケージは既知の非互換性があります:
- pkgstats - ロードされたモジュールを非 root で表示しようとして致命的なエラーとして扱います
Out-of-tree モジュールは CONFIG_PAX_SIZE_OVERFLOW
などのカーネル防御機能との互換性を解決するためのパッチを必要とします:
- AUR の nvidia-grsecAUR パッケージはプロプライエタリの NVIDIA ドライバーにパッチを適用して
CONFIG_PAX_USERCOPY
やCONFIG_PAX_CONSTIFY_PLUGIN
機能との互換性を確保します
PaX
PaX プロジェクトは grsecurity に使われている多数の脆弱性攻撃弱体化を提供しています。詳しくは PaX のドキュメントを見て下さい。
設定
ユーザーから扱える設定は sysctl で実行しながら変えることができます。デフォルト設定は /etc/sysctl.d/05-grsecurity.conf
設定ファイルで設定されており、必要に応じて変更することができます。
Trusted path execution
Trusted path execution (TPE) はファイルの実行を規制する選択的な機能です。kernel.grsecurity.tpe
sysctl を 1
に設定することで有効にできます。TPE は root でないユーザーが書き込み可能なファイルを実行してしまうことを防止します。ファイルの実行のルールを厳しくすることで、(ウェブサーバーのアップロード + CGI エクスプロイトなど) 脆弱性攻撃や永続的なバックドアをある程度予防できます。
tpe
グループをホワイトリストやブラックリストとして使う
デフォルトで、kernel.grsecurity.tpe_invert
は 1
に設定されており、ホワイトリストベースモデルで TPE を使うようになっています。規制は tpe
グループのメンバーでない全てのユーザーに適用されます。kernel.grsecurity.tpe_invert
が 0
に設定されている場合、反対に tpe
グループは制限を受けるユーザーのブラックリストとして機能し、グループに入っていないユーザーは影響を受けません。
ホワイトリストモデルが推奨され、通常はシステム管理を行わないユーザーをホワイトリストに追加するだけで十分です。root 以外で実行されるサービスの隔離を少しだけ改善させます。
互換性
コンテナや普通の chroot はそれぞれローカルの /etc/group
を保持するため、TPE の使い勝手の良さが台無しになる可能性があります。コンテナ内の同じ id のグループもホワイトリストとして機能しますが、コンテナがユーザー名前空間を使うと破壊されます (Arch のカーネルではサポートされていません)。
root でない全てのユーザーに一部制限をかける
kernel.grsecurity.tpe_restrict_all
sysctl スイッチを 1
に設定すると root でないユーザーが、他のユーザーや root によって書き込み可能なファイルを実行するのを止めます。この機能は /etc/sysctl.d/05-grsecurity.conf
によってデフォルトで有効にされています。
chroot の防御
chroot はサービスを分離させるのによく使わえる手法です。Grsecurity には chroot から脱獄するのを防いでコンテナと同じように制限をかけてロックダウンする機能があります。sysctl スイッチを使うことで機能のオンオフを切り替えられます。詳しい機能の説明は、configuration documentation を見て下さい。
以下の設定は /etc/sysctl.d/05-grsecurity.conf
によってデフォルトで有効になっており、互換性の問題を起こしません:
kernel.grsecurity.chroot_deny_fchdir = 1 kernel.grsecurity.chroot_deny_shmat = 1 kernel.grsecurity.chroot_deny_sysctl = 1 kernel.grsecurity.chroot_deny_unix = 1 kernel.grsecurity.chroot_enforce_chdir = 1 kernel.grsecurity.chroot_findtask = 1
以下の機能はデフォルトでオフになっています、コンテナの互換性を維持するためです:
#kernel.grsecurity.chroot_caps = 1 #kernel.grsecurity.chroot_deny_chmod = 1 #kernel.grsecurity.chroot_deny_chroot = 1 #kernel.grsecurity.chroot_deny_mknod = 1 #kernel.grsecurity.chroot_deny_mount = 1 #kernel.grsecurity.chroot_deny_pivot = 1 #kernel.grsecurity.chroot_restrict_nice = 1
ソケット制限
ソケットへのアクセスを制限するためのグループが3つあります。socket-deny-client
グループのユーザーは他のホストに接続することができません。socket-deny-server
グループはポートを開くことができません。socket-deny-all
グループは両方の制限がかかります。
カーネル監査
カーネルにセキュリティ関連のログ機能が追加されています。
デフォルトでは、kernel.grsecurity.rwxmap_logging
だけが有効です。PaX の MPROTECT 機能などによって mprotect
または mmap
システムコールをアプリケーションが拒否された場合にエラーを記録します。ほとんどの場合、アプリケーションは故意に動的マシンのコード生成を実行しており、例外を設定する必要があります。しかし、コンパイラやリンカにバグがあったり、アプリケーションやライブラリのコードにバグが存在しているためにエラーが残ることもあります。また、MPROTECT 機能によって脆弱性攻撃が防がれた時にもエラーが記録されます。例外については PaX を見て下さい。
他の監査機能は大量に誤検知が発生するのでデフォルトでは無効になっていますが、sysctl で有効にすることができます。ログメッセージが多すぎる場合 kernel.grsecurity.audit_group
スイッチを 1
に設定することで audit
グループのユーザーについて kernel.grsecurity.audit_chdir
や kernel.grsecurity.exec_logging
を制限することができます。
/proc の情報を隠匿
linux-grsec パッケージは /proc
の強固な制限を有効にしていません (CONFIG_GRKERNSEC_PROC
)。代わりに、hidepid=2
マウントオプションを /proc
で設定することで他のユーザーのプロセスを隠匿することができます。gid
オプションを使うと制限からの例外をグループに設定できます。hidepid
マウントオプションはプロセスの名前空間ごとにローカルなのであまり強い副作用がありません。コンテナごとに設定することが可能です。ただし、細かい情報の隠匿がされないのでカスタムカーネルのコンパイルが望ましい場合もあります。
2014.10-3
現在 filesystem パッケージには proc
グループがありますが、以下がパッケージに適用されていません:
- systemd-logind サービスには例外を指定する必要があります。ユニットの
SupplementaryGroups
エントリにproc
を追加してください。 polkitd
ユーザーをproc
グループに追加する必要があります。 (FS#43930)
RBAC
ロールベースアクセス制御 (Role Based Access Control)
ファイル (もしくは総じて情報) への不正アクセスを防ぐのに使われるアクセス制御メカニズムには基本の2つのタイプがあります: DAC (Discretionary Access Control, 任意アクセス制御) と MAC (Mandatory Access Control, 強制アクセス制御) です。デフォルトで、Linux は DAC メカニズムを使っています: ファイルの作成者がファイルにアクセスできるユーザーを定義します。逆に MAC システムでは全てのユーザーが管理者の設定したルールに従います。
grsecurity がサポートしている MAC の実装はロールベースアクセス制御 (Role Based Access Control) と呼ばれます。RBAC はそれぞれのユーザーにロール(役割)を割り当てます。各ロールには特定のオブジェクトで実行できる操作が何かを定義します。ロールと操作の集合を上手く記述すれば、ユーザーは管理者がしても良いと命じた作業だけしか行えないように制限されます。デフォルトの "deny-all" では管理者が考えていない行動をユーザーが行えないことが保証されます。
gradm を使う
gradm はシステムのポリシーを管理・整備するためのツールです。これを使って、RBAC システムを有効化・無効化したり、RBAC ルールをリロード、ロールを変更、管理モードのパスワードの設定などができます。
gradm をインストールするとデフォルトのポリシーが /etc/grsec/policy
にインストールされます。
デフォルトでは、RBAC ポリシーは有効になっていません。システムに RBAC ポリシーをいつ発動させるか決めるのはシステム管理者の仕事です。RBAC システムを有効にする前に管理者パスワードを設定してください。
# gradm -P admin Setting up grsecurity RBAC password Password: (Enter a well-chosen password) Re-enter Password: (Enter the same password for confirmation) Password written in /etc/grsec/pw # gradm -E
RBAC システムを無効化するには、gradm -D
を実行してください。無効化の権限がない場合、まず admin ロールに切り替える必要があります:
# gradm -a admin Password: (Enter your admin role password) # gradm -D
admin ロールから外れたい場合、次を実行してください:
# gradm -u admin
ポリシーを生成する
RBAC システムには"学習モード"という名前の素晴らしい機能があります。学習モードはあなたのシステムにあわせて予測による最低限の権限ポリシーを生成することができます。これによって時間とお金を節約して、迅速に多数のセキュアなサーバーを配置することが可能になります。
学習モードを使うには、gradm を使って有効にしてください:
# gradm -F -L /etc/grsec/learning.log
次にシステムを使用します、通常通りに作業を行なって下さい。locate や rsync などのファイル i/o の負担が重い操作は避けるようにしてください、処理時間が大幅にスローダウンしてしまいます。
適切なポリシーを作るのに十分だと思えるほどシステムを使用したら、gradm に処理させて /etc/grsec/learning.roles
にロールを作成してください:
# gradm -D # gradm -F -L /etc/grsec/learning.log -O /etc/grsec/learning.roles
/etc/grsec/learning.roles
を検査して問題なかったら /etc/grsec/policy
(モード 0600
) として保存して完了です。
# mv /etc/grsec/learning.roles /etc/grsec/policy # chmod 0600 /etc/grsec/policy
これで新規学習したポリシーを使って RBAC システムを有効にすることが可能になりました。
# gradm -E
ポリシーを調整する
grsecurity 2.x の興味深い機能に設定ファイルの Set Operation Support があります。現在、(この場合オブジェクトの) 和集合・積集合・差集合をサポートしています。
define objset1 { /root/blah rw /root/blah2 r /root/blah3 x } define somename2 { /root/test1 rw /root/blah2 rw /root/test3 h }
以下は使用のサンプルで、作られたオブジェクトはサブジェクトに追加されます:
subject /somebinary o $objset1 & $somename2
上の場合、次のように展開されます:
subject /somebinary o /root/blah2 r
This is the result of the & operator which takes both sets and returns the files that exist in both sets and the permission for those files that exist in both sets.
subject /somebinary o $objset1 | $somename2
この例は以下のように展開されます:
subject /somebinary o /root/blah rw /root/blah2 rw /root/blah3 x /root/test1 rw /root/test3 h
This is the result of the | operator which takes both sets and returns the files that exist in either set. If a file exists in both sets, it is returned as well and the mode contains the flags that exist in either set.
subject /somebinary o $objset1 - $somename2
この例は以下のように展開されます:
subject /somebinary o /root/blah rw /root/blah2 h /root/blah3 x
This is the result of the - operator which takes both sets and returns the files that exist in the set on the left but not in the match of the file in set on the right. If a file exists on the left and a match is found on the right (either the filenames are the same, or a parent directory exists in the right set), the file is returned and the mode of the second set is removed from the first set, and that file is returned.
In some obscure pseudo-language you could see this as:
if ( ($objset1 contained /tmp/blah rw) and ($objset2 contained /tmp/blah r) ) then $objset1 - $objset2 would contain /tmp/blah w if ( ($objset1 contained /tmp/blah rw) and ($objset2 contained / rwx) ) then $objset1 - $objset2 would contain /tmp/blah h
As for order of precedence (from highest to lowest): "-, & |".
If you do not want to bother remembering precedence, parenthesis support is also included, so you can do things like:
(($set1 - $set2) | $set3) & $set4
/etc/grsec/policy を直接調整する
Sometimes, full learning mode doesnt work for a particular program and direct revisions to the policy file will need to be made. One might simply want to tweak the policy file to add or remove access to directories without requiring one to reinitiate learning mode or recreating a policy file. The file itself is composed of Roles and Subjects. A Role determines what user the ruleset applies to, while the Subject could be seen as what process/program the ruleset applies to.
Consider a situation where the role is "username", while the subject is /usr/lib/firefox/firefox. Within the curly braces of this role/subject rule, directories will be listed, along with flags that dictate what capacities (read, write, execute, etc) you wish to give that subject (firefox for example) under that role (username, when firefox is ran under the user "username" for example). Here is a list of flags and what they do:
a This object can be opened for appending. c Allow creation of the file/directory. d Allow deletion of the file/directory. f Needed to mark the pipe used for communication with init to transfer the privilege of the persistent role; only valid within a persistent role. Transfer only occurs when the file is opened for writing. h This object is hidden. i This mode only applies to binaries. When the object is executed, it inherits the ACL of the subject in which it was contained. l Lowercase L. Allow a hardlink at this path. Hardlinking requires a minimum of c and l modes, and the target link cannot have any greater permission than the source file. m Allow creation of setuid/setgid files/directories and modification of files/directories to be setuid/setgid. p Reject all ptraces to this object. r This object can be opened for reading. t This object can be ptraced, but cannot modify the running task. This is referred to as a 'read-only ptrace'. w This object can be opened for writing or appending. x This object can be executed (or mmap'd with PROT_EXEC into a task).
So for example, if you want firefox to have read access to the home folder of the user username, be able to do everything (read, write, create and destroy files, execute) in /home/username/Downloads, but not be able to see /home/username/secretstuff or anything in /, your ruleset might look like this:
# Role: username subject /usr/lib/firefox/firefox o { / h /home/username r /home/username/Downloads rwxcd /home/username/secretstuff h }
Of course, a Firefox ruleset will need more than just the above (like access to directories it needs to run in /usr for example); compare the above with what is generated by full-learning-mode and you quickly see the pattern. The idea is that you want to limit each process as much as possible to limit the changes it can make to the filesystem in the event it is compromised. Much more info is available on the GRsecurity RBAC wiki page.
Wine を使う; /etc/grsec/policy に必要な変更
wine を使用する場合、NTFS パーティション上にある wine アプリの実行可能ファイルを、RBAC を有効にしながら動作させるには、サブジェクトを使ってロール (user) の /usr/bin/wine-preloader の Subject モードに "O" を追加する必要があります。これが .wine にある実行可能ファイルに適用されるのかどうかは不明です。システムを完全学習モードにして wine を実行して、セッションから /etc/grsec/policy を生成しても RBAC は wine プログラムが動作するのを止めます:
grsec: (username:U:/usr/bin/wine-preloader) denied load of writable library /mnt/winblows/Program Files (x86)/Diablo II/Game.exe by /usr/bin/wine-preloader[Game.exe:7518] uid...
Subject モードの最後に "O" を追加することでこの問題を修正できます。ルールセットの例 (subject /usr/bin/wine-preloader の後ろにある大文字の O に注目してください):
# Role: username subject /usr/bin/wine-preloader O { / r <other listed files generated by full-learning mode> rwcdx }
"O" は Subject モードに追加できる様々なフラグの内の一つです。他に使えるフラグは:
A Protect the shared memory of this subject. No other processes but processes contained within this subject may access the shared memory of this subject. C Auto-kill all processes belonging to the attacker's IP address upon violation of security policy. K When processes belonging to this subject generate an alert, kill the process. O Allow loading of writable libraries. T Deny execution of binaries or scripts that are writable by any other subject in the policy. This flag is evaluated at policy enable time. All binaries with execute permission that are writable by another subject (ignoring special roles) will be reported and the RBAC system will not allow itself to be enabled until the changes are made.
このリンク を見て下さい。
トラブルシューティング
Out-of-tree カーネルモジュールのコンパイルが失敗する
PaX と grsecurity は GCC のプラグインを使って防御機能を実装しています。プラグインをビルドするのに使用されたコンパイラの設定やバージョンが、カーネルモジュールをビルドするときと同じである必要があります。例えば、gcc-multilib パッケージのコンパイラは使えません。カーネルをビルドするのに使用されたのと同じコンパイラツールチェインが必要だからです。また、GCC のマイナーアップグレードがあったら linux-grsec を再ビルドする必要があります。カーネルの再ビルドは Arch Build System で行うことができます。FS#43057 を見て下さい。