# 密码为什么不该重复用：一次泄露，为什么会连着一串账号失守

撞库不猜密码，它拿的是别处泄露的现成答案；长度和复杂度都挡不住它，能挡住它的是“每条密码唯一”，加上一道与域名绑定的第二因素。

> 账号安全 · 日常防骗习惯 · 反诈通用框架 · 约 7 分钟 · 10 月 12 日

## 本篇要点

1. 撞库（credential stuffing）不猜密码，它拿的是从别处泄露出来的、已经确认可用的账号密码，去其他网站批量试登录，所以密码再复杂也挡不住它。
2. 密码“强度”和密码“唯一性”是两个目标：长度和随机性决定被猜中的难度，只有“不在别处重复使用”才决定一次泄露会连带失守几个账号。
3. 网站端的防御（加盐哈希、已泄露密码黑名单）只能管自家这串密码，没有任何一个网站看得见你在别处用什么密码，唯一性只能靠用户自己保证。
4. NIST SP 800-63B-4 已不再强制字符组合规则和定期更换密码，改为要求单因素密码至少 15 位、并与已泄露密码黑名单逐字比对；理由是用户会用可预测的变体应付复杂度规则。
5. 密码管理器靠零知识加密把风险重新分配：密码在本地加密后才上传，解锁密钥由主密码本地派生，服务商只拿到密文；代价是主密码成为单点，必须长、必须专用、必须开双因素认证，且通常无法找回。
6. 撞库是双因素认证最能拦住的一类攻击，短信码、验证器 App、passkey 都能拦住它；各方式的强弱差异主要体现在能否被交到假网站手里，passkey 与域名绑定，假站拿不到签名。
7. 行动顺序是先给邮箱、支付和可重置其他账号的账号设长而唯一的密码并开启双因素认证，再升级到 passkey，同时检查找回路径不要留在最弱环节。
8. “复杂不重要”只对撞库成立：长度仍是防在线猜解和离线破解的主要因子，只是当二者只能先改一件时，应优先消除重复使用。

---

前面几篇讲的都是骗子主动来找你：钓鱼链接、冒充公检法的电话、刷单群。你只要不点、不说、不转，就挡住了。

还有一条完全不同的失守路径，它不需要你做错任何事。你什么都没点，某天却发现邮箱被人改绑了。起点可能是三四年前随手注册过的一个小网站——那个网站被拖库了，而你在上面用的密码，跟你现在用的某一个一样。

## 撞库：带着答案去考试

安全行业把这类攻击叫**撞库**（credential stuffing）。OWASP 的定义是：把偷来的用户名和密码对，自动注入其他网站的登录表单，试图获取账号访问权 [1]。

它和暴力破解不是一回事。暴力破解是在**猜**——试一万个密码看哪个对，所以密码越乱越难猜。撞库**不猜**：攻击者手里拿的已经是确认可用的账号密码，他做的只有一件事，把这串密码拿到别的网站再登一次。CrowdStrike 的解释里因此有一句听上去很反直觉的话：撞库中“密码强度不是问题”，因为攻击者的起点就是一个已经暴露的账号；再强的密码，只要被共享在多个账号上，就是一个负担 [2]。

这件事已经工业化了：攻击者从黑市买“撞库清单”（combo list），一份动辄上亿条已验证的账号密码对，然后用脚本批量登录，配合大量代理 IP 轮换、自动破解图形验证码，绕开单站点的限速 [3]。命中一次，这个账号就被标记为“可用”，可以立刻拿去改绑邮箱、转走余额，或者以你的名义去骗你通讯录里的人。

```mermaid
flowchart LR
  A["你注册过的某个网站被拖库"] --> B["你的邮箱 + 那串密码被打包流出"]
  B --> C["脚本拿着这串密码去其他网站批量试登录（撞库）"]
  C --> D{"同一串密码还用在了几个地方？"}
  D -- "只有这一个" --> E["损失限于该网站"]
  D -- "还用在 N 个账号" --> F{"这些账号开了第二因素吗？"}
  F -- "开了" --> G["只有密码，登不进去"]
  F -- "没开" --> H["账号失守：改绑、盗刷、冒充"]
```

## “复杂”和“唯一”解决的不是同一件事

我们对密码的期待里混着两个不同目标：

