如果你也遇到过这种场景:一台跑了多年的 Linux 服务器,管理员交接时 root 密码没写进文档,业务还不能停;或者你正在做一次有授权的渗透测试,拿到了目标主机/etc/shadow文件,需要在短时间内判断哪些账号存在弱口令——那么这篇关于 Linux 密码破解的内容,正好可以帮你把整条链路理清楚。
我先说清楚边界:文中的所有技巧,请只用于你自己的虚拟机、实验环境,或者已经获得书面授权的安全测试项目。破解他人系统密码属于违法行为,这不是吓唬人,而是这些年我见过太多人因为“我只是试一下”把自己的职业生涯搭进去。授权是底线,没有授权的一切操作都是非法入侵。
这篇文章不会只丢几个命令让你“照着跑”。我会从 Linux 密码存储的原理讲起,然后拆解主流破解工具的用法和速度模型,再补上忘记 root 密码时的合法恢复路径,最后回到防守端,用破解者的视角告诉你怎样加固才能让密码扛住常见攻击。如果你能坚持看到最后,对密码存储和口令安全的理解会和绝大多数运维不一样。
1. 从 /etc/shadow 说起:Linux 密码到底是怎么存的
很多人把“破解密码”想成对密码进行反向解密,这是最初级的误解。要真正理解破解工具在做什么,必须先搞清楚 Linux 系统把密码放哪、用什么格式存、算法处理过一次之后输出的是什么。
1.1 早期 /etc/passwd 的尴尬:为什么哈希会被单独挪走
在 Unix 的早期设计里,用户密码的哈希值直接写在/etc/passwd文件里。这个文件对所有用户都是可读的,因为很多系统操作(比如ls -l显示文件属主)都需要读取它。这样一来,任何能在机器上创建普通账号的人,都可以直接复制所有用户的密码哈希。离线破解不受登录次数限制,想跑多久就跑多久。
后来系统把密码哈希挪到了/etc/shadow,并且把权限限制为只有 root 用户可以读取,普通用户只能看到/etc/passwd里的 x 占位符。这个改动把“可读的哈希”变成了“受保护的哈希”,是 Linux 口令安全史上里程碑式的变化。今天的主流发行版都遵循这个设计,所以你在一台服务器上执行cat /etc/shadow,看到的不是明文,而是形如$6$...的密文片段。
1.2 shadow 文件逐字段拆解:破解工具真正关注的是哪一段
/etc/shadow的每一行代表一个用户,冒号分隔 9 个字段:
username:password_hash:last_change:min:max:warn:inactive:expireusername:用户名。password_hash:密码哈希,也可能直接是!或*,表示账号被锁定、没有登录密码。last_change:上次修改密码的日期,以 1970-01-01 起的天数计算。min:两次修改密码的最小间隔天数。max:密码最长使用天数,超过则要求修改。warn:到期前多少天开始警告。inactive:账号到期后宽限多少天。expire:账号过期时间。
破解工具真正关心的只有第二个字段。现代 Linux 哈希的格式是:
$id$salt$hash其中$id是算法标识,常见的包括:
| 标识 | 算法 | 典型场景 |
|---|---|---|
$1$ | MD5 | 老版本系统 |
$5$ | SHA-256 | 可配置的现代系统 |
$6$ | SHA-512 | 大多数现代发行版默认值 |
$y$ | yescrypt | 新版 Fedora、RHEL 9 之后 |
$argon2i$ | Argon2 | 某些定制系统 |
$salt$是随机加盐,用来防止两个相同密码产生相同哈希;hash是算法输出后的密文。破解时我们要构造的“哈希字符串”,就是完整保留$id$salt$hash这一整段,因为它包含了算法、盐值和最终结果,工具需要用这些信息去验证猜测的明文是否匹配。
1.3 哈希不是加密:不可逆的本质决定了破解思路
密码哈希是单向函数,输入密码可以算出固定长度的输出,但拿到输出不能反推出输入。所以严格来说,破解工具做的是“猜测明文 → 用同样的算法和盐值计算哈希 → 和目标哈希比对”,命中即破解成功。这类似于有人把锁住的保险箱放在你面前,你不可能远程直接“读”出钥匙的形状,只能不断拿钥匙去试,能打开的那把就是答案。
这里有一个常见的认知误区:很多人以为哈希不可逆就是安全的。实际上,只要密码本身足够简单,比如长度短、纯数字、使用常见单词,攻击者根本不需要“逆向”,只需要把所有可能性枚举一遍就能撞出来。你后面会看到,一张经典的密码字典加几秒钟的 GPU 运算,就能让弱口令原形毕露。这也是为什么密码学安全最终取决于“密钥空间”而不是“算法不可逆”。
2. 破解思路与速度模型:为什么短密码几分钟就没了
在动手跑工具前,先建立一套速度概念。如果你不理解“什么样的密码在什么硬件下需要多长时间”,就很容易在破解时犯方向性错误——比如一开始就上 14 位穷举,结果跑了一周也没结果。
2.1 一条口令的完整破解链路
我们以一个授权测试场景为例:你拿到了目标主机的/etc/shadow,其中某个用户的哈希长这样:
$6$randomsalt$G4K4PzVn3Q...破解工具的处理流程非常直白:
- 读取哈希,识别算法和盐值。
- 从字典、规则生成器或掩码里取出一个候选明文。
- 用同样的算法和盐值计算候选明文的哈希。
- 比对结果。一致则输出明文;不一致则继续下一个候选。
这个过程完全在本地离线进行,不受目标服务器登录失败次数限制。这就是为什么离线破解远比在线猜密码可怕:在线破解一次失败了还能触发锁定,离线破解则只是本地 CPU/GPU 在“烧卡”。
2.2 字典攻击和规则变异:攻击者的第一选择
暴力穷举听起来很酷,但真正有经验的人一开始基本都选字典。所谓字典攻击,就是用一份记录的常见密码列表去尝试。最著名的rockyou.txt来自一次真实的数据泄露,里面有几千万条密码,按使用频率排序。很多测试目标只要用这份字典跑一遍,就能命中一部分账号。
但字典只覆盖“别人已经用过的密码”。如果目标管理员稍有安全意识,字典里的原样密码可能打不进去。这时候需要用规则变异:比如在密码末尾补两位年份、首字母大写、加上常见数字符号组合。John the Ripper 内置了大量规则,hashcat 也支持指定规则文件。举个例子,字典里有admin,规则可以生成Admin,admin123,admin2019,admin!等变体。规则越多,候选数量呈几何级增长,但也能覆盖到更多真实场景。
我先给一个重要的实践建议:第一轮攻击不要直接跑全量暴力。先用一个精简的高频密码列表(比如 top 1000),配合出场率最高的几十条规则,目标是在最短时间覆盖最可能的弱口令。很多安全测试中,60% 以上的弱口令都是这样被发现的,而不是靠 8 位以上穷举。
2.3 掩码穷举:用数字说话
当字典和规则都失败时,才考虑掩码穷举。hashcat 里用-a 3表示掩码攻击,?d代表数字,?l代表小写字母,?u代表大写字母,?s代表特殊符号。比如?u?l?l?l?l?d?d表示“一个大写字母 + 四个小写字母 + 两个数字”。
为什么短密码在 GPU 面前毫无还手之力?我们算一笔账:
- 8 位纯数字密码,组合数是
10^8 = 1亿。 - 现代中高端显卡跑某些哈希时每秒可以尝试数十亿次(取决于算法效率)。
- 即使按每秒 1 亿次估算,1 亿个组合只要 1 秒。
如果密码变成 8 位小写字母,组合数是26^8 ≈ 2080亿,同样按每秒 1 亿次,需要约 2000 秒,也就是半小时出头。如果再加进大写字母和数字,时间立刻顶到几十天。这就是为什么密码长度哪怕只增加几位,安全强度都会有天壤之别。
2.4 彩虹表和盐:为什么它在 Linux 面前基本失效
彩虹表是“用空间换时间”的预计算破解方案:预先算好海量哈希值,破解时直接查表,速度极快。但它有个致命前提——哈希必须没有加盐,或者盐值固定。
Linux 的 shadow 哈希几乎总是带随机盐的。两个用户即使设置完全相同的密码,因为盐不同,哈希字符串也不同。彩虹表只能对固定输入做预计算,遇到每行都不同的盐就完全失效。所以现代 Linux 密码破解基本不谈彩虹表,大家默认用字典或掩码实时计算。这也算是一个流传很广、但实际操作中没太大意义的概念。
3. 实操:用 John the Ripper 与 hashcat 跑一份测试哈希
这一节进入动手环节。我会假设你已经有一台自己的 Linux 虚拟机,并且在里面创建了一个测试账号,密码故意设得很弱,比如test123。以下所有命令只在你自己机器上跑,不要指向任何非授权目标。
3.1 准备一份合法可测的哈希
在测试机上新建用户并设置一个弱密码:
useradd -m testuser passwd testuser输入两次密码,比如test123。然后从 shadow 里取出 testuser 那一行:
grep testuser /etc/shadow你会看到类似下面的输出:
testuser:$6$Nn2Q7TzR$GyEme9XTUl...:18915:0:99999:7:::把第二段($6$...)单独复制到一个文本文件,比如target_hash.txt。保存时只需要这一行,用户名有没有都行,John 和 hashcat 都能识别。
3.2 John the Ripper 基础用法
大多数发行版可以直接安装:
apt install john # 或者 dnf install johnJohn 最方便的一点是能自动识别哈希格式,也可以手动指定。基础命令:
john --wordlist=rockyou.txt target_hash.txt如果字典路径不存在,先用系统自带的小字典试试,或者下载一份公开的字典放到指定路径。实际场景里,rockyou.txt是最常用的入门字典。
破解结束后查看结果:
john --show target_hash.txt如果输出里出现了testuser:test123这样的明文,说明破解成功。John 默认会把结果保存在~/.john/john.pot里,再次执行--show不会重复跑,只会显示已经破解出的内容。
如果不想用字典,也可以用简单模式:
john --single target_hash.txt--single模式会结合目标用户名、上下文信息自动生成候选,对某些场景很有效,而且速度非常快。
3.3 hashcat 在 GPU 上的实战与参数优化
hashcat 是另一个绕不开的工具,尤其当你手头有独立显卡时,它的并行能力比 John 默认的 CPU 模式高很多。安装:
apt install hashcat对$6$开头的 SHA-512 crypt 哈希,hashcat 的模块 ID 是1800。命令格式:
hashcat -m 1800 -a 0 target_hash.txt rockyou.txt-m 1800:指定哈希类型。-a 0:字典攻击。- 如果成功后想输出明文,会通过
--show查看:
hashcat --show -m 1800 target_hash.txt如果是掩码穷举,比如 8 位纯数字:
hashcat -m 1800 -a 3 target_hash.txt ?d?d?d?d?d?d?d?d常用参数说明:
-w 3:提高运行优先级,让显卡跑满,但机器会明显变卡。-O:启用内核算子优化,某些环境大幅提速。--potfile-path:指定结果保存文件,防止误删历史结果。
需要注意,hashcat 对系统环境有要求。Linux 下建议用 root 运行,并确认显卡驱动和 OpenCL 环境正常。如果是在虚拟机里跑,宿主机的 N 卡和 AU 卡性能直接决定速度;没有独立 GPU 时,hashcat 也可以跑 CPU 内核,但速度会慢很多,这时直接用 John 更省心。
3.4 破解失败后的思路调整:别死磕暴力
我见过太多人一上来就跑-a 3 ?a?a?a?a?a?a?a?a,跑了两天没结果,然后开始怀疑工具坏了。实际上,当字典和简单规则打不动时,最该做的不是把长度加长,而是收集目标信息,做一个“个人专属字典”。
具体做法是:把公司名、产品名、管理员姓名、生日、电话号、键盘次序(如qwerty、1qaz2wsx)、常用年份全部整理进一个文本,然后用工具自动生成组合变体。比如公司名acme加上2023、@、!等后缀。这种字典数量级一般只有几千到几十万,GPU 几秒就能跑完,但命中率往往远超全量穷举。
记住一个原则:破解的本质是猜中“人”的心理,而不是穷尽数学空间。现实中大多数密码都和人的习惯紧密相关,只要你能猜中几个关键词,效率会高得吓人。
4. 忘记 root 密码:合法的系统重置路线
破解密码是拿回失落的明文,而忘记密码时我们更关心的是如何恢复系统控制权。这部分操作在绝大多数发行版上都成立,核心思想是:只要你能物理接触机器,就有办法重置密码。
4.1 单用户模式与 rd.break:CentOS/RHEL 系的操作
重启系统,在 GRUB 菜单界面快速按e进入编辑模式。找到以linux开头的那一行(不同版本可能是linux16或linuxefi),在行尾添加参数:
rd.break按Ctrl+X启动,系统会进入一个很精简的 emergency 环境。此时根文件系统被挂载在/sysroot,并且默认是只读的。依次执行:
mount -o remount,rw /sysroot chroot /sysroot passwd root touch /.autorelabel exit reboottouch /.autorelabel是给 SELinux 的强制重新标记用的。如果系统没开 SELinux,这步可以省略,但执行了也无害。重新登录后,root 密码就是新设置的值。
Ubuntu/Debian 系的差异在于参数改成init=/bin/bash,启动后进入bash,此时根分区可能还是只读,也要先mount -o remount,rw /,然后passwd root,再重启。
4.2 使用 Live CD + chroot:更稳妥的通用方案
如果 GRUB 损坏或者不方便手动编辑启动项,用 Live CD 会更稳妥。启动 Live 环境后,先找到原系统的根分区:
lsblk假设根分区是/dev/sda2,挂载并 chroot:
mount /dev/sda2 /mnt mount --bind /dev /mnt/dev mount --bind /proc /mnt/proc mount --bind /sys /mnt/sys chroot /mnt passwd root这里为什么要 bind 挂载/dev、/proc、/sys?因为 chroot 后的环境需要访问设备文件和内核信息,passwd 工具及其依赖很可能需要这些。如果只是修改/etc/shadow文本,不绑也能做;但执行passwd这种工具时,建议完整挂载,避免报错。
4.3 直接替换 shadow 中的哈希:手工急救法
除了用passwd修改,还有一类更“黑客”的做法:生成一个新的密码哈希,替换 shadow 文件里对应行。比如:
openssl passwd -6 # 输入新密码,生成 SHA-512 哈希拿到输出后,手动编辑/etc/shadow,把目标用户第二字段替换成这个新哈希。这样即使不执行任何交互式工具,也能完成密码重置。
注意,这个方法在紧急恢复时很好用,但手误概率也高。建议先在测试机上练熟,而不是到生产服务器上第一次尝试。改完之后务必检查last_change字段的值,以免出现时间戳异常导致某些策略误判密码过期。
4.4 物理安全与防恢复:为什么单用户模式是“双刃剑”
单用户模式和 Live CD 重置密码的能力,对忘记密码的管理员来说是救命稻草,但也意味着任何能碰触到服务器物理接口的人,都可以轻松拿走控制权。如果机房安保不可控,必须在更底层做加固:
- 给 BIOS/UEFI 设置密码,防止他人从移动介质启动。
- 使用 LUKS 做全盘加密,这样即使硬盘被拆走,也无法读取文件系统。
- 给 GRUB 设置密码,防止未授权者进入单用户或 emergency 模式。
- 记录所有
/etc/shadow的修改时间,启用审计日志。
这里要特别强调:硬盘加密(LUKS)是最关键的一层。没有加密的 Linux 服务器,物理接触等于 root 到手;有加密之后,即使攻击者拿到硬盘,也必须面对密文和口令破解的额外问题。
5. 从破解视角反推:如何让系统密码扛住主流攻击
会破解之后,最直接的收益是能反过来审计自己负责的系统。我每次做安全巡检,都会把/etc/shadow拉下来用 John 跑一遍,跑出来的弱口令寥寥无几,系统就相对安全;如果一跑一大片,那就得反思密码策略是不是形同虚设。
5.1 密码策略:把“长度”放在“复杂度”前面
过去很多组织强制要求“至少一个大写、一个小写、一个数字、一个特殊字符、三个月换一次”,结果用户普遍把密码设成Passw0rd!2023这种可预测模式。安全界现在的共识是:更推荐长密码或短语,而不是复杂的短密码。
以 8 位混合字符和 16 位小写字母做对比:
- 8 位混合(大小写+数字+符号):密钥空间约
95^8 ≈ 6.6e15。 - 16 位纯小写:密钥空间约
26^16 ≈ 4.4e22。
后者虽然“看起来不复杂”,但暴力穷举代价高了几个数量级。而且长短语更容易记忆,用户不需要写在便利贴上。
5.2 PAM 与 pwquality:在系统层面落实策略
RHEL/CentOS 系可以通过authselect或直接修改/etc/security/pwquality.conf来设置密码质量规则。一个实用的配置示例:
minlen = 16 dcredit = -1 ucredit = -1 lcredit = -1 ocredit = -1这表示最小长度 16 位,且必须包含数字、大写、小写、特殊符号各至少 1 个。不过要注意,规则太严会导致用户体验变差,实际运维中可以结合“长度优先、复杂度适度”的原则调整。
SSH 侧也有必要限制暴力尝试次数。在/etc/ssh/sshd_config里设置:
MaxAuthTries 3 MaxSessions 10再搭配fail2ban监控日志,自动封禁短时间内多次认证失败的 IP。虽然这不能阻止离线破解,但能挡住绝大多数在线爆破脚本。
5.3 定期做口令自检:把 hashcat 用成审计工具
安全运维团队完全可以把破解工具变成“内审工具”。每季度把/etc/shadow导出到隔离的审计机,用 John 或 hashcat 跑一遍高频口令字典,然后人工确认哪些账号命中。命中说明该账号的密码出现在公开泄露库中,必须强制修改。
这个做法的好处是,不惊动业务就能掌握全服务器弱口令分布。我实操中经常发现,某些服务账号因为长期不登录,密码还是建号时的手动输入产物,完全就是字典前几名的热门词。这类账号平时没人关注,反而是最容易被利用的后门。
要注意保护隐私和合规:审计用的 shadow 文件不要复制到个人笔记本,跑出的明文也不能放在公共文档里。完成后清理临时目录,只在报告中记录“哪些账号需整改”,不记录实际明文。
6. 常见误区与经验碎片:这些坑我都踩过
最后写一些散落在我实操经验里的要点,不算系统性的教程,但每一条都可能帮你省下半天排查时间。
第一,不要天真地以为“哈希不可逆”等于“哈希安全”。哈希算法只是单向,但如果密码本身在字典里,可逆不可逆根本没有区别。安全的关键是让密码不被猜到,而不是依赖算法不可逆。
第二,把破解结果和密码本身混为一谈。登录进系统的人,本地可能还保存了/etc/shadow的备份或日志输出。任何提取 shadow 的步骤都尽量在隔离环境里做,防止结果外泄。
第三,修改 shadow 文件时先备份。无论用passwd还是直接编辑器改哈希,都建议先复制一份原始 shadow 到安全目录。万一语法写错,可能导致所有用户无法登录。
第四,运维脚本里绝对不要写明文密码。我见过有人在/etc/rc.local里放echo password | passwd --stdin,理由竟然是“自动化创建用户”。一旦这台机器被入侵,等于把钥匙主动交给攻击者。用 sudo 策略、SSH 密钥、Hashicorp Vault 这类方案来处理自动化授权。
第五,破解工具不是越新越好,而是要匹配目标。一个 2024 年的新发行版可能用 yescrypt,老工具未必支持。遇到不认识的开头符号,先查该发行版的文档,确定算法后再选 hashcat 模块。盲目拿-m 1800硬跑非 SHA-512 哈希,只会得到“无有效哈希”的报错。
第六,注意保存破解中间结果。John 的.pot文件和 hashcat 的.potfile都会记录已破解结果。如果你中途断了,重新运行时它们会自动跳过已破解的哈希,不会白白浪费时间。千万别手滑删掉这些文件。
在我做过的安全审计里,真正被攻破的系统,绝大多数不是因为内核漏洞多高级,而是因为某个账号密码太弱,或者物理安全形同虚设。Linux 密码破解的技术含量,其实不在于跑通一条命令,而在于你是否理解“为什么需要这么设、这么存、这么防”。把上面这些链路走一遍,你再去管理生产服务器,看待密码和权限的方式会很不一样。