概要・前提

Linux の棚卸作業は主に /etc/passwd/etc/shadow/etc/group/etc/sudoers の4ファイルと、lastloglast コマンドを組み合わせて行います。操作には root 権限(または sudo 実行権限)が必要です。

動作確認環境

  • RHEL / CentOS / Rocky Linux 7 〜 9
  • Ubuntu 20.04 / 22.04 / 24.04
  • Amazon Linux 2 / 2023

ユーザー一覧の取得

/etc/passwd にすべてのローカルユーザーが記録されています。フィールドは ユーザー名:パスワード:UID:GID:コメント:ホームディレクトリ:シェル の順です。

全ユーザー一覧(整形表示)

# UID / GID / ホームディレクトリ / シェルを整形して表示
awk -F: '{printf "%-20s UID=%-6s GID=%-6s HOME=%-25s SHELL=%s\n", $1,$3,$4,$6,$7}' /etc/passwd

ログインシェルを持つ(人間)ユーザーのみ抽出

# /sbin/nologin・/bin/false を除いた実ユーザー
grep -v -E ':/sbin/nologin$|:/bin/false$|:/usr/sbin/nologin$' /etc/passwd | awk -F: '{print $1, $3, $7}'

UID 1000 以上のユーザーのみ(一般ユーザー)

awk -F: '$3 >= 1000 {print $1, $3, $6, $7}' /etc/passwd

グループ別ユーザー一覧

# /etc/group の内容を表示(グループ名:GID:メンバーリスト)
awk -F: '{printf "GROUP=%-20s GID=%-6s MEMBERS=%s\n", $1,$3,$4}' /etc/group

ロック状態の確認

/etc/shadow のパスワードフィールドが !! または ! で始まるアカウントはロック状態です。passwd -S コマンドでも確認できます。

passwd コマンドで一覧確認

# 全ユーザーのステータスを確認(root 権限必要)
for user in $(awk -F: '{print $1}' /etc/passwd); do
  passwd -S "$user" 2>/dev/null
done

出力の第2フィールドの意味は以下のとおりです。

表示 意味
PSPassword Set(有効)
LKLocked(ロック済み)
NPNo Password(パスワードなし)

shadow ファイルを直接確認(ロック状態のみ抽出)

# !! または ! で始まるエントリ=ロックユーザー
sudo awk -F: '$2 ~ /^!/ {print "LOCKED:", $1}' /etc/shadow

usermod でロック/アンロック

# ロック
sudo usermod -L username

# アンロック
sudo usermod -U username

最終ログイン日時

lastlog コマンドは /var/log/lastlog を読み取り、各ユーザーの最終ログイン日時を返します。

全ユーザーの最終ログイン

lastlog

一度もログインしていないユーザーを除外

lastlog | grep -v 'Never logged in' | grep -v 'Username'

特定ユーザーの最終ログイン

lastlog -u username

直近のログイン履歴(last コマンド)

# 直近 50 件
last -n 50

# 特定ユーザー
last username

# 失敗ログイン(lastb は root 権限が必要)
sudo lastb -n 30

特権の確認

Linux の特権ユーザーは UID=0 の root が基本です。UID=0 を持つアカウントが複数存在しないか確認します。

UID=0 のアカウントを確認

awk -F: '$3 == 0 {print "UID=0:", $1}' /etc/passwd

root グループ(GID=0)のメンバー確認

grep '^root:' /etc/group

wheel グループ(管理者グループ)のメンバー確認

grep '^wheel:' /etc/group

su コマンドの実行権限確認

# /etc/pam.d/su で wheel グループ制限を確認
grep -E 'wheel|pam_wheel' /etc/pam.d/su

sudo 権限

/etc/sudoers および /etc/sudoers.d/ 配下のファイルに sudo 権限の定義があります。必ず visudo または cat で確認し、直接編集しないこと。

sudoers の内容を確認

# visudo -c で構文チェックも兼ねる
sudo visudo -c

# 内容を表示(root 権限必要)
sudo cat /etc/sudoers

sudoers.d ディレクトリ配下を一括確認

sudo ls -la /etc/sudoers.d/
sudo grep -r '' /etc/sudoers.d/

NOPASSWD 設定(パスワードなし sudo)を抽出

sudo grep -r 'NOPASSWD' /etc/sudoers /etc/sudoers.d/ 2>/dev/null

特定ユーザーの sudo 権限確認

# そのユーザー自身が実行(-l: list)
sudo -l -U username

パスワード期限

chage コマンドで各ユーザーのパスワードポリシーを確認します。/etc/shadow の第4〜8フィールドに対応しています。

特定ユーザーのパスワード期限情報

sudo chage -l username

全ユーザーのパスワード期限を一覧表示

for user in $(awk -F: '$3 >= 1000 {print $1}' /etc/passwd); do
  echo "=== $user ==="
  sudo chage -l "$user" 2>/dev/null
done

パスワード無期限(Max days = -1)ユーザーを抽出

sudo awk -F: '$5 == 99999 || $5 == -1 {print "NO EXPIRY:", $1}' /etc/shadow

パスワードポリシーのデフォルト値確認

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

一定期間未使用ユーザー

90日以上ログインのないユーザーを抽出する例です。lastlog の出力を日数で絞り込みます。

lastlog で 90 日以上未ログインを抽出

lastlog -b 90 | grep -v 'Never logged in' | grep -v 'Username'

一度もログインしたことがないユーザー

lastlog | grep 'Never logged in'

shadow の最終パスワード変更日から未使用を判定

# 第3フィールド:最終パスワード変更日(1970/01/01 からの日数)
# 現在の日数との差分を計算
TODAY=$(( $(date +%s) / 86400 ))
sudo awk -F: -v today="$TODAY" '
  $3 != "" && $3 != "0" {
    diff = today - $3
    if (diff > 90) printf "USER=%-20s LAST_PW_CHANGE=%s days ago\n", $1, diff
  }
' /etc/shadow

ホームディレクトリの最終アクセス日で判定

for user in $(awk -F: '$3 >= 1000 {print $1}' /etc/passwd); do
  homedir=$(getent passwd "$user" | cut -d: -f6)
  if [ -d "$homedir" ]; then
    atime=$(stat -c %X "$homedir")
    now=$(date +%s)
    days=$(( (now - atime) / 86400 ))
    if [ "$days" -gt 90 ]; then
      echo "UNUSED($days days): $user"
    fi
  fi
done

無効化されたユーザー

Linux でのユーザー無効化は主に ①パスワードロック ②ログインシェルを /sbin/nologin に変更 ③アカウント有効期限の設定 の3方式があります。

方式1:パスワードロック済みユーザー

sudo awk -F: '$2 ~ /^!/ {print "LOCKED:", $1}' /etc/shadow

方式2:nologin シェルのユーザー(サービスアカウント含む)

awk -F: '$7 ~ /nologin|false/ {print "NOLOGIN:", $1, $7}' /etc/passwd

方式3:アカウント有効期限切れのユーザー

# shadow 第8フィールド:アカウント有効期限(日数、空=無制限)
TODAY=$(( $(date +%s) / 86400 ))
sudo awk -F: -v today="$TODAY" '
  $8 != "" && $8 != "0" && $8+0 < today {
    print "EXPIRED:", $1, "(expired on day " $8 ")"
  }
' /etc/shadow

usermod でアカウント有効期限を設定・確認

# 有効期限を設定(例: 2025-12-31)
sudo usermod -e 2025-12-31 username

# 有効期限を削除(無制限)
sudo usermod -e "" username

# 設定確認
sudo chage -l username | grep 'Account expires'