【ausearch】SELinuxのログの見方とトラブルシュート, 監査設定, リアルタイム表示~

auditd と audit.log

CentOS等のLinuxにおいて、audit.logを出力している『auditd』というデーモンが標準で動作しています。

これは『監査が必要なアクセスに対してログを取る』仕組みです。

監査とは何か問題が起きたときに犯人を捜す証拠となるようなものを残す仕組みのことで、例えば秘密の管理簿ファイルを監査する設定にしておけば、誰がその管理簿ファイルへアクセスしたかが後から分かるようになります。

デフォルトでは主にSELinuxによるアクセス制御sshアクセスcronによるアクセス等がログされるよう設定されていますが、例えば以下のような設定をすれば、そのファイルにアクセスするたびにログが生成されるため、『いつ誰がそのファイルを触ったか』といったことを後から知ることができます。

ausearch の使い方

audit.log は cat等で直接見てもタイムスタンプ時刻がUNIX-timeとなっていたりと色々と分かりにくいです。そのため、ausearchというコマンドが用意されています。

例えば

ausearch -i

というコマンドを打てば、audit.logおよびローテーションされたログを全て、時間やその他の属性値を人間に分かりやすい形で表示してくれます。

-i オプションは interpret(解釈)の略です。

結果からも分かる通り、このコマンドはaudit.logファイルに対してではなく、auditdに対してログ表示を要求します。

ですが以下のようにファイルを指定することもできます。

ausearch -i -if /var/log/audit/audit.log

auditd はログを非同期でDiskに書き込みます。つまり、ログすべき情報がある程度メモリ上に溜まった、もしくはある程度時間が経ったタイミングで、メモリからaudit.log(つまりhddやssd等)に書き込みます

コマンドを叩いた時点でメモリにあるログはそのままでは出力されません。ですが-lを付けることでメモリ上のログも出力できます。

ausearch -i -l

これは、auditdのログ用のメモリのバッファがブロックバッファ(ログ複数行)なのですが、このコマンドにより一時的にラインバッファ(ログ1行ずつ)に変わります。

ただし、昔はともかく、現在のflush(メモリキャッシュからディスクへ書き込み)方式はデフォルトで "INCREMENTAL_ASYNC" という方式になっており、ブロックバッファ上限に達しなくてもある時間が経過すればディスクに書き込むようになっています。そして、ある時間というのも人間の感覚しては差を認識できないくらいのごく短い時間であるため、-lオプションを付けることにあまり意味はありません。

ausearch をリアルタイムに見たいとき

ausearch を tail -f に渡すことはできませんが、逆に tailf で /var/log/audit.log を標準出力し、それを auserach にパイプラインで渡すことができます。

tailf /var/log/audit/audit.log | ausearch -i -l

SELinuxのログを抽出したい場合

SELinuxのログは他の監査ログと混ざった状態でaudit.logに出力されます。SELinux関連のログだけ抽出したい場合は -m オプション で avcを指定します。

ausearch -i -m avc

avc とは Access Vector Cache のことで、アクセス拒否される動作については繰り返し行われる可能性が高く、毎回SELinuxのポリシーを聞きに行ってしまうとパフォーマンスに影響が出ます。なのでパフォーマンス向上を目的としてキャッシュするわけです。

SELinuxでトラブルシュートを行うときは、permissiveにして確認するのも良いですが、以下を実行しながら再現させれば状況がリアルタイムに分かります。

tail -f /var/log/audit/audit.log | ausearch -i -l -m avc

SELinux に関するauditログの見方

SELinux は主にプロセスから Kernel へ System Call が発行されたタイミングでAVCと呼ばれる許可ルールキャッシュにより精査され、その System Call が実行許可 or 拒否されます。拒否された場合は例えば以下のように audit.log に "avc: denied" のエラーが出ます。

type=AVC msg=audit(2018年03月07日 01:01:53.995:344) : avc: denied { name_bind } for pid=12225 comm=sshd src=10022 scontext=system_u:system_r:sshd_t:s0-s0:c0.c1023 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket

scontext はプロセスのコンテキストです。プロセス名は comm= に書かれている通り、sshd ですので、sshd のコンテキストが [system_u:system_r:sshd_t:s0-s0:c0.c1023] であることが分かります。

tcontext はそのプロセスがアクセスしようとしているリソースのコンテキストです。リソースはファイル/ディレクトリが有名ですが、ネットワークリソース(TCP/UDPポート待ち受けやOutbound通信)もあります。

tclass は SELinux のパーミッションのオブジェクトクラスのことで、scontext が行おうとしている操作の種類です。tcp_socket とありますのでこれはリソースがTCPポートであることが分かります。そのうえで、src=を見ると10022 とありますので、tcontext  の主体は TCP:10022番ポートであり、このポートにコンテキスト [system_u:object_r:unreserved_port_t:s0] がラベルされていることが分かります。

