# lidsconf -A -o /some/file -j READONLY
これにより、LIDS が有効になっていれば、(root を含む) 何者かが /some/file
を変更したり削除したりするのを防ぐことができます。LFS にいるなら、適切なファイルパーミッションがあり、パーティションが読みとり専用で mount されているのでなければ、自由に /some/file
を変更することができます。
上と同じですが、指定するのは /some/directory
です。
# lidsconf -A -o /some/directory -j READONLY
オブジェクトがディレクトリの場合、LIDS はディレクトリそのものと、再帰的にその下の同じファイルシステム上にあるものを保護します。(e.g. LIDS の ACL はファイルシステムの境界を越しません!
) これは覚えておくべき非常に重要なことで、それにより、はからずもシステムの一部を保護されないままにしておくことがなくなります。
読みとり専用として保護しておきたいと思うディレクトリは、/etc
でしょう。
# lidsconf -A -o /etc -j READONLY
# lidsconf -A -o /some/file_or_directory -j DENY繰り返しますが、これで、root すらアクセスが出来なくなります。さらに、もしこれがディレクトリであれば、その下にある全てのファイルとディレクトリも隠されます (もちろん、同じファイルシステムにあれば、です)。
# lidsconf -A -o /some/log/file -j APPENDこれにより、同時に誰かがファイルの末尾に書きこんでも、既存の内容を消したり変更したりできないようになります。
システムログを追記専用として保護する簡単な方法はこうです −
# lidsconf -A -o /var/log -j APPEND
これにより、/var/log
以下にある全てのファイルが追記専用として保護されます。READ や DENY と同様に、このターゲットも再帰的です。
ユーザが自分自身をシステムに認証させるには、いくつかのプログラムに /etc/shadow
への読みとり専用のアクセスをさせる必要があります。読みとりアクセスを与えるように考慮するかも知れないプログラムとしては − login, sshd, su, vlock
などがあります。
login プログラムが /etc/shadow
を読めるようにするには、この ACL を使います −
# lidsconf -A -s /bin/login -o /etc/shadow -j READONLYこの場合、"-s" オプションは subject である
/bin/login
を指定しています。subject に対して、オブジェクト (/etc/shadow
への読みとり専用アクセスを与えていることになります。
できません。この問題を修正するには、/etc/mtab
ファイルを削除して、/proc/mounts
へのシンボリックリンクに置きかえる方法があります。これを機能させるためには、起動スクリプトを修正して、全ての mount
と umount
コマンドが "-n" オプションを使うようにする必要があります。これにより、mount
と umount
は /etc/mtab
ファイルを更新しなくなります。
例えば、こういうものを −
mount -av -t nonfs,noproc
起動スクリプトの中に見つけたなら、このように変更します −
mount -av -n -t nonfs,noproc
こういった mount
コマンドは、起動スクリプト全体に散在しているでしょう。それら全てを捕まえるために、grep を使ってください。同じ方法で、全 umount
コマンドの修正もしたいと思うでしょう。
これは、/lib
が読みこみ専用で保護されている時に (そうするのは、よいことです) 発生します。受けとるエラーは、こういう感じになります −
LIDS: depmod (3 12 inode 16119) pid 13203 user (0/0) on tty2: Try to open /lib/modules/2.2.18/modules.dep for writing,flag=578
これは、起動時に /etc/rc.d/rc.sysinit
起動スクリプトがモジュールの依存性を再構築しようとするからです。通常、これは必要ありません。というのも、モジュールを追加したり変更したり削除したりしない限り、モジュールの依存性は変化しないからです。エラーは無害ですが、見るのがいやなら単純に /etc/rc.d/rc.sysinit
スクリプト中でモジュールの依存性を再構築している行 (depmod -a
といったものを探してください) をコメントアウトすることができます。
なされません。ログのローテーションは、LIDS_GLOBAL が無効になっている時に、ログローテーションユーティリティを手動で実行してなされるべきものです。ログのローテーションを生起する cron のジョブは無効にするべきです。(別解については 下記 を参照してください)
しても構いませんが、お勧めしません。誰かがシステムに侵入し、例え彼らがログを変更することができなくても、侵入の間に集められた情報を持ったログが地上から姿を消すまで、(ログローテーションユーティリティを手動で実行して) ローテートを必要なだけ繰り返すことができます。これは、高度なセキュリティのために支払うべき代価の一部なのです。
ログローテーションユーティリティに /var/log
への書きこみアクセスをさせる別解としては、cron デーモンに /var/log への書きこみ許可を与え、それを継承可能とする方法があります。
lidsconf -A -s /usr/sbin/crond -i -o /var/log -j WRITE
これで、誰かが手動でログローテーションユーティリティを実行することはできませんが、cron デーモンによって実行された時は動作するようになります。
警告:
cron デーモンに脆弱性が見つかった場合は、誰かがそこを突くと、cron が /var/log
への書きこみ権をもっているためにログを一掃できてしまいます。これは、そもそも MAC を用いる目的を無為にします。なにしろ、脆弱性が見つかれば、今やアクセス制御は迂回され得るのですから。このオプションは自己責任のもとに使うように!
更新:
新しい
時間制限機能のため、crond が /var/log
に書きこみ権限をもっているなら、それを特定の時間帯に制限するのをお勧めします。例えば、logrotated が crond によって毎日 6:00 AM に実行されるなら、crond の書きこみ権限を 1 分間に制限します −
/sbin/lidsconf -A -s /usr/sbin/crond -i 2 -o /var/log -t 0600-0601 -j WRITE1 分が十分な長さでないなら、logrotated が無事実行を終えるまで、時間を 1 分づつ増やしてください。
これは、CAP_SYS_ADMIN 権限を全体で無効にしていて、かつファイルシステムをアンマウントするための適切な権限を shutdown スクリプトに与えていない場合におこります。例えば、Red Hat6.2 では、/etc/rc.d/init.d/halt
スクリプトがファイルシステムのアンマウントを行います。それに CAP_SYS_ADMIN 権限を与える必要があります。そうして、ファイルシステムのアンマウントが可能になるのです −
# lidsconf -A -s /etc/rc.d/init.d/halt -o CAP_SYS_ADMIN -i 1 -j GRANT
ターゲット "GRANT" は LIDS に subject (この場合、/etc/rc.d/init.d/halt
) に CAP_SYS_ADMIN 権限を許可するように伝えます。 "-i 1" オプションは、ACL の "継承レベル" を 1 にセットします。
これにより、/etc/rc.d/init.d/halt
スクリプトを実行できる誰かにも、ファイルシステムのアンマウントが可能になることに注意してください。もしマシンに物理的にアクセスできるなら、シャットダウンスクリプトに権限を与えるよりも、シャットダウンの前に LIDS_GLOBAL を無効にするだけの方がいいかもしれません。とはいえ、停電時にシステムをシャットダウンさせることができる UPS を持っているなら、LIDS_GLOBAL を無効にするわけにはいかないでしょう。
特権ポート (1024 以下のもの) で走るサービスは、ポートにバインドするために CAP_NET_BIND_SERVICE 権限を必要とします。/etc/lids/lids.cap
ファイルでこの権限を全体的に無効にしているなら、プログラム毎にその権限を許可せねばなりません。
# lidsconf -A -s /usr/local/bin/apache -o CAP_NET_BIND_SERVICE -j GRANTあるいは、LIDS_GLOBAL が無効なときにサービスを開始してください。
LFS は、単一の端末セッションに適用されます。デーモンは、制御端末から自分を切り離すために、自分自身を fork します。こうなると、それはもはや端末の LFS には接続されておらず、ゆえに LIDS に保護されることになるのです。
/etc/lids/lids.cap
ファイルが LIDS で強化された Linux カーネルで利用できる全権限のリストを保持しています。頭に "+" のあるものが、有効になっているもので、"-" が頭についているものは、無効なものです。権限の状態を変更するには、単にテキストファイルを編集して "+" を "-" に変えれば権限は無効になりますし、逆だと有効になります。ファイルの編集が終わったら、LIDS に設定ファイルを
リロードさせる必要があります。
使用している X サーバには CAP_SYS_RAWIO 権限が必要です。
# lidsconf -A -s /path/to/your/X_server -o CAP_SYS_RAWIO -j GRANTを試してください。
あなたが望む全ての ACL をシステムに追加するシェルスクリプトを作成するのをお勧めします。こうすれば、システムを変更した時に、はからずも何かを保護されないままにしておくことはありません。スクリプトは、古い ACL を消すことから始めれば、2 重に設定することもありません。
# lidsconf -Z
このシェルスクリプトを保護するには、それへのアクセスを DENY する ACL を作ったり、/etc/lids
ディレクトリへ配置して自動的に DENY で保護されるようにもできます。
LIDS は自動的に /etc/lids
ディレクトリを DENY で保護します。
更新:LIDS 1.1.0 以降では、デフォルトで /etc/lids
を DENY して保護することはなくなりました。必要なら、自分自身でこの ACL を作成しなければなりません。
不幸にも、これについて出来ることはそう多くありません。init
は起動の度にこのファイルを再作成するので、毎回 iノード番号が変化するのです。これにより、そのファイルは LIDS には扱いにくくなります。このエラーは無害ですし、/etc/initrunlvl
がなくてもシステムは適切に機能します。
できます。バージョン 0.9.12 から 2.2.18 までは、これがデフォルトの動作でした。現在は、デフォルトでは、子はその親からファイル ACL を継承しません。親プロセスから子プロセスへファイル ACL が移行できるようにするには、"-i <継承レベル>" オプションを使う必要があります。
"継承レベル" (別名 TTL) とは、ACL が継承される世代数を決定します。TTL に 1 が指定されれば、ACL で指定された subject とその子全ては ACL を継承します。しかし、子の子 (別の言い方をすれば ACL の subject の孫) は ACL を継承しません (こうなるようにするには、TTL を 2 にする必要があります)。
注意:権限を許可する ACL にも、これらと同じ継承のルールが適用されます。
セキュリティ上の更新: LIDS 1.1.1prex 及び 0.10.1 以降では、保護されたプログラムのみがその親から ACL を継承することができます。保護されていないプロセスに ACL の継承を許すと、exploit の原因となります。
最初にするべきことは、単純にプログラムを実行して、LIDS がどんな違反を通告してくるかを見ることです。とはいえ、何度これをやっても、十分な情報は得られません。これが起きた時は、strace を使ってプログラムを追いかけて、どのシステムコールが失敗しているのか見ることができます。こうすると、たいていの場合はどの権限が違反しているのか、よい示唆を得ることができます。
注意:全体で CAP_SYS_PTRACE を無効にしているなら、LIDS が有効な状態でプログラムの追跡ができるように、一時的に strace に CAP_SET_PTRACE 権限を与える必要があります。
残念ながら、簡単な解は存在しません。これは、passwd
ユーティリティがパスワードを変更するたびに /etc/shadow
ファイルを再作成するからです。これにより、passwd
ユーティリティを成功裏に使う度に、違う i ノードからファイルが始まるのです。
システム管理者には、簡単な解決法があります。LFS を開始して、LFS の中から passwd
ユーティリティを使うのです。パスワードを変更する必要のあるユーザがいる場合、LDAP を使えば、ユーザが自分のパスワードを変更できるクライアント認証手段を提供してくれます。
標準的 unix システムファイルを使って、UNIX 認証をする時に、ユーザが自分のシステムパスワードを変更できるようにする選択肢があります。ですが、お勧めはできません。/usr/bin/passwd
に /etc への書きこみアクセスを与えれば、いつでも shadow ファイルをその i ノード番号に関わらず修正できるようになります。
警告:
誰かが /usr/bin/password
や、それが使うライブラリ/PAM モジュールの何れかに脆弱性を発見すれば、その人は潜在的に /etc
ディレクトリへの書きこみアクセスを得ることができます。
脆弱性が見つかれば、あなたのアクセス制御を出し抜くことができるわけで、これはそもそも MAC を用いる目的を無駄にするものです。このオプションは自己の裁量で使うようにしてください。
/usr/bin/passwd
に /etc
への書きこみアクセスを与えることにしたのなら、/etc
の下にあって、/usr/bin/passwd
が修正できるようにしたくないファイルとディレクトリ全てを保護する ACL を作成することをお勧めします。
これにより、上記のリスクが著しく減少します (しかも正確に行えば、完全に取り除くこともできます)。
/sbin/lidsconf -A -s /usr/bin/passwd -o /etc -j WRITE /sbin/lidsconf -A -s /usr/bin/passwd -o /etc/hosts.allow -j READONLY /sbin/lidsconf -A -s /usr/bin/passwd -o /etc/hosts.deny -j READONLY /sbin/lidsconf -A -s /usr/bin/passwd -o /etc/rc0.d -j READONLY /sbin/lidsconf -A -s /usr/bin/passwd -o /etc/rc1.d -j READONLY /sbin/lidsconf -A -s /usr/bin/passwd -o /etc/rc2.d -j READONLY /sbin/lidsconf -A -s /usr/bin/passwd -o /etc/rc3.d -j READONLY /sbin/lidsconf -A -s /usr/bin/passwd -o /etc/rc4.d -j READONLY /sbin/lidsconf -A -s /usr/bin/passwd -o /etc/rc5.d -j READONLY /sbin/lidsconf -A -s /usr/bin/passwd -o /etc/rc6.d -j READONLY /sbin/lidsconf -A -s /usr/bin/passwd -o /etc/init.d -j READONLY /sbin/lidsconf -A -s /usr/bin/passwd -o /etc/cron.d -j READONLY /sbin/lidsconf -A -s /usr/bin/passwd -o /etc/pam.d -j READONLY ..
上は、どんなに想像力を逞しくしたところで完全なリストではありませんが、きっかけにはなります。/etc
に passwd
にアクセスさせたくないファイルやディレクトリを追加したときはいつでも、それを保護する新しい ACL を作らねばならないことも、頭に入れておいてください。
i ノードの更新に関するメモ:
/etc/shadow
や /etc/passwd
へのアクセスを許可する ACL を定義したなら、LIDS に
i ノードを更新したことを知らせ、それから設定ファイルを
リロードするのを忘れないようにしなければなりません。さもないと、問題が生じることになります。
例えば:/etc/passwd
が DENY で保護されており、/bin/login
は /etc/passwd
を読めるものとします。パスワードを変更した後、i ノードが更新されなければ、誰かが次回ログインしようとした時に問題が発生します。/bin/login
は /etc/passwd
を読みこむことができず、ログインが不可能になります。あるいはさらに酷く、単に <ENTER> キーを押すだけでログインできるようになってしまうのです。
デフォルトでは、ssh/scp は外向きのコネクションを作成する時に、ソースポートとして特権ポートを使おうとします。これには、CAP_NET_BIND_SERVICE 権限が必要です。ですが、ソースポートとして 1023 以上のポートを使うように強いるため、ssh_config
中でこのオプションを指定することができます −
UsePrivilegedPort No
あるいは、ssh (scp は ssh を使うので、これも動作します) に CAP_NET_BIND_SERVICE を許可することもできます −
lidsconf -A -s /usr/bin/ssh -o CAP_NET_BIND_SERVICE -j GRANT
bash
が隠しファイルにアクセスしようとしている、とレポートを出しています。これはどうすれば直りますか?
これは、デフォルトポリシーを DENY として 秘密鍵を保護している時に発生します。openssh-server の RPM で提供される init スクリプトは /etc/ssh
下に秘密鍵ファイルがあるかチェックします。スクリプトは発見できなかった場合、それを生成するために ssh-keygen を実行します。Beckeygenthe 鍵は実際にはそこにあるので、ssh-keygen は失敗して、起動スクリプトは終了します。
これを修正するには、起動スクリプトから鍵ファイルのチェックを削除します −
start) # Create keys if necessary #do_rsa_keygen; <------------ Comment out these lines #do_dsa_keygen; echo -n "Starting sshd: " if [ ! -f $PID_FILE ] ; then sshd RETVAL=$? if [ "$RETVAL" = "0" ] ; then success "sshd startup" touch /var/lock/subsys/sshd else failure "sshd startup" fi fi echo ;;
注意: これが意味するのは、sshd が起動するより前に、手動で秘密鍵を作る必要がある、ということです。さもなければ、起動は失敗します。
隠しプロセスでも、そのプロセス id (pid) がわかれば kill できます。多くのシステムでは、起動時に開始された全プロセスの pid を、/var
(普通 /var/run
が使われます) の下のどこかに保存します。シャットダウンスクリプトを修正して、これらのファイルから pid を読み、適切なシグナルを送るようにできます。
例えば、システムが pid を /var/run/<プロセス名>.pid
に保存しているなら、以下の行をシャットダウンスクリプトに追加することができます −
for p in `ls /var/run/*.pid` do kill -15 `cat $p` done sleep 5 sync;sync;sync for p in `ls /var/run/*.pid` do kill -9 `cat $p` done sleep 5 sync;sync;syncこれらの行を含むシャットダウンスクリプトに、CAP_KILL と CAP_INIT_KILL 権限を許可しなければなりません。
/var/run
ディレクトリを init スクリプト群以外の全てから隠すのも、おそらくよい考えです。
別解としては、全てのプロセスに、TERM と KILL のシグナルを単に送るというのもあります。
MAX_PROC=65535 trap : 1 2 15 I=1;while (( $I < $MAX_PROC ));do I=$(($I+1)); if (( $$ != $I ));then kill -15 $I; fi; done sleep 5 sync;sync;sync; I=1; while (( $I < $MAX_PROC ));do I=$(($I+1)); if (( $$ != $I ));then kill -9 $I; fi; done sync;sync;sync
Nenad Micic はシャットダウン時に隠れプロセスを kill する独自の C プログラム を書きました。
これらのカーネルオプションを選択するようにしてください −
... [*] Security alert when execing unprotected programs before sealing [*] Do not execute unprotected programs before sealing lids ... [*] Allow switching LIDS protections ... [*] Allow reloading config. file
出発点としてよいのは、init スクリプトやシステムバイナリ、ライブラリを保護するものでしょう (ディストロによってこれらは変化することに注意) −
/sbin/lidsconf -A -o /etc/rc0.d -j READONLY /sbin/lidsconf -A -o /etc/rc1.d -j READONLY /sbin/lidsconf -A -o /etc/rc2.d -j READONLY /sbin/lidsconf -A -o /etc/rc3.d -j READONLY /sbin/lidsconf -A -o /etc/rc4.d -j READONLY /sbin/lidsconf -A -o /etc/rc5.d -j READONLY /sbin/lidsconf -A -o /etc/rc6.d -j READONLY /sbin/lidsconf -A -o /etc/init.d -j READONLY /sbin/lidsconf -A -o /etc/rc -j READONLY /sbin/lidsconf -A -o /etc/rc.local -j READONLY /sbin/lidsconf -A -o /etc/rc.sysconfig -j READONLY /sbin/lidsconf -A -o /bin -j READONLY /sbin/lidsconf -A -o /sbin -j READONLY /sbin/lidsconf -A -o /lib -j READONLY /sbin/lidsconf -A -o /usr/bin -j READONLY /sbin/lidsconf -A -o /usr/sbin -j READONLY /sbin/lidsconf -A -o /usr/lib -j READONLY
/usr/local
が別のパーティションにあるなら、以下の ACL も加えてください −
/sbin/lidsconf -A -o /usr/local/bin -j READONLY /sbin/lidsconf -A -o /usr/local/sbin -j READONLY /sbin/lidsconf -A -o /usr/local/lib -j READONLY
/etc/lids/lids.cap
ファイルで、CAP_SYS_RAWIO と CAP_SYS_PTRACE も無効にするべきです。CAP_SYS_RAWIO を無効にしなければ、デバイスに直接書きこむことで、誰でも上記のファイル保護を無視できてしまいます。
X Window System を実行しているなら、LIDS の下で X を動作させることについて、 上記 も参照するようにしてください。
できます。LIDS バージョン 0.10.1 for 2.2.19 とバージョン 1.0.10 for 2.4.5 での新しい機能で、ACL の記載を時間制限できるようにします。例えば、ログインを 9:00 AM から 6:00 PM (18:00) までの時間のみ許すには −
/sbin/lidsconf -A -s /bin/login -o /etc/shadow -t 0900-1800 -j READ
これで、/bin/login
は /etc/shadow
ファイルを指定された時間帯にのみ読むことができるので、その時間帯以外のあらゆるログインの試みは失敗します。否定のために "!" 演算子を使うこともできます (例えば、ACL がリストされた時間帯以外の全アクセスを許容する、など)。
crond に時間制限された権限を与えるなら、(root を含む)全員から crontab を隠し、crond のみがそれらを読めるようにすることを特にお勧めします。さもなければ、その crontab を見て、どの時間に何かを試して食いものにすればいいか、誰かが検討をつけてしまうかも知れません。ユーザのものだけでなく、システムの crontab を守ることも忘れないでください。
例えば、これらは隠すべきです −
/var/spool/cron/ /etc/crontab /etc/cron.hourly/ /etc/cron.daily/ /etc/cron.weekly/ /etc/cron.monthly/ /etc/cron.d/
警告:
この新しい機能はシステムの時刻に依存しているので、システムの時刻を変更し得るどんなプログラム (例えば /sbin/hwclock
) にも、CAP_SYS_RAWIO を与えるべきではありません。
これによって、誰かがシステムの時刻を変更して、時間制限をすり抜けてしまうかもしれません。
バージョン 0.10.1 for 2.2.19 とバージョン 1.0.11 for 2.4.6 からは、プログラムがバインドできる特権ポートを制限できます。プログラムに CAP_NET_BIND_SERVICE 権限を与える場合には、プログラムがバインドできるポート (群) をその後に指定します。次のようにします −
/sbin/lidsconf -A -s /bin/httpd -o CAP_NET_BIND_SERVICE 80-80 -j GRANT
または、SSL 用に 443 ポートもバインドする必要があるなら −
/sbin/lidsconf -A -s /bin/httpd -o CAP_NET_BIND_SERVICE 80-80,443-443 -j GRANT
プログラムがポートの範囲を必要とするなら、このようにしてみて下さい −
/sbin/lidsconf -A -s /path/to/program -o CAP_NET_BIND_SERVICE 423-867 -j GRANT
はい、"-a" オプションで quotaon を開始すればよいのです。
多くのエディタ (例えば vi) は、編集中のファイルをテンポラリファイルにコピーします。変更は全てそのテンポラリファイルに対してなされるのです。エディタを終了すると、テンポラリファイルがオリジナルのファイルを上書きします。これによってオリジナルファイルの i ノードが変わり、そのファイルに関係していた以前の LIDS ACL はもう機能しなくなるのです。こう入力して −
/sbin/lidsconf -Ulids.conf 内のファイルの i ノードを更新してください。