Info: Version 1.8.x is available.

English Page

Last modified: $Date: 2015-08-31 22:19:51 +0900 (Mon, 31 Aug 2015) $

TOMOYO Linux の世界
第6回:「不正ログインを撲滅しよう」

今回の内容

セキュアOSを使えばサービスに不要な資源へのアクセスを禁止することができます.これにより,バッファオーバーフローなどによって制御を奪われた場合の被害を限定することが可能となります.

では,正規の手続き(ユーザ認証)を経てログインした場合はどうでしょうか.当然ながら本来の(正規の)管理者は意図したとおりにシステムを操作できなければいけません.ということは,ログイン認証を突破されてしまうとセキュアOSであったとしても壊滅的な被害は免れないということです.正規の管理者の操作を可能としながら,ログイン認証を強化することが課題となります.

TOMOYO Linux ではドメイン遷移を応用することにより,正規の手続きを経てログインされた場合でも被害を限定することができます.今回は,無料で構築できる不正ログイン撃退システムと,管理者権限を分割する手法について紹介します.

不正ログイン撃退システムについて

踏み台にされるのを防ぎたい!

パスワードブルートフォース攻撃によるSSHサービスへの不正侵入が増加しています.侵入された結果,フィッシングサイトとして悪用されたり,他のホストへ侵入するための攻撃プログラムを設置されたりするといった被害が発生しています.

管理者権限がなくとも攻撃プログラムの設置と実行は可能です.「公開情報しか置いていないサーバだからログインされたって平気だよ」とか「管理者権限でのログインさえ防げれば大丈夫だよ」などと言ってはいられません.インターネットにつながっているサーバは,自分が被害者になるのと同時に加害者にもなってしまうと考えて,予防策を講じることが大切です.

機密情報を保護したい!

すべての Linux/UNIX のシステムはログイン認証に対応しています. PAM ( Pluggable Authentication Modules )や公開鍵認証のような認証を強化する手段は存在していますが,ログイン認証自体の考え方は基本的に同一です.考えてみると個人利用のサーバでもエンタープライズ用途のサーバでも同一の認証で良いのか疑問になってきます.

ログイン認証についても,用途ごとにその用途に適したレベルで設定したいと思いませんか?できれば追加の費用をかけたりしないで….そのネガイ, TOMOYO Linux が叶えましょう.

ログイン認証は複数回できるか?

従来の不正ログイン対策は,「ログイン認証は1回限り.突破されたらおしまい」というのが常識でした.そのため,1回しかないチャンスで少しでも安全な認証を実現するために,公開鍵認証やバイオメトリクス認証の導入が始まっています.これは,セキュアOSを使っていても変わりません.

ところが, TOMOYO Linux の場合は事情が違います. TOMOYO Linux であれば,「ログイン認証は何回でも強制可能.だから突破される心配は無用」を実現することが可能です.そのため, TOMOYO Linux では従来どおりの認証方式でログインしてもらうことができます.

どうして複数回できるの?

TOMOYO Linux ではログイン認証専用の機構を備えているわけではありませんが,これまで連載で説明してきたドメインに基づく強制アクセス制御の応用によりログイン認証の強化が可能です.

TOMOYO Linux では,ログイン後に行える操作を「追加のユーザ認証を行うためのプログラムを実行すること」だけに限定することがとても簡単に実現できます.しかも追加のユーザ認証プログラムで利用する認証方式に制限はありませんし,国際的に標準化された規格に従う必要もありません.

要件はただ1つ,何かの条件を満たしたら次のプログラム(通常はシェル)を起動するということだけです.強制アクセス制御により,ポリシーで許可されていない資源へのアクセスは禁止されているので,迂回されることはありません.

たとえば,図1のようなスクリプトでも利用可能です.「スクリプト自体にパスワードを埋め込んでいたら誰でも読めてしまって意味がない」と思われるかもしれませんが,強制アクセス制御によりスクリプトの内容を読めないようにすることができます(心配ならパスワードだけ外部のファイルに分離したり,C言語で記述しても結構です).

