打口令只有三种打法——蛮力攻击、字典攻击、密码列表攻击;三者的成本差着好几个量级,所以"不复用"比"设得复杂"更重要,"够长"比"够怪"更值钱。
上一节(权限只交给合适的人)把认证和授权分开了。这一节专门钻进"认证"里最常被打的那一环——口令。
这也是本篇第一次出现可以真算的数字(破解时间)。之所以要算,是因为口令这件事上直觉特别不可靠:大多数人以为"P@ssw0rd! 比 applebananaorange 强",一算就知道反了。
一、先分清两件事:偷和猜
打口令的攻击分两大类,混在一起谈是很多讨论失焦的原因:
第一类:偷。 攻击者通过钓鱼、撞库、恶意软件、买数据等方式直接拿到口令明文。这类攻击跟你的口令有多强毫无关系——它是"P@ssw0rd!"还是 30 位随机串都一样。
第二类:猜。 攻击者拿到的是口令的哈希值(从数据库泄露里拿到),或者只有一个登录界面,需要想办法算出/试出那个口令。只有这一类,"口令强度"才起作用。
所以本节讲的三种攻击都属于第二类。而第一类的防御在别的地方——不复用、开多因子、防钓鱼。
二、蛮力攻击:最笨也最诚实
蛮力攻击的做法是:把所有可能的组合一个一个试过来。
它的成本公式很朴素:
要试的次数 = 字符集大小 ^ 口令长度
所需时间 = 要试的次数 ÷ 每秒能试多少次
这道公式里藏着两个关键变量:
- 长度是"指数":长度每加 1,尝试次数乘上字符集大小。所以长度是杠杆。
- 字符集是"底数":从纯小写(26)扩到大小写数字符号(95),底数变大,但也只是乘几倍;而人为了满足"必须有符号"的规则,往往写成
Password1!这种可预测形态——理论上变大,实际上没怎么变。
这就是当前主流指南(NIST SP 800-63B)态度转变的原因:长度比复杂度更值得要求。
三、字典攻击:不猜字母,猜"人会怎么想"
字典攻击不试随机组合,而是拿词表去试:常见词、人名、品牌名、影视名、地名,再加上变形规则(首字母大写、末尾加数字、字符替换如 o→0、a→@)。
它的杀伤力在于:人的口令几乎都来自有限的那批词加有限的那几种变形。
所以 P@ssw0rd! 这种口令在"数学上"看着不弱(有大小写、有符号、有数字),在字典攻击面前几乎等于裸奔——因为 password 是词表里的第一个词,@ 和 0 是变形规则里最常用的两条。
一句话:蛮力攻击考验长度,字典攻击考验"你的口令是不是能被人想到"。
四、密码列表攻击:连算都不用算
第三种最常见、也最快:拿一份泄露口令清单直接试。
它的原理是"复用":A 网站泄露了一亿条"账号+口令",攻击者就拿这批口令去 B 网站、C 网站挨个试——因为在 B、C 网站里,总有相当比例的人用的是同一个口令。
这就叫撞库。它的特点是:
- 成本几乎为零(不需要计算,只需要发送请求)
- 成功率高(因为人真的在复用)
- 它打的是"习惯",不是"强度"——你那个口令再复杂,只要在别的站点用过一次并且那边泄露了,它就在清单里
所以本节最该记住的一句话是:
在"泄露口令清单"面前,口令的复杂度毫无意义——你唯一能做的是别让它出现在那份清单里(也就是不复用),以及开多因子。
五、在线和离线,是两个世界
同样的口令,在两种场景下的破解难度差着天文数字:
| 场景 | 攻击者的速度 | 防守方的武器 |
|---|---|---|
| 在线(对着登录框试) | 受限于网络和限速,每秒几次 | 失败锁定、限速、验证码、风险识别 |
| 离线(拿到哈希在自己机器上算) | 一块现代显卡每秒可试上百亿次 | 只靠口令本身的强度 |
这个区别非常重要,因为它决定了防守的着力点:
- 如果攻击者只能在线试,那么"账号锁定 + 限速"比口令强度更有用——试几次就锁,再强的攻击也进不来。
- 如果哈希已经泄露(离线),那么一切取决于口令本身,而这时候唯一能救你的就是长度和多因子(哈希之外还要过一关)。
所以正确的做法是两边都做:限速与锁定(挡在线)、长度与多因子(挡离线)。
六、动手 Demo:三类攻击的破解时间估算
下面这个 Demo 用同一批口令把三种打法跑一遍,看它们的差距有多大。
GPU = 1e10 # 离线:一块现代显卡每秒可试 100 亿次快速哈希
ONLINE = 5 / 60.0 # 在线:限速 5 次/分钟,且通常几次就锁号
def brute(sec, size, n):
return (size ** n) / sec # 字符集^长度 ÷ 每秒尝试次数
实跑输出:
============================================================================================
一、同一个口令,三种打法
============================================================================================
口令 长度 蛮力(离线) 字典+变形 泄露列表
----------------------------------------------------------------------------------------
123456 6 瞬间 瞬间 ★ 命中
password 8 21 秒 瞬间 ★ 命中
P@ssw0rd! 9 2 年 瞬间 ★ 命中
company2026 11 152 天 10 秒 —
zhang1985 9 2.8 小时 10 秒 —
Tr0ub4dor&3 11 1.8 万年 10 秒 —
applebananaorange 17 359.5 万年 —(不在表里) —
correct-horse-battery-staple 28 4e+22 年(天文数字)—(不在表里) —
============================================================================================
二、再看在线攻击(隔着一道限速的门)
============================================================================================
口令 在线(5次/分钟) 说明
----------------------------------------------------------------------------------------
123456 2.0 分钟 列表前几位就是它,试十几次就中
password 2.0 分钟 列表前几位就是它,试十几次就中
P@ssw0rd! 2.0 分钟 列表前几位就是它,试十几次就中
company2026 14 天 限速之后在线猜变慢了,但远没到安全
zhang1985 14 天 限速之后在线猜变慢了,但远没到安全
Tr0ub4dor&3 14 天 限速之后在线猜变慢了,但远没到安全
applebananaorange 4e+17 年(天文数字)在线打它没意义
correct-horse-battery-staple 5e+33 年(天文数字)在线打它没意义
④ 读这张表要读出两件事:
第一,凡是在【泄露密码列表】里的口令,破解时间都是瞬间——
攻击者根本不用算,直接查表。所以【不复用】比【设得复杂】重要得多。
第二,最后两条长口令,离线硬算要几万年以上,
可它们连大小写都没混——长度赢过了复杂度。
⑤ 这就是当前主流指南(NIST SP 800-63B):
单靠口令登录的场景,最短 15 个字符;不强制大小写和符号混排;
系统要拿泄露口令库筛一遍,命中就拒收;
并且不再要求定期换口令——定期换只会把人逼成 2026春季 变 2026夏季。
读这个输出:最有信息量的两行是 P@ssw0rd! 和 applebananaorange 的对比。
P@ssw0rd!:蛮力要 2 年,字典攻击瞬间。看起来"很复杂",但它是由一个词加最常见的变形规则拼出来的。applebananaorange:三个普通单词拼起来、全是小写、毫无符号——蛮力要 359.5 万年,字典也不在表里。
这就是本节最想让人亲眼看到的一件事:"看着复杂"和"实际难破"是两回事;真正起作用的是长度和不可预测性。
再看第二张表的 123456:蛮力只要瞬间,但因为限速,在线攻击要 2 分钟——还是一次就试中的。而 company2026 在线要 14 天。同一个登录框,限速一开,攻击成本从"秒"抬到了"两周"——这就是"在线"和"离线"的分水岭。
七、⚠️ 2026 现状
- 主流指南的六条已经明确(NIST SP 800-63B 第 4 版,2025 年定稿):① 单独用口令时最少 15 个字符,配合多因子时可放宽到 8;② 系统应允许至少 64 个字符并接受空格;③ 不强制大小写数字符号混合;④ 不要求定期更换,只在有泄露证据时强制;⑤ 新设置的口令必须与泄露口令库和常见口令库比对,命中就拒收;⑥ 允许使用口令管理工具和粘贴,不做密码提示和密保问题。
- "凭据滥用"仍是主要的入口之一。近两年的泄露报告里,被盗凭据、撞库、口令喷洒始终排在最常见入口的前列——也就是说,虽然"直接破解"的成本被抬高了,但"直接拿到"的路一直很通畅。所以多因子(下一节)的重要性已经超过口令强度本身。
- 口令喷洒是值得单独记的一种打法。它和蛮力正好相反:不针对一个账号试很多口令,而是拿少数几个最常用的口令,去试很多很多账号。这样既不会触发"单账号锁定",又能撞出一批账号。对策很具体:监控"同一口令被很多账号尝试"这个模式,而不只是监控单账号失败次数。
30 秒实验
把你现在正在用的两个网站的口令,在心里做一个判断(不用真的写出来):
- 这两个口令是不是同一个,或者只是换了几个字符?
- 它们是不是由一个常见词加变形拼出来的?
- 如果明天第一个网站泄露了,第二个网站还守得住吗?
只要 3 答"守不住",那就是最该处理的一种情况——它属于"密码列表攻击"的目标,跟你口令有多复杂无关。处理办法只有两个:换成不重复的口令(交给口令管理工具生成),或者开多因子。
常见误区
-
错误:口令里混了大小写和符号就更安全。——纠正:复杂度带来的提升远小于长度,而且人满足复杂度规则的方式高度可预测(首字母大写、末尾加
1!)。字典攻击就是专门打这个习惯的。Demo 里P@ssw0rd!和applebananaorange的对比就是最好的说明。 -
错误:定期换口令更安全。——纠正:当前主流指南明确不要求定期更换。定期换会把人逼向"可预测的变化"(年份、月份、数字加一),反而更容易被猜中;同时带来大量现实成本的投入。正确的做法是在有泄露证据时强制更换。
-
错误:我的口令很复杂,所以不怕泄露。——纠正:如果它在别的站点用过,就"已经"在攻击者的清单里了。这时复杂度不起作用。不复用是唯一有效的对策。
-
错误:把口令设得很长但很好猜(比如一整句话的拼音)就安全。——纠正:长度确实有效,但"可预测"会让长度打折——流行的句子、歌词、名言都在词表里。随机的多个不相关词才是又长又难猜的做法(Demo 里的
correct-horse-battery-staple就是这种思路)。
自测三问(点开对答案)
1. 为什么说"密码列表攻击"跟前两种攻击不是一回事? —— 因为前两种是**"猜"**(要计算或尝试),而密码列表攻击是**"试"**——攻击者直接用从别处泄露的真实口令去撞库,**不需要任何计算,命中率却很高**。它打的不是口令强度,是**复用习惯**。 2. 同样一个 8 位口令,为什么"在线"要几个月、"离线"只要几十秒? —— 因为**两者的速度差着好几个量级**:在线受网络和限速约束(每秒几次),离线是在自己机器上算(每秒上百亿次)。所以防守要**两边都做**:限速与锁定挡在线,长度与多因子挡离线。 3. 为什么 NIST 建议"允许粘贴口令、支持口令管理工具"? —— 因为**禁止粘贴会把人推向短口令**(手打不方便,就写短一点)。允许工具生成和自动填充,人才可能真的用上"每个站点一个的、长的、随机的"口令。**这又是一次"便利性和安全性同向"的例子**——顺人性的规定才落地得下去。- ☐ 下一节(1-10 使用一次性密码安全性更高)
相关笔记
- 权限只交给合适的人 —— 上一篇:认证、授权、最小权限的框架
- 使用一次性密码安全性更高 —— 下一篇:口令之外再加一道——一次性口令与多因子
- 密码使用环境的变化 —— 账号太多怎么办:口令管理工具
- 🛡️ 网络与信息安全 · 索引 —— 全课路线图