你的系统从没被攻破过,但你的用户照样被盗号了——因为密码是在别人家泄露的。这就是撞库最让人头疼的地方:漏洞不在你这,锅却得你背。
一、什么是撞库攻击
撞库(Credential Stuffing)是指攻击者拿着从 A 网站泄露的「用户名 + 密码」组合,批量、自动化地去尝试登录 B、C、D……网站,利用用户跨平台复用密码的习惯来盗取账号。
它的核心前提只有一句话:绝大多数人,在不同网站用着同一套密码。
攻击者不需要破解你的密码哈希,不需要找你系统的漏洞,甚至不需要懂太多技术。他只要:
- 搞到一份泄露的凭证库(网上几十亿条,免费的、卖的都有);
- 写个脚本 / 买个现成工具(Sentry MBA、OpenBullet 这类);
- 挂上代理 IP 池,把这批账号密码往你的登录接口上撞。
撞中一个是一个。
撞库 ≠ 暴力破解
这两个经常被混为一谈,但本质不同:
| 维度 | 撞库 (Credential Stuffing) | 暴力破解 (Brute Force) |
|---|---|---|
| 输入 | 已知的真实账号密码对 | 针对单账号穷举密码 |
| 依赖 | 用户跨站复用密码 | 密码强度弱 |
| 命中率 | 低但稳定(0.1%~2%) | 取决于密码复杂度 |
| 流量特征 | 海量账号、每个只试一两次 | 单账号、高频尝试 |
| 防御重点 | 凭证信誉 + 风控 + 人机识别 | 频率限制 + 锁定 + 强密码 |
注意最后一行的流量特征差异——这正是很多传统防御失效的原因:你设了「单账号连续失败 5 次锁定」,但撞库每个账号只试一次就换下一个,你的锁定策略根本不会触发。
撞库不是孤立的,它在一条黑产链路里
撞库通常是整条数据犯罪链路的「变现末端」:
入侵系统导出数据库] --> B[洗库
清洗整理有价值凭证] B --> C[撞库
批量尝试登录其他站点] C --> D[盗号变现
盗刷/勒索/再贩卖] style A fill:#ffe0e0 style B fill:#fff0d0 style C fill:#ffd0d0 style D fill:#e0d0ff
- 拖库(脱库):攻击者攻破某系统,把整个用户库导出窃取;
- 洗库:对拖出来的数据做清洗、去重、整理出可用凭证;
- 撞库:拿这批凭证去撞别的网站。
所以当你的用户在你这被撞库盗号时,源头往往是另一家公司几个月前的数据泄露。你能做的不是阻止源头,而是「让别人泄露的密码在你这撞不动」。
二、撞库的危险性
很多团队对撞库的重视程度不够,因为「我们系统又没漏洞」。但撞库的危害恰恰在于它绕过了「漏洞」这个概念。
1. 命中率虽低,绝对量惊人
假设攻击者手里有 1000 万条泄露凭证,你这边复用率哪怕只有 0.5%,那也是 5 万个被攻陷的账号。对一个支付、电商或社交平台来说,5 万个被盗账号意味着什么,不用我多说。
2. 它是「合法流量」,极难识别
撞库用的是真实存在的账号、正确格式的密码,请求本身完全合规。它不像 SQL 注入有 payload 特征,也不像 DDoS 有流量洪峰。单看一次请求,你无法区分它是攻击者还是正常用户。 必须从聚合维度(IP、设备、行为、时序)才能识别。
3. 直接通往资损与合规事故
对支付 / 金融系统尤其致命。账号一旦被撞开:
- 盗刷余额、盗用绑定的支付方式;
- 利用账号做洗钱、薅羊毛、刷单;
- 拖出更多用户隐私,触发数据合规处罚(GDPR / 本地数据保护法)。
在受监管的支付场景下,一次大规模撞库导致的资损 + 监管问询 + 用户信任崩塌,远比修一个代码 bug 的成本高得多。
4. 它会持续不断地发生
只要还有新的数据泄露事件(每个月都有),就会有新的凭证库流入黑市,你就会持续被撞。这不是「修一次就好」的问题,而是需要常态化防御的对抗。
三、作为服务提供者,如何防御撞库
撞库防御没有银弹,核心思路是分层纵深防御(Defense in Depth):在凭证、人机、风控、限流、监控五个层面叠加,让攻击者的成本远高于收益。
下面按「从必做到进阶」的优先级展开。
防御全景图
识别代理/秽IP] end L1 --> L2 subgraph L2[第 2 层 · 人机识别] direction LR CAP[自适应验证码] BEH[行为/设备指纹] end L2 --> L3 subgraph L3[第 3 层 · 凭证安全] direction LR PWN[泄露密码比对] MFA[多因素认证 MFA] end L3 --> L4 subgraph L4[第 4 层 · 风控评分] direction LR RISK[实时风险评分引擎] end L4 --> Decision{决策} Decision -->|低风险| Pass[放行] Decision -->|中风险| Challenge[二次验证] Decision -->|高风险| Block[拦截/告警] Monitor[第 5 层 · 监控与响应] -.审计.-> L1 Monitor -.审计.-> L4 style Block fill:#ffb0b0 style Pass fill:#b0ffb0 style Challenge fill:#fff0b0
1. 凭证层:从根上减少「可被撞中」的账号
① 拦截已泄露的密码(性价比最高的一招)
在用户注册和改密码时,比对密码是否出现在已知泄露库中。最优雅的做法是接入 Have I Been Pwned 的 k-anonymity 接口:
- 客户端对密码做 SHA-1,取哈希前 5 位发给 HIBP;
- HIBP 返回所有以这 5 位开头的哈希后缀列表;
- 客户端在本地比对完整哈希。
整个过程中,完整密码和完整哈希都不会离开你的系统,既能查泄露,又不泄密。
# 伪代码示意
hash = SHA1(password).upper() # 例: 5BAA61E4C9B93F3F0682250B6CF8331B7EE68FD8
prefix, suffix = hash[:5], hash[5:] # 5BAA6 / 1E4C9B93F3F0682250B6CF8331B7EE68FD8
candidates = GET https://api.pwnedpasswords.com/range/{prefix}
if suffix in candidates:
reject("该密码已在数据泄露中出现,请更换")② 强制 MFA / 多因素认证
这是对抗撞库最有效的单点措施。即使攻击者撞中了正确密码,没有第二因素(TOTP、短信、邮件 OTP、Passkey)也登不进去。
- 高敏感操作(支付、改密、改绑)必须强制 MFA;
- 对登录可以做自适应 MFA:正常设备 + 正常地点免验,异常时才触发,平衡安全与体验。
- 长期方向是推 Passkey / WebAuthn,从根本上消灭「可被撞」的共享密码。
③ 密码哈希要用慢哈希
虽然这主要防的是拖库后被反推,但属于凭证安全基本功:用 bcrypt / scrypt / Argon2 加盐慢哈希,绝不用 MD5 / SHA-1 裸存。这样即使你自己被拖库,泄露的也不是明文。
2. 人机识别层:让自动化脚本跑不动
① 自适应验证码
不要无脑给所有用户上验证码(伤体验、流失高),而是按风险触发:同一 IP 短时间内大量登录、命中 IP 信誉黑名单、行为异常时,才弹出验证码或滑块。推荐用 reCAPTCHA v3、hCaptcha 或 Cloudflare Turnstile 这类「无感打分 + 必要时挑战」的方案。
② 设备指纹与行为分析
采集设备指纹(浏览器特征、屏幕、字体、Canvas 等)和行为特征(鼠标轨迹、输入节奏、页面停留)。撞库脚本往往:
- 设备指纹高度雷同或频繁变化;
- 没有真实的鼠标 / 键盘交互;
- 直接打登录接口,跳过了正常页面流程。
这些都是可以量化打分的异常信号。
3. 限流与信誉层:抬高攻击成本
① 多维度限流
不要只按账号限流(撞库每个账号只试一次,按账号限流形同虚设),要做多维度组合限流:
- 单 IP / IP 段 在时间窗内的登录尝试次数;
- 单设备指纹 的尝试次数;
- 全站登录失败率的整体监控(突增即预警)。
② IP 信誉库
接入或自建 IP 信誉库,识别并重点盯防:数据中心 IP、已知代理 / VPN 出口、Tor 出口节点、历史恶意 IP。撞库通常依赖大规模代理 IP 池来绕过单 IP 限流,IP 信誉是有效的对抗手段。
⚠️ 注意:不要简单粗暴地「拉黑整个 IP 段」,容易误伤 NAT 后的大量正常用户(尤其移动网络、企业出口)。要结合其他信号综合决策。
4. 风控层:把所有信号汇总成一个决策
前面所有层的信号——IP 信誉、设备指纹、行为评分、是否泄露密码、地理位置、登录时间——最终都应该汇入一个实时风险评分引擎,输出一个风险分,再据此分级处置:
直接放行] Engine --> R2[中风险
验证码/二次验证] Engine --> R3[高风险
拦截+人工/告警] style R1 fill:#b0ffb0 style R2 fill:#fff0b0 style R3 fill:#ffb0b0
分级处置的好处是对正常用户几乎无感,只在高风险时才加摩擦,避免一刀切伤害体验。
5. 监控与响应层:你得先看得见,才谈得上防
防御不是部署完就结束,可观测性同样关键:
- 指标监控:登录成功率、失败率、验证码触发率、MFA 触发率、按 IP/地区/设备的分布。撞库发生时,失败率和异常 IP 占比会出现明显突增。
- 实时告警:对全站登录失败率突增、单 IP 大量尝试、命中泄露库的登录等设置阈值告警。
- 审计日志:完整记录登录尝试(谁、何时、从哪、结果),既用于事后溯源,也用于训练风控模型。注意日志里绝不能记明文密码。
- 应急预案:一旦确认正在被撞库,要有手段快速响应——临时全局开启验证码、收紧限流阈值、对疑似受影响账号强制改密 + 下线会话、必要时短信 / 邮件通知用户。
四、落地优先级建议
如果你的团队现在还没做任何撞库防御,不必一口气全上。按投入产出比,我建议这个顺序:
第一梯队(立刻做,成本低收益高)
- 注册 / 改密时接入 HIBP 泄露密码比对;
- 高敏感操作强制 MFA;
- 多维度限流(IP + 设备),而非只按账号;
- 登录失败率监控与告警。
第二梯队(逐步建设)
- 自适应验证码(按风险触发);
- IP 信誉库;
- 设备指纹采集。
第三梯队(进阶 / 长期)
- 实时风险评分引擎,统一决策;
- 行为生物特征分析;
- 推动 Passkey / WebAuthn 替代密码。
一句话总结防御哲学:你无法阻止别处的密码泄露,但你可以让「泄露的密码在你这里撞不动」。 把单点防御叠成纵深防御,让攻击者的成本高到不值得,他自然就去撞别人家了。
说到底,撞库防御是一场没有终点的对抗。只要还有人用 123456 当所有网站的通用密码,只要还有公司在拖库,这场仗就得一直打下去。我们能做的,是让自己的系统不要成为那块最软的柿子。