☰
Linux密码破解与shadow安全:从哈希原理到John/hashcat实战
2026/10/9 12:46:51 网站建设 项目流程

如果你也遇到过这种场景:一台跑了多年的 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:expire
  • username:用户名。
  • 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...

破解工具的处理流程非常直白:

  1. 读取哈希,识别算法和盐值。
  2. 从字典、规则生成器或掩码里取出一个候选明文。
  3. 用同样的算法和盐值计算候选明文的哈希。
  4. 比对结果。一致则输出明文;不一致则继续下一个候选。

这个过程完全在本地离线进行,不受目标服务器登录失败次数限制。这就是为什么离线破解远比在线猜密码可怕:在线破解一次失败了还能触发锁定,离线破解则只是本地 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 john

John 最方便的一点是能自动识别哈希格式,也可以手动指定。基础命令:

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 reboot

touch /.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 密码破解的技术含量,其实不在于跑通一条命令,而在于你是否理解“为什么需要这么设、这么存、这么防”。把上面这些链路走一遍,你再去管理生产服务器,看待密码和权限的方式会很不一样。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询