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
コメントやシェアをお願いします!
もぎゃ
同じLinux Squareの会議室で、
操作ログ取得について - Linux Square
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=30685&forum=10&7
という話があがっていますね。
特に新しい情報はないと思いますが、まあご参考まで。
drk
kosakaさん>chmod a+w /tmp として、/tmp 配下への書き込み権限を与えて下さい。この手のエラーはパーミッションが関係していると思うので、/tmp/log/script_logs までの書き込み権限を与えれば、エラーは消えると思います。質問の?はこのパーミッションを旨く与えればできると思います。
kosaka
はじめまして。
参考にさせていただいて実装してみたのですが、
-bash: /etc/profile: 許可がありません
スクリプトを開始しました、ファイルは /tmp/log/script_logs/kosaka/20061123072720 です
と表示されます。
?「許可がありません」となってしまうのはなぜでしょうか?
? root以外のものが、loggingしたファイルを編集削除できないように
したいのですが、どうしたら良いでしょうか?
drk
カズさん>先週末にメールをお送り致しましたので、宜しければそちらもご覧頂ければ幸いです。宜しくお願い致します。
カズ
貴重なコメントありがとうございます.
bashrcだとbash起動ごとに読み込まれるようですので,
今はその部分に修正を加えておりますが,
それでも難しい場合は,お教え頂いたようにcronで細かい時間設定をして.bash_historyを収集してみます.
cronというコマンドを今まで知りませんでした,ありがとうございます.
追伸:
もし差し支えなければ讃岐うどんと醤油豆セット(1500円くらいのもので恐縮なのですが・・・(^_^;))
をお贈りしたいのですが,
ご都合のよい発送先をメールにてお教え頂ければと思います次第です.
※最寄の郵便局をお教え頂ければ,局留めという形でお送りすることもできま す.(その郵便局まで取りに行かなければいけない,という面倒はありますが)
また気の向かれたときに,どうかよろしくお願い申し上げます.
drk
カズさん>おぉぉ!まさにCUIしか前提に考えておりませんでした。もし簡単にbashのログを取得するのであれば、上記で説明している.bash_historyをcronで収集するだけでも十分意味があるかもしれませんね。
どうでしょう?
カズ
ふと思ったのですが,
上で紹介してくださっているシェルは,
CUIで操作するという前提での話しなのでしょうか.
なんとなく,そんな気がしてきたのですが
現在,Vine3.2のGUI上で
一生懸命,bashを検知してログをためてくれないなぁ・・と
試行錯誤しているような感じでおります.
p_proc=`ps -ef|grep $PPID|grep bash|awk '{print $8}'`
if [ "$p_proc" = -bash ]
then
script $logfile
exit
fi
カズ
/etc/profileに直接書き込んでみたのですが、
bashの起動によるログの自動生成の部分がうまくいきません。
ユーザー名のフォルダー生成まではうまく行きました。
drkさまのメールアドレスが、ブログの中から
うまく探せず、止むを得ず掲示板へ記載いたしました。
香川の名産、しょうゆ豆もお贈りしますので、
折り返しメール頂けましたら、幸いに存じます。
どうかよろしくお願い申し上げます。
drk
カズさん>、/etc/profile に vim とかで直接追記して頂ければ問題ないかと思います。echo "....."の本文中を。
うまくいかない場合は、メールなり下さい。よろしくお願いします。
カズ
drkさま
紹介してくださっているコマンド履歴の自動ロギングの
シェルスクリプトを是非動かしてみたいのですが、
予備知識不足でうまく動かせません。
(初歩的な質問で恥ずかしいのですが)
紹介して頂いているシェルスクリプトの文は、
ターミナル上で打ち込めば、/etc/profileに
書き込まれるという理解でよろしいのでしょうか。
それとも、あらかじめ/etc/profileに、上記のシェルスクリプトの文を
記載するものなのでしょうか。
どうかご教授のほど、よろしくお願い申し上げます。
...うまく、動きました曉には、
大したものではございませんが、
せめてものお礼に、讃岐うどんをお贈り致したく存じます。
どうかご教授のほど、お願い申し上げます。
drk
maximaさん>hack有り難うございました。早速僕もhack版に変更したいと思います。
maxima
先のコメントの22行目(最後から3行目)ですがエスケープが抜けてました。
誤)script $logfile
正)script \$logfile
失礼しました(^^;
maxima
はじめまして。
この記事、非常に参考になりました。
FC4のbashで試してみたところ、19行目のawkの部分のシングルクォートが消えてしまうようでしたので、下記のようにechoをダブルクォートに変更したところ、うまくいきました。
取り急ぎご報告まで。
--------
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
--------