深入解析 Linux /etc/shadow 文件:安全、结构与最佳实践

在 Linux 系统的安全体系中,用户密码的保护是至关重要的一环。你是否曾好奇,你的登录密码在系统中是如何被存储和管理的?答案就藏在一个名为 /etc/shadow 的文件里。这个文件是 Linux 影子密码套件的核心,它取代了旧时代所有用户都可读的 /etc/passwd 密码存储方式,极大地增强了系统的安全性。

本文将深入剖析 /etc/shadow 文件的每一个细节,包括其存在的必要性、文件格式、每个字段的含义、相关的管理命令,以及一系列确保系统安全的最佳实践。无论你是系统管理员、安全工程师,还是对 Linux 内部机制充满好奇的爱好者,这篇文章都将为你提供全面而深入的理解。

目录#

  1. 为什么需要 /etc/shadow?
  2. /etc/shadow 文件格式详解
  3. 密码哈希字段的深层解析
  4. 管理 /etc/shadow 的常用命令
  5. 安全最佳实践
  6. 故障排查示例
  7. 总结
  8. 参考引用

为什么需要 /etc/shadow?#

在引入 /etc/shadow 之前,用户加密后的密码哈希值直接存储在 /etc/passwd 文件中。而 /etc/passwd 文件需要对所有用户可读(权限为 644),因为许多系统工具(如 ls 需要将 UID 映射为用户名)都需要读取它。

这种设计带来了一个严重的安全问题:任何用户都可以获取到所有用户的密码哈希值。这使得暴力破解攻击变得非常容易。攻击者可以轻松地复制这些哈希,然后在自己的机器上不受限制地尝试破解。

为了解决这个缺陷,影子密码套件 被引入。其核心思想是:

  • 分离认证信息:将用户账户信息(用户名、UID、GID等)和认证信息(密码哈希值)分开存放。
  • 限制访问权限:账户信息保留在全局可读的 /etc/passwd 中,而敏感的密码哈希则被转移到只有 root 用户 才能读取的 /etc/shadow 文件中(权限通常为 640)。

这样一来,普通用户无法再轻易获取到密码哈希,极大地提高了暴力破解的难度,从而增强了系统的整体安全性。

/etc/shadow 文件格式详解#

让我们通过一个典型的 /etc/shadow 文件条目来理解其结构:

username:$y$j9T$8GMoJpI...$X1D2wq...:19617:0:99999:7:::

每个条目对应一个用户,由冒号 : 分隔成多个字段。以下是每个字段的详细解释:

  1. 用户名 (Username)

    • 对应 /etc/passwd 中的用户名。
  2. 加密后的密码 (Encrypted Password)

    • 这是最核心的字段。它存储的是用户密码经过哈希算法处理后的字符串。
    • 格式通常为 $id$salt$hash,其中 id 表示哈希算法。
    • 如果该字段为 *!,则表示该账户被锁定,无法使用密码登录。! 通常表示密码被 passwd -l 命令锁定。
  3. 最后一次密码修改时间 (Last password change)

    • 表示从 1970 年 1 月 1 日(纪元)到最后一次修改密码那天的天数。
    • 例如,19617 大约对应 2023 年 9 月 21 日。
    • 值为 0 表示用户下次登录时必须更改密码。
  4. 密码最小有效期 (Minimum password age)

    • 密码修改后,必须经过多少天才能再次修改。
    • 默认为 0,表示可以随时修改。设置为 7 则意味着修改密码后 7 天内不能再次修改。这可以防止用户快速改回旧密码。
  5. 密码最大有效期 (Maximum password age)

    • 密码多少天后过期,用户必须修改密码。
    • 例如 99999 天(几乎是 273 年)意味着密码永不过期。建议设置为 90180 等更合理的值以符合安全策略。
  6. 密码过期警告期 (Password warning period)

    • 在密码即将过期之前,提前多少天向用户显示警告信息。
    • 例如 7,表示在密码过期前 7 天开始警告用户。
  7. 密码过期宽限期 (Password inactivity period)

    • 密码过期后,仍然允许用户登录的宽限天数。在此期间,用户登录后会强制要求修改密码。
    • 如果超过这个宽限期密码仍未修改,账户将被完全锁定。
    • 如果此字段为空,则代表宽限期功能被禁用。
  8. 账户过期日期 (Account expiration date)

    • 指定一个绝对日期(同样以纪元天数表示),在此日期之后,账户将无法再登录,即使密码有效也不行。
    • 常用于临时账户。如果为空,则表示账户永不过期。
  9. 保留字段 (Reserved field)

    • 为未来使用而保留,目前为空。

密码哈希字段的深层解析#