図1のスクリプトを例に解説します.この内容を /bin/auth1 という名前で保存して,「 chmod 755 /bin/auth1 」により実行可能な状態にしておいてください.なお,これはあくまで例であり,実際のシステムに導入する場合は,自分の好きな方法で認証方式を作成してください.侵入者が思いもよらないような認証方式であればあるほど,破ることが困難な防御を実現できます.

■図1 追加認証用のサンプルスクリプト
#! /bin/sh -p
for i in 1 2 3
do
  echo -n 'Password: '
  read -r -s passwd
  echo
  [ "$passwd" = "SAKURA" ] && exec $SHELL
done
echo 'Incorrect password.'

構築してみよう

例として,SSH経由でログインするシステムを保護する場合で説明します.ログインシェルとして /bin/bash が指定されているものと仮定します.

●準備

「 <kernel> /usr/sbin/sshd /bin/bash 」( /usr/sbin/sshd からログインした場合のログインシェルのドメイン)に対してアクセス制御を有効にし,ポリシーで許可されたプログラムしか実行できない状態にします(「 <kernel> /usr/sbin/sshd 」( /usr/sbin/sshd のドメイン)にもアクセス制御を適用しないと, /usr/sbin/sshd から /bin/tcsh などを実行することで回避されてしまうので注意してください.).

まず,「 <kernel> /usr/sbin/sshd /bin/bash 」ドメインが keep_domain に指定されていないことを確認してください( keep_domain については連載第3回で紹介しました).もし, keep_domain <kernel> /usr/sbin/sshd /bin/bash という指定がされていた場合はポリシーエディタを使用して削除してください.

また,「 <kernel> /usr/sbin/sshd /bin/bash /bin/auth1 /bin/bash 」ドメイン(追加の認証を通過後のドメイン)から先にアクセス制御を適用しない場合には,ドメインを遷移させる必要がないのでポリシーエディタを使用して keep_domain <kernel> /usr/sbin/sshd /bin/bash /bin/auth1 /bin/bash という指定を追加してください(図2).

■図2 認証を強化するためのドメインの状態
fig-6-2.png

●学習

この連載の2回目で図3のプロファイルを定義しましたので,今回も同じプロファイルを使用します. /usr/sbin/sshd からログインしたドメインを学習モードにします.コンソールから図4のコマンドを実行してください.

■図3 今回使用するプロファイル
PROFILE_VERSION=20090903
PREFERENCE::learning={ verbose=no }
PREFERENCE::permissive={ verbose=yes }
PREFERENCE::enforcing={ verbose=yes }
0-CONFIG::file={ mode=disabled }
1-CONFIG::file={ mode=learning }
2-CONFIG::file={ mode=permissive }
3-CONFIG::file={ mode=enforcing }
■図4 「 <kernel> /usr/sbin/sshd /bin/bash 」ドメインを学習モードにする
# /usr/sbin/ccs-setprofile -r 1 '<kernel> /usr/sbin/sshd /bin/bash'

/usr/sbin/sshd からログインして, /bin/auth1 を実行します.パスワードを尋ねられるので SAKURA と入力して Enter を押します.認証が成功し, $SHELL に指定されている /bin/bash が起動されます(図5).

■図5 /bin/auth1 の認証に成功し, /bin/bash が起動するまでを学習させる
# /bin/auth1
Password: SAKURA
#

以上で追加の認証を行うのに必要なアクセス許可が学習されました. exit コマンドを2回実行して /usr/sbin/sshd からログアウトしてください.

●確認と強制

「 <kernel> /usr/sbin/sshd /bin/bash 」ドメイン以下を確認モードに,「 <kernel> /usr/sbin/sshd /bin/bash /bin/auth1 /bin/bash 」ドメイン以下を無効モードにします.コンソールから図6のコマンドを実行してください.

■図6 「 <kernel> /usr/sbin/sshd /bin/bash 」ドメイン以下を確認モードに,「 <kernel> /usr/sbin/sshd /bin/bash /bin/auth1 /bin/bash 」ドメイン以下を無効モードにする
# /usr/sbin/ccs-setprofile -r 2 '<kernel> /usr/sbin/sshd /bin/bash'
# /usr/sbin/ccs-setprofile -r 0 '<kernel> /usr/sbin/sshd /bin/bash /bin/auth1 /bin/bash'

