Linux のパスワードポリシーと攻撃の検知

サイバーセキュリティBeginner
オンラインで実践に進む

はじめに

この実験では、堅牢なパスワードポリシーを実装・適用し、Linux システムのセキュリティを強化するための基本的な手法を学びます。システム全体に適用されるルールを設定し、パスワードに最小文字数と、大文字・小文字・数字など複数種類の文字を組み合わせることを要求します。また、パスワードを定期的に変更させる有効期限ポリシーも設定します。これにより、システムの主要な設定ファイルを変更し、漏えいしたパスワードによるリスクを低減できます。

ポリシーを定めるだけでなく、新しく作成するユーザーアカウントにも強力なパスワード要件が適用されることを確認します。その後は予防的なセキュリティ対策から事後的な検知へ進み、システムの認証ログを監視する方法を学びます。ログを分析することで、総当たり攻撃やその他の不正アクセスの試みを示す可能性がある、連続したログイン失敗などの不審な活動を特定できるようになります。

Linux のパスワード複雑性と有効期限に関するローカルポリシーを設定する

このステップでは、堅牢なパスワードポリシーを設定して Linux システムのセキュリティを強化する方法を学びます。強力なパスワードポリシーは、複雑性有効期限という 2 つの重要な側面を適用する、基本的なセキュリティ制御です。複雑性のルールでは複数種類の文字を組み合わせるよう求めることで、パスワードを推測されにくくします。一方、有効期限のルールではパスワードを定期的に変更させ、認証情報が漏えいした場合のリスクを低減します。ここでは、標準的な Linux ユーティリティを使用してシステム全体の設定ファイルを変更し、これらのポリシーを適用します。

まず、パスワードの複雑性について確認しましょう。Ubuntu などの最新の Debian 系システムでは、パスワード品質は pam_pwquality モジュールによって管理されます。その設定は /etc/security/pwquality.conf ファイルに保存されています。

デフォルト設定を確認してみましょう。cat コマンドで設定ファイルの内容を表示します。ここでは grep を使ってコメント行と空行を除外し、見やすくします。

grep -vE '^#|^$' /etc/security/pwquality.conf

デフォルト設定がいくつか表示される場合もあれば、有効な設定が何もないためファイルが空に見える場合もあります。次に、より強力なポリシーを適用します。このファイルの編集には管理者権限が必要なため、nano エディターを sudo とともに使用します。

sudo nano /etc/security/pwquality.conf

ファイルに次の行を追加して、新しいポリシーを適用します。これらの設定により、パスワードは 10 文字以上で、少なくとも数字 1 文字、大文字 1 文字、小文字 1 文字を含む必要があります。また、管理者が別のユーザーのパスワードを設定する場合にもチェックが適用されます。

minlen = 10
dcredit = -1
ucredit = -1
lcredit = -1
enforce_for_root

各オプションの意味を確認しましょう。

  • minlen = 10: パスワードの最小文字数を 10 文字に設定します。
  • dcredit = -1: 数字を少なくとも 1 文字含めるよう要求します。負の値は「少なくとも 1 つ」を意味します。
  • ucredit = -1: 大文字を少なくとも 1 文字含めるよう要求します。
  • lcredit = -1: 小文字を少なくとも 1 文字含めるよう要求します。
  • enforce_for_root: 管理者が品質チェックに失敗したパスワードを強制的に受け入れることを防ぎます。sudo adduser は root 権限で新規ユーザーのパスワードを設定するため、この設定が必要です。

行を追加したら、Ctrl+XYEnter の順に押してファイルを保存し、nano を終了します。

次に、パスワードの有効期限を設定します。これらの設定では、パスワードを使用できる最長期間と、変更間隔の最短期間を定義します。新規ユーザーアカウントに適用されるデフォルト値は /etc/login.defs に保存されています。

grep を使用して、このファイル内の関連設定を確認します。

grep -E 'PASS_MAX_DAYS|PASS_MIN_DAYS|PASS_WARN_AGE' /etc/login.defs

デフォルト値が表示されます。多くの場合、PASS_MAX_DAYS には非常に大きな値が設定されており、実質的に有効期限が無効になっています。

##       PASS_MAX_DAYS   Maximum number of days a password may be used.
PASS_MAX_DAYS   99999
##       PASS_MIN_DAYS   Minimum number of days allowed between password changes.
PASS_MIN_DAYS   0
##       PASS_WARN_AGE   Number of days warning is given before a password expires.
PASS_WARN_AGE   7

ここでは、9,000 日でパスワードが期限切れになるポリシーを設定します。sudo nano でファイルを開きます。

sudo nano /etc/login.defs

PASS_MAX_DAYS の行を探し、値を 99999 から 9000 に変更します。また、ユーザーが短期間に何度もパスワードを変更するのを防ぐため、PASS_MIN_DAYS7 に設定することもできます。

##       PASS_MAX_DAYS   Maximum number of days a password may be used.
PASS_MAX_DAYS   9000
##       PASS_MIN_DAYS   Minimum number of days allowed between password changes.
PASS_MIN_DAYS   7
##       PASS_WARN_AGE   Number of days warning is given before a password expires.
PASS_WARN_AGE   14