{ } にあるのは tclass の種類に応じた、具体的なパーミッションの内容です。{ name_bind } とは『インタフェースでTCP/UDPのポートで待ち受け(バインド)する』ための権限です。

なので上記のケースでは、sshd が TCP:10022番ポートをListenしようとしたが、SELinux のルールにより拒否された、ということが分かります。

これを解消するためには以下のようにします。TCP:10022番ポートのコンテキストのタイプを unreserved_port_t から、ssh_port_t というタイプに変更するコマンドです。

# yum -y install policycoreutils-python
# semanage port -a -t ssh_port_t -p tcp 10022

ssh_port_t は元々TCP:22番ポートが含まれており、上記コマンドにより TCP:10022番ポートも追加されます。sshd_t という scontext から ssh_port_t という tcontext への name_bind は許可ルールが元から入っていますので、これでListen出来るようになるわけです。

SELinux の仕組みや許可ルール、パーミッションの種類等を基本から学びたい方は以下のページをご参照下さい。

【図解】SELinuxとは?〜仕組みやメリット・効果の基礎入門解説〜
【図解】SELinuxとは?〜仕組みやメリット・効果の基礎入門解説〜
SELinuxとは ~概要と仕組み~ SELinux とはSecure-Enh...

監査の設定の仕方と確認方法

デフォルトでは監査ルールは何も入っていません。

[root@localhost audit]# auditctl -l
No rules

以下の設定を入れることで

[root@localhost audit]# auditctl -w /etc/ssh/sshd_config -p warx -k sshd_config
[root@localhost audit]# auditctl -l
-w /etc/ssh/sshd_config -p rwxa -k sshd_config
[root@localhost audit]#

この設定により、/etc/ssh/sshd_config に関するコマンドが実行されるたびに監査ログが記録されます。例えば上記設定をした後、"# cat /etc/ssh/sshd_config" と打つとaudit.logには以下のように出力されます。

type=SYSCALL msg=audit(1521210470.616:549): arch=c000003e syscall=2 success=yes exit=3 a0=7fff120bb8e3 a1=0 a2=1fffffffffff0000 a3=7fff120b99e0 items=1 ppid=43178 pid=43390 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts1 ses=6 comm="cat" exe="/usr/bin/cat" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key="sshd_config"

type=CWD msg=audit(1521210470.616:549): cwd="/etc/audit"

type=PATH msg=audit(1521210470.616:549): item=0 name="/etc/ssh/sshd_config" inode=33964307 dev=fd:00 mode=0100600 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:etc_t:s0 objtype=NORMAL
type=PROCTITLE msg=audit(1521210470.616:549): proctitle=636174002F6574632F7373682F737368645F636F6E666967

1番目のtype=SYSCALL で始まるログは、SYSTEMCALLでcatコマンドを呼び出し、sshd_configを読み込んだことに対するログです。auid=1000 とあるので、uid=1000のユーザが読み込んだことが分かります。ausearch -i で読み込むと、このauid=1000もユーザ名に変換して表示してくれます。

2番目のtype=CWD は Currend Work Directory つまりどのディレクトリからコマンドを起動したかを記録しています。

最後のtype=PATHはアクセスしたファイル(sshd_config)のファイル情報です。

auditdの設定ファイル(デフォルト) と マニュアル

auditd の設定ファイルは "/etc/audit/auditd.conf" です。CentOS7.4のデフォルトでは以下のようになっています。

[root@localhost ~]# more /etc/audit/auditd.conf
#
# This file controls the configuration of the audit daemon
#
local_events = yes
write_logs = yes
log_file = /var/log/audit/audit.log
log_group = root
log_format = RAW
flush = INCREMENTAL_ASYNC
freq = 50
max_log_file = 8
num_logs = 5
priority_boost = 4
disp_qos = lossy
dispatcher = /sbin/audispd
name_format = NONE
##name = mydomain
max_log_file_action = ROTATE
space_left = 75
space_left_action = SYSLOG
action_mail_acct = root
admin_space_left = 50
admin_space_left_action = SUSPEND
disk_full_action = SUSPEND
disk_error_action = SUSPEND
use_libwrap = yes
##tcp_listen_port =
tcp_listen_queue = 5
tcp_max_per_addr = 1
##tcp_client_ports = 1024-65535
tcp_client_max_idle = 0
enable_krb5 = no
krb5_principal = auditd
##krb5_key_file = /etc/audit/audit.key
distribute_network = no
[root@localhost audit]#

シェアする

  • このエントリーをはてなブックマークに追加

フォローする