ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Linux /etc/shadow 文件深度解析:密码安全与账号认证实战

Linux /etc/shadow 文件深度解析:密码安全与账号认证实战 有一次线上服务半夜报警登录认证大面积失败。我 SSH 进去试了一下密码明明是对的却被拒绝。后来一行一行看 /etc/shadow才发现某个系统账号的密码哈希前面不知什么时候多出了一个感叹号。一个符号让服务中断了十几分钟也让我重新意识到这个平时不太有人关注的文件其实是整个 Linux 认证体系里最关键的一环。简单说/etc/shadow 就是 Linux 专门用来保存用户密码摘要和密码策略的影子文件。它解决了早期 /etc/passwd 人人可读带来的安全问题。这篇内容我会从文件来历、9 个字段、哈希格式、实操修改密码策略到常见认证故障排查完整过一遍。不管你是刚接触 Linux 的新手还是每天都要碰服务器的运维读完都能直接上手使用。1. /etc/shadow 到底是什么——先弄懂它的定位1.1 shadow 文件与 passwd 文件的“分家”逻辑要理解 /etc/shadow得先回头看 /etc/passwd。早期 UNIX 系统把所有用户信息都写在 /etc/passwd 一个文件里用户名、UID、GID、家目录、登录 shell以及密码的加密结果全部并列存放。问题在于/etc/passwd 必须对所有用户开放读取因为很多命令要靠它把数字 UID 转换成用户名比如 ls -l 显示文件属主时普通用户执行也需要读这个文件。一个所有用户都能读的文件里面却保存着每个账号的密码哈希这就像把保险柜钥匙挂在门口。虽然保存的不是明文但早期加密算法相对较弱攻击者把哈希拖回去跑字典很容易撞出弱口令。于是后来系统做了拆分把密码哈希和密码策略信息单独放到 /etc/shadow 里/etc/passwd 对应的位置只留一个 x 占位表示“真正的密码不在这里”。我们可以用门锁来类比/etc/passwd 是门牌号任何人都能知道某某住在几零几/etc/shadow 是保险柜钥匙的保管记录只有锁匠能看。普通命令查用户基本信息走 /etc/passwd 就够了完全没有必要触碰密码哈希这类敏感数据。这个拆分的核心原则一直沿用到现在最小权限能不看就不看能不看就不暴露。1.2 权限模型为什么默认连普通用户都读不了默认情况下/etc/shadow 的所有者是 root属组是 shadow权限是 640rw-r-----。部分发行版也可能是 600 甚至 000但无论哪一种核心原则都一样只有 root 能读只有 root 能写。属组设置成 shadow是为了让少数需要读取密码信息的系统程序通过 group 方式获得读取权限而不是把整个文件开放给所有人。这里我要特别提醒一句很多安全问题不是因为系统设计不行而是有人手动把 /etc/shadow 的权限改成了 644 甚至 777。恢复默认权限的命令很简单chown root:shadow /etc/shadow chmod 640 /etc/shadow不过在部分系统上shadow 组的名称可能是 root 或其他执行前先看看 ls -l /etc/shadow 的输出别凭记忆强行对号入座。除了 shadow 本身同类的还有一个 /etc/gshadow它是群组密码的影子文件逻辑和 shadow 完全一样稍后排查群组问题时也会用上。2. 逐字段拆解 shadow 文件——9 列字段排序详解2.1 字段总览一行的 9 个位置分别放什么打开 /etc/shadow每一行代表一个用户账号各个字段用冒号分隔。以 root 用户为例常见的一行长这样root:$6$Abc123def...:19000:0:99999:7:::这一行里一共有 9 个字段顺序和含义可以整理成一张速查表字段位置含义常见值示例1用户名root2密码哈希或锁定标记$6$... 或 ! 或 *3最后一次修改密码的日期19000自 1970-01-01 起的天数4两次修改密码的最短间隔天数05密码有效期上限天数999996密码过期前多少天开始警告77密码过期后多少天禁用账号空或数字8账号失效日期空或数字9保留字段空我个人习惯是先记住一句话9 个字段、冒号分隔、密码在第 2 列。后面处理密码修改、账号锁定、登录失败等绝大多数问题都围绕这一列展开。第 3 到第 8 列则控制账号的生命周期状态平时用 chage 命令修改不需要手动去编辑数字。2.2 密码哈希串拆解算法标识、盐值与哈希值第 2 列是整个文件里最核心的内容。很多人第一次看到 $6$xxxxxxxx$yyyyy 这种字符串会发懵其实拆开看非常清晰第一个 $ 和第二个 $ 之间的数字表示加密算法第二个 $ 和第三个 $ 之间的部分是盐值salt最后一段是哈希值。常见的算法标识有这些标识算法建议$1$MD5不建议强度偏低$2a$ / $2y$Blowfish视场景选用$5$SHA-256一般$6$SHA-512很多系统的默认值$y$yescrypt新一代方案部分发行版已默认$argon2id$Argon2id安全性更优逐步普及盐值的作用是防止相同密码产生相同哈希。假设两个用户都把密码设成 Hello123不加盐的话哈希结果完全一样攻击者破解一次等于同时破两个账号。加了随机盐值之后即使密码一样最终哈希也完全不同攻击成本显著提高。这就像两个人设置了同样的行李箱密码但每把锁里都加了不同的内衬外部看起来就是两把完全不同的锁。实际操作中检查系统里有哪些账号还在用弱算法可以用一条命令扫出来awk -F: ($2 ~ /^\$1\$/) {print $1 : MD5 hash} /etc/shadow如果输出里出现了用户说明这些账号还在使用 MD5建议尽快安排改密让系统重新生成更安全的哈希。2.3 生命周期字段过期时间与状态联动第 3 到第 8 列都是和时间相关的字段但它们的值不是常见日期格式而是“从 1970-01-01 00:00:00 UTC 起算的天数”。系统内核用整数天数做比较更简单不需要解析各种日期格式。比如第 3 列为 19000大约对应 2022 年年初。要在 Linux 里把这个数字换算成可读日期可以这样date -d 1970-01-01 UTC 19000 days %F反推今天是第几天用这个echo $(( $(date -u %s) / 86400 ))第 3 列是密码最后修改时间passwd 修改密码后会自动更新。第 4 列是最短修改间隔0 表示随时能改密码7 就代表改完密码后 7 天内不能再改。第 5 列是密码有效期上限99999 表示近似永不过期。第 6 列是过期前警告天数第 7 列是密码过期后的宽限天数超过后账号被禁用。第 8 列是账号失效日期一旦到达账号直接无法登录和密码是否过期无关。理解这些字段后再看 chage 命令的输出就会非常通透。比如用户登录时提示 “password will expire”大概率就是第 5、6 列在起作用。3. 实操新建用户、改策略亲手读懂 shadow3.1 用 useradd 新建用户观察字段变化光看理论容易忘我建议你在测试虚拟机里跟着操作一遍。先创建一个测试用户useradd -m testuser grep testuser /etc/shadow执行 useradd 后testuser 会在 shadow 文件里出现一行但第 2 列通常是 ! 或 *表示密码尚未设置或者账号当前不允许直接登录。如果这时候尝试 ssh 登录 testuser会直接提示认证失败。接着设置密码passwd testuser输入两遍密码后再查看 shadowgrep testuser /etc/shadow第 2 列就会变成一长串以 $ 开头的哈希字符串第 3 列也会自动变成今天对应的天数。这个过程能很清楚地看到useradd 只负责创建账号框架真正“写入密码”的动作发生在 passwd 这一步两者对 shadow 文件的更新内容不一样。3.2 用 chage 调整密码策略验证字段联动chage 是专门管理密码生命周期字段的命令。比如想让 testuser 的密码 30 天内必须修改修改后最短 5 天才能再次修改提前 3 天开始警告执行chage -M 30 -m 5 -W 3 testuser再查看 shadow第 4、5、6 列就会分别变成 5、30、3。想查看完整策略用chage -l testuserchage -l 会把数字日期转换成人类可读格式方便确认。每次修改完策略我都会习惯性去 shadow 里核对一眼确认字段确实发生了变化这样排查问题时心里有底。chage 命令还有一个常用操作直接把账号失效日期设为指定日期chage -E 2026-12-31 testuser执行后第 8 列会出现一个大数字日期。这个机制很适合给临时外包账号设置访问期限到期自动失效不需要人工去删。3.3 手动编辑 shadow 的正确打开方式虽然 chage 和 passwd 能解决绝大多数需求但有时候确实需要手动改 shadow。比如想快速清除某个账号的密码哈希、手动加上锁定标记或者复制其他机器上的用户配置。Linux 提供了专门的编辑命令 vipw 和 vipw -s前者编辑 /etc/passwd后者编辑 /etc/shadow。vipw 会先锁定文件避免多方同时编辑冲突保存后还会提示你检查格式。如果你执意直接 vi /etc/shadow我强烈建议先备份再动手cp /etc/shadow /etc/shadow.bak vipw -s pwckpwck 会遍历所有账号检查字段数量、用户名是否存在、家目录是否有效等。这里最容易踩的坑有两个一是手动编辑时把冒号删掉或者多打了一个冒号导致整行解析失败二是复制粘贴哈希值时把末尾字符漏掉用户密码当场失效。这些坑我自己都踩过所以“改之前备份、改之后 pwck”这条底线从来没有破过。提示无论是在测试环境还是生产环境修改 shadow 之前都要先备份。编辑完千万别直接退出终端先开一个新窗口验证 root 用户还能不能登录再关旧窗口。这样可以避免“改完文件把自己锁在门外”的尴尬。4. 常见问题与排查技巧实录4.1 密码明明没错却登录失败先看第 2 列是不是有 !有一次线上服务一直报认证失败我排查之后发现/etc/shadow 里对应账号第 2 列的开头不知道什么时候多了一个感叹号。! 开头的哈希代表这个账号被锁定即使密码正确系统也会拒绝认证。产生感叹号的原因很多可能是被安全策略自动禁用也可能是管理员执行过 passwd -l。快速找出所有被锁定的账号awk -F: $2 ~ /^!/ {print $1, locked} /etc/shadow如果要解锁passwd -u testuser解锁前最好先确认这个账号是正常业务账号还是已经废弃的僵尸账号。很多时候这类小问题反而是系统里存在异常账号的信号比如某个离职员工的账号还留在服务器上应该直接删除而不是解锁。4.2 root 密码忘记怎么办这是运维群里最常被问的问题之一。如果你有物理机或虚拟机控制台权限通常可以在引导界面进入急救模式不同发行版叫法不同比如单用户模式、rescue 模式、emergency mode。进入后把根分区以可读写方式挂载再执行 passwd root 重置密码。关键细节在于急救模式下根文件系统通常默认只读挂载直接 passwd 会提示无法更新 shadow。需要先重新挂载为可读写mount -o remount,rw / passwd root有些发行版还需要先 chroot 到实际系统目录再执行 passwd。操作前确认系统有快照或备份万一过程中弄坏文件还能回滚。这个问题本质上是应急流程最好提前准备好操作手册别等到半夜再说。4.3 权限被改坏导致的异常有时候为了临时排查问题有人会把 /etc/shadow 的权限改成 644 甚至 777以为只是“看一下”。这样一来任何普通用户都能读取所有密码哈希前面所有安全设计全部白费。系统在安全检查时也可能报错。恢复权限的标准操作chown root:shadow /etc/shadow chmod 640 /etc/shadow不过正如前面说的不同发行版的属组名可能有差异先看 ls -l /etc/shadow 再定。权限问题本身不复杂难的是发现它建议把对 shadow 权限的检查加入到日常巡检脚本里。4.4 空密码和异常账号排查安全审计时空密码账号是重点关注对象。第 2 列为空的账号意味着可能不需要密码就能登录。现代发行版默认禁止空密码登录但如果有人改过 PAM 配置风险就会重新出现。检查命令awk -F: ($2 ) {print $1, no password} /etc/shadow另一个需要重点关注的是 UID 为 0 的账号。正常情况下 UID 0 只有 root如果 /etc/passwd 里出现其他账号也是 0说明系统里可能存在提权后门。检查命令awk -F: $3 0 {print $1, $6} /etc/passwd我见过有些攻击者会新增一个 UID 为 0 的隐藏账号来留后门这种账号往往不依赖 shadow 文件本身而是通过系统文件一致性问题绕过去所以日常审计绝不能只盯着影子文件看还要结合 passwd 一起排查。5. 安全加固建议从影子文件开始守住认证体系5.1 密码算法与强度检查/etc/shadow 的设计已经告诉我们密码哈希是敏感数据。第一道防线是权限第二道防线是密码哈希算法。如果发现系统里大量存在 $1$ 开头的 MD5 哈希那说明密码强度体系已经落后于当前安全要求需要安排用户改密。在 Debian 系系统里可以通过 /etc/pam.d/common-password 里的密码模块配置来指定哈希算法常见做法是设置 sha512 或 yescrypt。RHEL 系系统通过 authconfig 或相关的系统安全配置来调整。现代系统里我通常建议优先使用 yescrypt 或 Argon2id它们对 GPU 暴力破解的抵抗能力更强。判断某个用户的哈希算法grep ^testuser: /etc/shadow | cut -d: -f2 | cut -d$ -f2输出的数字就是算法标识可以和前面的速查表对照。 ### 5.2 建立密码生命周期策略 除了算法本身密码生命周期管理同样重要。/etc/login.defs 里有几个核心参数PASS_MAX_DAYS、PASS_MIN_DAYS、PASS_WARN_AGE分别控制密码最大有效天数、最短修改间隔、过期前警告天数。默认值往往是 99999等于不限制这对生产环境并不合适。 更合理的方式是结合 login.defs 和 chage 命令双层设置。login.defs 负责创建新用户时的默认策略chage 负责对已有账号逐个调整。比如把全局密码周期设置为 180 天 bash sed -i s/^PASS_MAX_DAYS.*/PASS_MAX_DAYS 180/ /etc/login.defs然后对重要账号做单独收紧。密码策略的本质是平衡安全性和易用性过短容易引发用户反感过长又会留下长期不变的弱口令风险180 天是很多企业环境里比较常见的折中值。5.3 定期审计与备份最后分享我自己的一个巡检习惯每隔两周做一次账号审计重点检查三件事。第一/etc/shadow 的权限是否是 640 或更严格第二有没有 UID 为 0 的异常账号第三第 2 列以 ! 或 * 开头的账号是否明确属于历史遗留该清理的坚决清理。备份方面不要把 /etc/shadow 单独备份到本机同一个磁盘分区否则磁盘损毁时备份也没有意义。我会在夜间任务里把 shadow、passwd、group 三个文件打包加密传到独立的存储位置保留最近 30 天版本。恢复的时候也要注意文件权限别从备份解压出来之后把权限弄丢了。我在实际工作中发现很多所谓的安全事故并不是攻击手段多高明而是最基础的文件权限、密码策略长期没人检查日积月累变成了漏洞。/etc/shadow 是很小的一个文件但它身后是整个系统的认证边界。抽出一下午时间把账号和密码策略完整梳理一遍比装十个安全软件更能让人睡得安稳。
返回列表