ファイルを保存して nano を終了します。/etc/login.defs の設定は、この変更後に作成されるユーザーに適用されます。既存のユーザー(ここでは labex ユーザー)にポリシーを適用するには、chage コマンドを使用します。

まず、labex ユーザーの現在の有効期限情報を確認します。

sudo chage -l labex

パスワードが無期限になっていることが表示されます。

Last password change                                    : Jul 22, 2023
Password expires                                        : never
Password inactive                                       : never
Account expires                                         : never
Minimum number of days between password change          : 0
Maximum number of days between password change          : 99999
Number of days of warning before password expires       : 7

次に、chage-M オプションを使用して、labex ユーザーの最長使用日数を 9000 に設定します。

sudo chage -M 9000 labex

もう一度ユーザーの有効期限情報を確認し、変更を検証します。

sudo chage -l labex

Password expires の日付が更新され、最長使用日数が 9000 日に設定されていることを確認できます。これで、有効期限ポリシーが正常に適用されました。

Last password change                                    : Jul 22, 2023
Password expires                                        : Jan 01, 2048
Password inactive                                       : never
Account expires                                         : never
Minimum number of days between password change          : 0
Maximum number of days between password change          : 9000
Number of days of warning before password expires       : 7

これで、Linux システムのパスワード複雑性ポリシーと有効期限ポリシーの両方を正常に設定できました。

新規ユーザーアカウントに強力なパスワードを適用する

このステップでは、前のステップで設定したパスワードの複雑性ポリシーと有効期限ポリシーが、新規ユーザーアカウントに適用されることを確認します。最も分かりやすいテスト方法は、新しいユーザーを作成し、ルールに違反するパスワードを設定してみることです。これにより、pam_pwquality モジュールとシステムのデフォルト設定が連携し、アカウント作成時から新しいアカウントを保護する仕組みを確認できます。

Debian 系システムでユーザーを作成する際は、対話形式で操作できる使いやすいスクリプトである adduser コマンドを使用します。testuser という名前の新しいユーザーを作成しましょう。

sudo adduser testuser

システムから新しいユーザーのパスワードを設定するよう、すぐに求められます。ここでポリシーが検証されます。

まず、ポリシーに違反する単純で弱いパスワードを設定してみます。新しいパスワードの入力を求められたら、password と入力して Enter を押します。

