搜 索

如何防御撞库攻击

  • 2阅读
  • 2026年06月07日
  • 0评论
首页 / 编程 / 正文
你的系统从没被攻破过,但你的用户照样被盗号了——因为密码是在别人家泄露的。这就是撞库最让人头疼的地方:漏洞不在你这,锅却得你背。

一、什么是撞库攻击

撞库(Credential Stuffing)是指攻击者拿着从 A 网站泄露的「用户名 + 密码」组合,批量、自动化地去尝试登录 B、C、D……网站,利用用户跨平台复用密码的习惯来盗取账号。

它的核心前提只有一句话:绝大多数人,在不同网站用着同一套密码。

攻击者不需要破解你的密码哈希,不需要找你系统的漏洞,甚至不需要懂太多技术。他只要:

  1. 搞到一份泄露的凭证库(网上几十亿条,免费的、卖的都有);
  2. 写个脚本 / 买个现成工具(Sentry MBA、OpenBullet 这类);
  3. 挂上代理 IP 池,把这批账号密码往你的登录接口上撞。

撞中一个是一个。

撞库 ≠ 暴力破解

这两个经常被混为一谈,但本质不同:

维度撞库 (Credential Stuffing)暴力破解 (Brute Force)
输入已知的真实账号密码对针对单账号穷举密码
依赖用户跨站复用密码密码强度弱
命中率低但稳定(0.1%~2%)取决于密码复杂度
流量特征海量账号、每个只试一两次单账号、高频尝试
防御重点凭证信誉 + 风控 + 人机识别频率限制 + 锁定 + 强密码

注意最后一行的流量特征差异——这正是很多传统防御失效的原因:你设了「单账号连续失败 5 次锁定」,但撞库每个账号只试一次就换下一个,你的锁定策略根本不会触发。

撞库不是孤立的,它在一条黑产链路里

撞库通常是整条数据犯罪链路的「变现末端」:

flowchart LR A[拖库
入侵系统导出数据库] --> 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. 它会持续不断地发生

只要还有新的数据泄露事件(每个月都有),就会有新的凭证库流入黑市,你就会持续被撞。这不是「修一次就好」的问题,而是需要常态化防御的对抗。

flowchart TD L[别处发生新的数据泄露] --> M[新凭证流入黑市] M --> N[攻击者更新撞库字典] N --> O[针对你的接口发起撞库] O --> P{你的防御是否到位} P -->|是| Q[大量请求被拦截] P -->|否| R[账号被盗 / 资损] Q --> L R --> L style R fill:#ffb0b0 style Q fill:#b0ffb0

三、作为服务提供者,如何防御撞库

撞库防御没有银弹,核心思路是分层纵深防御(Defense in Depth):在凭证、人机、风控、限流、监控五个层面叠加,让攻击者的成本远高于收益。

下面按「从必做到进阶」的优先级展开。

防御全景图

flowchart TB Req[登录请求] --> L1 subgraph L1[第 1 层 · 边缘限流] direction LR RL[IP / 接口限流] REP[IP 信誉库
识别代理/秽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 Pwnedk-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 信誉、设备指纹、行为评分、是否泄露密码、地理位置、登录时间——最终都应该汇入一个实时风险评分引擎,输出一个风险分,再据此分级处置:

flowchart LR subgraph Signals[输入信号] S1[IP 信誉] S2[设备指纹] S3[行为评分] S4[地理/时间异常] S5[全站失败率] end Signals --> Engine[风险评分引擎] Engine --> R1[低风险
直接放行] Engine --> R2[中风险
验证码/二次验证] Engine --> R3[高风险
拦截+人工/告警] style R1 fill:#b0ffb0 style R2 fill:#fff0b0 style R3 fill:#ffb0b0

分级处置的好处是对正常用户几乎无感,只在高风险时才加摩擦,避免一刀切伤害体验。

5. 监控与响应层:你得先看得见,才谈得上防

防御不是部署完就结束,可观测性同样关键:

  • 指标监控:登录成功率、失败率、验证码触发率、MFA 触发率、按 IP/地区/设备的分布。撞库发生时,失败率和异常 IP 占比会出现明显突增。
  • 实时告警:对全站登录失败率突增、单 IP 大量尝试、命中泄露库的登录等设置阈值告警。
  • 审计日志:完整记录登录尝试(谁、何时、从哪、结果),既用于事后溯源,也用于训练风控模型。注意日志里绝不能记明文密码。
  • 应急预案:一旦确认正在被撞库,要有手段快速响应——临时全局开启验证码、收紧限流阈值、对疑似受影响账号强制改密 + 下线会话、必要时短信 / 邮件通知用户。

四、落地优先级建议

如果你的团队现在还没做任何撞库防御,不必一口气全上。按投入产出比,我建议这个顺序:

  1. 第一梯队(立刻做,成本低收益高)

    • 注册 / 改密时接入 HIBP 泄露密码比对;
    • 高敏感操作强制 MFA;
    • 多维度限流(IP + 设备),而非只按账号;
    • 登录失败率监控与告警。
  2. 第二梯队(逐步建设)

    • 自适应验证码(按风险触发);
    • IP 信誉库;
    • 设备指纹采集。
  3. 第三梯队(进阶 / 长期)

    • 实时风险评分引擎,统一决策;
    • 行为生物特征分析;
    • 推动 Passkey / WebAuthn 替代密码。

一句话总结防御哲学:你无法阻止别处的密码泄露,但你可以让「泄露的密码在你这里撞不动」。 把单点防御叠成纵深防御,让攻击者的成本高到不值得,他自然就去撞别人家了。


说到底,撞库防御是一场没有终点的对抗。只要还有人用 123456 当所有网站的通用密码,只要还有公司在拖库,这场仗就得一直打下去。我们能做的,是让自己的系统不要成为那块最软的柿子。
评论区
暂无评论
avatar