- **强度**：一串密码被猜中、被破解的难度，主要由长度决定。
- **唯一性**：这串密码泄露之后会连带影响几个账号，只取决于你有没有在别处重复用它。

长度、随机性、大小写和符号混搭，全都在提高第一项，对第二项毫无帮助。一条 30 位的随机串，只要它在十个网站上是同一条，泄露一次就等于十次失守——而且因为它又长又难记，你还特别舍不得换。

麻烦的是，这件事网站帮不了你。服务端能做的防御都在自家范围内，比如把已知泄露和常见密码做成黑名单：你设置密码时跟它比对，命中就拒绝。NIST 最新的身份认证指南（SP 800-63B-4）要求单因素密码最低 15 个字符，同时取消了强制字符组合规则，也不再要求定期更换密码 [4]。取消复杂度规则的依据是，用户会极其可预测地应付它——本来想用 `password` 的人，被要求加数字就写成 `Password1`，再要求加符号就写成 `Password1!`，定期更换的结果也大同小异 [5]。

这条要求正好说明黑名单的作用范围：它是网站拿你的密码去跟全世界泄露过的密码比对，所以拦得住“你设了一个烂密码”，拦不住“你把这串密码同时用在别处”。没有任何一个网站看得见你在别处用什么密码。

所以在长度和唯一性之间，如果只能先改一件，答案永远是唯一性：它挡住的是已经发生过的泄露，而不是一次猜测的运气。

## 泄露为什么会发生，“我很小心”为什么不够

泄露是别人家服务器的事。你控制不了对方有没有加盐哈希、用的是不是足够昂贵的哈希算法。同一个库被拖走，结果差别很大：存得好的网站，攻击者拿到的是一堆难以还原的哈希；存得差的，密码基本等于明文。撞库之所以划算，正是因为“能直接拿来用”的那批库足够多——攻击者根本不需要破解你的密码。

所以“我从不点奇怪链接”是真实有效的防护，但它防的是钓鱼，不是撞库。

## 工具一：密码管理器，把“唯一”变成不费力

一个人记不住 60 条互不相同的强密码，这是事实，不是意志力问题。密码管理器的做法是：你只需要记住**一个主密码**，其余每个网站一条又长又随机的密码，由它生成、由它填入。

它要回答的质疑是“那我的密码不都放在一个篮子里了吗”。答案在加密架构里：主流管理器采用**零知识（zero-knowledge）加密**，你的密码在自己的设备上加密之后才上传，服务商服务器上存的是密文，解锁密钥由主密码在本地派生，服务商既不保存也不掌握它 [6]。即使服务商的服务器被攻破，攻击者拿到的是密文，不是你的密码清单。

这套设计把风险重新分配了：原本你要赌“我注册过的几十个网站都不出事”，现在只需要守住一个主密码和你的设备。主密码怎么设？与其拼一个短而复杂的 `P@ssw0rd!`，不如用多个词组成的**口令短语（passphrase）**，长度是强度的主要来源，短语既长又好记 [5]。三条边界一起记住：主密码要长、且只用于这个管理器；管理器账号本身要开双因素认证；零知识也意味着忘了主密码通常无法找回，所以要保存好恢复码。

## 工具二：双因素认证，让“密码已被知道”不再致命

前面有一篇讲过验证码为什么不能给别人，这里补上它在防撞库里的位置。

密码证明“你知道一串东西”，第二因素证明“你拥有某样东西”。撞库的攻击者手里只有用户名和密码，没有你的手机，也没有你的设备。所以撞库恰好是双因素认证最能拦住的一类攻击：短信验证码、验证器 App、passkey，都能拦住它 [7]。哪怕某个网站只提供最弱的短信验证码，也值得开。

但“开了 2FA”这四个字几乎不携带信息。各方法真正的分水岭，是能不能被交到假网站手里 [7]：短信验证码会被 SIM 卡补卡（把你的号码转到别人卡上）和中继钓鱼拿走；验证器 App 的 6 位码不走电话网络、防住了补卡，但它仍是一串给人看的数字，造假站的人在几秒内转发给真站，照样能过；passkey / FIDO2 安全密钥与域名绑定，域名对不上时浏览器根本不会把它拿出来签名，假站拿不到任何可用的东西。