Adding user `testuser' ...
Adding new group `testuser' (1001) ...
Adding new user `testuser' (1001) with home directory `/home/testuser' ...
Copying files from `/etc/skel' ...
New password:

password は短すぎ、大文字や数字も含まないため、ルールに違反します。そのためシステムに拒否されます。表示されるメッセージは環境によって異なりますが、BAD PASSWORD で始まり、再度パスワードの入力を求められます。

BAD PASSWORD: The password fails the dictionary check
New password:

このパスワードは複数のルールに違反していますが、システムは再入力を求める前に、そのうち 1 つの理由を表示します。

警告が表示されるだけで、必ずしも拒否されたとは限りません。コマンドが再度パスワードの入力を求めた場合に、拒否されたことが分かります。ステップ 1 で追加した enforce_for_root 設定により、特権で実行される adduser プロセスでも弱いパスワードは受け入れられません。

ヒント: 誤ってユーザーを作成した場合は、sudo deluser testuser を使用してユーザーを削除し、もう一度やり直せます。

次に、すべての条件を満たすパスワードを入力します。入力を求められたら N7vQ2mR9xK4p と入力して Enter を押します。確認のため、同じパスワードをもう一度入力します。

New password:
Retype new password:
passwd: password updated successfully

成功です。強力なパスワードが受け入れられました。続いて、ユーザーに関する追加情報の入力を求められます。各項目で Enter を押し、デフォルト値をそのまま使用できます。

Changing the user information for testuser
Enter the new value, or press ENTER for the default
        Full Name []:
        Room Number []:
        Work Phone []:
        Home Phone []:
        Other []:
Is the information correct? [Y/n] Y

これで testuser ユーザーが作成されました。id コマンドを使用して、ユーザーが存在することを確認できます。

id testuser

ユーザー ID、グループ ID、所属グループが表示されます。

uid=1001(testuser) gid=1001(testuser) groups=1001(testuser)

次に、/etc/login.defs で設定したパスワードの有効期限ポリシーが、この新しいユーザーに自動的に適用されたことを確認します。chage コマンドで testuser の有効期限情報を表示します。

sudo chage -l testuser

Maximum number of days between password change が、設定どおり 9000 になっていることを確認できます。

Last password change                                    : Jul 22, 2023
Password expires                                        : Jan 01, 2048
Password inactive                                       : never
Account expires                                         : never
Minimum number of days between password change          : 7
Maximum number of days between password change          : 9000
Number of days of warning before password expires       : 14

最後に、システムを整理するため、テストユーザーを削除します。deluser コマンドでユーザーアカウントを削除できます。

sudo deluser testuser

ユーザーが削除されたことを示す確認メッセージが表示されます。

Removing user `testuser' ...
Warning: group `testuser' has no more members.
Done.

これで、新しいユーザーの作成、パスワードポリシーの適用テスト、デフォルトの有効期限ルールの確認が完了しました。

認証ログを監視してログイン失敗を検知する

このステップでは、総当たり攻撃などの潜在的なセキュリティ脅威を検知するため、システムの認証ログを監視する方法を学びます。システム管理では、ログを定期的に確認して不審な活動を見つけることが重要です。ログイン失敗は、不正アクセスの試みを示す重要な指標です。ここでは、意図的にログインを失敗させ、その後、標準的な Linux コマンドを使って対応するログエントリを検索・分析します。

Ubuntu などの Debian 系システムでは、認証イベント(成功・失敗の両方)が通常 /var/log/auth.log ファイルに記録されます。このファイルを読むには管理者権限が必要です。

まず、ログイン失敗を発生させます。su(ユーザー切り替え)コマンドを使用して、自分自身のユーザーアカウントである labex への切り替えを試みますが、意図的に間違ったパスワードを入力するため、安全に実行できます。

su labex

パスワードの入力を求められます。wrongpassword のような誤ったパスワードを入力して Enter を押します。

Password:
su: Authentication failure

失敗のパターンを作るため、もう一度実行します。

su labex

再度、間違ったパスワードを入力します。これでログデータが生成されたので、認証ログファイルを確認しましょう。sudotail コマンドを使って /var/log/auth.log の末尾数行を表示します。ここには最新のイベントが記録されています。

sudo tail /var/log/auth.log

失敗した su の試行に関連する新しい行がいくつか表示されます。出力には、タイムスタンプ、プロセス(su)、失敗メッセージが含まれます。

Jul 22 16:45:01 labex-vm su[12345]: pam_unix(su:auth): authentication failure; logname=labex uid=1000 euid=0 tty=/dev/pts/0 ruser=labex rhost=  user=labex
Jul 22 16:45:01 labex-vm su[12345]: FAILED SU (to labex) labex on /dev/pts/0
Jul 22 16:45:15 labex-vm su[12346]: pam_unix(su:auth): authentication failure; logname=labex uid=1000 euid=0 tty=/dev/pts/0 ruser=labex rhost=  user=labex
Jul 22 16:45:15 labex-vm su[12346]: FAILED SU (to labex) labex on /dev/pts/0

ログを手作業で検索すると時間がかかります。より効率的な方法は、grep で特定のキーワードに絞り込むことです。ここでは、authentication failure を含むすべての行を検索します。

sudo grep "authentication failure" /var/log/auth.log

このコマンドを実行すると、パターンに一致する行だけが表示されるため、先ほど発生させたログイン失敗を簡単に確認できます。

次に、この監視処理を自動化する簡単なシェルスクリプトを作成します。このスクリプトはログ内の失敗を確認し、集計結果を表示します。~/project ディレクトリで、nano を使用して log_monitor.sh という新しいファイルを作成します。

nano log_monitor.sh

エディターに次の Bash スクリプトを入力します。このスクリプトは grep-c オプションを使ってログイン失敗の件数を数え、その後、状態メッセージを表示します。

#!/bin/bash

LOG_FILE="/var/log/auth.log"
FAILURE_COUNT=$(sudo grep -c "authentication failure" $LOG_FILE)

echo "--- Authentication Log Monitor ---"
if [ "$FAILURE_COUNT" -gt 0 ]; then
  echo "WARNING: Found $FAILURE_COUNT failed login attempts."
else
  echo "OK: No failed login attempts found."
fi
echo "--------------------------------"

Ctrl+XYEnter の順に押してファイルを保存し、nano を終了します。

次に、chmod コマンドを使用して新しいスクリプトを実行可能にします。

chmod +x log_monitor.sh

最後に、監視スクリプトを実行して結果を確認します。

./log_monitor.sh

ログイン失敗を発生させているため、スクリプトはそれらを検知し、正確な件数とともに警告を表示します。

--- Authentication Log Monitor ---
WARNING: Found 2 failed login attempts.
--------------------------------

これで、認証失敗をシミュレート、検知し、基本的な監視スクリプトを作成する方法を学びました。これは、システムのセキュリティを維持するうえで重要なスキルです。

まとめ

この実験では、堅牢なローカルパスワードポリシーを設定して Linux システムのセキュリティを強化する方法を学びました。pam_pwquality モジュールを使用してパスワードの複雑性ルールを適用するため、/etc/security/pwquality.conf ファイルを変更しました。具体的には、パスワードの最小文字数を設定し、数字・大文字・小文字をそれぞれ少なくとも 1 文字含めることで、推測されやすい認証情報からシステムを保護しました。

さらに、新しいユーザーアカウントの作成時に、これらの強力なパスワードポリシーが適用されることを確認しました。また、システムの認証ログを監視してセキュリティイベントを検知・分析する重要なスキルも学びました。連続したログイン失敗などのイベントは、潜在的な攻撃を示す可能性があります。