密码字段 $y$j9T$8GMoJpI...$X1D2wq... 遵循 Modular Crypt Format (MCF),其中 $ 符号作为分隔符。

  • y哈希算法标识符。这是关键信息,常见的标识符有:

    • 1: MD5(已过时,不安全)
    • 2a/2y: Blowfish(bcrypt)
    • 5: SHA-256
    • 6: SHA-512(现代 Linux 发行版的默认算法
    • y: Yescrypt(一些最新发行版,如 Ubuntu 22.04+,开始采用的更抗 ASIC/GPU 破解的算法)
  • j9T盐值 (Salt)。一个随机生成的字符串,与用户密码组合后再进行哈希。盐值的作用是确保即使两个用户使用相同的密码,其哈希值也完全不同,从而防止彩虹表攻击。

  • 8GMoJpI...$X1D2wq...计算出的密码哈希值。这是将“密码+盐值”经过指定算法(包括多轮迭代)计算后的最终结果。

验证过程:当用户登录时,系统会取出该字段中的盐值,与用户输入的密码组合,使用相同的算法和迭代次数进行计算。如果计算结果与存储的哈希值匹配,则密码正确。

管理 /etc/shadow 的常用命令#

直接编辑 /etc/shadow 文件是危险且容易出错的。你应该始终使用以下专用命令来管理它:

1. passwd - 修改用户密码#

这是最常用的命令。

# 修改当前用户自己的密码
passwd
 
# root 用户修改其他用户的密码
sudo passwd username

2. chage - 更改密码过期信息#

chage(change age)命令是管理密码策略的强大工具。

# 查看用户密码过期信息
sudo chage -l username
 
# 交互式地设置所有策略
sudo chage username
 
# 设置密码 90 天后过期
sudo chage -M 90 username
 
# 设置账户在 2024-12-31 过期
sudo chage -E 2024-12-31 username
 
# 强制用户下次登录时修改密码
sudo chage -d 0 username

3. usermod - 锁定和解锁账户#

# 锁定账户(在密码字段前添加 `!`)
sudo usermod -L username
 
# 解锁账户
sudo usermod -U username

4. pwck - 检查影子文件的完整性#

该命令用于验证 /etc/passwd/etc/shadow 文件的一致性。

sudo pwck

安全最佳实践#

  1. 永远不要手动编辑 /etc/shadow:除非你非常清楚后果,否则总是使用 passwdchage 等高级命令。
  2. 使用强哈希算法:确保系统默认使用 SHA-512 或 Yescrypt 等强算法。可以通过查看 /etc/login.defs 中的 ENCRYPT_METHOD 变量来确认。
  3. 实施合理的密码策略
    • 设置密码最大有效期(如 90 天)。
    • 设置密码最小长度和复杂度要求(通过 pam_pwquality 模块实现)。
    • 禁止使用近期用过的密码(通过 pam_unixremember 选项实现)。
  4. 定期审核账户:使用 chage -l 检查系统账户(如 rootdaemon)是否被设置为密码过期,以及普通账户的过期状态。锁定所有不再使用的账户。
  5. 保护文件权限:定期检查 /etc/shadow 的权限是否为 640,所有者为 root:shadow
    ls -l /etc/shadow
    # 期望输出:-rw-r----- 1 root shadow
  6. 监控文件变更:使用诸如 aidetripwire 等完整性检查工具来监控 /etc/shadow 的未授权变更。

故障排查示例#

问题:用户 alice 无法登录,系统提示“密码错误”,但密码确认正确。

排查步骤

  1. 检查账户状态

    sudo chage -l alice
    • 查看密码是否已过期。
    • 查看账户是否已过绝对到期日。
  2. 检查账户是否被锁定

    sudo passwd -S alice
    # 或者查看 shadow 文件
    sudo grep alice /etc/shadow
    • 如果密码字段以 ! 开头,则账户被锁定。使用 sudo usermod -U alice 解锁。
  3. 检查 PAM 配置:如果上述都正常,问题可能出在 PAM 模块上(如超出最大登录尝试次数被临时锁定),需要检查 /etc/pam.d/system-auth/etc/pam.d/common-auth 等文件。

总结#

/etc/shadow 文件是 Linux 系统安全的基石之一。通过将敏感的密码哈希信息与公开的账户信息分离并严格限制访问权限,它有效地防御了离线的密码破解攻击。理解其文件格式、哈希原理以及正确的管理命令,对于任何一位系统管理员来说都是必备技能。遵循本文概述的最佳实践,将帮助你构建一个更坚固、更安全的 Linux 环境。

参考引用#

  1. shadow(5) - Linux 手册页: man 5 shadow
  2. passwd(1) - Linux 手册页: man 1 passwd
  3. chage(1) - Linux 手册页: man 1 chage
  4. crypt(3) - Linux 手册页: man 3 crypt(关于密码哈希格式)
  5. Linux PAM (Pluggable Authentication Modules) 文档
  6. Linux Foundation - Security Guides