Linux/UNIX 上でコマンドの実行履歴を残す方法

最近、セキュリティ関連の話が多いが身の回りで多いのですが、今回は、Linux / UNIX 系で誰がいつどのコマンドを実行したかってのをログにとる方法のお話しです。

@IT:止められないUNIXサーバの管理対策 第6回 - Page2」にも参考になるロギングの話が掲載されていますが、実行コマンドのログをとる方法は以下の5つが考えられます。

  • sudo を使って実行ログをとる
  • .bash_history を定期的にバックアップして実行ログとして保存する
  • script コマンドを使うことで実行ログ(画面出力のコピー)をとる
  • システムアカウンティング機能(psacct)を有効にして実行ログをとる
  • 実行シェルを改造し、ログを保存するようにする
- スポンサーリンク -

僕が考えつくところで、セキュリティ的に最も強固であるのはシェルの改造と思います。但し、その OS 上で使える Shell をその改造 Shell のみに限定する必要があります。※別の Shell を起動して実行されてはログが残りませんから。。。

但し、Shell の改造となるとかなり難易度が高くなってしまうのであまり現実的ではありません。

それ以外の方法は何かしら穴があるので、セキュリティ要件として使うのはちょっと無理っぽいかもしれません。

  • sudo の場合 → sudo -s で抜け道がある。
  • .bash_history の場合 → 実行ユーザが .bash_history を削除できる
  • script コマンドの場合 → 実行ユーザがログファイルを削除できる
  • システムアカウンティング機能(psacct)の場合 → 余分な情報が多すぎ
  • 実行シェルを改造し、ログを保存するようにする → 実装が難しい

現実的なところは、psacct あたりでしょうか。

chkconfig --add psacct
chkconfig --level 2345 psacct on
とでもしておけば、lastcomm コマンドでコマンド履歴を閲覧することができるようになります。
chkconfig         S     root     pts/0      0.17 secs Wed Mar 15 22:02
perl                    apache   __         0.59 secs Wed Mar 15 22:02
chkconfig         S     root     pts/0      0.00 secs Wed Mar 15 22:02
runlevel          S     root     pts/0      0.00 secs Wed Mar 15 22:02
chkconfig         S     root     pts/0      0.00 secs Wed Mar 15 22:02
perl                    apache   __         0.09 secs Wed Mar 15 22:02
crond             SF    root     __         0.00 secs Wed Mar 15 22:02
chkproc.pl        S     root     __         0.00 secs Wed Mar 15 22:02
ps                S     root     __         0.01 secs Wed Mar 15 22:02
perl                    apache   __         0.09 secs Wed Mar 15 22:02
perl                    apache   __         0.09 secs Wed Mar 15 22:02
perl                    apache   __         0.09 secs Wed Mar 15 22:01
perl                    apache   __         0.09 secs Wed Mar 15 22:01
psacct            S     root     pts/0      0.01 secs Wed Mar 15 22:01
touch             S     root     pts/0      0.00 secs Wed Mar 15 22:01
initlog           S     root     pts/0      0.00 secs Wed Mar 15 22:01
accton            S     root     pts/0      0.00 secs Wed Mar 15 22:01

但し、Shell から実行したコマンドだけでなく、Apache 等のプロセスが実行したものも全てログとして出力されるので、ログは結構肥大化しますし、なによりロギングする不可が気になるところです。


さて、では自分が実行したコマンド履歴を備忘録的に見たいという要件だとするとどうでしょう?

この場合では、script コマンドによるロギングが圧倒的に情報量が多いです。例えば、Shell から SQL*plus を起動して SQL を実行した結果。なんてのも全てログとして保存することができます。ようは、標準出力として出力したものを全てコピーして保存することができます。

そのため、現場ではサーバにミドルウェアをインストールをしたり設定したりするときに、script コマンドを実行して全ての実行ログをとって、それをドキュメントとして加工してから納品する。なんてことが行われています。

但し、能動的に script をコマンドを打つ必要があるので、自分たちが運用者として Shell を触っている時には、ほぼ100%の確率で実行することを忘れてしまっています。

そんなこんなで最近作った便利シェルスクリプトはこちら。

mkdir /tmp/log
mkdir /tmp/log/script_logs
chmod -R 777 /tmp/log

echo "
## loggin ----------
now=`date +%Y%m%d%H%M%S`
user=`whoami`
logfile=/tmp/log/script_logs/$user/$now

if [ ! -e /tmp/log/script_logs/$user ]
then
    mkdir /tmp/log/script_logs/$user
fi
if [ -e $logfile ]
then
    mv -f $logfile $logfile.bak
fi
p_proc=`ps -ef|grep $PPID|grep bash|awk '{print $8}'`
if [ "$p_proc" = -bash ]
then
    script $logfile 
    exit
fi" >> /etc/profile

何をしているスクリプトかというと、/etc/profile に script コマンドの自動起動および script コマンドの exit にあわせて Shell も自動で exit するようにしています。Shell も自動で exit することで、自分自身、script コマンド経由でログインしていると言うことは、ps -ef 等でプロセスを見ないと把握できないくらいです。

※逆に、ps でプロセスをみれば、script コマンドが実行されていることがわかるので、セキュリティー要件としては十分ではありません。kill できてしまいますので。


さて、肝心のログの方は、/tmp/log/script_logs/ユーザ名/yyyymmddhhmiss 形式のログが勝手にできています。必要時にログインした時間帯などからログを適宜閲覧すれば、自分が何をして、どんな結果になったのかを見ることができます。勝手にログが溜まる。ってところがポイントです。

実行ログをとるにはどうするんだっけ?と調べた時の参考サイト一覧
 - ずんWiki - acctでコマンド実行のログを取る
 - @IT:止められないUNIXサーバの管理対策 第6回 - Page2
 - Linuxでの操作ログ - Linux Square

- スポンサーリンク -