この状態で /usr/sbin/sshd からログインして, /bin/auth1 を実行します.エラーメッセージが表示されないことを確認してください.確認したら,「 <kernel> /usr/sbin/sshd /bin/bash 」ドメイン以下を強制モードに,「 <kernel> /usr/sbin/sshd /bin/bash /bin/auth1 /bin/bash 」ドメイン以下を無効モードにします.コンソールから図7のコマンドを実行してください.

■図7 「 <kernel> /usr/sbin/sshd /bin/bash 」ドメイン以下を強制モードに,「 <kernel> /usr/sbin/sshd /bin/bash /bin/auth1 /bin/bash 」ドメイン以下を無効モードにする
# /usr/sbin/ccs-setprofile -r 3 '<kernel> /usr/sbin/sshd /bin/bash'
# /usr/sbin/ccs-setprofile -r 0 '<kernel> /usr/sbin/sshd /bin/bash /bin/auth1 /bin/bash'

これで完成です.簡単だと思いませんか?

●試してみよう

ブルートフォース攻撃によりパスワードを割り出された,あるいはバッファオーバーフローなどにより認証を経ずにログインに成功されてしまったという想定で効果を確認してみましょう(図8).

■図8 auth1 以外のコマンドは拒否される
Last login: Tue Feb 27 17:12:10 2007
# whoami
-bash: /usr/bin/whoami: Operation not permitted
# /bin/auth1
Password: password
Password: root
Password: guest
Incorrect password.
# exec 4</bin/auth1; while read -u 4; do echo $REPLY; done
-bash: /bin/auth1: Operation not permitted
-bash: read: 4: invalid file descriptor: Bad file descriptor
# exit

せっかく /usr/sbin/sshd からログインしましたが,侵入者には何が許可されているかはわかりません(ポリシーを参照するためのポリシーが定義されていないからです).思いつくままにさまざまなコマンドを実行しても,もちろん auth1 以外のコマンドは拒否されます.もし侵入者がセキュアOSのことを知らなかったらさぞや驚くことでしょう.

侵入者は結局ログアウトするしかありません.仮に侵入者が /bin/auth1 というプログラムを実行できるということに気が付いたとしても,そのスクリプトの処理内容を読めませんからその処理の内容を知ることはできません(ただし,シェルスクリプトの場合,環境変数 SHELLOPTS に verbose:noexec が定義されていると /bin/auth1 を実行することでプログラムの内容が丸見えになってしまいますので,実際のシステムに適用する場合には環境変数の影響を受けない言語で作成することを推奨します.).やはりログアウトするしかありません.

正規の利用者であれば,何が許可されているかを知っているはずなので,すぐに /bin/auth1 を実行し,正しいパスワードを入力して先に進むことができます(図9).

■図9 /bin/auth1 を実行して正しいパスワードを入力する
Last login: Tue Feb 27 17:14:10 2007
# /bin/auth1
Password: SAKURA
# whoami
root
# exec 4</bin/auth1; while read -u 4; do echo $REPLY; done
#! /bin/sh
for i in 1 2 3
do
  echo -n 'Password: '
  read -r -s passwd
  echo
  [ "$passwd" = "SAKURA" ] && exec $SHELL
done
echo 'Incorrect password.'
#

/bin/auth1 だけでは心配だという人は, /bin/auth2 や /bin/auth3 も作成して直列に並べて,「 <kernel> /usr/sbin/sshd /bin/bash /bin/auth1 /bin/bash /bin/auth2 /bin/bash /bin/auth3 /bin/bash 」ドメインまで到達できたらアクセス制御が適用されなくなるというようにすることもできます. TOMOYO Linux のポリシーはこのような階層的な処理の記述に適していることに注目ください.

本方法が適用できない場合

上で紹介した追加認証による防御は,SSHやTelnetやコンソールログインのようにプロセスとユーザの対応付けを維持でき,任意のコマンドを実行できるシェルが提供されている場合にのみ利用可能です.毎回TCPコネクションを切断してしまうHTTPによるログインや,シェルが提供されないFTPによるログインなどには適用できません.