也就是说，这三种方式防撞库的能力差不多，差别主要体现在防钓鱼上。落到行动上：先给邮箱、支付账户，以及“可以用来重置其他账号”的账号（Apple ID、Google 账号、微软账号这类）配上 2FA，有条件时再升级到 passkey。

## 今天可以做的三件事

1. **先处理上面那三个账号**：各设一条长而唯一的密码，并开启双因素认证。
2. **泄露过的密码不要“改一改再用”**。`Password2024` 改成 `Password2025` 是无效动作，攻击者的字典里本来就收录了这类变体。
3. **检查恢复路径**。常见情况是双因素认证做得不错，但找回方式还挂在最弱的环节上，比如用一个短信验证码就能重置那个已经受保护的邮箱。攻击者会从最弱的门进。

## 两点边界

第一，撞库不保证必然得手。很多服务有异地登录风控、失败次数限速，会拦下一部分；是否失守也取决于泄露的那份密码是否“可直接使用”。这不是放松的理由，但你真正要做的是查清自己有没有在那个站用了重复密码，有就换。

第二，不要把“复杂不重要”听成“密码可以简单”。准确的说法是：字符组合规则和定期改密码的价值被高估了，长度仍然是防在线猜解和离线破解的主要因子。正确的做法是两件同时成立——每条密码都够长，并且互不相同；只能在两者里先做一件时，先做“不重复”。

## 术语表

- 撞库（credential stuffing）：拿已经泄露、确认可用的用户名密码，去其他网站批量试登录；它不猜密码，所以密码强度在这里不起作用。
- 密码强度与密码唯一性：强度决定“一次猜中难不难”，唯一性决定“一次泄露牵连几个账号”，两者由不同的做法解决。
- 零知识加密：你在自己设备上加密后才上传数据，解锁密钥由主密码在本地派生，服务商只保存密文，也无从查看或找回。
- 已泄露密码黑名单（blocklist）：服务端在你设置密码时把整条密码与已知泄露、常见密码清单比对，命中就拒绝，用来挡住最容易被猜中的那批密码。
- 抗钓鱼的第二因素：与域名绑定的凭证（passkey / FIDO2 安全密钥），假网站无法从你这里拿到可用的签名；而短信码和验证器 App 的 6 位码都能被实时转发出去。

## 来源

1. [OWASP: Credential stuffing — 撞库的定义与攻击步骤](https://owasp.org/www-community/attacks/Credential_stuffing)
2. [CrowdStrike: What is Credential Stuffing? — 说明撞库中密码强度不起作用](https://www.crowdstrike.com/en-us/cybersecurity-101/cyberattacks/credential-stuffing/)
3. [Stripe: Credential Stuffing Attack Prevention Explained — combo list 规模与绕开限速的方式](https://stripe.com/resources/more/credential-stuffing)
4. [NIST SP 800-63B-4: Authenticator and Verifier Requirements — 密码长度、组合规则、定期更换与黑名单要求](https://pages.nist.gov/800-63-4/sp800-63b/authenticators/)
5. [NIST SP 800-63B-4 附录 A: Strength of Passwords — 长度是强度主要因子，组合规则收益有限](https://pages.nist.gov/800-63-4/sp800-63b/passwords/)
6. [Bitwarden: Inside zero knowledge encryption — 本地加密与主密码派生密钥的机制](https://bitwarden.com/en-gb/blog/end-to-end-encryption-and-zero-knowledge/)
7. [Dashlane: MFA Methods Compared — 短信、验证器 App、FIDO2 密钥与 passkey 的强弱对比](https://www.dashlane.com/blog/mfa-methods-compared)
8. [Have I Been Pwned — 查询邮箱是否出现在已知泄露事件中](https://haveibeenpwned.com/)

---

原文：https://pangzhengboyin.com/articles/why-password-reuse-breaks-many-accounts-16131cdd

> **庞征博引** · 想学的，慢慢都会
>
> 庞征博引是把想学的东西写成连载的 AI 学习工具。说出想学什么，它会先了解你的基础，再把主题写成一篇篇 5–10 分钟能读完的文章；边读边问，接下来学什么跟着你走。这篇就是这样写出来的。
>
> 开始你自己的连载 → https://pangzhengboyin.com
