Bashの機能を用いて実行したコマンドをsyslogで記録させる

前回、実行したログをsyslogで記録させるSnoopy Loggerを紹介したのだが、今回紹介する機能はbashを利用してそれと同じような事が出来る。
そう、bashでは4.1以降だとhistoryをsyslogに出力出来るようになっている。

…ただ、どうやらセキュリティの問題(コンソールで実行したコマンドにパスワードが入っていたりなど?真偽は不明)もあるようで、ディストリビューションに入っているbashではこの機能はオミットされているようだ。
そのため、この機能を使うにはbashを別途コンパイルする必要がある。

今回は、こちらのサイトの内容を元にCentOS 7上でこの作業を行っていく。

1.前提となるパッケージのダウンロード

コンパイルを行うにあたって、前提となるパッケージをダウンロードしておく。
必要になるのはgccとmake。

yum -y install gcc make

2.コンパイル

まずはbashのソースをこちらからダウンロードしてくる。
ダウンロードするのは、2015年3月時点において最新版の4.3.30とする。

wget http://ftp.gnu.org/gnu/bash/bash-4.3.30.tar.gz
tar xzvf bash-4.3.30.tar.gz
cd bash-4.3.30

そのままコンパイルしても機能が有効化されないため、「config-top.h」の110行目に、以下のように一行追記する。
また、自身の環境に応じて112行目のファシリティ、113行目のプライオリティを変更すると良いだろう。
ファシリティ、プライオリティで設定出来る値はこちらを参考にてもらいたい。

なお、初期設定ではファシリティはUSER、プライオリティはInfoとなっている。

Before

/* Define if you want each line saved to the history list in bashhist.c:
   bash_add_history() to be sent to syslog(). */
/* #define SYSLOG_HISTORY */
#if defined (SYSLOG_HISTORY)
#  define SYSLOG_FACILITY LOG_USER
#  define SYSLOG_LEVEL LOG_INFO
#endif

/* Define if you want to include code in shell.c to support wordexp(3) */
/* #define WORDEXP_OPTION */

/* Define as 1 if you want to enable code that implements multiple coprocs */
#ifndef MULTIPLE_COPROCS
#  define MULTIPLE_COPROCS 0

After

/* Define if you want each line saved to the history list in bashhist.c:
   bash_add_history() to be sent to syslog(). */
/* #define SYSLOG_HISTORY */
#define SYSLOG_HISTORY
#if defined (SYSLOG_HISTORY)
#  define SYSLOG_FACILITY LOG_USER
#  define SYSLOG_LEVEL LOG_INFO
#endif

/* Define if you want to include code in shell.c to support wordexp(3) */
/* #define WORDEXP_OPTION */

/* Define as 1 if you want to enable code that implements multiple coprocs */
#ifndef MULTIPLE_COPROCS
#  define MULTIPLE_COPROCS 0

以下は、ファシリティを「local6」、プライオリティを「Debug」にした例。

/* Define if you want each line saved to the history list in bashhist.c:
   bash_add_history() to be sent to syslog(). */
/* #define SYSLOG_HISTORY */
#define SYSLOG_HISTORY
#if defined (SYSLOG_HISTORY)
#  define SYSLOG_FACILITY LOG_LOCAL6
#  define SYSLOG_LEVEL LOG_DEBUG
#endif

/* Define if you want to include code in shell.c to support wordexp(3) */
/* #define WORDEXP_OPTION */

/* Define as 1 if you want to enable code that implements multiple coprocs */
#ifndef MULTIPLE_COPROCS
#  define MULTIPLE_COPROCS 0

基本的には、デフォルトのままではなく上記のようにファシリティ、プライオリティを指定した方がいいだろう。
ファイル編集後、コンパイルを行う。

./configure
make
make install

作成したファイルは「/usr/local/bin」に格納されるので、存在している事を確認する。

ls -la /usr/local/bin/bash

それでは、実際に ログが出力される事を確認しよ。
「/etc/rsyslog.conf」を開き、75行目辺りに以下の行を追記する。

# Save Command History
ファシリティ.プライオリティ          /var/log/ログファイル名

実際に設定した場合の例が以下。

# Save Command History
local6.debug          /var/log/history.log

上記設定後、rsyslogの再起動を行う。

systemctl restart rsyslog

rsyslog再起動後、コンパイルしたbashに切り替えを行い、コマンドの実行ログが記録される事を確認する。

/usr/local/bin/bash
ls -la
cat /var/log/history.log

無事、実行したコマンドがログとして記録されている。

3.既存のbashを入れ替える

既存のbashを置き換えるため、「/etc/passwd」を編集し、rootユーザのログインシェルを「/usr/local/bin/bash」に切り替える。

sed -i '/root/ s|/bin/bash|/usr/local/bin/bash|g' /etc/passwd

上記コマンド実行後、再度サーバにログインを行う。
無事ログインできることを確認したら、いままで接続していたセッションをクローズする。

新しいセッションのみになったら、バックアップを取得の上、「/bin/bash」に「/usr/local/bin/bash」をコピーする。

cp /bin/bash /tmp/bash
cp /usr/local/bin/bash /bin/bash

ファイルの上書き後、「/etc/passwd」を再度編集する。

sed -i '/root/ s|/usr/local/bin/bash|/bin/bash|g' /etc/passwd

無事にログインでき、コマンドがログに出力されることを確認する。

4.パッケージ管理ソフトの対象外とする

さて、これで無事に設定はできたのだが、このままだとパッケージ管理ソフト(yumなど)でアップデートを行った際に上書きされてしまい、またログに記録されないようになってしまう。
そのため、以下のコマンドを実行しbashをyumの対象から除外する設定を行う。

echo "exclude=bash*" >> /etc/yum.conf

※脆弱性が出た場合、自分でコンパイルする必要があります。

これで、無事に実行コマンドをログに記録できるようになった。