scp や sftp などのようにログインシェルから直接起動されるプログラムに対してこの手法を使うには, TOMOYO Linux が提供する execute_handler 機能を利用します.( execute_handler 機能については後述します.)さらに,セキュアOSの持つ強制アクセス制御によりアクセス可能な資源を限定することもできます.たとえばホームディレクトリ直下の scp というディレクトリ以下だけアクセスできるようにすることができます. scp や sftp はログインシェルから直接起動されるため,それらの動作するドメインは「 <kernel> /usr/sbin/sshd /bin/bash /usr/bin/scp 」や「 <kernel> /usr/sbin/sshd /bin/bash /usr/libexec/openssh/sftp-server 」のようになりますので,ポリシーのイメージとしては図10のようになります(ライブラリファイルなどは省略しています).

■図10 scp 用のポリシー
<kernel> /usr/sbin/sshd /bin/bash /usr/bin/scp
use_profile 3
allow_create /home/\*/scp/\* 0-0666
allow_create /home/\*/scp/\{\*\}/\* 0-0666
allow_unlink /home/\*/scp/\*
allow_unlink /home/\*/scp/\{\*\}/\*
allow_read/write /home/\*/scp/\*
allow_read/write /home/\*/scp/\{\*\}/\*

パス名をグループ化するための path_group という構文を用いて例外ポリシーで図11のように定義しておくことによりドメインポリシーを図12のようにシンプルに見通し良く記述できます.

■図11 scp 用のファイルをグループ化する
path_group SCP_FILE /home/\*/scp/\*
path_group SCP_FILE /home/\*/scp/\{\*\}/\*
■図12 図11を利用したポリシー
<kernel> /usr/sbin/sshd /bin/bash /usr/bin/scp
use_profile 3
allow_create @SCP_FILE 0-0666
allow_unlink @SCP_FILE
allow_read/write @SCP_FILE

必要に応じて、 if path1.uid=task.uid などの条件を付与することができます.

SSHは通信内容を暗号化しますが,ファイル自体を暗号化してくれるわけではありません.より安全を求める場合は, scp や sftp で送受信するファイルをあらかじめ gpg などで暗号化しておけば, scp や sftp がアクセス可能なディレクトリに置かれているファイルを保護することができます.

管理者権限を分割する方法について

従来の権限分割手法

従来の権限分割手法は, sudo コマンドで実行できるコマンドを制限するなどといったアプリケーションレベルでの手法でした.しかし,アプリケーションレベルでの手法には,コマンドインジェクションが可能な脆弱性がしばしば発見されるなど,抜け道が心配という問題があります.

セキュアOSによる権限分割手法

セキュアOSの多くは, RBAC ( Role Based Access Control :役割ベースのアクセス制御)機能を備えています.この機能を使うと,ロール(役割)に基づいて実行可能なコマンドや読み書きできるファイルを制限することができ,実際の運用で重宝する機能です.

TOMOYO Linux による権限分割手法

TOMOYO Linux は RBAC のための機能を備えていませんが,ドメイン遷移を使えば RBAC と同様の制御を行うことができます.

SELinux では,複数のドメインをまとめてグループ化したものをロールとして定義し,それをユーザに割り当てます.ユーザが属しているロールに含まれていないドメインへ遷移する必要が生じた場合には,ユーザは目的のドメインが含まれているロールに切り替えるという操作を行います.

TOMOYO Linux にはロールという概念はありませんが,実はドメインこそが各時点におけるロールに相当します(しかも,ロールの存在を意識する必要はありません).ドメインを割り当てるのと同時にロールを割り当てていることにもなります.

構築してみよう

例として,Webサーバの管理(Webサーバの再起動やWebコンテンツの更新)だけを別の人に委託したい場合で説明します.ログインシェルとして /bin/bash が指定されているものと仮定します.

実際に構築するのに必要な手法はすでに説明済みです.不正ログイン対策では認証を直列に配置したのに対し,管理者権限の分割では認証を並列に配置すれば実現できます(図13,図14).

■図13 管理者権限の分割前のドメインの状態
fig-6-13-ja.png
■図14 管理者権限の分割後のドメインの状態
fig-6-14-ja.png

ただし,認証を通過後のドメインにもアクセス制御を行うプロファイル(この連載ではプロファイル3)を割り当てなければいけない点に注意してください.アクセス制御が行われないプロファイルが割り当てられたドメインに一度でも到達することができれば,そこから先の行動を制限できなくなるので,管理者権限の分割になりません.

