AIDEでLinuxサーバーの改ざんを検知する方法

AIDEでLinuxサーバーの改ざんを検知する方法

Linuxサーバーで改ざん検知の仕組み構築する場合、まず思いつく方法はTripwireを使った方法ですが、現在のRedHat系Linuxでは、Tripwinreと同じような仕組みでよりシンプルな設定で改ざん検知ができるソフトウェアとして「 Advanced Intrusion Detection Environment ( AIDE ) 」が利用できます。

そこでここでは、RedHat系Linux(AlmaLinux9)で、AIDEを使って改ざんを検知する方法を解説します。

AIDEとは

Advanced Intrusion Detection Environment (AIDE) は、ファイルの改ざんを検出するソフトウェアで、「Host-based Intrusion Detection System(HIDS)ホスト型不正侵入検知システム 」に位置づけられる無料ソフトウェアです。

IDS(不正侵入検知システム)には、ホスト型とネットワーク型があり、HIDS(ホスト型不正侵入検知システムは、コンピューターへの不正侵入を検知し、NIDS(ネットワーク型不正侵入検知システム)は、 ネットワークへの不正侵入を検知します。

AIDEの仕組みは、ファイル改ざん検知ソフトウェアとして有名なTripwireと似た点が多く、ローカルシステム上のファイルとディレクトリーの状態(内容や属性)を記録したデータベースを作成し、そのデータベースを基にファイルの整合性をチェックします。

また、AIDEは多くのLinuxディストリビューションで標準のリポジトリから簡単にインストールでき、設定方法もTripwireより分かりやすいというメリットがあります。

AIDEの使い方

ここからは、RedHat系Linux(AlmaLinux9)で、AIDEのインストールから構築方法までを解説します。

AIDEのインストール

AlmaLinux9では、標準のリポジトリからAIDEをインストールできます。

# dnf install aide

インストールされるバージョンは、以下のとおりです。

# aide -v
Aide 0.16

AIDEの設定

AIDEの設定は、設定ファイル「/etc/aide.conf」をテキストエディターで編集して行います。

設定ファイルでは、AIDEの基本的な動作設定(ログの出力先やログの詳細度など)や、どのようなチェックを行うか、どのディレクトリやファイルをチェックするのかを定義します。

なお、一般的なチェック方法(チェックルール)やチェック対象のディレクトリやファイルはあらかじめ定義されているので、まずはデフォルト設定で使い始めてチェックするディレクトリやファイルを調整するとよいでしょう。

以下が、デフォルトの設定ファイルの内容です。

# vi /etc/aide.conf

# Example configuration file for AIDE.

@@define DBDIR /var/lib/aide
@@define LOGDIR /var/log/aide

# The location of the database to be read.
database=file:@@{DBDIR}/aide.db.gz

# The location of the database to be written.
#database_out=sql:host:port:database:login_name:passwd:table
#database_out=file:aide.db.new
database_out=file:@@{DBDIR}/aide.db.new.gz

# Whether to gzip the output to database
gzip_dbout=yes

# Default.
verbose=5

report_url=file:@@{LOGDIR}/aide.log
report_url=stdout
#report_url=stderr
#NOT IMPLEMENTED report_url=mailto:[email protected]
#NOT IMPLEMENTED report_url=syslog:LOG_AUTH

# These are the default rules. ←これ以降にチェックルールが定義されています。
#
#p:      permissions
#i:      inode:
#n:      number of links
#u:      user
#g:      group
#s:      size
#b:      block count
#m:      mtime
#a:      atime
#c:      ctime
#S:      check for growing size
#acl:           Access Control Lists
#selinux        SELinux security context
#xattrs:        Extended file attributes
#md5:    md5 checksum
#sha1:   sha1 checksum
#sha256:        sha256 checksum
#sha512:        sha512 checksum
#rmd160: rmd160 checksum
#tiger:  tiger checksum

#haval:  haval checksum (MHASH only)
#gost:   gost checksum (MHASH only)
#crc32:  crc32 checksum (MHASH only)
#whirlpool:     whirlpool checksum (MHASH only)

#R:             p+i+n+u+g+s+m+c+acl+selinux+xattrs+md5
#L:             p+i+n+u+g+acl+selinux+xattrs
#E:             Empty group
#>:             Growing logfile p+u+g+i+n+S+acl+selinux+xattrs

# You can create custom rules like this.
# With MHASH...
# ALLXTRAHASHES = sha1+rmd160+sha256+sha512+whirlpool+tiger+haval+gost+crc32
ALLXTRAHASHES = sha1+rmd160+sha256+sha512+tiger
# Everything but access time (Ie. all changes)
EVERYTHING = R+ALLXTRAHASHES

# Sane
# NORMAL = R+sha512
NORMAL = p+i+n+u+g+s+m+c+acl+selinux+xattrs+sha512

# For directories, don't bother doing hashes
DIR = p+i+n+u+g+acl+selinux+xattrs

# Access control only
PERMS = p+u+g+acl+selinux+xattrs

# Logfile are special, in that they often change
LOG = p+u+g+n+S+acl+selinux+xattrs

# Content + file type.
CONTENT = sha512+ftype

# Extended content + file type + access.
CONTENT_EX = sha512+ftype+p+u+g+n+acl+selinux+xattrs

# Some files get updated automatically, so the inode/ctime/mtime change
# but we want to know when the data inside them changes
DATAONLY =  p+n+u+g+s+acl+selinux+xattrs+sha512

# Next decide what directories/files you want in the database.
# これ以降にチェック対象のディレクトリやファイルとどのチェックルールを適用するかが定義されています。

/boot       CONTENT_EX
/opt        CONTENT

# Admins dot files constantly change, just check perms
/root/\..* PERMS
!/root/.xauth*
# Otherwise get all of /root.
/root   CONTENT_EX

# These are too volatile
!/usr/src
!/usr/tmp

# Otherwise get all of /usr.
/usr    CONTENT_EX

# trusted databases
/etc/hosts$      CONTENT_EX
/etc/host.conf$  CONTENT_EX
/etc/hostname$   CONTENT_EX
/etc/issue$      CONTENT_EX
/etc/issue.net$  CONTENT_EX
/etc/protocols$  CONTENT_EX
/etc/services$   CONTENT_EX
/etc/localtime$  CONTENT_EX
/etc/alternatives CONTENT_EX
/etc/sysconfig   CONTENT_EX
/etc/mime.types$ CONTENT_EX
/etc/terminfo    CONTENT_EX
/etc/exports$    CONTENT_EX
/etc/fstab$      CONTENT_EX
/etc/passwd$     CONTENT_EX
/etc/group$      CONTENT_EX
/etc/gshadow$    CONTENT_EX
/etc/shadow$     CONTENT_EX
/etc/subgid$     CONTENT_EX
/etc/subuid$     CONTENT_EX
/etc/security/opasswd$ CONTENT_EX
/etc/skel        CONTENT_EX
/etc/sssd        CONTENT_EX
/etc/machine-id$ CONTENT_EX
/etc/swid        CONTENT_EX
/etc/system-release-cpe$ CONTENT_EX
/etc/shells$     CONTENT_EX
/etc/tmux.conf$  CONTENT_EX
/etc/xattr.conf$ CONTENT_EX

# networking
/etc/firewalld      CONTENT_EX
!/etc/NetworkManager/system-connections
/etc/NetworkManager CONTENT_EX
/etc/networks$ CONTENT_EX
/etc/dhcp CONTENT_EX
/etc/wpa_supplicant CONTENT_EX
/etc/resolv.conf$ DATAONLY
/etc/nscd.conf$ CONTENT_EX

# logins and accounts
/etc/login.defs$ CONTENT_EX
/etc/libuser.conf$ CONTENT_EX
/var/log/faillog$ PERMS
/var/log/lastlog$ PERMS
/var/run/faillock PERMS
/etc/pam.d CONTENT_EX
/etc/security CONTENT_EX
/etc/securetty$ CONTENT_EX
/etc/polkit-1 CONTENT_EX
/etc/sudo.conf$ CONTENT_EX
/etc/sudoers$ CONTENT_EX
/etc/sudoers.d CONTENT_EX

# Shell/X startup files
/etc/profile$ CONTENT_EX
/etc/profile.d CONTENT_EX
/etc/bashrc$ CONTENT_EX
/etc/bash_completion.d CONTENT_EX
/etc/zprofile$ CONTENT_EX
/etc/zshrc$ CONTENT_EX
/etc/zlogin$ CONTENT_EX
/etc/zlogout$ CONTENT_EX
/etc/X11 CONTENT_EX

# Pkg manager
/etc/dnf CONTENT_EX
/etc/yum.conf$ CONTENT_EX
/etc/yum CONTENT_EX
/etc/yum.repos.d CONTENT_EX

# This gets new/removes-old filenames daily
!/var/log/sa
# As we are checking it, we've truncated yesterdays size to zero.
!/var/log/aide.log

# auditing
# AIDE produces an audit record, so this becomes perpetual motion.
/var/log/audit PERMS
/etc/audit CONTENT_EX
/etc/libaudit.conf$ CONTENT_EX
/etc/aide.conf$  CONTENT_EX

# System logs
/etc/rsyslog.conf$ CONTENT_EX
/etc/rsyslog.d CONTENT_EX
/etc/logrotate.conf$ CONTENT_EX
/etc/logrotate.d CONTENT_EX
/etc/systemd/journald.conf$ CONTENT_EX
/var/log LOG+ANF+ARF
/var/run/utmp LOG

# secrets
/etc/pkcs11 CONTENT_EX
/etc/pki CONTENT_EX
/etc/crypto-policies CONTENT_EX
/etc/certmonger CONTENT_EX
/var/lib/systemd/random-seed$ PERMS

# init system
/etc/systemd CONTENT_EX
/etc/rc.d CONTENT_EX
/etc/tmpfiles.d CONTENT_EX

# boot config
/etc/default CONTENT_EX
/etc/grub.d CONTENT_EX
/etc/dracut.conf$ CONTENT_EX
/etc/dracut.conf.d CONTENT_EX

# glibc linker
/etc/ld.so.cache$ CONTENT_EX
/etc/ld.so.conf$ CONTENT_EX
/etc/ld.so.conf.d CONTENT_EX
/etc/ld.so.preload$ CONTENT_EX

# kernel config
/etc/sysctl.conf$ CONTENT_EX
/etc/sysctl.d CONTENT_EX
/etc/modprobe.d CONTENT_EX
/etc/modules-load.d CONTENT_EX
/etc/depmod.d CONTENT_EX
/etc/udev CONTENT_EX
/etc/crypttab$ CONTENT_EX

#### Daemons ####

# cron jobs
/etc/at.allow$ CONTENT
/etc/at.deny$ CONTENT
/etc/anacrontab$ CONTENT_EX
/etc/cron.allow$ CONTENT_EX
/etc/cron.deny$ CONTENT_EX
/etc/cron.d CONTENT_EX
/etc/cron.daily CONTENT_EX
/etc/cron.hourly CONTENT_EX
/etc/cron.monthly CONTENT_EX
/etc/cron.weekly CONTENT_EX
/etc/crontab$ CONTENT_EX
/var/spool/cron/root CONTENT

# time keeping
/etc/chrony.conf$ CONTENT_EX
/etc/chrony.keys$ CONTENT_EX

# mail
/etc/aliases$ CONTENT_EX
/etc/aliases.db$ CONTENT_EX
/etc/postfix CONTENT_EX

# ssh
/etc/ssh/sshd_config$ CONTENT_EX
/etc/ssh/ssh_config$ CONTENT_EX

# stunnel
/etc/stunnel CONTENT_EX

# printing
/etc/cups CONTENT_EX
/etc/cupshelpers CONTENT_EX
/etc/avahi CONTENT_EX

# web server
/etc/httpd CONTENT_EX

# dns
/etc/named CONTENT_EX
/etc/named.conf$ CONTENT_EX
/etc/named.iscdlv.key$ CONTENT_EX
/etc/named.rfc1912.zones$ CONTENT_EX
/etc/named.root.key$ CONTENT_EX

# xinetd
/etc/xinetd.conf$ CONTENT_EX
/etc/xinetd.d CONTENT_EX

# IPsec
/etc/ipsec.conf$ CONTENT_EX
/etc/ipsec.secrets$ CONTENT_EX
/etc/ipsec.d CONTENT_EX

# USB guard
/etc/usbguard CONTENT_EX

# Ignore some files
!/etc/mtab$
!/etc/.*~

# Now everything else
/etc    PERMS

# With AIDE's default verbosity level of 5, these would give lots of
# warnings upon tree traversal. It might change with future version.
#
#=/lost\+found    DIR
#=/home           DIR

チェック対象のディレクトリやファイルを追加するときは、既存の設定内容を参考にするか「man aide.conf」で「EXAMPLE」セクションを参照するとよいでしょう。

# man aide.conf
:
:
EXAMPLES
              / R

       This adds all files on your machine to the database. This one line is a fully qualified configuration file.

              !/dev

       This ignores the /dev directory structure.

              =/foo R

       Only /foo and /foobar are taken into the database. None of their children are added.

              =/foo/ R

       Only /foo and its children (e.g. /foo/file and /foo/directory) are taken into the database.  The  children  of
       sub-directories (e.g. /foo/directory/bar) are not added.

              All=p+i+n+u+g+s+m+c+a+md5+sha1+tiger+rmd160

       This  line  defines group All. It has all attributes and all md checksum functions. If you absolutely want all
       digest functions then you should enable mhash support and add +crc32+haval+gost to the end of  the  definition
       for All. Mhash support can only be enabled at compile-time.
:
:

AIDEデータベースの作成

設定ファイルを作成したら、次に以下のコマンドで現在のディレクトリやファイルの状態をデータベースファイルに記録します。(データベースファイルの作成には少し時間がかかります。)

# aide --init
Start timestamp: 2025-02-09 02:46:06 +0900 (AIDE 0.16)
AIDE initialized database at /var/lib/aide/aide.db.new.gz

Number of entries:      52356

---------------------------------------------------
The attributes of the (uncompressed) database(s):
---------------------------------------------------

/var/lib/aide/aide.db.new.gz
  MD5      : +F0kzzaUvUyLQlEVruGBMw==
  SHA1     : 6gNodoyBKg0wap8JWdaFHVmjr3I=
  RMD160   : 9clclQYbfZlFizAknV2tDzJi3f8=
  TIGER    : ZpNPsk9Fpge19bYxB2PBSIeugzwGgxJq
  SHA256   : Y3liGB6csF+XN5dlcw1GpxwmeOmy1med
             A0PIGSiYfOA=
  SHA512   : +znluvXK9aNeuBi4MgKFf3uUKzxK7m0g
             83ak6UTC+97QKBAiYlJi7fRKQgBA+1h4
             CGpahRs+5R0nkjzii0dSEw==


End timestamp: 2025-02-09 02:47:24 +0900 (run time: 1m 18s)

データベースファイルが作成されたら、データベースファイルの名前を変更します。

# mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz

整合性チェックの実行

改ざんをチェック(整合性チェック)を実行するときは、以下のコマンドを実行します。

実行結果は、画面に出力されるとともにログファイル「 /var/log/aide/aide.log 」に記録され、整合性に問題のあるファイルや、どのような問題(ファイルが作成された、ファイルが削除された、ファイルが変更された)があるのかを確認できます。

以下の結果画面では、Summary欄の「Add entries:」が「1」と表示されていることから、ファイルが追加されたことが分かります。また、その下には具体的にどのファイルが追加されたかを確認できます。

# aide --check

Start timestamp: 2025-02-09 02:53:16 +0900 (AIDE 0.16)
AIDE found differences between database and filesystem!!

Summary:
  Total number of entries:      52357
  Added entries:                1
  Removed entries:              0
  Changed entries:              0

---------------------------------------------------
Added entries:
---------------------------------------------------

f++++++++++++++++: /root/test.txt
:
:
省略

整合性チェックの定期実行

AIDEはリアルタイムに整合性チェックすることはできないので、整合性チェックを定期的に実行したいときは、整合性チェックを行うコマンドをcronなどで定期実行させる必要があります。

たとえば、整合性チェックを実行して結果をメール通知させたいときは、以下のようなシェルスクリプトを作成して、cronで定期実行するよう設定するとよいでしょう。

# vi /root/aide.sh

#!/bin/sh
AIDE=/usr/sbin/aide
HOSTNAME=`hostname`
MAILADDR=<送信先メールアドレス>
SUBJECT="AIDE Check Report: "
$AIDE -C | mail -s "$SUBJECT $HOSTNAME" \
-S v15-compat=yes \
-S mta=smtp://<ユーザー名>:<パスワード>@<SMTP サーバーホスト名>:<ポート番号> \
-S smtp-auth=login \
-S smtp-use-starttls \
-S from=<送信元メールアドレス> \
-S nss-config-dir=/etc/openldap/certs/ \
$MAILADDR
$AIDE --update
mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz

電子メールを送信するmailコマンドがシステムにインストールされていない時は、以下のコマンドでインストールできます。

# dnf install s-nail

以下では、上で作成したシェルスクリプトをcronで毎日午前4時に実行するよう設定しています。

# vi /etc/crontab

* 4 * * * root sh /root/aide.sh 2>&1

あとがき

小規模なLinuxサーバーで改ざんチェックを行いたいなら、AIDEを使った方法が導入や設定がそれほど難しくなくておすすめです。