AIDE(Advanced Intrusion Detection Environment)


AIDE は、オープンソースのホスト型侵入検知システム(HIDS)で、RHEL等主要なディストリビューションに含まれるパッケージです。
これを使うことで、例えば、Apacheで公開しているhtmlファイル等の改ざん監視を行えます。

aideの改ざん監視の仕組みは、監視ポリシーに従い、パーミッションmd5チェックサム
などのルールセットにより、監視対象ファイルやディレクトリに対しチェックを行います。
これらの結果を基準値(ベース)としてデータベースファイルに保存します。

同様に、定期的に監視ポリシーに従い、監視対象に対しチェックを行い、
データベースと比較し違いがある場合には、これを改ざんとして、検知します。

AIDE利用方法

RHEL5で利用方法を説明します。

1. AIDEのインストール
AIDEをインストールするには、以下のコマンドを実行します。

#yum install aide


2. 設定ファイルの編集
インストール時の標準のままでも動作しますが、必要がある場合には、設定ファイルを編集します。

#vi /etc/aide.conf


3.AIDEデータベースファイルの作成
ベースとなるAIDEデータベースファイルを作成します。

#aide --init
#cp /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz


aideは、データベースファイル(aide.db.new.gz)を/var/lib/aideディレクトリに新たに作成します。
これを、手動でベースとしてコピーコマンド等で保存します。

通常、管理者は、セキュリティのため、ネットワーク接続前に、データベースファイルを作成しておくべきです。


4.改ざんチェック
システムの現在状態との比較を行うには、以下のコマンドを実行します。

#aide --check

改ざんが検知されると以下のような結果が出力されます。

AIDE found differences between database and filesystem!!
Start timestamp: 2009-11-30 14:39:45
Summary:
Total number of files=11247,added files=0,removed files=0,changed files=1


Changed files:
changed:/bin/ls

Detailed information about changes:

File: /bin/ls
Mtime : 2009-11-30 14:26:18 , 2009-11-30 14:39:39
Ctime : 2009-11-30 14:26:18 , 2009-11-30 14:39:39


5.データベースファイルの更新
結果を確認し、改ざんが検知された場合でも、その変更が問題なければ、現在の状態のデータベースを作成し、新たなベースとします。

#aide --init
#cp /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz

この チェック aide --check からAIDEデータベース作成 aide --init は、 aide --update コマンドで省略可能です。
その場合、4と5の操作は、次のようになります。

#aide --update
#cp /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz


参考)
How do I check the software integrity on Red Hat Enterprise Linux 5?

監視ポリシー(aide.conf)

監視ポリシーは、インストール時の標準のものでも、例えば/etcや/bin配下などの広範囲にチェックを行ってくれます。

ただし、標準では、/var/logや/root配下もチェックしますので、
ユーザーのログイン、rootがコマンドを実行しただけで、改ざんとして通知されます。
こうした検知が煩わしい、もしくは独自ファイルの監視を行いたい場合、カスタマイズが必要です。

例えば、以下の例の場合、全てのファイルに関して、パーミッション、ユーザー、グループに変更があった場合、改ざんとして検知されます。

/ p+u+g


詳細は、manコマンドで確認してください。

運用(定期チェック)

改ざんチェックおよびデータベースファイルの更新(aide --update)を行います。
改ざんを検知した場合は、管理者へメール通知を行います。
管理者は、内容を確認し、問題がなければ、データベースファイルを更新します。
(mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz)

定期チェック用スクリプト

RHELでは、定期チェックのスクリプトが提供されないため、自作する必要があります。
Debian系で提供されている定期チェックスクリプトを、RHEL用に修正します。

パラメタファイル(/etc/default/aide)

後述の定期チェックスクリプトのパラメタファイルです。
結果の通知先(MAILTO)を実際にメールを送付したい宛先に設定してください。

# These settings are mainly for the wrapper scripts around aide,
# such as aideinit and /etc/cron.daily/aide

# This is the email address reports get mailed to

MAILTO=root

# Set this to suppress mailings when there's nothing to report

 
#QUIETREPORTS=1