●準備

まず,「 <kernel> /usr/sbin/sshd /bin/bash 」ドメインが keep_domain に指定されていないことを確認してください.また,「 <kernel> /usr/sbin/sshd /bin/bash /bin/auth1 /bin/bash 」ドメイン( /bin/auth1 を通過後のドメイン)と「 <kernel> /usr/sbin/sshd /bin/bash /bin/auth2 /bin/bash 」ドメイン( /bin/auth2 を通過後のドメイン)をそれぞれ keep_domain に指定してください.

全権を持つ自分を認証するためのプログラムとして /bin/auth1 を,Webサーバの管理権限だけを持つ別の人を認証するためのプログラムとして /bin/auth2 を使うものとします.

●学習

学習方法は不正ログイン対策の場合と同様です.

コンソールから図15のコマンドを実行してください.

■図15 「 <kernel> /usr/sbin/sshd /bin/bash 」ドメインを学習モードする
# /usr/sbin/ccs-setprofile -r 1 '<kernel> /usr/sbin/sshd /bin/bash'

この状態で /usr/sbin/sshd からログインして, /bin/auth1 と /bin/auth2 を実行します.認証に成功すると,それぞれ「 <kernel> /usr/sbin/sshd /bin/bash /bin/auth1 /bin/bash 」ドメインと「 <kernel> /usr/sbin/sshd /bin/bash /bin/auth2 /bin/bash 」ドメインが作成され,必要なアクセス許可が学習されます.

確認したら,「 <kernel> /usr/sbin/sshd /bin/bash 」ドメイン以下を強制モードに,「 <kernel> /usr/sbin/sshd /bin/bash /bin/auth1 /bin/bash 」ドメイン以下を無効モードに,「 <kernel> /usr/sbin/sshd /bin/bash /bin/auth2 /bin/bash 」ドメイン以下を学習モードにします.コンソールから図16のコマンドを実行してください.

■図16 「 <kernel> /usr/sbin/sshd /bin/bash 」ドメイン以下を強制モードに,「 <kernel> /usr/sbin/sshd /bin/bash /bin/auth1 /bin/bash 」ドメイン以下を無効モードに,「 <kernel> /usr/sbin/sshd /bin/bash /bin/auth2 /bin/bash 」ドメイン以下を学習モードにする
# /usr/sbin/ccs-setprofile -r 3 '<kernel> /usr/sbin/sshd /bin/bash'
# /usr/sbin/ccs-setprofile -r 0 '<kernel> /usr/sbin/sshd /bin/bash /bin/auth1 /bin/bash'
# /usr/sbin/ccs-setprofile -r 1 '<kernel> /usr/sbin/sshd /bin/bash /bin/auth2 /bin/bash'

この状態で /usr/sbin/sshd からログインして, /bin/auth2 を実行します.認証に成功すると「 <kernel> /usr/sbin/sshd /bin/bash /bin/auth2 /bin/bash 」ドメインに遷移します.このドメインは keep_domain に指定されているので,これ以上遷移することはありません.

ここで,Webサーバを再起動させるのに必要なアクセス許可を学習させてみましょう(図17).

■図17 Webサーバの再起動に必要なアクセス許可を学習させる
# service httpd start
# service httpd stop
# service httpd restart

scp や sftp でアップロードしたコンテンツを /var/www/html/ ディレクトリ以下に展開するかもしれません.その操作に必要なアクセス許可も学習させてみましょう(図18).

■図18 アップロードしたコンテンツを展開する操作のアクセス許可を学習させる
# cd /var/www/html/
# tar -zxf /home/demo/scp/web-contents.tar.gz

Webコンテンツの更新のためにエディタを必要とするかもしれません.エディタに必要なアクセス許可も学習させてみましょう(図19).

■図19 エディタを起動し,アクセス許可を学習させる
# emacs

他にも必要な操作があれば学習させます.また,パス名をパターン化する必要があるかもしれません.パス名をパターン化する方法はこの連載の2回目で紹介しました.

●確認と強制

