
1. 忘密码这事儿的底层逻辑为什么叫恢复而不是破解先说个扎心的事实我做了这么多年Linux运维自己亲手把服务器root密码搞丢的次数比被黑客攻击的次数多得多。大多数时候不是被入侵就是单纯地——密码过期了、记在便签上找不到了、上一个同事离职时把密码带走了。所以破译root密码这个标题在真实工作场景里更像是一个系统管理员找回自己系统访问权限的过程而不是恶意攻击。要理解怎么恢复密码得先搞清楚Linux到底把密码存在哪儿。早期Unix系统确实把加密后的密码存在/etc/passwd里这个文件所有用户都能读于是任何用户都能拿到密文去暴力跑字典。后来嫌这太不安全就把真正的密码散列挪到了/etc/shadow这个文件只有root或有特定权限的进程能读。/etc/passwd里的密码字段就变成了一个x占位符系统看到x就知道真正的密码散列去/etc/shadow里找。/etc/shadow里每个用户一行冒号分隔root用户那行长这样root:$6$rounds656000$cVZp...:19000:0:99999:7:::具体字段含义依次是登录名、密码散列、最后一次修改密码距1970年1月1日的天数、两次修改密码之间最少间隔天数、密码有效期、过期前警告天数、宽限期天数、账号失效日期、保留字段。其中第二段的$6$表示采用SHA-512算法这也是现代主流发行版的默认算法。这里有个关键的认知点所谓破译在实际运维中几乎从来不是去逆运算那个散列——SHA-512目前没有任何可行的逆向手段暴力跑几十万亿次组合根本不现实。正规且高效的思路只有一条以某类特殊方式进入系统然后直接把/etc/shadow里的密码字段改掉或者直接清空它。本质上就是拔掉门锁换一把新锁而不是研究怎么把旧钥匙配出来。这也解释了为什么下面要讲的几种方案全都是围绕如何绕过正常的登录认证流程进入系统来展开的。搞清楚了密码存储机制和恢复思路后面那些看似神奇的操作就都顺理成章了。只要物理接触或控制台权限在你手里root密码从来就不存在真正的丢失问题。适用人群很明确自己服务器忘密码的站长、接手离职同事机器的运维、在虚拟机或物理机上做实验的学习者。有一点必须说清楚这套方法只适用于你有合法权限操作这台设备本身用在不该用的地方那就是另一回事了。2. 方案一单用户模式的完整操作与原理拆解2.1 为什么单用户模式可以不输密码直接进系统单用户模式是所有恢复方案里最经典、最常用的一个也是大多数Linux运维面试必问的操作。它的本质是系统在启动过程中进入一个最小化的运行环境只有最基本的内核服务和shell其他服务全部不启动并且默认跳过密码验证直接给你一个root shell。为什么能这样因为在系统设计里单用户模式主要用于系统修复和维护比如修复损坏的文件系统、排查启动失败、找回密码。如果这里还要密码那系统出事儿了管理员也进不去修复功能就成了摆设。不过现代系统通常有个保护机制如果你设置了/etc/shadow里root密码散列部分系统在单用户模式也会要求输入密码如果你进入单用户模式后发现自己被要求输密码十有八九是用了带SELinux或额外加固配置的发行版。后面会说怎么绕。具体操作流程是这样的。重启系统在GRUB引导菜单出现时快速按下键盘上的e键进入GRUB编辑界面。找到以linux或linux16开头的那一行这行内容通常是linux /boot/vmlinuz-xxx root/dev/mapper/xxx ro quiet把ro改成rw然后在行尾加上init/bin/bash或者single或者1。如果只想进单用户模式加single或数字1就行如果想直接拿shell用init/bin/bash更直接。改完按CtrlX或者F10启动系统会跳过正常的init流程直接给你一个root权限的shell。进到shell之后密码恢复就三条命令mount -o remount,rw / passwd rootmount -o remount,rw /为什么必要因为系统以init/bin/bash方式启动时根文件系统通常是只读挂载的直接改密码会报只读文件系统错误。先重新挂载成可写passwd root才能把修改写进/etc/shadow。这三条命令走完重启进系统用新密码登录就行了。2.2 GRUB加密与SELinux的干扰项处理上面流程看着简单实际生产环境里经常会遇到两个拦路虎。第一个是GRUB密码保护。很多服务器为了安全在GRUB引导菜单上加了口令按e键编辑前会先要求输入GRUB用户名和密码。如果这个密码你也忘了事情就变得麻烦不少但也不是完全没法解决。物理机上可以通过引导盘比如用Linux安装U盘启动进入rescue模式去重设GRUB密码或者直接编辑/etc/grub.d/下的配置文件然后重新生成/boot/grub/grub.cfg。虚拟机上则可以在宿主机层面修改虚拟机配置指定一个临时的initrd或直接改内核启动参数。第二个是SELinux。在RHEL、CentOS、Fedora这些默认开启SELinux的系统上通过init/bin/bash改完密码之后下次正常启动时SELinux可能会因为安全上下文异常而拒绝某些操作甚至导致系统起不来。解决方案是在改密码前先创建一个/.autorelabel文件touch /.autorelabel这个文件的作用是告诉SELinux在下次启动时自动重新标记所有文件的安全上下文。如果你忘了做这一步启动时又报SELinux相关的错也不用慌在GRUB启动参数里临时加selinux0来跳过SELinux进入系统之后再重新放行。这个坑我在CentOS 7上踩过不止一次强烈建议每次用init/bin/bash方式改密码后都补上touch /.autorelabel这一步。注意init/bin/bash这种方式在systemd时代依然是有效的但部分新发行版特别是Fedora 33之后的版本默认禁用了通过内核参数直接指定init的行为需要额外在GRUB启动参数里确认没有usr或者安全启动策略拦截引导。遇到这种情况别死磕单用户模式直接切到救援模式或方案三。3. 方案二systemd救援模式与rd.break应急Shell3.1 systemd时代的救援模式怎么玩从RHEL 7开始systemd成了主流init系统传统的single参数还在但更推荐的做法是使用systemd.unitrescue.target或者systemd.unitemergency.target。本质上单用户模式在systemd里就是被rescue.target取代了而emergency.target是更深的紧急状态。操作流程还是先重启进GRUB按e编辑启动行把ro改成rw去掉quiet方便看日志然后在行尾加上systemd.unitrescue.target保存启动后系统会进入一个文本模式的救援环境提示你输入root密码——注意如果正常登录系统时root有密码这里也是要密码的。那这个方案的意义在哪它的核心价值在于救援目标里你拥有一个相对完整的用户环境可以挂载文件系统、查看日志、修复服务比init/bin/bash那个裸shell干活舒服得多。如果连密码都没有那就得换一种更狠的写法。在GRUB编辑界面把ro改成rw然后在行尾追加rd.break这个参数是dracut一个用于生成initramfs的工具提供的调试入口。启动时initramfs执行到某一步会直接中断给一个shell而且这个shell是没有密码验证的。当你看到类似Switch root:的提示符时输入mount -o remount,rw /sysroot chroot /sysroot passwd rootchroot /sysroot这一步是把根目录切换到真正的系统根目录因为在rd.break阶段你所在的还是一个内存文件系统环境不是实际的硬盘系统。切进去之后passwd root修改的就是硬盘上真实系统的密码。改完输入exit退出chroot再输入exit或reboot重启拔掉rd.break参数它会自动失效因为那只是一次性引导参数正常启动用新密码登录。3.2 三种systemd单元目标该怎么选这里我把systemd的几个目标模式整理成一张表方便大家在实际操作时对号入座目标等价旧模式启动内容适用场景是否需要密码rescue.target单用户模式基本系统挂载root shell修复文件系统、重设密码视配置而定通常需要emergency.target无最小环境几乎不挂载根文件系统严重故障需要密码multi-user.target运行级别3完整多用户文本模式正常运维需要密码rd.break无initramfs阶段中断shell绕过认证改密码不需要实际经验是能进rescue.target就优先进它因为它环境完整进不去或者要密码再考虑rd.break。rd.break是最接近物理级后门的合法入口如果你碰到的设备连rd.break都进不去那基本是有BIOS/UEFI密码或者引导加载器加了密这时候就要看方案四的思路了。用rd.break改完密码同样建议顺手执行touch /.autorelabel在chroot之后执行尤其是RHEL系系统。另外还要注意有些系统上/sysroot下因为没有正确挂载/proc、/sys、/dev某些命令可能报错进chroot之前可以先把这些虚拟文件系统补挂上mount -o bind /dev /sysroot/dev mount -o bind /proc /sysroot/proc mount -o bind /sys /sysroot/sys这些细节不处理大部分时候passwd也能用但如果你碰到passwd: Cannot change password这类异常优先检查这些虚拟文件系统有没有挂好。4. 方案三终极杀招init/bin/sh与其他旁门左道4.1 从内核启动参数直接拿Shell的完整套路init/bin/bash和init/bin/sh本质上是一回事只是有的发行版里/bin/bash符号链接指向/bin/sh有的则是独立的两个文件。这个方案的价值在于它不依赖systemd甚至不依赖initramfs完整运行直接从内核把控制权交给shell。所以在一些古老的系统、嵌入式定制系统或者精简环境中它是唯一可行的手段。完整流程再细化一下每一步都有讲究1. 重启在GRUB菜单按e编辑 2. 找到linux/linux16行把ro改成rw 3. 行尾追加 init/bin/bash如果系统提示找不到bash就换成 init/bin/sh 4. 按CtrlX或F10启动 5. 出现bash提示符后确认根文件系统是否可写mount | grep / 6. 如果显示ro执行 mount -o remount,rw / 7. 执行 passwd root按提示输入两次新密码 8. 如果需要恢复SELinux上下文执行 touch /.autorelabel 9. 输入 exec /sbin/init 直接启动正常系统或者 reboot -f 重启第9步有两种收尾方式。exec /sbin/init是让系统不重启直接从当前状态继续走正常启动流程优点是不用退出当前会话缺点是有时候init进程状态不对会卡住。reboot -f是强制重启简单粗暴成功率最高。我个人一般用reboot -f省心。4.2 修改/etc/shadow的三种编辑手段passwd命令是标准做法但不是唯一做法。在某些极端场景下比如shell环境里缺少passwd命令、PAM配置损坏导致passwd无法正常工作就需要直接编辑/etc/shadow。方法一直接用vi编辑。找到root那行的第二个字段把它替换成一个已知的密文。比如你可以在一台正常机器上执行openssl passwd -6生成一个新散列然后把生成结果粘到shadow文件里。需要注意生成散列时用的算法要和系统配置一致现代系统基本就是-6即SHA-512。方法二把密码字段清空。删除root:和下一个冒号之间的所有字符使其变成root::19000:0:99999:7:::这样登录时不需要输密码直接回车就能进。这是应急手段进入系统后务必第一时间用passwd root设置新密码否则系统处于无密码状态极度危险。方法三用chpasswd命令。在sh环境下执行echo root:新密码 | chpasswd或者chpasswd root:新密码这个方法比编辑shadow文件安全因为它走的是标准PAM流程但前提是chpasswd命令在当前环境可用。我给个优先级排序日常恢复优先passwdpasswd不可用时用chpasswd两者都不行才直接改shadow文件清空密码字段是最不得已的下策。4.3 嵌入式设备和虚拟化环境的特殊处理热词里有一大堆嵌入式linux 忘了密码电视盒子root天翼网关默认密码光猫管理员密码这类场景这些都是嵌入式Linux的密码恢复问题。嵌入式设备的套路跟标准服务器不太一样因为它们往往没有完整GRUB菜单给你按e编辑有的甚至是只读文件系统。常见的嵌入式Linux恢复思路有这么几种第一看有没有调试串口或UART接口。大部分嵌入式开发板、电视盒子、光猫都会在PCB上预留调试串口引脚接上TTL转USB线波特率通常是115200或57600就能直接进到一个串口终端。很多嵌入式系统的默认shell就是root权限或者在uboot引导阶段可以设置bootargs参数添加init/bin/sh——原理跟方案三完全一样只是入口从GRUB换成了uboot。第二挂载根文件系统镜像改密码。嵌入式系统很多用基于Flash的只读根文件系统常见格式有jffs2、ubifs、squashfs等。做法是把Flash里的根文件系统镜像提取出来在PC上用工具如jefferson解jffs2、ubi_reader解ubifs解开修改/etc/shadow之后重新打包刷回去。这套操作属于嵌入式开发的范畴没有一定基础的情况下别轻易尝试容易把设备刷成砖。第三利用uboot命令行。设备上电时在串口终端狂按回车或空格进入uboot提示符执行setenv bootargs consolettyS0,115200 root/dev/mmcblk0p2 rw init/bin/sh boot后面的流程就跟方案三一样了。这里要注意每台设备的root分区和设备号都不一样先通过printenv查看当前的bootargs了解原来的启动参数是什么样子再基于它做修改别盲目照抄我的命令。虚拟化环境里则简单得多。VMware虚拟机可以通过vmware-vdiskmanager挂载vmdk磁盘然后直接编辑里面的shadow文件KVM/QEMU虚拟机可以用guestmount或virt-customize工具离线修改虚拟机镜像。推荐virt-customize一条命令就能解决virt-customize -a /path/to/disk.qcow2 --root-password password:NewPass不需要启动虚拟机直接离线改安全高效比所有引导参数方案都省事。这个工具是libguestfs包里的Debian系安装命令是apt install libguestfs-toolsRHEL系是yum install libguestfs-tools。5. 密码恢复之后的加固与防遗忘锦囊5.1 恢复完密码别急着走三件收尾事很多朋友改完密码一重启登录成功就以为万事大吉了。其实还有几件事值得顺手做掉尤其是生产环境。第一检查/etc/shadow里root密码是否真的生效。用passwd -S root查看root密码状态正常输出类似root P 09/01/2023 0 99999 7 -1中间的P表示密码已设置。如果显示L表示锁定NP表示没有密码都要进一步处理。第二排查有没有其他账号也处于不安全状态。恢复过程中如果使用了清空密码字段的手段要确认没有其他用户账号也受影响。用awk -F: ($2){print $1} /etc/shadow快速找出所有密码为空的账号逐一处理。第三检查系统日志里有没有异常登录记录。用last或lastlog看登录历史用journalctl -u sshd确认SSH服务运行状态确保整个恢复过程没有被人利用间隙做过手脚。这套检查做完才能真正放心地把机器重新投入生产。5.2 如何让自己不再忘密码制度与技术双保险根据我自己和身边同行的经验root密码丢失大多不是记性差而是没有一套科学的密码管理习惯。几个实际有效的做法用密码管理器统一管理服务器密码而不是散落在便签、Excel、微信聊天记录里。KeePassXC和Bitwarden都是不错的开源选择。重要服务器开启SSH密钥登录日常操作全程免密root密码只作为最后的Console应急通道。密钥登录配好后即使密码忘了也能通过SSH密钥登进去改密码恢复成本极低。生产环境配置sudo权限体系限制直接root登录让管理员通过普通用户sudo -i切换root这样root密码的使用频率大幅下降遗忘概率也就降低了。定期演练密码恢复流程。我见过不少团队在割接或者审计前才发现没人会进单用户模式临时抱佛脚翻文档慌得一批。每半年在测试机上演习一次恢复流程成本很低收益很大。另外推荐一个热词里提到的思路linux运维故障案例是很好的学习素材。密码恢复只是Linux运维故障里很小的一个分支类似的故障案例解决方案整理多了遇到问题才有底。千万别犯的错永远不要在多台服务器之间共用root密码更不要在文档里明文记录生产环境密码。真出了安全事故你第一个被问责。6. 常见问题与排查技巧实录6.1 这些坑我基本都踩过提前帮你排雷现象一进单用户模式后passwd报Authentication token manipulation error。这种多半是/etc/shadow所在的文件系统还是只读或者文件权限异常。先执行mount -o remount,rw /再检查/etc/shadow文件权限正常应该是-rw-r-----属主root属组shadow。如果权限被改坏了chmod 640 /etc/shadow chown root:shadow /etc/shadow修回来。现象二改完密码重启系统一直卡在登录界面循环。这种大概率是PAM配置出了问题或者密码散列算法不匹配。回想一下是不是用了openssl passwd生成散列时算法选错了比如系统用的是$6$而你生成的是$1$。解决办法是重新进单用户模式用passwd root重新设置一次让系统自己生成正确格式的散列。现象三VMware虚拟机按e键进不去GRUB编辑界面。虚拟机的BIOS启动太快按键时机很难把握。解法是在.vmx配置文件里加一行bios.bootDelay 5000让BIOS界面停留5秒给你充足时间按按键。KVM虚拟机则可以在VNC窗口里启动时疯狂按Esc调出GRUB菜单。现象四UEFI安全启动拦截内核参数修改。现在新一点的发行版都默认开了Secure Boot修改了GRUB启动项后签名校验可能不通过提示文件被篡改。解法是在BIOS设置里临时关闭Secure Boot进入系统改完密码后再恢复开启。注意这个只对你自己物理掌控的机器有效云服务器通常在控制台层面就能改启动参数不受Secure Boot影响。现象五改完密码后SSH还是连不上。这种一般不是密码恢复的问题而是SSH服务配置了PermitRootLogin no禁用root直接登录。要么在/etc/ssh/sshd_config里改成PermitRootLogin yes要么用普通用户登录后su -切root。别在这上面死磕半天。6.2 一套完整的RHEL系恢复实操记录最后放一份我在CentOS 7.9物理机上实际走通的完整过程照着做应该不会出错# 重启机器在GRUB菜单按e # 光标移到 linux16 开头那行行尾添加 rd.break # 按 CtrlX 启动 # 出现 switch_root:/# 提示符后依次执行 mount -o remount,rw /sysroot chroot /sysroot echo root:MyNewPass123 | chpasswd touch /.autorelabel exit exit # 系统重启后等待SELinux relabel完成自动进入登录界面 # 用新密码登录root确认无误这里用chpasswd而不是passwd原因是在chroot环境里passwd有时会因为无法正确解析PAM模块路径而报错而chpasswd在管道场景下更稳定些。密码里我建议至少包含大写字母、小写字母、数字、特殊字符长度超过12位。6.3 恢复速查表场景首选方案备选方案备注普通物理机/虚拟机GRUB可用single/rescue.target改密码init/bin/bash记得remount rwRHEL/CentOS 7root密码遗失rd.break chroot救援模式记得touch /.autorelabelGRUB也加密引导U盘rescue模式虚拟机挂载镜像离线改物理机可能要清CMOS嵌入式开发板/盒子串口uboot传参提取镜像改shadow留意只读文件系统KVM/QEMU虚拟机virt-customize离线改密单用户模式离线改最安全云服务器控制台VNC启动参数重置密码功能各家云控制台支持不同这张表基本涵盖了我职业生涯里遇到过的所有忘密码场景。核心逻辑永远是想尽办法在绕过认证的情况下拿到一个可以修改文件的shell然后改密码。所有方案都逃不出这个框架理解了这个框架你就能根据具体设备的情况自由组合出合适的解法。我个人在实际操作中的体会是单用户模式和rd.break这些方案实操三次以上才能真正熟练尤其要适应不同发行版的细微差别。比如Debian系的ro改rw后还需要确认mount命令可用Ubuntu新版把GRUB的编辑快捷键改过一轮预装RHEL的云镜像有时连GRUB菜单都默认隐藏。说一千道一万真正的硬功夫还是平时多练。另外强烈建议在自己电脑上的虚拟机里把几种方案来回折腾几遍——这个过程练熟之后以后不管遇到什么怪系统脑子里都有底不会慌。