# This parameter defines which aide command to run from the cron script.
# Sensible values are "update" and "check".
# Default is "check", ensuring backwards compatibility.
# Since "update" does not take any longer, it is recommended to use "update",
# so that a new database is created every day. The new database needs to be
# manually copied over the current one, though.

COMMAND=update

# This parameter defines how many lines to return per e-mail. Output longer
# than this value will be truncated in the e-mail sent out.

LINES=1000

# This parameter gives a grep regular expression. If given, all output lines
# that _don't_ match the regexp are listed first in the script's output. This
# allows to easily remove noise from the aide report.

NOISE=""

# This parameter defines which options are given to aide in the daily
# cron job. The default is "-V4".

AIDEARGS=""
定期チェックスクリプト(/etc/cron.daily/aide)

クーロンで、 aide --update を定期実行、結果をメールで通知します。

#!/bin/bash

PATH="/sbin:/usr/sbin:/bin:/usr/bin"
LOGDIR="/var/log/aide"
LOGFILE="aide.log"
CONFFILE="/etc/aide.conf"
ERRORLOG="error.log"
ERRORTMP=`mktemp -t "$ERRORLOG".XXXXXXXXXX`

[ -f /usr/sbin/aide ] || exit 0

AIDEARGS="-V4"

if [ -f /etc/default/aide ]; then
        . /etc/default/aide
fi

FQDN=`hostname -f`
DATE=`date +"at %Y-%m-%d %H:%M"`

# default values

MAILTO="${MAILTO:-root}"
DATABASE="${DATABASE:-/var/lib/aide/aide.db.gz}"
LINES="${LINES:-1000}"
COMMAND="${COMMAND:-check}"

if [ ! -f $DATABASE ]; then
        (
        echo "Fatal error: The AIDE database does not exist!"
        echo "This may mean you haven't created it, or it may mean that someone has removed it."
        ) | /usr/bin/mail -s "Daily AIDE report for $FQDN" $MAILTO
        exit 0
fi

aide $AIDEARGS --$COMMAND >"$LOGDIR/$LOGFILE" 2>"$ERRORTMP"
RETVAL=$?

if [ -n "$QUIETREPORTS" ] && [ $QUIETREPORTS -a \! -s $LOGDIR/$LOGFILE -a \! -s $ERRORTMP ]; then
        # Bail now because there was no output and QUIETREPORTS is set
        exit 0
fi