許可したい操作に必要なアクセス許可を学習させたら,不足がないかどうか確認します.「 <kernel> /usr/sbin/sshd /bin/bash /bin/auth2 /bin/bash 」ドメインを確認モードに変更します.コンソールから図20のコマンドを実行してください.

■図20 「 <kernel> /usr/sbin/sshd /bin/bash /bin/auth2 /bin/bash 」ドメインを確認モードに変更
# /usr/sbin/ccs-setprofile -r 2 '<kernel> /usr/sbin/sshd /bin/bash /bin/auth2 /bin/bash'

アクセス許可の不足がないことを確認したら,強制モードに変更します.コンソールから図21のコマンドを実行してください.これで完成です.許可したい操作を学習させる必要があるとはいえ,さほど時間はかかりません.そして効果は絶大です.

■図21 「<kernel> /usr/sbin/sshd /bin/bash /bin/auth2 /bin/bash」ドメインを強制モードに変更
# /usr/sbin/ccs-setprofile -r 3 '<kernel> /usr/sbin/sshd /bin/bash /bin/auth2 /bin/bash'

より高度な使い方

最後にいくつか Tips を紹介します.

ログインシェル

ログインシェルとして使われる /bin/bash などは豊富な内部コマンドを備えています.たとえば(次回紹介する CONFIG::ipc::signal による制限を有効にしていない場合は)内部コマンドの kill を用いて任意のプロセスを強制終了させてしまうなどといった悪事を働くことができてしまいます.

このような事態を避けるために, TOMOYO Linux ツールの中に含まれている falsh をログインシェルとして使用することができます(図22).

■図22 falsh を /bin/ 以下に移動
# mv /usr/lib/ccs/misc/falsh /bin/

ログインシェルを /bin/falsh に変更するには図23のようにします.

■図23 ログインシェルを /bin/falsh に変更
# usermod -s /bin/falsh root

サーバ自身のネットワークの制限

/usr/sbin/sshd にはポート転送などTCPコネクションを中継する機能があります. /usr/sbin/sshd のドメイン( <kernel> /usr/sbin/sshd ドメイン)に対して次回紹介する CONFIG::network による制限を行うことで,より強固な防御を行うことができるようになります.

サーバからクライアントへ向けてTCPコネクションを確立する必要のないサーバの場合, CONFIG::network による制限をしておくことで,ワームやウィルスなどにより他のサーバへ攻撃するための踏み台として利用されてしまうのを防ぐ効果もあります.

使う必要がないことがわかっている機能であれば,強制アクセス制御により明示的に使わせないようにしておく価値があります.

公開鍵認証によるバッチ処理

公開鍵認証を用いて /usr/sbin/sshd から自動ログインしてバッチ処理を行う場合があります.そのような場合にも今回紹介した手法が役に立ちます.

バッチ処理のためのアカウントで使うログインシェルを,対話的処理のためのアカウントで使うログインシェル(この連載では /bin/bash を使用しています)とは異なるシェル(たとえば /bin/tcsh )にするだけで,「 <kernel> /usr/sbin/sshd /bin/tcsh 」のようにドメインを分離することができるようになります(図24).

■図24 ドメインを分離する
fig-6-24-ja.png

参考情報

NTT データでは,今回の連載で説明したログイン認証の強化方法について,2006年10月にプレスリリースを行っています.リリースの説明はできるだけ平易に記述したつもりですが,セキュアOSについて予備知識がない方にはやや難しかったかもしれません.本稿を読まれた方であれば,その原理と利点(価値)について十分にご理解いただけると思います.

セキュアOS「TOMOYO Linux」を用いた柔軟かつ強固な利用者認証方式のプロトタイプを開発(NTTデータプレスリリース)

さらに詳しい内容に興味を持たれた方は,ぜひ2005年9月に愛知県立大学情報学ワークショップ2005で発表した論文,「セキュリティ強化OSによるログイン認証の強化手法」をご参照ください.

「セキュリティ強化OSによるログイン認証の強化手法」/原田季栄,松本隆明/静岡大学『情報学研究』第11巻,93~102頁/2005年

execute_handler の利用例については以下のチュートリアルをご参照ください.

次回予告

次回は,ファイル以外のアクセス制御について紹介します.

第5回へ戻る 第7回へ進む


目次へ戻る

sflogo.php