
忘了Linux root密码这件事我每年总要处理那么几回。有的是客户服务器交接时原管理员离职没留下密码有的是自己折腾虚拟机实验忘了改回密码还有的是云主机密钥丢了只能干瞪眼。标题里的“密码破解”听着很黑客实际操作起来大部分场景就是合法地帮系统“找回”密码。这篇文章我会从基础的单用户模式到救援磁盘、内核传参、甚至是全盘加密的情况把主流方案和背后的原理一次讲清楚。先说一个底线概念这篇文章讨论的是自己拥有设备所有权或者已经获得对方明确授权的密码恢复场景。真正的“破解”也仅限于对已知的加密文件做口令恢复比如自己加密的压缩包、共享文件的口令测试。超过这个边界的用途不在讨论范围内。搞清楚边界再看下面这些操作就不会跑偏。1. 先搞懂Linux密码存在哪才知道要从哪里下手1.1 shadow文件的字段结构Linux把用户信息拆成两部分/etc/passwd负责存放用户名、UID、家目录这些“明面”信息/etc/shadow存放加密后的密码串。shadow文件只有root能读普通用户连看的权限都没有。这就是为什么破解密码的核心路线本质上是想办法获得root权限然后重新设置密码或者修改shadow文件。shadow每一行用冒号分成若干字段对恢复密码有用的是前两个root:$6$saltvalue$hashedpassword:19000:0:99999:7:::第一个字段是用户名第二个字段是加密后的密码串。$6$表示SHA-512加密$y$是yescrypt$2b$是bcrypt。如果这个位置只有!或者*代表账号被锁定或者没有密码直接删除这个字段内容就能让用户免密登录。理解了这一点你就能明白网上那些“删除密码字段”的操作到底在改什么。1.2 为什么“破解”通常是“重置”对shadow的加密串做暴力破解技术上可行但代价极大。SHA-512在现代GPU上虽然跑得动但一个足够复杂的密码大小写数字符号12位以上几乎不可能穷举。所以实际运维中99%的“忘记密码”场景走的是重置——绕开密码验证在命令行为系统中重新设置一个新密码。这比破解高效得多也是下面所有方案的核心思路。涉及暴力破解的场景只有一种我偶尔会碰压缩包口令忘了配合字典或掩码还能抢救一下。系统层面的口令暴力破解说实话现实里几乎没有运维会去做性价比太低。2. 开始破解前先评估你的现场属于哪种类型2.1 按系统类型和启动方式分类不同发行版、不同启动方式能用的方案差别很大。先看一张分类表场景类型典型环境推荐方案难度GRUB可交互物理机、虚拟机开机能看到引导菜单单用户模式 / init/bin/bash简单系统损坏root密码丢失服务器起不来但手上有安装介质救援模式 chroot中等RHEL系TPMCentOS/RHEL 7/8/9新装系统rd.break 强制切换中等磁盘全盘加密安装了LUKS加密的笔记本/服务器只能恢复密钥无法绕过困难云服务器无物理控制台只有远程SSH控制台VNC 单用户模式依赖厂商2.2 先检查有没有全盘加密我建议在任何密码恢复操作之前先确认磁盘是否用了LUKS加密。判断方法很简单开机时如果出现类似Please unlock disk sda5_crypt的界面那就说明分区加密了。一旦是LUKS加密恭喜你面前就是一座铁壁。不管是单用户模式还是chroot最终都要先解开加密层。而解密的密钥就是你的密码密码丢了等价于密钥丢了。这时候唯一可行的路子是回忆密码、用键盘布局排查有没有大小写错位或者查看当时备份的LUKS密钥文件。我这边的建议是遇到LUKS环境别硬刚把时间花在回忆密码上反而更现实。2.3 云服务器的特殊情况云服务器通常没有物理光驱和U盘启动的选项但大多数厂商提供VNC或Web终端控制台可以模拟物理键盘操作。只要能在开机过程中进入GRUB界面下面提到的单用户模式方法就依然适用。需要注意的是部分云平台开启了安全启动这会阻止init/bin/bash这类内核参数生效需要在引导界面临时关闭或通过平台配置调整。3. 实操方案一GRUB单用户模式改密码3.1 Ubuntu/Debian系的操作步骤这是最简单的一种适合Ubuntu、Debian、Mint等使用GRUB的系统在虚拟机里就能练习。重启系统在GRUB菜单出现时按e进入编辑模式。找到以linux开头的那一行这一行指定了内核镜像和启动参数在行尾加一个空格然后追加init/bin/bash再按CtrlX或F10启动系统此时系统不会进入正常登录流程而是直接给你一个root shell。然后挂载根分区为可写状态。mount -o remount,rw /对于Ubuntu 22.04之后的版本挂载后可能还需要处理一下SELinux或者AppArmor不过这些默认状态下不会挡路。接下来直接修改密码passwd root输入两遍新密码即可。如果还想顺便解锁其他账号passwd 用户名最后重启exec /sbin/init 或 reboot -f需要说明的是如果系统有systemd且使用了init/bin/bash可以用exec /sbin/init回到正常启动流程也可以直接强制重启对密码修改不会有影响。3.2 RHEL/CentOS系的single参数CentOS 7/8、RHEL、Rocky Linux等红帽系系统的操作略有不同。同样在GRUB界面按e找到linux16或linux开头的那一行在行尾追加single或者更通用的systemd.unitrescue.target启动后进入单用户模式同样是root shell。此时根分区可能是只读的需要执行mount -o remount,rw /然后修改密码或增加新用户。红帽系系统通常开启了SELinux修改shadow文件后如果遇到SELinux权限问题可以先touch /.autorelabel触发下次开机自动修复标签。3.3 为什么这个方案有效内核参数传递的底层逻辑这套方案能生效主要利用的是Linux内核参数机制。initxxx告诉内核启动后要执行的第一个用户态程序是/bin/bash而非systemd。内核把shell当作PID 1直接运行这个环节发生在用户身份校验之前因此拥有root权限。但要注意两点。第一如果你在系统启动到GRUB时看不到菜单需要开机时按住ShiftBIOS模式或狂按EscUEFI模式。第二如果启用了GRUB密码保护按e时会要求输入GRUB管理员密码那就需要回到第2.2节提到的“真有密码才有得谈”环节。另外我个人习惯在虚拟机里用这个方法之前先给虚拟机做一个快照万一输错参数导致系统起不来还能秒回恢复。4. 实操方案二救援模式chroot重置密码4.1 用安装U盘进入Live环境如果系统已经损坏到无法进入GRUB或者你用的是云主机但不支持修改内核参数就需要使用安装介质进入救援模式。准备一个同发行版的系统U盘开机选择“Try Ubuntu”或“Rescue a broken system”这类入口进入临时系统环境。进入Live桌面后打开终端先用lsblk和fdisk -l确认Linux系统盘的标识。sudo fdisk -l假设系统盘是/dev/sda1先挂载根分区到/mntsudo mount /dev/sda1 /mnt如果存在独立的/boot分区也需要一并挂载但对于改密码来说不必须。接着需要挂载一些虚拟文件系统让chroot环境下的命令能正常工作sudo mount --bind /dev /mnt/dev sudo mount --bind /proc /mnt/proc sudo mount --bind /sys /mnt/sys4.2 chroot切根后修改密码现在切根到目标系统sudo chroot /mnt /bin/bash进入之后你的shell看起来变了实际上文件系统根已经切换到了目标系统。先检查一下挂载是否正常df -h mount | grep /mnt然后直接修改密码passwd rootchroot环境可以看作是“在外面把目标系统的手术室搭好然后走进去动手术”。这个方法比单用户模式更稳定因为不会受到当前系统的服务启动状态影响而且能修的远不止密码比如grub-install修复引导、apt修复依赖、编辑fstab误配置等都可以在这里一并处理。实际救援过程中有两点经验一是挂载顺序别乱dev/proc/sys不挂载的话很多命令会报错二是改完密码后如果想确认有没有生效可以用grep root /etc/shadow看看第二个字段有没有从!或x变成一串新的哈希值。4.3 不用chroot也可以用systemd-shell对于RHEL系系统可以不依赖外部介质在GRUB界面追加rd.break启动后会自动break进入dracut环境的shell此时物理根分区还未被挂载。你需要找到根分区设备通常是/dev/mapper/或者/dev/sda2之类的路径手动挂载mount -o remount,rw /sysroot chroot /sysroot然后执行passwd root完成修改。这个方案的原理和chroot一致只是把救援环境从外部U盘搬到了系统自身的内置initramfs里。dracut环境的可用命令有限但vi和mount这些基础工具还是有的操作时多留意提示切根成功后再改密码是最稳妥的顺序。5. 实操方案三修改shadow文件直接清空密码5.1 手动编辑shadow的步骤如果你已经在root shell环境下还有一种比passwd更暴力的方法直接编辑shadow文件清空密码字段。vi /etc/shadow找到目标用户那行把第二个字段第一个冒号和第二个冒号之间的内容全部删除只保留前后两个冒号root::19000:0:99999:7:::保存退出。此时这个用户就没有密码登录时直接回车就能进入系统。进入系统后立刻执行passwd root设置新密码否则系统处于无密码状态安全上是不允许长期持续的。提示清空密码字段在Ubuntu上的效果是确实免密登录但在部分系统上如果PAM配置了nullok以外的策略可能不允许空密码登录。遇到这种情况建议还是老老实实passwd设置密码。5.2 为什么这个方法适合批量处理一次性要重置多台服务器、多个用户密码时passwd一个个交互执行效率太低。可以先在脚本里生成密码哈希值然后批量替换shadow字段openssl passwd -6 -salt SALT 你的新密码拿到输出的哈希串后用sed批量处理多台主机sed -i s|^root:.*:|root:哈希串:| /etc/shadow这样做的好处是脚本可以写成循环配合Ansible或expect批量执行省去了每台机器手工交互的麻烦。这里唯一的坑是哈希串里的$符号是正则表达式特殊字符用sed时最好把分隔符换成|避免转义地狱。6. 如果没有物理接触已知哈希的离线破解6.1 提取哈希和基本思路有的场景是如果你手上已经拿到了一份shadow文件或者数据库备份不需要在目标机器上做任何操作只想离线验证某些弱密码是否存在这时候可以用hashcat或John the Ripper这类工具。以hashcat为例先确认哈希格式是$6$开头对应hashcat的模式编号1800sha512crypthashcat -m 1800 shadow哈希值 字典.txt也可以配合掩码规则hashcat -m 1800 -a 3 shadow哈希值 ?u?l?l?l?l?d?d?d纯数字或纯小写字母的密码在GPU下可以很快跑完但复杂密码只能碰运气。**我实际测过8位小写数字混合的密码一张普通显卡几分钟到几十分钟就能出结果但12位随机大小写混合就要按年来计算了。**所以在离线破解场景中目标通常不是“破解”而是“验证弱口令”这属于安全审计的范畴。6.2 字典的选择与定制网上可以找到很多现成字典但真正好用的字典是要结合目标场景定制的。比如目标客户是某工厂的生产管理系统那么拼音缩写、企业名称、年份数字组合的命中率会显著高于通用字典。我通常的做法是把通用字典里的高频词弱密码Top1000拉出来再结合域名、公司名、常见数字模式做规则扩展最后用hashcat的规则引擎跑一遍hashcat -m 1800 shadow哈希 基础字典 -r 规则文件.rule规则文件是hashcat的灵魂一条$1$2$3规则表示在密码末尾追加123一条c规则表示首字母大写。这些规则非常实用有空值得深入研究一下。7. 常见问题与踩坑实录7.1 SELinux导致chroot后无法登录在RHEL系系统中chroot改完密码后可能遇到SELinux标签错乱的问题。表现为新密码设置成功但登录时仍然被拒绝或者报SELinux is preventing...错误。解决办法是在chroot环境里创建autorelabel标记touch /.autorelabel这样重启后系统会自动重新标记全部文件的SELinux上下文。还有更彻底的方案是修改/etc/selinux/config里的SELINUXdisabled但我个人不推荐这种“关安全换便利”的做法除非是应急场景。7.2 GRUB菜单不显示有些新装系统默认不显示GRUB菜单而是直接启动。这种情况下修改内核参数需要开机时按住Shift老式BIOS或狂按EscUEFI只要看到GRUB界面就成功了。还有一点容易被忽略**物理机和虚拟机在处理按键时时机不一样虚拟机可以试试在开机动画出现前一直按住。**如果实在进不去GRUB就用4.1节的外部介质方案绕路。7.3 修改密码后无法解析主机名改完密码重启有可能会出现类似sudo: unable to resolve host的报错。这个不是改密码造成的而是/etc/hosts里主机名没有对应到本机IP。顺手在/etc/hosts里加一行127.0.1.1 你的主机名就能解决。这个故障经常被误认为是密码改坏了实际是两个独立问题碰巧同时在同一个维护窗口里发生。7.4 虚拟机Ubuntu修改密码后时间漂移使用单用户模式登录后系统时钟可能因为失去NTP同步而漂移改完密码回到正常系统时时间不对会导致证书校验失败、日志记录混乱。解决办法是正常系统启动后执行一次sudo timedatectl set-ntp true sudo systemctl restart systemd-timesyncd这些都是小细节但往往就是这些细节决定了一次维护是顺利收工还是折腾到半夜。8. 密码恢复后的安全加固建议8.1 防患于未然的GRUB密码既然能从GRUB进入单用户模式那么任何能碰到物理键盘的人都能重置root密码这意味着物理接触等于拥有最高权限。要挡住这个口子可以给GRUB本身设置密码验证。在/etc/grub.d/00_header或者专门配置文件里生成PBKDF2哈希grub-mkpasswd-pbkdf2然后把生成的哈希写入/etc/grub.d/40_custom更新GRUB配置update-grub这样按e修改启动参数时就要先输入GRUB管理员密码。这个措施和BIOS密码是两层防线也是物理安全的最佳实践。8.2 给Linux系统增加一层全盘加密如果你工作的环境对数据安全要求比较高强烈建议在安装系统时启用LUKS全盘加密。虽然代价是每次开机都要输密码但带来的安全感完全值得。全盘加密之后单用户模式和chroot这些密码恢复方案全部失效暴力破解也无从谈起。唯一的风险还是密钥管理。密钥丢失就是数据彻底丢失所以安装时要备份LUKS头信息和密钥文件cryptsetup luksHeaderBackup /dev/sda --header-backup-file header-backup.img8.3 养成好的密码管理习惯最后这个建议是给所有运维老哥的个人密码库一定要做好分级管理。我自己用KeePassXC管理服务器密码每台机器密码独立且随机生成长度不低于16位。这样即使一台机器泄露不会连带到其他机器。同时开启密码历史审计定期刷新一次高权限账号口令。密码恢复技能是保底手段但真正的高手是让这个技能永远闲置。9. 留给你的实操建议折腾Linux密码的原理其实就一句话想办法得到一个能操作系统的shell不管是通过内核参数、救援介质还是离线提取然后把密码重置成你知道的值。围绕这个核心变化的就是不同的入口和不同的系统限制。我建议你在自己的虚拟机里把单用户、rd.break和救援模式三个流程各练一遍练完以后遇到真实故障就不慌了。照例分享一个我现在还在用的小技巧在做任何密码恢复操作前先把/etc/shadow文件复制一份备份到安全位置。这个操作五秒钟就能完成但它能让你在误操作导致账号全锁时秒回原状。经历过一次所有账号全部被锁、连root都进不去的惨况后我就再也没跳过这一步。祝你的Linux运维之路少踩坑多睡安稳觉。