(cat << EOF;
This is an automated report generated by the Advanced Intrusion Detection
Environment on $FQDN ${DATE}.

EOF

# include error log in daily report e-mail

if [ "$RETVAL" != "0" ]; then
        cat > "$LOGDIR/$ERRORLOG" << EOF;

*****************************************************************************
*                    aide returned a non-zero exit value                    *
*****************************************************************************

EOF
        echo "exit value is: $RETVAL" >> "$LOGDIR/$ERRORLOG"
else
        touch "$LOGDIR/$ERRORLOG"
fi
< "$ERRORTMP" cat >> "$LOGDIR/$ERRORLOG"
rm -f "$ERRORTMP"

if [ -s "$LOGDIR/$ERRORLOG" ]; then
        errorlines=`wc -l "$LOGDIR/$ERRORLOG" | awk '{ print $1 }'`
        if [ ${errorlines:=0} -gt $LINES ]; then
                cat << EOF;

****************************************************************************
*                      aide has returned many errors.                      *
*           the error log output has been truncated in this mail           *
****************************************************************************

EOF
                echo "Error output is $errorlines lines, truncated to $LINES."
                head -$LINES "$LOGDIR/$ERRORLOG"
                echo "The full output can be found in $LOGDIR/$ERRORLOG."
        else
                echo "Errors produced  ($errorlines lines):"
                cat "$LOGDIR/$ERRORLOG"
        fi
else
        echo "AIDE produced no errors."
fi

# include de-noised log

if [ -n "$NOISE" ]; then
        NOISTEMP=`mktemp -t aidenoise.XXXXXXXXXX`
        NOISTEMP2=`mktemp -t aidenoise.XXXXXXXXXX`
        sed -n '1,/^Detailed information about changes:/p' "$LOGDIR/$LOGFILE" | \
        grep '^\(changed\|removed\|added\):' | \
        grep -v "^added: THERE WERE ALSO [0-9]\+ FILES ADDED UNDER THIS DIRECTORY" > $NOISETMP2

        if [ -n "$NOISE" ]; then
                < $NOISETMP2 grep -v "^\(changed\|removed\|added\):$NOISE" > $NOISETMP
                rm -f $NOISETMP2
                echo "De-Noised output removes everything matching $NOISE."
        else
                mv $NOISETMP2 $NOISETMP
                echo "No noise expression was given."
        fi

        if [ -s "$NOISETMP" ]; then
                loglines=`< $NOISETMP wc -l | awk '{ print $1 }'`
                if [ ${loglines:=0} -gt $LINES ]; then
                        cat << EOF;

****************************************************************************
*   aide has returned long output which has been truncated in this mail    *
****************************************************************************

EOF
                        echo "De-Noised output is $loglines lines, truncated to $LINES."
                        < $NOISETMP head -$LINES
                        echo "The full output can be found in $LOGDIR/$LOGFILE."
                else
                        echo "De-Noised output of the daily AIDE run ($loglines lines):"
                        cat $NOISETMP
                fi
        else
                echo "AIDE detected no changes after removing noise."
        fi
        rm -f $NOISETMP
        echo "============================================================================"
fi

# include non-de-noised log

if [ -s "$LOGDIR/$LOGFILE" ]; then
        loglines=`wc -l "$LOGDIR/$LOGFILE" | awk '{ print $1 }'`
        if [ ${loglines:=0} -gt $LINES ]; then
                cat << EOF;

****************************************************************************
*   aide has returned long output which has been truncated in this mail    *
****************************************************************************

EOF
                echo "Output is $loglines lines, truncated to $LINES."
                head -$LINES "$LOGDIR/$LOGFILE"
                echo "The full output can be found in $LOGDIR/$LOGFILE."
        else
                echo "Output of the daily AIDE run ($loglines lines):"
                cat "$LOGDIR/$LOGFILE"
        fi
else
        echo "AIDE detected no changes."
fi
) | /bin/mail -s "Daily AIDE report for $FQDN" $MAILTO

ログ

AIDEログ

/var/log/aide/aide.log

エラーログ(定期チェックスクリプトで出力するエラーログ)

/var/log/aide/error.log

ログローテーション(/etc/logrotate.d/aide)

# Logrotate file for aide RPM

/var/log/aide/*log {
daily
missingok
rotate 7
create 0600 root root
}

Tips&トラブルシュート

データベースファイルの格納場所

最も重要なこととして、データベースをどこに格納するかという問題があります。
データベースファイル自体が、侵入者に改ざんされてしまっては、全く意味がありません。
そのため、データベースファイルはリモートサーバやReadOnlyの外部メディアに置くことが推奨されています。

正規表現を使った監視対象の設定

aide.confに定義する監視対象は、正規表現も使った表現も可能です。
以下の例の場合、全ファイル、パーミッション、ユーザーおよびグループのチェックに加え、/etcディレクトリ配下は加えてatimeの値チェックも行います。ただし、/etc/hoge.confはチェックを行いません。

/ p+u+g
=/etc p+u+g+a
!/etc/hoge.conf


詳細は、 AIDE Manual を参照してください。

lgetfilecon_raw failedエラー

Selinuxをdisabledにしている状態でデータベース作成(aide --init)を行うと、大量のlgetfilecon_raw failedエラーが出力されます。
これは、aideは、標準のポリシーにselinuxのチェックが含まれるためです。
設定ファイル(aide.conf)に以下を加えます。

R=p+i+l+n+u+g+s+m+c+acl+xattrs+md5
L=p+i+l+n+u+g+acl+xattrs
>=p+l+u+g+i+n+S+acl+xattrs

参考)
Re【AIDE】lgetfilecon_raw failed